Browse Source

support --mode, --orientation, --monitor with --evdev

master
evan 5 years ago
parent
commit
4fa89a9119
  1. 84
      remarkable_mouse/evdev.py
  2. 9
      remarkable_mouse/pynput.py
  3. 8
      remarkable_mouse/remarkable_mouse.py

84
remarkable_mouse/evdev.py

@ -1,5 +1,8 @@
import logging import logging
import struct import struct
import subprocess
from screeninfo import get_monitors
import time
logging.basicConfig(format='%(message)s') logging.basicConfig(format='%(message)s')
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -24,6 +27,7 @@ def create_local_device():
# Set device properties to emulate those of Wacom tablets # Set device properties to emulate those of Wacom tablets
device.name = 'reMarkable tablet' device.name = 'reMarkable tablet'
device.id = { device.id = {
'bustype': 0x18, # i2c 'bustype': 0x18, # i2c
'vendor': 0x056a, # wacom 'vendor': 0x056a, # wacom
@ -85,6 +89,28 @@ def create_local_device():
return device.create_uinput_device() return device.create_uinput_device()
# remap screen coordinates to wacom coordinates
def remap(x, y, wacom_width, wacom_height, monitor_width,
monitor_height, mode, orientation=None):
if orientation in ('bottom', 'top'):
x, y = y, x
monitor_width, monitor_height = monitor_height, monitor_width
ratio_width, ratio_height = wacom_width / monitor_width, wacom_height / monitor_height
if mode == 'fit':
scaling = max(ratio_width, ratio_height)
elif mode == 'fill':
scaling = min(ratio_width, ratio_height)
else:
raise NotImplementedError
return (
scaling * (x - (monitor_width - wacom_width / scaling) / 2),
scaling * (y - (monitor_height - wacom_height / scaling) / 2)
)
def pipe_device(args, remote_device, local_device): def pipe_device(args, remote_device, local_device):
""" """
Pipe events from a remote device to a local device. Pipe events from a remote device to a local device.
@ -94,7 +120,65 @@ def pipe_device(args, remote_device, local_device):
remote_device (paramiko.ChannelFile): read-only stream of input events remote_device (paramiko.ChannelFile): read-only stream of input events
local_device: local virtual input device to write events to local_device: local virtual input device to write events to
""" """
# give time for virtual device creation before running xinput commands
time.sleep(1)
# set orientation with xinput
orientation = {'left': 0, 'bottom': 1, 'top': 2, 'right': 3}[args.orientation]
result = subprocess.run(
'xinput --set-prop "reMarkable tablet stylus" "Wacom Rotation" {}'.format(orientation),
capture_output=True,
shell=True
)
if result.returncode != 0:
log.warning("Error setting orientation: %s", result.stderr)
# set monitor to use
monitor = get_monitors()[args.monitor]
log.debug('Chose monitor: {}'.format(monitor))
result = subprocess.run(
'xinput --map-to-output "reMarkable tablet stylus" {}'.format(monitor.name),
capture_output=True,
shell=True
)
if result.returncode != 0:
log.warning("Error setting monitor: %s", result.stderr)
# set stylus pressure
result = subprocess.run(
'xinput --set-prop "reMarkable tablet stylus" "Wacom Pressure Threshold" {}'.format(args.threshold),
capture_output=True,
shell=True
)
if result.returncode != 0:
log.warning("Error setting pressure threshold: %s", result.stderr)
# set fitting mode
min_x, min_y = remap(
0, 0,
MAX_ABS_X, MAX_ABS_Y, monitor.width, monitor.height,
args.mode,
args.orientation
)
max_x, max_y = remap(
monitor.width, monitor.height,
MAX_ABS_X, MAX_ABS_Y, monitor.width, monitor.height,
args.mode,
args.orientation
)
log.debug("Wacom tablet area: {} {} {} {}".format(min_x, min_y, max_x, max_y))
result = subprocess.run(
'xinput --set-prop "reMarkable tablet stylus" "Wacom Tablet Area" \
{} {} {} {}'.format(min_x, min_y, max_x, max_y),
capture_output=True,
shell=True
)
if result.returncode != 0:
log.warning("Error setting fit: %s", result.stderr)
import libevdev import libevdev
# While debug mode is active, we log events grouped together between # While debug mode is active, we log events grouped together between
# SYN_REPORT events. Pending events for the next log are stored here # SYN_REPORT events. Pending events for the next log are stored here
pending_events = [] pending_events = []

9
remarkable_mouse/pynput.py

@ -27,8 +27,9 @@ wacom_height = 20967
# finger_height = 1023 # finger_height = 1023
# remap wacom coordinates in various orientations # remap wacom coordinates to screen coordinates
def remap(x, y, wacom_width, wacom_height, monitor_width, monitor_height, mode, orientation=None): def remap(x, y, wacom_width, wacom_height, monitor_width,
monitor_height, mode, orientation):
if orientation == 'bottom': if orientation == 'bottom':
y = wacom_height - y y = wacom_height - y
@ -43,9 +44,9 @@ def remap(x, y, wacom_width, wacom_height, monitor_width, monitor_height, mode,
ratio_width, ratio_height = monitor_width / wacom_width, monitor_height / wacom_height ratio_width, ratio_height = monitor_width / wacom_width, monitor_height / wacom_height
if mode == 'fit': if mode == 'fill':
scaling = max(ratio_width, ratio_height) scaling = max(ratio_width, ratio_height)
elif mode == 'fill': elif mode == 'fit':
scaling = min(ratio_width, ratio_height) scaling = min(ratio_width, ratio_height)
else: else:
raise NotImplementedError raise NotImplementedError

8
remarkable_mouse/remarkable_mouse.py

@ -84,11 +84,11 @@ def main():
parser.add_argument('--key', type=str, metavar='PATH', help="ssh private key") parser.add_argument('--key', type=str, metavar='PATH', help="ssh private key")
parser.add_argument('--password', default=None, type=str, help="ssh password") parser.add_argument('--password', default=None, type=str, help="ssh password")
parser.add_argument('--address', default='10.11.99.1', type=str, help="device address") parser.add_argument('--address', default='10.11.99.1', type=str, help="device address")
parser.add_argument('--mode', default='fit', choices=['fit', 'fill']) parser.add_argument('--mode', default='fit', choices=['fit', 'fill'], help="scale setting")
parser.add_argument('--orientation', default='right', choices=['top', 'left', 'right', 'bottom'], help="position of tablet buttons") parser.add_argument('--orientation', default='right', choices=['top', 'left', 'right', 'bottom'], help="position of tablet buttons")
parser.add_argument('--monitor', default=0, type=int, metavar='NUM', help="monitor to use") parser.add_argument('--monitor', default=0, type=int, metavar='NUM', help="monitor to output to")
parser.add_argument('--threshold', default=1000, type=int, help="stylus pressure threshold (default 1000)") parser.add_argument('--threshold', metavar='THRESH', default=600, type=int, help="stylus pressure threshold (default 600)")
parser.add_argument('--evdev', action='store_true', default=False, help="use evdev to support pen tilt (requires root, no OSX support)") parser.add_argument('--evdev', action='store_true', default=False, help="use evdev to support pen pressure (requires root, Linux only)")
args = parser.parse_args() args = parser.parse_args()

Loading…
Cancel
Save