From 08bfa2b669fc9789d807d10a096ca5f8576e4bf7 Mon Sep 17 00:00:00 2001 From: DCS-87 <68989076+DCS-87@users.noreply.github.com> Date: Tue, 30 Jan 2024 17:32:34 +0100 Subject: [PATCH 01/23] Add files via upload Add windows pen pressure support --- remarkable_mouse/pen.py | 195 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 195 insertions(+) create mode 100644 remarkable_mouse/pen.py diff --git a/remarkable_mouse/pen.py b/remarkable_mouse/pen.py new file mode 100644 index 0000000..ea9ec6b --- /dev/null +++ b/remarkable_mouse/pen.py @@ -0,0 +1,195 @@ +import logging +import struct +import ctypes +from screeninfo import get_monitors + +from .codes import codes, types +from .common import get_monitor, remap, wacom_max_x, wacom_max_y, log_event +from ctypes import * +from ctypes.wintypes import * + +logging.basicConfig(format='%(message)s') +log = logging.getLogger('remouse') +log.debug('Using pen injection') + +# Constants +# For penMask +PEN_MASK_NONE= 0x00000000 # Default +PEN_MASK_PRESSURE= 0x00000001 +PEN_MASK_ORIENTATION= 0x00000002 +PEN_MASK_TILT_X= 0x00000004 +PEN_MASK_TILT_Y= 0x00000008 + +# For penFlag +PEN_FLAG_NONE= 0x00000000 + +# For pointerType +PT_POINTER= 0x00000001 # All +PT_TOUCH= 0x00000002 +PT_PEN= 0x00000003 +PT_MOUSE= 0x00000004 + +#For pointerFlags +POINTER_FLAG_NONE= 0x00000000 # Default +POINTER_FLAG_NEW= 0x00000001 +POINTER_FLAG_INRANGE= 0x00000002 +POINTER_FLAG_INCONTACT= 0x00000004 +POINTER_FLAG_FIRSTBUTTON= 0x00000010 +POINTER_FLAG_SECONDBUTTON=0x00000020 +POINTER_FLAG_THIRDBUTTON= 0x00000040 +POINTER_FLAG_FOURTHBUTTON=0x00000080 +POINTER_FLAG_FIFTHBUTTON= 0x00000100 +POINTER_FLAG_PRIMARY= 0x00002000 +POINTER_FLAG_CONFIDENCE= 0x00004000 +POINTER_FLAG_CANCELED= 0x00008000 +POINTER_FLAG_DOWN= 0x00010000 +POINTER_FLAG_UPDATE= 0x00020000 +POINTER_FLAG_UP= 0x00040000 +POINTER_FLAG_WHEEL= 0x00080000 +POINTER_FLAG_HWHEEL= 0x00100000 +POINTER_FLAG_CAPTURECHANGED=0x00200000 + +# Structs Needed +class POINTER_INFO(Structure): + _fields_=[("pointerType",c_uint32), + ("pointerId",c_uint32), + ("frameId",c_uint32), + ("pointerFlags",c_int), + ("sourceDevice",HANDLE), + ("hwndTarget",HWND), + ("ptPixelLocation",POINT), + ("ptHimetricLocation",POINT), + ("ptPixelLocationRaw",POINT), + ("ptHimetricLocationRaw",POINT), + ("dwTime",DWORD), + ("historyCount",c_uint32), + ("inputData",c_int32), + ("dwKeyStates",DWORD), + ("PerformanceCount",c_uint64), + ("ButtonChangeType",c_int) + ] + +class POINTER_PEN_INFO(Structure): + _fields_=[("pointerInfo",POINTER_INFO), + ("penFlags",c_int), + ("penMask",c_int), + ("pressure", c_uint32), + ("rotation", c_uint32), + ("tiltX", c_int32), + ("tiltY", c_int32)] + +class DUMMYUNIONNAME(Structure): + _fields_=[("penInfo",POINTER_PEN_INFO) + ] + +class POINTER_TYPE_INFO(Structure): + _fields_=[("type",c_uint32), + ("penInfo",POINTER_PEN_INFO) + ] + +# Initialize Pointer and Touch info +pointerInfo = POINTER_INFO(pointerType=PT_PEN, + pointerId=0, + ptPixelLocation=POINT(950, 540), + pointerFlags=POINTER_FLAG_NEW) +penInfo = POINTER_PEN_INFO(pointerInfo=pointerInfo, + penMask=(PEN_MASK_PRESSURE | PEN_MASK_TILT_X | PEN_MASK_TILT_Y), + pressure=0, + tiltX=0, + tiltY=0) + +pointerTypeInfo = POINTER_TYPE_INFO(type=PT_PEN, + penInfo=penInfo) + +device = windll.user32.CreateSyntheticPointerDevice(3, 1, 1) +print("Initialized Pen Injection as number ", device) +currently_down = False + +def updatePenInfo(down, x=0, y=0, pressure=0, tiltX=0, tiltY=0): + global currently_down + if down == True: + pointerTypeInfo.penInfo.pointerInfo.pointerFlags = (POINTER_FLAG_DOWN if not currently_down==True else POINTER_FLAG_UPDATE | POINTER_FLAG_INCONTACT) + currently_down = True + else: + pointerTypeInfo.penInfo.pointerInfo.pointerFlags = (POINTER_FLAG_UP if currently_down==True else POINTER_FLAG_UPDATE | POINTER_FLAG_INRANGE) + currently_down = False + + pointerTypeInfo.penInfo.pointerInfo.ptPixelLocation.x = x + pointerTypeInfo.penInfo.pointerInfo.ptPixelLocation.y = y + pointerTypeInfo.penInfo.pressure = pressure + pointerTypeInfo.penInfo.tiltX = tiltX + pointerTypeInfo.penInfo.tiltY = tiltY + +def applyPen(): + result = windll.user32.InjectSyntheticPointerInput(device, byref(pointerTypeInfo), 1) + if (result == False) and (log.level == logging.DEBUG): + error_code = ctypes.get_last_error() + print(f"Failed trying to update pen input. Error code: {error_code}") + print(f"Error message: {ctypes.WinError(error_code).strerror}") + +def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode): + """Loop forever and map evdev events to mouse + + Args: + rm_inputs (dictionary of paramiko.ChannelFile): dict of pen, button + and touch input streams + orientation (str): tablet orientation + monitor_num (int): monitor number to map to + region (boolean): whether to selection mapping region with region tool + threshold (int): pressure threshold + mode (str): mapping mode + """ + + monitor, _ = get_monitor(region, monitor_num, orientation) + log.debug('Chose monitor: {}'.format(monitor)) + + x = y = mapped_x = mapped_y = press = mapped_press = tiltX = tiltY = 0 + + stream = rm_inputs['pen'] + + while True: + try: + data = stream.read(16) + except TimeoutError: + continue + + e_time, e_millis, e_type, e_code, e_value = struct.unpack('2IHHi', data) + + # handle x direction + if codes[e_type][e_code] == 'ABS_X': + x = e_value + + # handle y direction + if codes[e_type][e_code] == 'ABS_Y': + y = e_value + + # handle pressure + if codes[e_type][e_code] == 'ABS_PRESSURE': + press = e_value + mapped_press = int(press* (1024/4095)) + + # handle tilt + if codes[e_type][e_code] == 'ABS_TILT_X': + tiltX = int(e_value*(90/6300)) + + # handle pressure + if codes[e_type][e_code] == 'ABS_TILT_Y': + tiltY = int(e_value*(90/6300)) + + if codes[e_type][e_code] == 'SYN_REPORT': + mapped_x, mapped_y = remap( + x, y, + wacom_max_x, wacom_max_y, + monitor.width, monitor.height, + mode, orientation, + ) + + # handle draw + if press > 0: + updatePenInfo(True, int(mapped_x), int(mapped_y), mapped_press, tiltX, tiltY) + else: + updatePenInfo(False, int(mapped_x), int(mapped_y), mapped_press, tiltX, tiltY) + applyPen() + + # if log.level == logging.DEBUG: + # log_event(e_time, e_millis, e_type, e_code, e_value) \ No newline at end of file From f658c3fdf0b1f7dfc5eb9f5393ad69e9057406c8 Mon Sep 17 00:00:00 2001 From: DCS-87 <68989076+DCS-87@users.noreply.github.com> Date: Tue, 30 Jan 2024 17:35:21 +0100 Subject: [PATCH 02/23] Update remarkable_mouse.py Add pen pressure support for windows --- remarkable_mouse/remarkable_mouse.py | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/remarkable_mouse/remarkable_mouse.py b/remarkable_mouse/remarkable_mouse.py index 69a6717..21baf60 100755 --- a/remarkable_mouse/remarkable_mouse.py +++ b/remarkable_mouse/remarkable_mouse.py @@ -141,6 +141,7 @@ def main(): parser.add_argument('--region', action='store_true', default=False, help="Use a GUI to position the output area. Overrides --monitor") 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 pressure (requires root, Linux only)") + parser.add_argument('--pen', action='store_true', default=False, help="use pen input to support pen pressure in windows") args = parser.parse_args() @@ -164,6 +165,9 @@ def main(): if args.evdev: from remarkable_mouse.evdev import read_tablet + elif args.pen: + from remarkable_mouse.pen import read_tablet + else: from remarkable_mouse.pynput import read_tablet From 59211db21728d9657fedd00a52bd4840cbeee720 Mon Sep 17 00:00:00 2001 From: DCS-87 <68989076+DCS-87@users.noreply.github.com> Date: Tue, 30 Jan 2024 17:37:04 +0100 Subject: [PATCH 03/23] Update README.md --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index a52f29e..531a62a 100644 --- a/README.md +++ b/README.md @@ -64,5 +64,6 @@ optional arguments: --region Use a GUI to position the output area. Overrides --monitor --threshold THRESH stylus pressure threshold (default 600) --evdev use evdev to support pen pressure (requires root, Linux only) + --pen use pen injection to support pen pressure (Windows only) ``` From d7425824e8eeb1f156523a0f7a3f98f2521567f8 Mon Sep 17 00:00:00 2001 From: DCS-87 <68989076+DCS-87@users.noreply.github.com> Date: Fri, 2 Feb 2024 13:08:21 +0100 Subject: [PATCH 04/23] Fix monitor selection, better handling of flags minimizes error messages --- remarkable_mouse/pen.py | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/remarkable_mouse/pen.py b/remarkable_mouse/pen.py index ea9ec6b..66990ad 100644 --- a/remarkable_mouse/pen.py +++ b/remarkable_mouse/pen.py @@ -1,6 +1,7 @@ import logging import struct import ctypes +import time from screeninfo import get_monitors from .codes import codes, types @@ -108,7 +109,7 @@ class POINTER_TYPE_INFO(Structure): def updatePenInfo(down, x=0, y=0, pressure=0, tiltX=0, tiltY=0): global currently_down if down == True: - pointerTypeInfo.penInfo.pointerInfo.pointerFlags = (POINTER_FLAG_DOWN if not currently_down==True else POINTER_FLAG_UPDATE | POINTER_FLAG_INCONTACT) + pointerTypeInfo.penInfo.pointerInfo.pointerFlags = (POINTER_FLAG_DOWN if not currently_down==True else POINTER_FLAG_UPDATE | POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT) currently_down = True else: pointerTypeInfo.penInfo.pointerInfo.pointerFlags = (POINTER_FLAG_UP if currently_down==True else POINTER_FLAG_UPDATE | POINTER_FLAG_INRANGE) @@ -172,24 +173,23 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode) if codes[e_type][e_code] == 'ABS_TILT_X': tiltX = int(e_value*(90/6300)) - # handle pressure if codes[e_type][e_code] == 'ABS_TILT_Y': tiltY = int(e_value*(90/6300)) if codes[e_type][e_code] == 'SYN_REPORT': + mapped_x, mapped_y = remap( x, y, wacom_max_x, wacom_max_y, monitor.width, monitor.height, mode, orientation, ) + # handle draw + if press > 0: + updatePenInfo(True, max(int(monitor.x+mapped_x),0), max(int(monitor.y+mapped_y),0), mapped_press, tiltX, tiltY) + else: + updatePenInfo(False, max(int(monitor.x+mapped_x),0), max(int(monitor.y+mapped_y),0), mapped_press, tiltX, tiltY) + applyPen() - # handle draw - if press > 0: - updatePenInfo(True, int(mapped_x), int(mapped_y), mapped_press, tiltX, tiltY) - else: - updatePenInfo(False, int(mapped_x), int(mapped_y), mapped_press, tiltX, tiltY) - applyPen() - # if log.level == logging.DEBUG: # log_event(e_time, e_millis, e_type, e_code, e_value) \ No newline at end of file From fa358dd34c935e9d12d53b26da33403213ee31f2 Mon Sep 17 00:00:00 2001 From: DCS-87 <68989076+DCS-87@users.noreply.github.com> Date: Fri, 2 Feb 2024 13:16:38 +0100 Subject: [PATCH 05/23] Update README.md --- README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README.md b/README.md index 531a62a..f3a47a1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,9 @@ +# remarkable_mouse with pressure and tilt for Windows + +While using the excellent remarkable mouse from Evidlo I needed to have pressure sensitivity for Windows. I don't really know how to code but following the logic an through online searches came to a solution. It is probably not pretty, but it works and it also enables tilt in Windows by creating a virtual pen injection. Use the --pen flag to load this mode. Would be great of someone would take this, implement it correctly and create a tray tool out of it with some options (switch windows during usage for instance). + +You can download a zip of this repo and install with 'pip install path-to-zip'. + # remarkable_mouse Use your reMarkable as a graphics tablet. From 6ab1ec8c95fb43016f0364fff697fbdea69e8f1c Mon Sep 17 00:00:00 2001 From: asklevan Date: Tue, 16 Jul 2024 23:29:57 -0400 Subject: [PATCH 06/23] Cleaned up pen.py --- pyvenv.cfg | 5 +++++ remarkable_mouse/pen.py | 39 ++++++++++++++++++++++----------------- 2 files changed, 27 insertions(+), 17 deletions(-) create mode 100644 pyvenv.cfg diff --git a/pyvenv.cfg b/pyvenv.cfg new file mode 100644 index 0000000..451f68a --- /dev/null +++ b/pyvenv.cfg @@ -0,0 +1,5 @@ +home = C:\Users\Guest1\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0 +include-system-site-packages = false +version = 3.12.3 +executable = C:\Users\Guest1\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\python.exe +command = C:\Users\Guest1\AppData\Local\Microsoft\WindowsApps\PythonSoftwareFoundation.Python.3.12_qbz5n2kfra8p0\python.exe -m venv E:\Programming Projects\remarkable_mouse_winpress diff --git a/remarkable_mouse/pen.py b/remarkable_mouse/pen.py index 66990ad..a24fbcc 100644 --- a/remarkable_mouse/pen.py +++ b/remarkable_mouse/pen.py @@ -14,6 +14,13 @@ log.debug('Using pen injection') # Constants + +MAX_ABS_PRESSURE=4095 +MAX_WIN_PRESSURE=1024 +MAX_ANGLE=90 +MAX_ABS_TILT=6300 + + # For penMask PEN_MASK_NONE= 0x00000000 # Default PEN_MASK_PRESSURE= 0x00000001 @@ -102,17 +109,17 @@ class POINTER_TYPE_INFO(Structure): pointerTypeInfo = POINTER_TYPE_INFO(type=PT_PEN, penInfo=penInfo) -device = windll.user32.CreateSyntheticPointerDevice(3, 1, 1) +device = windll.user32.CreateSyntheticPointerDevice(PT_PEN, 1, 1) print("Initialized Pen Injection as number ", device) currently_down = False -def updatePenInfo(down, x=0, y=0, pressure=0, tiltX=0, tiltY=0): +def applyPen(x=0, y=0, pressure=0, tiltX=0, tiltY=0): global currently_down - if down == True: - pointerTypeInfo.penInfo.pointerInfo.pointerFlags = (POINTER_FLAG_DOWN if not currently_down==True else POINTER_FLAG_UPDATE | POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT) + if pressure > 0: + pointerTypeInfo.penInfo.pointerInfo.pointerFlags = (POINTER_FLAG_DOWN if not currently_down else POINTER_FLAG_UPDATE | POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT) currently_down = True else: - pointerTypeInfo.penInfo.pointerInfo.pointerFlags = (POINTER_FLAG_UP if currently_down==True else POINTER_FLAG_UPDATE | POINTER_FLAG_INRANGE) + pointerTypeInfo.penInfo.pointerInfo.pointerFlags = (POINTER_FLAG_UP if currently_down else POINTER_FLAG_UPDATE | POINTER_FLAG_INRANGE) currently_down = False pointerTypeInfo.penInfo.pointerInfo.ptPixelLocation.x = x @@ -120,13 +127,14 @@ def updatePenInfo(down, x=0, y=0, pressure=0, tiltX=0, tiltY=0): pointerTypeInfo.penInfo.pressure = pressure pointerTypeInfo.penInfo.tiltX = tiltX pointerTypeInfo.penInfo.tiltY = tiltY - -def applyPen(): + result = windll.user32.InjectSyntheticPointerInput(device, byref(pointerTypeInfo), 1) if (result == False) and (log.level == logging.DEBUG): error_code = ctypes.get_last_error() print(f"Failed trying to update pen input. Error code: {error_code}") print(f"Error message: {ctypes.WinError(error_code).strerror}") + + def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode): """Loop forever and map evdev events to mouse @@ -167,14 +175,14 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode) # handle pressure if codes[e_type][e_code] == 'ABS_PRESSURE': press = e_value - mapped_press = int(press* (1024/4095)) + mapped_press = int(press* (MAX_WIN_PRESSURE / MAX_ABS_PRESSURE)) # handle tilt if codes[e_type][e_code] == 'ABS_TILT_X': - tiltX = int(e_value*(90/6300)) + tiltX = int(e_value*( MAX_ANGLE / MAX_ABS_TILT )) if codes[e_type][e_code] == 'ABS_TILT_Y': - tiltY = int(e_value*(90/6300)) + tiltY = int(e_value*( MAX_ANGLE /MAX_ABS_TILT )) if codes[e_type][e_code] == 'SYN_REPORT': @@ -184,12 +192,9 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode) monitor.width, monitor.height, mode, orientation, ) + # handle draw - if press > 0: - updatePenInfo(True, max(int(monitor.x+mapped_x),0), max(int(monitor.y+mapped_y),0), mapped_press, tiltX, tiltY) - else: - updatePenInfo(False, max(int(monitor.x+mapped_x),0), max(int(monitor.y+mapped_y),0), mapped_press, tiltX, tiltY) - applyPen() + applyPen(max(int(monitor.x+mapped_x),0), max(int(monitor.y+mapped_y),0), mapped_press, tiltX, tiltY) - # if log.level == logging.DEBUG: - # log_event(e_time, e_millis, e_type, e_code, e_value) \ No newline at end of file + if log.level == logging.DEBUG: + log_event(e_time, e_millis, e_type, e_code, e_value) \ No newline at end of file From 560482d5b2b622e91f29a393138b42414ecf95e2 Mon Sep 17 00:00:00 2001 From: aklevans Date: Tue, 16 Jul 2024 23:38:35 -0400 Subject: [PATCH 07/23] clean up file --- remarkable_mouse/pen.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/remarkable_mouse/pen.py b/remarkable_mouse/pen.py index a24fbcc..416f715 100644 --- a/remarkable_mouse/pen.py +++ b/remarkable_mouse/pen.py @@ -15,12 +15,12 @@ # Constants +# Max values for linux / windows MAX_ABS_PRESSURE=4095 MAX_WIN_PRESSURE=1024 MAX_ANGLE=90 MAX_ABS_TILT=6300 - # For penMask PEN_MASK_NONE= 0x00000000 # Default PEN_MASK_PRESSURE= 0x00000001 @@ -119,7 +119,7 @@ def applyPen(x=0, y=0, pressure=0, tiltX=0, tiltY=0): pointerTypeInfo.penInfo.pointerInfo.pointerFlags = (POINTER_FLAG_DOWN if not currently_down else POINTER_FLAG_UPDATE | POINTER_FLAG_INRANGE | POINTER_FLAG_INCONTACT) currently_down = True else: - pointerTypeInfo.penInfo.pointerInfo.pointerFlags = (POINTER_FLAG_UP if currently_down else POINTER_FLAG_UPDATE | POINTER_FLAG_INRANGE) + pointerTypeInfo.penInfo.pointerInfo.pointerFlags = (POINTER_FLAG_UP if currently_down==True else POINTER_FLAG_UPDATE | POINTER_FLAG_INRANGE) currently_down = False pointerTypeInfo.penInfo.pointerInfo.ptPixelLocation.x = x From 9f575150f3aafb2bf0d5a4dca7ffc65d5bacb7e8 Mon Sep 17 00:00:00 2001 From: aklevans Date: Wed, 17 Jul 2024 12:08:44 -0400 Subject: [PATCH 08/23] Auto update monitor based on mouse --- remarkable_mouse/common.py | 22 ++++++++++++++++++++-- remarkable_mouse/evdev.py | 10 ++++++++-- remarkable_mouse/pen.py | 11 +++++++++-- remarkable_mouse/pynput.py | 13 +++++++++++-- remarkable_mouse/remarkable_mouse.py | 4 ++++ 5 files changed, 52 insertions(+), 8 deletions(-) diff --git a/remarkable_mouse/common.py b/remarkable_mouse/common.py index a320651..3116f4a 100644 --- a/remarkable_mouse/common.py +++ b/remarkable_mouse/common.py @@ -3,7 +3,6 @@ import logging import sys from screeninfo import get_monitors, Monitor - from .codes import codes, types logging.basicConfig(format='%(message)s') @@ -12,7 +11,25 @@ wacom_max_y = 15725 wacom_max_x = 20967 -def get_monitor(region, monitor_num, orientation): +def get_current_monitor_num(): + """ Get monitor number that the mouse is currently on + + Returns: + int: monitor number that mouse is currently on, or 0 if couldn't pick one + """ + from pynput.mouse import Controller + + mouse = Controller() + mouse_x = mouse.position[0] + mouse_y = mouse.position[1] + + for i, monitor in enumerate(get_monitors()): + if mouse_x >= monitor.x and mouse_x < monitor.x + monitor.width and mouse_y >= monitor.y and mouse_y < monitor.y + monitor.height: + return i + return 0 + + +def get_monitor(region, monitor_num, orientation, auto_adjust): """ Get info of where we want to map the tablet to Args: @@ -20,6 +37,7 @@ def get_monitor(region, monitor_num, orientation): monitor_num (int): index of monitor to use. Implies region=False orientation (str): Location of tablet charging port. ('top', 'bottom', 'left', 'right') + Returns: screeninfo.Monitor diff --git a/remarkable_mouse/evdev.py b/remarkable_mouse/evdev.py index 19af7e0..466f3b1 100644 --- a/remarkable_mouse/evdev.py +++ b/remarkable_mouse/evdev.py @@ -8,7 +8,7 @@ import libevdev from .codes import codes, types -from .common import get_monitor, remap, wacom_max_x, wacom_max_y, log_event +from .common import get_monitor, remap, wacom_max_x, wacom_max_y, log_event, get_current_monitor_num logging.basicConfig(format='%(message)s') log = logging.getLogger('remouse') @@ -76,7 +76,7 @@ def create_local_device(): return device.create_uinput_device() -def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode): +def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor): """Pipe rM evdev events to local device Args: @@ -101,6 +101,12 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode) # for input_name, stream in cycle(rm_inputs.items()): stream = rm_inputs['pen'] while True: + if auto_monitor: + new_monitor = get_current_monitor_num() + if new_monitor != monitor_num: + monitor_num = new_monitor + monitor, _ = get_monitor(region, monitor_num, orientation) + try: data = stream.read(16) except TimeoutError: diff --git a/remarkable_mouse/pen.py b/remarkable_mouse/pen.py index 416f715..89863e0 100644 --- a/remarkable_mouse/pen.py +++ b/remarkable_mouse/pen.py @@ -5,7 +5,7 @@ from screeninfo import get_monitors from .codes import codes, types -from .common import get_monitor, remap, wacom_max_x, wacom_max_y, log_event +from .common import get_monitor, remap, wacom_max_x, wacom_max_y, log_event, get_current_monitor_num from ctypes import * from ctypes.wintypes import * @@ -136,7 +136,7 @@ def applyPen(x=0, y=0, pressure=0, tiltX=0, tiltY=0): -def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode): +def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor): """Loop forever and map evdev events to mouse Args: @@ -149,6 +149,7 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode) mode (str): mapping mode """ + monitor, _ = get_monitor(region, monitor_num, orientation) log.debug('Chose monitor: {}'.format(monitor)) @@ -157,6 +158,12 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode) stream = rm_inputs['pen'] while True: + if auto_monitor: + new_monitor = get_current_monitor_num() + if new_monitor != monitor_num: + monitor_num = new_monitor + monitor, _ = get_monitor(region, monitor_num, orientation) + try: data = stream.read(16) except TimeoutError: diff --git a/remarkable_mouse/pynput.py b/remarkable_mouse/pynput.py index c5c83cc..9247808 100644 --- a/remarkable_mouse/pynput.py +++ b/remarkable_mouse/pynput.py @@ -4,7 +4,7 @@ # from .codes import EV_SYN, EV_ABS, ABS_X, ABS_Y, BTN_TOUCH from .codes import codes -from .common import get_monitor, remap, wacom_max_x, wacom_max_y, log_event +from .common import get_monitor, remap, wacom_max_x, wacom_max_y, log_event, get_current_monitor_num logging.basicConfig(format='%(message)s') log = logging.getLogger('remouse') @@ -14,7 +14,7 @@ # finger_width = 767 # finger_height = 1023 -def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode): +def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor): """Loop forever and map evdev events to mouse Args: @@ -25,12 +25,15 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode) region (boolean): whether to selection mapping region with region tool threshold (int): pressure threshold mode (str): mapping mode + auto_monitor (str) """ from pynput.mouse import Button, Controller mouse = Controller() + + monitor, _ = get_monitor(region, monitor_num, orientation) log.debug('Chose monitor: {}'.format(monitor)) @@ -38,6 +41,12 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode) stream = rm_inputs['pen'] while True: + if auto_monitor: + new_monitor = get_current_monitor_num() + if new_monitor != monitor_num: + monitor_num = new_monitor + monitor, _ = get_monitor(region, monitor_num, orientation) + try: data = stream.read(16) except TimeoutError: diff --git a/remarkable_mouse/remarkable_mouse.py b/remarkable_mouse/remarkable_mouse.py index 21baf60..f71987d 100755 --- a/remarkable_mouse/remarkable_mouse.py +++ b/remarkable_mouse/remarkable_mouse.py @@ -142,6 +142,7 @@ def main(): 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 pressure (requires root, Linux only)") parser.add_argument('--pen', action='store_true', default=False, help="use pen input to support pen pressure in windows") + parser.add_argument('--auto-monitor', action='store_true', default=True, help="actively switch monitor to the one that the mouse is currently on") args = parser.parse_args() @@ -171,6 +172,7 @@ def main(): else: from remarkable_mouse.pynput import read_tablet + read_tablet( rm_inputs, orientation=args.orientation, @@ -178,6 +180,8 @@ def main(): region=args.region, threshold=args.threshold, mode=args.mode, + auto_monitor=args.auto-monitor, + ) except PermissionError: From 23279b3f22a14374967b67c07aa52a858d7e2350 Mon Sep 17 00:00:00 2001 From: aklevans Date: Wed, 17 Jul 2024 12:18:02 -0400 Subject: [PATCH 09/23] improve auto monitor --- remarkable_mouse/pynput.py | 6 +++--- remarkable_mouse/remarkable_mouse.py | 5 +++-- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/remarkable_mouse/pynput.py b/remarkable_mouse/pynput.py index 9247808..df5ba0d 100644 --- a/remarkable_mouse/pynput.py +++ b/remarkable_mouse/pynput.py @@ -43,9 +43,9 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, while True: if auto_monitor: new_monitor = get_current_monitor_num() - if new_monitor != monitor_num: - monitor_num = new_monitor - monitor, _ = get_monitor(region, monitor_num, orientation) + if new_monitor != monitor_num: + monitor_num = new_monitor + monitor, _ = get_monitor(region, monitor_num, orientation) try: data = stream.read(16) diff --git a/remarkable_mouse/remarkable_mouse.py b/remarkable_mouse/remarkable_mouse.py index f71987d..269c484 100755 --- a/remarkable_mouse/remarkable_mouse.py +++ b/remarkable_mouse/remarkable_mouse.py @@ -142,7 +142,7 @@ def main(): 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 pressure (requires root, Linux only)") parser.add_argument('--pen', action='store_true', default=False, help="use pen input to support pen pressure in windows") - parser.add_argument('--auto-monitor', action='store_true', default=True, help="actively switch monitor to the one that the mouse is currently on") + parser.add_argument('--auto-monitor', action='store_true', default=False, help="actively switch monitor to the one that the mouse is currently on. Overrides --monitor and --region") args = parser.parse_args() @@ -172,6 +172,7 @@ def main(): else: from remarkable_mouse.pynput import read_tablet + read_tablet( rm_inputs, @@ -180,7 +181,7 @@ def main(): region=args.region, threshold=args.threshold, mode=args.mode, - auto_monitor=args.auto-monitor, + auto_monitor=args["auto-monitor"], ) From fbaf3928ee9f0f0c695d8d754ea6b93c1b8c066a Mon Sep 17 00:00:00 2001 From: aklevans Date: Wed, 17 Jul 2024 12:52:10 -0400 Subject: [PATCH 10/23] begin implementing relative tracking --- remarkable_mouse/common.py | 1 + remarkable_mouse/evdev.py | 8 +++---- remarkable_mouse/pen.py | 8 +++---- remarkable_mouse/pynput.py | 16 +++++++++----- remarkable_mouse/remarkable_mouse.py | 32 +++++++++++++++++++--------- 5 files changed, 42 insertions(+), 23 deletions(-) diff --git a/remarkable_mouse/common.py b/remarkable_mouse/common.py index 3116f4a..fc82960 100644 --- a/remarkable_mouse/common.py +++ b/remarkable_mouse/common.py @@ -25,6 +25,7 @@ def get_current_monitor_num(): for i, monitor in enumerate(get_monitors()): if mouse_x >= monitor.x and mouse_x < monitor.x + monitor.width and mouse_y >= monitor.y and mouse_y < monitor.y + monitor.height: + print(i) return i return 0 diff --git a/remarkable_mouse/evdev.py b/remarkable_mouse/evdev.py index 466f3b1..b7d8969 100644 --- a/remarkable_mouse/evdev.py +++ b/remarkable_mouse/evdev.py @@ -76,7 +76,7 @@ def create_local_device(): return device.create_uinput_device() -def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor): +def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor, relative): """Pipe rM evdev events to local device Args: @@ -103,9 +103,9 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, while True: if auto_monitor: new_monitor = get_current_monitor_num() - if new_monitor != monitor_num: - monitor_num = new_monitor - monitor, _ = get_monitor(region, monitor_num, orientation) + if new_monitor != monitor_num: + monitor_num = new_monitor + monitor, _ = get_monitor(region, monitor_num, orientation) try: data = stream.read(16) diff --git a/remarkable_mouse/pen.py b/remarkable_mouse/pen.py index 89863e0..8e45c35 100644 --- a/remarkable_mouse/pen.py +++ b/remarkable_mouse/pen.py @@ -136,7 +136,7 @@ def applyPen(x=0, y=0, pressure=0, tiltX=0, tiltY=0): -def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor): +def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor, relative): """Loop forever and map evdev events to mouse Args: @@ -160,9 +160,9 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, while True: if auto_monitor: new_monitor = get_current_monitor_num() - if new_monitor != monitor_num: - monitor_num = new_monitor - monitor, _ = get_monitor(region, monitor_num, orientation) + if new_monitor != monitor_num: + monitor_num = new_monitor + monitor, _ = get_monitor(region, monitor_num, orientation) try: data = stream.read(16) diff --git a/remarkable_mouse/pynput.py b/remarkable_mouse/pynput.py index df5ba0d..bcdd2f2 100644 --- a/remarkable_mouse/pynput.py +++ b/remarkable_mouse/pynput.py @@ -14,7 +14,7 @@ # finger_width = 767 # finger_height = 1023 -def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor): +def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor, relative): """Loop forever and map evdev events to mouse Args: @@ -76,10 +76,16 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, monitor.width, monitor.height, mode, orientation, ) - mouse.move( - monitor.x + mapped_x - mouse.position[0], - monitor.y + mapped_y - mouse.position[1] - ) + if relative: + mouse.move( + monitor.x + mapped_x, + monitor.y + mapped_y + ) + else: + mouse.move( + monitor.x + mapped_x - mouse.position[0], + monitor.y + mapped_y - mouse.position[1] + ) if log.level == logging.DEBUG: log_event(e_time, e_millis, e_type, e_code, e_value) diff --git a/remarkable_mouse/remarkable_mouse.py b/remarkable_mouse/remarkable_mouse.py index 269c484..0a6e8c6 100755 --- a/remarkable_mouse/remarkable_mouse.py +++ b/remarkable_mouse/remarkable_mouse.py @@ -8,11 +8,16 @@ import struct from getpass import getpass from itertools import cycle +from platform import system import paramiko import paramiko.agent import paramiko.config +LINUX = "Linux" +WINDOWS = "Windows" + + logging.basicConfig(format='%(message)s') log = logging.getLogger('remouse') @@ -138,14 +143,17 @@ def main(): Stretch: take up both the entire tablet and monitor, but don't maintain aspect ratio.""") 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 output to") - parser.add_argument('--region', action='store_true', default=False, help="Use a GUI to position the output area. Overrides --monitor") + parser.add_argument('--region', action='store_true', default=False, help="Use a GUI to position the output area. Overrides --monitor and --auto-monitor") 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 pressure (requires root, Linux only)") - parser.add_argument('--pen', action='store_true', default=False, help="use pen input to support pen pressure in windows") - parser.add_argument('--auto-monitor', action='store_true', default=False, help="actively switch monitor to the one that the mouse is currently on. Overrides --monitor and --region") + parser.add_argument('--mouse', action='store_true', default=False, help="emulate mouse instead of pen (no pressure/tilt sensitivity). Default on macOS") + parser.add_argument('--auto-monitor', action='store_true', default=False, help="actively switch monitor to the one that the mouse is currently on. Overrides --monitor") + parser.add_argument('--relative', action='store_true', default=False, help="Use trackpad-like relative tracking instead of absolute tracking") args = parser.parse_args() + if args.region: + args["auto-monitor"] = False + if args.debug: log.setLevel(logging.DEBUG) print('Debugging enabled...') @@ -161,18 +169,22 @@ def main(): ) print("Connected to", args.address) + + # ----- Handle events ----- - if args.evdev: - from remarkable_mouse.evdev import read_tablet + system = system() - elif args.pen: + if args.mouse: + from remarkable_mouse.pynput import read_tablet + elif system == LINUX: + from remarkable_mouse.evdev import read_tablet + elif system == WINDOWS: from remarkable_mouse.pen import read_tablet - else: from remarkable_mouse.pynput import read_tablet - + read_tablet( rm_inputs, @@ -182,7 +194,7 @@ def main(): threshold=args.threshold, mode=args.mode, auto_monitor=args["auto-monitor"], - + relative=args.relative, ) except PermissionError: From 94dd67a166674d43857f8b21ad1c5e17e45b524f Mon Sep 17 00:00:00 2001 From: aklevans Date: Wed, 17 Jul 2024 13:06:30 -0400 Subject: [PATCH 11/23] inital implementation of relative for pynput --- remarkable_mouse/common.py | 4 ++-- remarkable_mouse/evdev.py | 1 + remarkable_mouse/pynput.py | 13 +++++++++++-- 3 files changed, 14 insertions(+), 4 deletions(-) diff --git a/remarkable_mouse/common.py b/remarkable_mouse/common.py index fc82960..385162a 100644 --- a/remarkable_mouse/common.py +++ b/remarkable_mouse/common.py @@ -24,8 +24,8 @@ def get_current_monitor_num(): mouse_y = mouse.position[1] for i, monitor in enumerate(get_monitors()): - if mouse_x >= monitor.x and mouse_x < monitor.x + monitor.width and mouse_y >= monitor.y and mouse_y < monitor.y + monitor.height: - print(i) + if (mouse_x >= monitor.x and mouse_x < monitor.x + monitor.width and + mouse_y >= monitor.y and mouse_y < monitor.y + monitor.height): return i return 0 diff --git a/remarkable_mouse/evdev.py b/remarkable_mouse/evdev.py index b7d8969..04ce3f5 100644 --- a/remarkable_mouse/evdev.py +++ b/remarkable_mouse/evdev.py @@ -97,6 +97,7 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, x = y = 0 + # loop inputs forever # for input_name, stream in cycle(rm_inputs.items()): stream = rm_inputs['pen'] diff --git a/remarkable_mouse/pynput.py b/remarkable_mouse/pynput.py index bcdd2f2..01f124f 100644 --- a/remarkable_mouse/pynput.py +++ b/remarkable_mouse/pynput.py @@ -39,6 +39,10 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, x = y = 0 + in_range = False + start_x = 0 + start_y = 0 + stream = rm_inputs['pen'] while True: if auto_monitor: @@ -50,6 +54,7 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, try: data = stream.read(16) except TimeoutError: + in_range = False continue e_time, e_millis, e_type, e_code, e_value = struct.unpack('2IHHi', data) @@ -77,15 +82,19 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, mode, orientation, ) if relative: + if not in_range: + start_x = mapped_x + start_y = mapped_y mouse.move( - monitor.x + mapped_x, - monitor.y + mapped_y + monitor.x + mapped_x - start_x - mouse.position[0], + monitor.y + mapped_y - start_y - mouse.position[1] ) else: mouse.move( monitor.x + mapped_x - mouse.position[0], monitor.y + mapped_y - mouse.position[1] ) + in_range = True if log.level == logging.DEBUG: log_event(e_time, e_millis, e_type, e_code, e_value) From 4802af2109c14a3629b3b9e318e76f1e90346133 Mon Sep 17 00:00:00 2001 From: aklevans Date: Wed, 17 Jul 2024 13:07:24 -0400 Subject: [PATCH 12/23] hotfix --- remarkable_mouse/pynput.py | 1 + 1 file changed, 1 insertion(+) diff --git a/remarkable_mouse/pynput.py b/remarkable_mouse/pynput.py index 01f124f..b7f05ab 100644 --- a/remarkable_mouse/pynput.py +++ b/remarkable_mouse/pynput.py @@ -85,6 +85,7 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, if not in_range: start_x = mapped_x start_y = mapped_y + in_range = True mouse.move( monitor.x + mapped_x - start_x - mouse.position[0], monitor.y + mapped_y - start_y - mouse.position[1] From 28acd6c05e47ac0e31fbdadf2270325790a1ff19 Mon Sep 17 00:00:00 2001 From: aklevans Date: Wed, 17 Jul 2024 13:12:08 -0400 Subject: [PATCH 13/23] relative move fix --- remarkable_mouse/pynput.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/remarkable_mouse/pynput.py b/remarkable_mouse/pynput.py index b7f05ab..b4c80ee 100644 --- a/remarkable_mouse/pynput.py +++ b/remarkable_mouse/pynput.py @@ -39,7 +39,7 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, x = y = 0 - in_range = False + in_range = True start_x = 0 start_y = 0 @@ -87,8 +87,8 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, start_y = mapped_y in_range = True mouse.move( - monitor.x + mapped_x - start_x - mouse.position[0], - monitor.y + mapped_y - start_y - mouse.position[1] + monitor.x + mapped_x - start_x, + monitor.y + mapped_y - start_y ) else: mouse.move( From 83e8eb7d67baf9bd1622cddd1971f8c3b401887c Mon Sep 17 00:00:00 2001 From: aklevans Date: Wed, 17 Jul 2024 23:36:25 -0400 Subject: [PATCH 14/23] Add dynamic monitor selection using multithreading --- remarkable_mouse/common.py | 2 +- remarkable_mouse/evdev.py | 10 ++-- remarkable_mouse/pen.py | 11 ++-- remarkable_mouse/pynput.py | 80 +++++++++++++++++++--------- remarkable_mouse/remarkable_mouse.py | 45 +++++++++++----- 5 files changed, 96 insertions(+), 52 deletions(-) diff --git a/remarkable_mouse/common.py b/remarkable_mouse/common.py index 385162a..4836ec7 100644 --- a/remarkable_mouse/common.py +++ b/remarkable_mouse/common.py @@ -30,7 +30,7 @@ def get_current_monitor_num(): return 0 -def get_monitor(region, monitor_num, orientation, auto_adjust): +def get_monitor(region, monitor_num, orientation): """ Get info of where we want to map the tablet to Args: diff --git a/remarkable_mouse/evdev.py b/remarkable_mouse/evdev.py index 04ce3f5..92cbf0d 100644 --- a/remarkable_mouse/evdev.py +++ b/remarkable_mouse/evdev.py @@ -76,7 +76,7 @@ def create_local_device(): return device.create_uinput_device() -def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor, relative): +def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor, relative, monitor_update): """Pipe rM evdev events to local device Args: @@ -102,11 +102,9 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, # for input_name, stream in cycle(rm_inputs.items()): stream = rm_inputs['pen'] while True: - if auto_monitor: - new_monitor = get_current_monitor_num() - if new_monitor != monitor_num: - monitor_num = new_monitor - monitor, _ = get_monitor(region, monitor_num, orientation) + if auto_monitor and monitor_update[0] != monitor_num: + monitor_num=monitor_update[0] + monitor, _ = get_monitor(region, monitor_num, orientation) try: data = stream.read(16) diff --git a/remarkable_mouse/pen.py b/remarkable_mouse/pen.py index 8e45c35..93ed692 100644 --- a/remarkable_mouse/pen.py +++ b/remarkable_mouse/pen.py @@ -135,8 +135,7 @@ def applyPen(x=0, y=0, pressure=0, tiltX=0, tiltY=0): print(f"Error message: {ctypes.WinError(error_code).strerror}") - -def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor, relative): +def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor, relative, monitor_update): """Loop forever and map evdev events to mouse Args: @@ -158,11 +157,9 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, stream = rm_inputs['pen'] while True: - if auto_monitor: - new_monitor = get_current_monitor_num() - if new_monitor != monitor_num: - monitor_num = new_monitor - monitor, _ = get_monitor(region, monitor_num, orientation) + if auto_monitor and monitor_update[0] != monitor_num: + monitor_num=monitor_update[0] + monitor, _ = get_monitor(region, monitor_num, orientation) try: data = stream.read(16) diff --git a/remarkable_mouse/pynput.py b/remarkable_mouse/pynput.py index b4c80ee..36309ae 100644 --- a/remarkable_mouse/pynput.py +++ b/remarkable_mouse/pynput.py @@ -1,7 +1,8 @@ import logging import struct from screeninfo import get_monitors - +import time +import math # from .codes import EV_SYN, EV_ABS, ABS_X, ABS_Y, BTN_TOUCH from .codes import codes from .common import get_monitor, remap, wacom_max_x, wacom_max_y, log_event, get_current_monitor_num @@ -9,12 +10,17 @@ logging.basicConfig(format='%(message)s') log = logging.getLogger('remouse') + + + + + # wacom digitizer dimensions # touchscreen dimensions # finger_width = 767 # finger_height = 1023 -def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor, relative): +def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor, relative, monitor_update): """Loop forever and map evdev events to mouse Args: @@ -33,40 +39,54 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, mouse = Controller() - monitor, _ = get_monitor(region, monitor_num, orientation) + log.debug('Chose monitor: {}'.format(monitor)) x = y = 0 - in_range = True - start_x = 0 - start_y = 0 - - stream = rm_inputs['pen'] + lastx_needsupdate=True + lasty_needsupdate=True + + stream = rm_inputs['pen'] while True: - if auto_monitor: - new_monitor = get_current_monitor_num() - if new_monitor != monitor_num: - monitor_num = new_monitor - monitor, _ = get_monitor(region, monitor_num, orientation) - + if auto_monitor and monitor_update[0] != monitor_num: + monitor_num=monitor_update[0] + monitor, _ = get_monitor(region, monitor_num, orientation) + + start = time.time() try: data = stream.read(16) except TimeoutError: - in_range = False continue + + # time spent waiting for stream.read(). Used to see if pen was lifted for relative tracking since stream.read() will wait until more data comes in + elapsed = time.time() - start + + if elapsed > 0.2: + print(elapsed) + lastx_needsupdate=True + lasty_needsupdate=True e_time, e_millis, e_type, e_code, e_value = struct.unpack('2IHHi', data) # handle x direction if codes[e_type][e_code] == 'ABS_X': x = e_value - + if lastx_needsupdate: + last_x = x + lastx_needsupdate = False + continue + # handle y direction if codes[e_type][e_code] == 'ABS_Y': y = e_value - + if lasty_needsupdate: + last_y = y + lasty_needsupdate = False + continue + + # handle draw if codes[e_type][e_code] == 'BTN_TOUCH': if e_value == 1: @@ -82,20 +102,32 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, mode, orientation, ) if relative: - if not in_range: - start_x = mapped_x - start_y = mapped_y - in_range = True + mapped_last_x, mapped_last_y = remap( + last_x, last_y, + wacom_max_x, wacom_max_y, + monitor.width, monitor.height, + mode, orientation, + ) + + + # print("startx", start_x) + # print("Mappedx", mapped_x) + # print("dx", monitor.x + mapped_x - start_x) + + print(mapped_x) + mouse.move( - monitor.x + mapped_x - start_x, - monitor.y + mapped_y - start_y + monitor.x + mapped_x - mapped_last_x, + monitor.y + mapped_y - mapped_last_y ) + else: mouse.move( monitor.x + mapped_x - mouse.position[0], monitor.y + mapped_y - mouse.position[1] ) - in_range = True + last_x = x + last_y = y if log.level == logging.DEBUG: log_event(e_time, e_millis, e_type, e_code, e_value) diff --git a/remarkable_mouse/remarkable_mouse.py b/remarkable_mouse/remarkable_mouse.py index 0a6e8c6..3baae5b 100755 --- a/remarkable_mouse/remarkable_mouse.py +++ b/remarkable_mouse/remarkable_mouse.py @@ -8,11 +8,13 @@ import struct from getpass import getpass from itertools import cycle -from platform import system - +import platform +import threading +from .common import get_current_monitor_num import paramiko import paramiko.agent import paramiko.config +import time LINUX = "Linux" WINDOWS = "Windows" @@ -130,6 +132,7 @@ def use_key(key): return {'pen': pen, 'touch': touch, 'button': button} + def main(): try: parser = argparse.ArgumentParser(description="use reMarkable tablet as a mouse input") @@ -146,7 +149,7 @@ def main(): parser.add_argument('--region', action='store_true', default=False, help="Use a GUI to position the output area. Overrides --monitor and --auto-monitor") parser.add_argument('--threshold', metavar='THRESH', default=600, type=int, help="stylus pressure threshold (default 600)") parser.add_argument('--mouse', action='store_true', default=False, help="emulate mouse instead of pen (no pressure/tilt sensitivity). Default on macOS") - parser.add_argument('--auto-monitor', action='store_true', default=False, help="actively switch monitor to the one that the mouse is currently on. Overrides --monitor") + parser.add_argument('--automonitor', action='store_true', default=False, help="actively switch monitor to the one that the mouse is currently on. Overrides --monitor") parser.add_argument('--relative', action='store_true', default=False, help="Use trackpad-like relative tracking instead of absolute tracking") args = parser.parse_args() @@ -173,7 +176,7 @@ def main(): # ----- Handle events ----- - system = system() + system = platform.system() if args.mouse: from remarkable_mouse.pynput import read_tablet @@ -185,17 +188,31 @@ def main(): from remarkable_mouse.pynput import read_tablet + check=threading.Condition() + + monitor_num_obj = [args.monitor] + + th = threading.Thread(target=read_tablet, kwargs={ + 'rm_inputs':rm_inputs, + 'orientation':args.orientation, + 'monitor_num': args.monitor, + 'region':args.region, + 'threshold':args.threshold, + 'mode':args.mode, + 'auto_monitor':args.automonitor, + 'relative':args.relative, + 'monitor_update': monitor_num_obj + }) + th.start() + + # checking every time slows down pen movement too much + if args.automonitor: + while(True): + time.sleep(0.2) + new_monitor = get_current_monitor_num() + if new_monitor != monitor_num_obj[0]: + monitor_num_obj[0] = new_monitor - read_tablet( - rm_inputs, - orientation=args.orientation, - monitor_num=args.monitor, - region=args.region, - threshold=args.threshold, - mode=args.mode, - auto_monitor=args["auto-monitor"], - relative=args.relative, - ) except PermissionError: log.error('Insufficient permissions for creating a virtual input device') From 77ea1eac9e77710733328762a61520ade256b993 Mon Sep 17 00:00:00 2001 From: aklevans Date: Thu, 18 Jul 2024 14:07:52 -0400 Subject: [PATCH 15/23] keyboard interrupt ends infinite loop --- remarkable_mouse/pynput.py | 52 ++++++++++++++++------------ remarkable_mouse/remarkable_mouse.py | 17 +++++---- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/remarkable_mouse/pynput.py b/remarkable_mouse/pynput.py index 36309ae..0d4ab35 100644 --- a/remarkable_mouse/pynput.py +++ b/remarkable_mouse/pynput.py @@ -7,12 +7,12 @@ from .codes import codes from .common import get_monitor, remap, wacom_max_x, wacom_max_y, log_event, get_current_monitor_num -logging.basicConfig(format='%(message)s') -log = logging.getLogger('remouse') - - +# The amount of time waiting for stream.read(16) that counts as the pen becoming out of range +TIMEOUT = 0.2 +logging.basicConfig(format='%(message)s') +log = logging.getLogger('remouse') # wacom digitizer dimensions @@ -45,6 +45,9 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, x = y = 0 + # only used for relative tracking + # last_x and last_y are reset if the pen goes out of range + last_x = last_y = 0 lastx_needsupdate=True lasty_needsupdate=True @@ -63,7 +66,7 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, # time spent waiting for stream.read(). Used to see if pen was lifted for relative tracking since stream.read() will wait until more data comes in elapsed = time.time() - start - if elapsed > 0.2: + if elapsed > TIMEOUT: print(elapsed) lastx_needsupdate=True lasty_needsupdate=True @@ -103,31 +106,36 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, ) if relative: mapped_last_x, mapped_last_y = remap( - last_x, last_y, - wacom_max_x, wacom_max_y, - monitor.width, monitor.height, - mode, orientation, - ) - - - # print("startx", start_x) - # print("Mappedx", mapped_x) - # print("dx", monitor.x + mapped_x - start_x) - - print(mapped_x) - + last_x, last_y, + wacom_max_x, wacom_max_y, + monitor.width, monitor.height, + mode, orientation, + ) + dx = mapped_x - mapped_last_x + dy = mapped_y - mapped_last_y + + # not sure why but moving in negative x and y is twice as fast as moving positive + # probably an issue with remap but this fix works + if dx < 0: + dx /= 2 + if dy < 0: + dy /= 2 + + print(dx) + mouse.move( - monitor.x + mapped_x - mapped_last_x, - monitor.y + mapped_y - mapped_last_y + dx, + dy ) + last_x = x + last_y = y else: mouse.move( monitor.x + mapped_x - mouse.position[0], monitor.y + mapped_y - mouse.position[1] ) - last_x = x - last_y = y + if log.level == logging.DEBUG: log_event(e_time, e_millis, e_type, e_code, e_value) diff --git a/remarkable_mouse/remarkable_mouse.py b/remarkable_mouse/remarkable_mouse.py index 3baae5b..2ac1227 100755 --- a/remarkable_mouse/remarkable_mouse.py +++ b/remarkable_mouse/remarkable_mouse.py @@ -202,16 +202,21 @@ def main(): 'auto_monitor':args.automonitor, 'relative':args.relative, 'monitor_update': monitor_num_obj - }) + }, + daemon=True) th.start() # checking every time slows down pen movement too much - if args.automonitor: + + try: while(True): - time.sleep(0.2) - new_monitor = get_current_monitor_num() - if new_monitor != monitor_num_obj[0]: - monitor_num_obj[0] = new_monitor + if args.automonitor: + time.sleep(0.2) + new_monitor = get_current_monitor_num() + if new_monitor != monitor_num_obj[0]: + monitor_num_obj[0] = new_monitor + except KeyboardInterrupt: + pass except PermissionError: From 97a9377c614324736000b631fe60c518b3b0f1fe Mon Sep 17 00:00:00 2001 From: aklevans <105876795+aklevans@users.noreply.github.com> Date: Thu, 18 Jul 2024 14:08:57 -0400 Subject: [PATCH 16/23] Update README.md --- README.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/README.md b/README.md index f3a47a1..531a62a 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,3 @@ -# remarkable_mouse with pressure and tilt for Windows - -While using the excellent remarkable mouse from Evidlo I needed to have pressure sensitivity for Windows. I don't really know how to code but following the logic an through online searches came to a solution. It is probably not pretty, but it works and it also enables tilt in Windows by creating a virtual pen injection. Use the --pen flag to load this mode. Would be great of someone would take this, implement it correctly and create a tray tool out of it with some options (switch windows during usage for instance). - -You can download a zip of this repo and install with 'pip install path-to-zip'. - # remarkable_mouse Use your reMarkable as a graphics tablet. From 52da600fee4d2d88edf7176e70eb473f66d6644a Mon Sep 17 00:00:00 2001 From: aklevans Date: Fri, 19 Jul 2024 17:00:32 -0400 Subject: [PATCH 17/23] remove relative tracking --- remarkable_mouse/pen.py | 2 +- remarkable_mouse/pynput.py | 59 ++++++++++------------------ remarkable_mouse/remarkable_mouse.py | 28 +++++-------- 3 files changed, 31 insertions(+), 58 deletions(-) diff --git a/remarkable_mouse/pen.py b/remarkable_mouse/pen.py index 93ed692..00df643 100644 --- a/remarkable_mouse/pen.py +++ b/remarkable_mouse/pen.py @@ -135,7 +135,7 @@ def applyPen(x=0, y=0, pressure=0, tiltX=0, tiltY=0): print(f"Error message: {ctypes.WinError(error_code).strerror}") -def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor, relative, monitor_update): +def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor, monitor_update): """Loop forever and map evdev events to mouse Args: diff --git a/remarkable_mouse/pynput.py b/remarkable_mouse/pynput.py index 0d4ab35..0c76f1b 100644 --- a/remarkable_mouse/pynput.py +++ b/remarkable_mouse/pynput.py @@ -20,7 +20,7 @@ # finger_width = 767 # finger_height = 1023 -def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor, relative, monitor_update): +def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor, monitor_update): """Loop forever and map evdev events to mouse Args: @@ -45,11 +45,6 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, x = y = 0 - # only used for relative tracking - # last_x and last_y are reset if the pen goes out of range - last_x = last_y = 0 - lastx_needsupdate=True - lasty_needsupdate=True stream = rm_inputs['pen'] while True: @@ -66,7 +61,7 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, # time spent waiting for stream.read(). Used to see if pen was lifted for relative tracking since stream.read() will wait until more data comes in elapsed = time.time() - start - if elapsed > TIMEOUT: + if elapsed > 0.2: print(elapsed) lastx_needsupdate=True lasty_needsupdate=True @@ -76,19 +71,10 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, # handle x direction if codes[e_type][e_code] == 'ABS_X': x = e_value - if lastx_needsupdate: - last_x = x - lastx_needsupdate = False - continue # handle y direction if codes[e_type][e_code] == 'ABS_Y': - y = e_value - if lasty_needsupdate: - last_y = y - lasty_needsupdate = False - continue - + y = e_value # handle draw if codes[e_type][e_code] == 'BTN_TOUCH': @@ -106,36 +92,31 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, ) if relative: mapped_last_x, mapped_last_y = remap( - last_x, last_y, - wacom_max_x, wacom_max_y, - monitor.width, monitor.height, - mode, orientation, - ) - dx = mapped_x - mapped_last_x - dy = mapped_y - mapped_last_y - - # not sure why but moving in negative x and y is twice as fast as moving positive - # probably an issue with remap but this fix works - if dx < 0: - dx /= 2 - if dy < 0: - dy /= 2 - - print(dx) - + last_x, last_y, + wacom_max_x, wacom_max_y, + monitor.width, monitor.height, + mode, orientation, + ) + + + # print("startx", start_x) + # print("Mappedx", mapped_x) + # print("dx", monitor.x + mapped_x - start_x) + + print(mapped_x) + mouse.move( - dx, - dy + monitor.x + mapped_x - mapped_last_x, + monitor.y + mapped_y - mapped_last_y ) - last_x = x - last_y = y else: mouse.move( monitor.x + mapped_x - mouse.position[0], monitor.y + mapped_y - mouse.position[1] ) - + last_x = x + last_y = y if log.level == logging.DEBUG: log_event(e_time, e_millis, e_type, e_code, e_value) diff --git a/remarkable_mouse/remarkable_mouse.py b/remarkable_mouse/remarkable_mouse.py index 2ac1227..b5d2cfb 100755 --- a/remarkable_mouse/remarkable_mouse.py +++ b/remarkable_mouse/remarkable_mouse.py @@ -145,18 +145,17 @@ def main(): Fill: take up the entire monitor, but not necessarily the entire tablet. Stretch: take up both the entire tablet and monitor, but don't maintain aspect ratio.""") 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 output to") - parser.add_argument('--region', action='store_true', default=False, help="Use a GUI to position the output area. Overrides --monitor and --auto-monitor") + parser.add_argument('--monitor', default=-1, type=int, metavar='NUM', help="override automatic monitor selection") + parser.add_argument('--region', action='store_true', default=False, help="Use a GUI to position the output area. Overrides --monitor and automatic monitor selection") parser.add_argument('--threshold', metavar='THRESH', default=600, type=int, help="stylus pressure threshold (default 600)") - parser.add_argument('--mouse', action='store_true', default=False, help="emulate mouse instead of pen (no pressure/tilt sensitivity). Default on macOS") - parser.add_argument('--automonitor', action='store_true', default=False, help="actively switch monitor to the one that the mouse is currently on. Overrides --monitor") - parser.add_argument('--relative', action='store_true', default=False, help="Use trackpad-like relative tracking instead of absolute tracking") + parser.add_argument('--evdev', action='store_true', default=False, help="use evdev to support pen pressure (requires root, Linux only)") + parser.add_argument('--pen', action='store_true', default=False, help="use pen input to support pen pressure in windows") args = parser.parse_args() - if args.region: - args["auto-monitor"] = False + automonitor = args.monitor == -1 and not args.region + if args.debug: log.setLevel(logging.DEBUG) print('Debugging enabled...') @@ -176,13 +175,10 @@ def main(): # ----- Handle events ----- - system = platform.system() - if args.mouse: - from remarkable_mouse.pynput import read_tablet - elif system == LINUX: + if args.evdev: from remarkable_mouse.evdev import read_tablet - elif system == WINDOWS: + elif args.pen: from remarkable_mouse.pen import read_tablet else: from remarkable_mouse.pynput import read_tablet @@ -199,24 +195,20 @@ def main(): 'region':args.region, 'threshold':args.threshold, 'mode':args.mode, - 'auto_monitor':args.automonitor, - 'relative':args.relative, + 'auto_monitor':automonitor, 'monitor_update': monitor_num_obj }, daemon=True) th.start() # checking every time slows down pen movement too much - - try: + if automonitor: while(True): if args.automonitor: time.sleep(0.2) new_monitor = get_current_monitor_num() if new_monitor != monitor_num_obj[0]: monitor_num_obj[0] = new_monitor - except KeyboardInterrupt: - pass except PermissionError: From 7d7697f439a737d827cbb2da717e8ff47286e7f0 Mon Sep 17 00:00:00 2001 From: aklevans Date: Fri, 19 Jul 2024 17:13:36 -0400 Subject: [PATCH 18/23] fix previous, allow interrupts --- remarkable_mouse/pynput.py | 46 +++++----------------------- remarkable_mouse/remarkable_mouse.py | 18 +++++------ 2 files changed, 16 insertions(+), 48 deletions(-) diff --git a/remarkable_mouse/pynput.py b/remarkable_mouse/pynput.py index 0c76f1b..c073e7d 100644 --- a/remarkable_mouse/pynput.py +++ b/remarkable_mouse/pynput.py @@ -1,15 +1,13 @@ import logging import struct from screeninfo import get_monitors -import time -import math + # from .codes import EV_SYN, EV_ABS, ABS_X, ABS_Y, BTN_TOUCH from .codes import codes from .common import get_monitor, remap, wacom_max_x, wacom_max_y, log_event, get_current_monitor_num -# The amount of time waiting for stream.read(16) that counts as the pen becoming out of range -TIMEOUT = 0.2 + logging.basicConfig(format='%(message)s') log = logging.getLogger('remouse') @@ -52,19 +50,11 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, monitor_num=monitor_update[0] monitor, _ = get_monitor(region, monitor_num, orientation) - start = time.time() try: data = stream.read(16) except TimeoutError: continue - # time spent waiting for stream.read(). Used to see if pen was lifted for relative tracking since stream.read() will wait until more data comes in - elapsed = time.time() - start - - if elapsed > 0.2: - print(elapsed) - lastx_needsupdate=True - lasty_needsupdate=True e_time, e_millis, e_type, e_code, e_value = struct.unpack('2IHHi', data) @@ -90,33 +80,13 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, monitor.width, monitor.height, mode, orientation, ) - if relative: - mapped_last_x, mapped_last_y = remap( - last_x, last_y, - wacom_max_x, wacom_max_y, - monitor.width, monitor.height, - mode, orientation, + + + mouse.move( + monitor.x + mapped_x - mouse.position[0], + monitor.y + mapped_y - mouse.position[1] ) - - - # print("startx", start_x) - # print("Mappedx", mapped_x) - # print("dx", monitor.x + mapped_x - start_x) - - print(mapped_x) - - mouse.move( - monitor.x + mapped_x - mapped_last_x, - monitor.y + mapped_y - mapped_last_y - ) - - else: - mouse.move( - monitor.x + mapped_x - mouse.position[0], - monitor.y + mapped_y - mouse.position[1] - ) - last_x = x - last_y = y + if log.level == logging.DEBUG: log_event(e_time, e_millis, e_type, e_code, e_value) diff --git a/remarkable_mouse/remarkable_mouse.py b/remarkable_mouse/remarkable_mouse.py index b5d2cfb..8c7da69 100755 --- a/remarkable_mouse/remarkable_mouse.py +++ b/remarkable_mouse/remarkable_mouse.py @@ -16,9 +16,6 @@ import paramiko.config import time -LINUX = "Linux" -WINDOWS = "Windows" - logging.basicConfig(format='%(message)s') log = logging.getLogger('remouse') @@ -27,6 +24,8 @@ config_path = os.path.expanduser('~/.ssh/config') +POLL_TIME = 0.2 + def open_rm_inputs(*, address, key, password): """ Open a remote input device via SSH. @@ -202,13 +201,12 @@ def main(): th.start() # checking every time slows down pen movement too much - if automonitor: - while(True): - if args.automonitor: - time.sleep(0.2) - new_monitor = get_current_monitor_num() - if new_monitor != monitor_num_obj[0]: - monitor_num_obj[0] = new_monitor + while(True): + time.sleep(POLL_TIME) + if automonitor: + new_monitor = get_current_monitor_num() + if new_monitor != monitor_num_obj[0]: + monitor_num_obj[0] = new_monitor except PermissionError: From 053f3c9d0b001bdbda1407e53ba9380e9a7176cc Mon Sep 17 00:00:00 2001 From: aklevans Date: Fri, 19 Jul 2024 17:15:18 -0400 Subject: [PATCH 19/23] automonitor for evdev fix --- remarkable_mouse/evdev.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/remarkable_mouse/evdev.py b/remarkable_mouse/evdev.py index 92cbf0d..4de0711 100644 --- a/remarkable_mouse/evdev.py +++ b/remarkable_mouse/evdev.py @@ -76,7 +76,7 @@ def create_local_device(): return device.create_uinput_device() -def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor, relative, monitor_update): +def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, auto_monitor, monitor_update): """Pipe rM evdev events to local device Args: @@ -104,7 +104,7 @@ def read_tablet(rm_inputs, *, orientation, monitor_num, region, threshold, mode, while True: if auto_monitor and monitor_update[0] != monitor_num: monitor_num=monitor_update[0] - monitor, _ = get_monitor(region, monitor_num, orientation) + monitor, (tot_width, tot_height) = get_monitor(region, monitor_num, orientation) try: data = stream.read(16) From b92edd1c7e26a598dc179401b2edd6e86ae2b9ec Mon Sep 17 00:00:00 2001 From: aklevans <105876795+aklevans@users.noreply.github.com> Date: Fri, 19 Jul 2024 17:20:14 -0400 Subject: [PATCH 20/23] Update README.md --- README.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 531a62a..f82d295 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,9 @@ pip install remarkable-mouse remouse ``` -By default, `10.11.99.1` is used as the address. Find your password in the reMarkable's [settings menu](https://remarkablewiki.com/tech/ssh). If you are on Linux using X11, you can use the `--evdev` option for pressure support. +By default, `10.11.99.1` is used as the address. Find your password in the reMarkable's [settings menu](https://remarkablewiki.com/tech/ssh). If you are on Linux using X11, you can use the `--evdev` option for pressure support or you are on Windows, you can use the `--pen` option. + +The monitor that the tablet will output to is dynamically changed to the one that the mouse is in. To output to only one monitor, use the `--monitor` flag. To use the `--region` flag, you may need to install the `python3-tk` or `python3-tkinter` package with your package manager. @@ -44,26 +46,26 @@ sudo --preserve-env=USER,PATH env remouse --evdev # Usage ``` -usage: remouse [-h] [--debug] [--key PATH] [--password PASSWORD] [--address ADDRESS] [--mode {fit,fill,stretch}] [--orientation {top,left,right,bottom}] [--monitor NUM] [--region] [--threshold THRESH] - [--evdev] +usage: remouse [-h] [--debug] [--key PATH] [--password PASSWORD] [--address ADDRESS] [--mode {fit,fill,stretch}] [--orientation {top,left,right,bottom}] [--monitor NUM] [--region] + [--threshold THRESH] [--evdev] [--pen] use reMarkable tablet as a mouse input -optional arguments: +options: -h, --help show this help message and exit --debug enable debug messages --key PATH ssh private key --password PASSWORD ssh password --address ADDRESS device address --mode {fit,fill,stretch} - Scale setting. Fit (default): take up the entire tablet, but not necessarily the entire monitor. Fill: take up the entire monitor, but not necessarily the entire tablet. Stretch: - take up both the entire tablet and monitor, but don't maintain aspect ratio. + Scale setting. Fit (default): take up the entire tablet, but not necessarily the entire monitor. Fill: take up the entire monitor, but not necessarily the entire + tablet. Stretch: take up both the entire tablet and monitor, but don't maintain aspect ratio. --orientation {top,left,right,bottom} position of tablet buttons - --monitor NUM monitor to output to - --region Use a GUI to position the output area. Overrides --monitor + --monitor NUM override automatic monitor selection + --region Use a GUI to position the output area. Overrides --monitor and automatic monitor selection --threshold THRESH stylus pressure threshold (default 600) --evdev use evdev to support pen pressure (requires root, Linux only) - --pen use pen injection to support pen pressure (Windows only) + --pen use pen input to support pen pressure in windows ``` From 8dedc3e804e20f2f1b76bdf5479c96c13db2979b Mon Sep 17 00:00:00 2001 From: aklevans <105876795+aklevans@users.noreply.github.com> Date: Fri, 19 Jul 2024 17:21:22 -0400 Subject: [PATCH 21/23] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f82d295..2e216f4 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,8 @@ pip install remarkable-mouse remouse ``` -By default, `10.11.99.1` is used as the address. Find your password in the reMarkable's [settings menu](https://remarkablewiki.com/tech/ssh). If you are on Linux using X11, you can use the `--evdev` option for pressure support or you are on Windows, you can use the `--pen` option. +By default, `10.11.99.1` is used as the address. Find your password in the reMarkable's [settings menu](https://remarkablewiki.com/tech/ssh). If you are on Linux using X11, you can use the `--evdev` option for pressure support. +If you are on Windows, you can use the `--pen` option for pressure support. The monitor that the tablet will output to is dynamically changed to the one that the mouse is in. To output to only one monitor, use the `--monitor` flag. From c3c728a573251ba4f6f817d546cb2dbecde30b70 Mon Sep 17 00:00:00 2001 From: aklevans <105876795+aklevans@users.noreply.github.com> Date: Fri, 19 Jul 2024 17:21:35 -0400 Subject: [PATCH 22/23] Update README.md --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 2e216f4..518dbc6 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,8 @@ remouse By default, `10.11.99.1` is used as the address. Find your password in the reMarkable's [settings menu](https://remarkablewiki.com/tech/ssh). If you are on Linux using X11, you can use the `--evdev` option for pressure support. If you are on Windows, you can use the `--pen` option for pressure support. -The monitor that the tablet will output to is dynamically changed to the one that the mouse is in. To output to only one monitor, use the `--monitor` flag. +The monitor that the tablet will output to is dynamically changed to the one that the mouse is in. To output to only one monitor, +use the `--monitor` flag. To use the `--region` flag, you may need to install the `python3-tk` or `python3-tkinter` package with your package manager. From 7a13e77d108b65eb49909cc9137960ed55d10d49 Mon Sep 17 00:00:00 2001 From: aklevans <105876795+aklevans@users.noreply.github.com> Date: Fri, 19 Jul 2024 17:21:47 -0400 Subject: [PATCH 23/23] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 518dbc6..2e216f4 100644 --- a/README.md +++ b/README.md @@ -18,8 +18,7 @@ remouse By default, `10.11.99.1` is used as the address. Find your password in the reMarkable's [settings menu](https://remarkablewiki.com/tech/ssh). If you are on Linux using X11, you can use the `--evdev` option for pressure support. If you are on Windows, you can use the `--pen` option for pressure support. -The monitor that the tablet will output to is dynamically changed to the one that the mouse is in. To output to only one monitor, -use the `--monitor` flag. +The monitor that the tablet will output to is dynamically changed to the one that the mouse is in. To output to only one monitor, use the `--monitor` flag. To use the `--region` flag, you may need to install the `python3-tk` or `python3-tkinter` package with your package manager.