dotfiles

My personal shell configs and stuff
git clone git://git.alex.balgavy.eu/dotfiles.git
Log | Files | Refs | Submodules | README | LICENSE

mouse.py (12087B)


      1 import os
      2 import pathlib
      3 import subprocess
      4 
      5 from talon import (
      6     Context,
      7     Module,
      8     actions,
      9     app,
     10     cron,
     11     ctrl,
     12     clip,
     13     imgui,
     14     noise,
     15     settings,
     16     ui,
     17 )
     18 from talon_plugins import eye_mouse, eye_zoom_mouse, speech
     19 from talon_plugins.eye_mouse import config, toggle_camera_overlay, toggle_control
     20 
     21 key = actions.key
     22 self = actions.self
     23 scroll_amount = 0
     24 click_job = None
     25 scroll_job = None
     26 gaze_job = None
     27 cancel_scroll_on_pop = True
     28 control_mouse_forced = False
     29 
     30 default_cursor = {
     31     "AppStarting": r"%SystemRoot%\Cursors\aero_working.ani",
     32     "Arrow": r"%SystemRoot%\Cursors\aero_arrow.cur",
     33     "Hand": r"%SystemRoot%\Cursors\aero_link.cur",
     34     "Help": r"%SystemRoot%\Cursors\aero_helpsel.cur",
     35     "No": r"%SystemRoot%\Cursors\aero_unavail.cur",
     36     "NWPen": r"%SystemRoot%\Cursors\aero_pen.cur",
     37     "Person": r"%SystemRoot%\Cursors\aero_person.cur",
     38     "Pin": r"%SystemRoot%\Cursors\aero_pin.cur",
     39     "SizeAll": r"%SystemRoot%\Cursors\aero_move.cur",
     40     "SizeNESW": r"%SystemRoot%\Cursors\aero_nesw.cur",
     41     "SizeNS": r"%SystemRoot%\Cursors\aero_ns.cur",
     42     "SizeNWSE": r"%SystemRoot%\Cursors\aero_nwse.cur",
     43     "SizeWE": r"%SystemRoot%\Cursors\aero_ew.cur",
     44     "UpArrow": r"%SystemRoot%\Cursors\aero_up.cur",
     45     "Wait": r"%SystemRoot%\Cursors\aero_busy.ani",
     46     "Crosshair": "",
     47     "IBeam": "",
     48 }
     49 
     50 # todo figure out why notepad++ still shows the cursor sometimes.
     51 hidden_cursor = os.path.join(
     52     os.path.dirname(os.path.realpath(__file__)), r"Resources\HiddenCursor.cur"
     53 )
     54 
     55 mod = Module()
     56 mod.list(
     57     "mouse_button", desc="List of mouse button words to mouse_click index parameter"
     58 )
     59 setting_mouse_enable_pop_click = mod.setting(
     60     "mouse_enable_pop_click",
     61     type=int,
     62     default=0,
     63     desc="Enable pop to click when control mouse is enabled.",
     64 )
     65 setting_mouse_enable_pop_stops_scroll = mod.setting(
     66     "mouse_enable_pop_stops_scroll",
     67     type=int,
     68     default=0,
     69     desc="When enabled, pop stops continuous scroll modes (wheel upper/downer/gaze)",
     70 )
     71 setting_mouse_wake_hides_cursor = mod.setting(
     72     "mouse_wake_hides_cursor",
     73     type=int,
     74     default=0,
     75     desc="When enabled, mouse wake will hide the cursor. mouse_wake enables zoom mouse.",
     76 )
     77 setting_mouse_hide_mouse_gui = mod.setting(
     78     "mouse_hide_mouse_gui",
     79     type=int,
     80     default=0,
     81     desc="When enabled, the 'Scroll Mouse' GUI will not be shown.",
     82 )
     83 setting_mouse_continuous_scroll_amount = mod.setting(
     84     "mouse_continuous_scroll_amount",
     85     type=int,
     86     default=80,
     87     desc="The default amount used when scrolling continuously",
     88 )
     89 setting_mouse_wheel_down_amount = mod.setting(
     90     "mouse_wheel_down_amount",
     91     type=int,
     92     default=120,
     93     desc="The amount to scroll up/down (equivalent to mouse wheel on Windows by default)",
     94 )
     95 
     96 continuous_scoll_mode = ""
     97 
     98 
     99 @imgui.open(x=700, y=0)
    100 def gui_wheel(gui: imgui.GUI):
    101     gui.text("Scroll mode: {}".format(continuous_scoll_mode))
    102     gui.line()
    103     if gui.button("Wheel Stop [stop scrolling]"):
    104         actions.user.mouse_scroll_stop()
    105 
    106 
    107 @mod.action_class
    108 class Actions:
    109     def mouse_show_cursor():
    110         """Shows the cursor"""
    111         show_cursor_helper(True)
    112 
    113     def mouse_hide_cursor():
    114         """Hides the cursor"""
    115         show_cursor_helper(False)
    116 
    117     def mouse_wake():
    118         """Enable control mouse, zoom mouse, and disables cursor"""
    119         eye_zoom_mouse.toggle_zoom_mouse(True)
    120         # eye_mouse.control_mouse.enable()
    121         if setting_mouse_wake_hides_cursor.get() >= 1:
    122             show_cursor_helper(False)
    123 
    124     def mouse_calibrate():
    125         """Start calibration"""
    126         eye_mouse.calib_start()
    127 
    128     def mouse_toggle_control_mouse():
    129         """Toggles control mouse"""
    130         toggle_control(not config.control_mouse)
    131 
    132     def mouse_toggle_camera_overlay():
    133         """Toggles camera overlay"""
    134         toggle_camera_overlay(not config.show_camera)
    135 
    136     def mouse_toggle_zoom_mouse():
    137         """Toggles zoom mouse"""
    138         eye_zoom_mouse.toggle_zoom_mouse(not eye_zoom_mouse.zoom_mouse.enabled)
    139 
    140     def mouse_cancel_zoom_mouse():
    141         """Cancel zoom mouse if pending"""
    142         if (
    143             eye_zoom_mouse.zoom_mouse.enabled
    144             and eye_zoom_mouse.zoom_mouse.state != eye_zoom_mouse.STATE_IDLE
    145         ):
    146             eye_zoom_mouse.zoom_mouse.cancel()
    147 
    148     def mouse_trigger_zoom_mouse():
    149         """Trigger zoom mouse if enabled"""
    150         if eye_zoom_mouse.zoom_mouse.enabled:
    151             eye_zoom_mouse.zoom_mouse.on_pop(eye_zoom_mouse.zoom_mouse.state)
    152 
    153     def mouse_drag():
    154         """(TEMPORARY) Press and hold/release button 0 depending on state for dragging"""
    155         # todo: fixme temporary fix for drag command
    156         button_down = len(list(ctrl.mouse_buttons_down())) > 0
    157         print(str(ctrl.mouse_buttons_down()))
    158         if not button_down:
    159             # print("start drag...")
    160             ctrl.mouse_click(button=0, down=True)
    161             # app.notify("drag started")
    162         else:
    163             # print("end drag...")
    164             ctrl.mouse_click(button=0, up=True)
    165 
    166         # app.notify("drag stopped")
    167 
    168     def mouse_sleep():
    169         """Disables control mouse, zoom mouse, and re-enables cursor"""
    170         eye_zoom_mouse.toggle_zoom_mouse(False)
    171         toggle_control(False)
    172         show_cursor_helper(True)
    173         stop_scroll()
    174 
    175         # todo: fixme temporary fix for drag command
    176         button_down = len(list(ctrl.mouse_buttons_down())) > 0
    177         if button_down:
    178             ctrl.mouse_click(button=0, up=True)
    179 
    180     def mouse_scroll_down():
    181         """Scrolls down"""
    182         mouse_scroll(setting_mouse_wheel_down_amount.get())()
    183 
    184     def mouse_scroll_down_continuous():
    185         """Scrolls down continuously"""
    186         global continuous_scoll_mode
    187         continuous_scoll_mode = "scroll down continuous"
    188         mouse_scroll(setting_mouse_continuous_scroll_amount.get())()
    189 
    190         if scroll_job is None:
    191             start_scroll()
    192 
    193         if setting_mouse_hide_mouse_gui.get() == 0:
    194             gui_wheel.show()
    195 
    196     def mouse_scroll_up():
    197         """Scrolls up"""
    198         mouse_scroll(-setting_mouse_wheel_down_amount.get())()
    199 
    200     def mouse_scroll_up_continuous():
    201         """Scrolls up continuously"""
    202         global continuous_scoll_mode
    203         continuous_scoll_mode = "scroll up continuous"
    204         mouse_scroll(-setting_mouse_continuous_scroll_amount.get())()
    205 
    206         if scroll_job is None:
    207             start_scroll()
    208         if setting_mouse_hide_mouse_gui.get() == 0:
    209             gui_wheel.show()
    210 
    211     def mouse_scroll_stop():
    212         """Stops scrolling"""
    213         stop_scroll()
    214 
    215     def mouse_gaze_scroll():
    216         """Starts gaze scroll"""
    217         global continuous_scoll_mode
    218         continuous_scoll_mode = "gaze scroll"
    219 
    220         start_cursor_scrolling()
    221         if setting_mouse_hide_mouse_gui.get() == 0:
    222             gui_wheel.show()
    223 
    224         # enable 'control mouse' if eye tracker is present and not enabled already
    225         global control_mouse_forced
    226         if eye_mouse.tracker is not None and not config.control_mouse:
    227             toggle_control(True)
    228             control_mouse_forced = True
    229 
    230     def copy_mouse_position():
    231         """Copy the current mouse position coordinates"""
    232         position = ctrl.mouse_pos()
    233         clip.set_text((repr(position)))
    234 
    235     def mouse_move_center_active_window():
    236         """move the mouse cursor to the center of the currently active window"""
    237         rect = ui.active_window().rect
    238         ctrl.mouse_move(rect.left + (rect.width / 2), rect.top + (rect.height / 2))
    239 
    240 
    241 def show_cursor_helper(show):
    242     """Show/hide the cursor"""
    243     if app.platform == "windows":
    244         import ctypes
    245         import winreg
    246 
    247         import win32con
    248 
    249         try:
    250             Registrykey = winreg.OpenKey(
    251                 winreg.HKEY_CURRENT_USER, r"Control Panel\Cursors", 0, winreg.KEY_WRITE
    252             )
    253 
    254             for value_name, value in default_cursor.items():
    255                 if show:
    256                     winreg.SetValueEx(
    257                         Registrykey, value_name, 0, winreg.REG_EXPAND_SZ, value
    258                     )
    259                 else:
    260                     winreg.SetValueEx(
    261                         Registrykey, value_name, 0, winreg.REG_EXPAND_SZ, hidden_cursor
    262                     )
    263 
    264             winreg.CloseKey(Registrykey)
    265 
    266             ctypes.windll.user32.SystemParametersInfoA(
    267                 win32con.SPI_SETCURSORS, 0, None, 0
    268             )
    269 
    270         except WindowsError:
    271             print("Unable to show_cursor({})".format(str(show)))
    272     else:
    273         ctrl.cursor_visible(show)
    274 
    275 
    276 def on_pop(active):
    277     if setting_mouse_enable_pop_stops_scroll.get() >= 1 and (gaze_job or scroll_job):
    278             stop_scroll()
    279     elif (
    280         not eye_zoom_mouse.zoom_mouse.enabled
    281         and eye_mouse.mouse.attached_tracker is not None
    282     ):
    283         if setting_mouse_enable_pop_click.get() >= 1:
    284             ctrl.mouse_click(button=0, hold=16000)
    285 
    286 
    287 noise.register("pop", on_pop)
    288 
    289 
    290 def mouse_scroll(amount):
    291     def scroll():
    292         global scroll_amount
    293         if (scroll_amount >= 0) == (amount >= 0):
    294             scroll_amount += amount
    295         else:
    296             scroll_amount = amount
    297         actions.mouse_scroll(y=int(amount))
    298 
    299     return scroll
    300 
    301 
    302 def scroll_continuous_helper():
    303     global scroll_amount
    304     # print("scroll_continuous_helper")
    305     if scroll_amount and (
    306         eye_zoom_mouse.zoom_mouse.state == eye_zoom_mouse.STATE_IDLE
    307     ):  # or eye_zoom_mouse.zoom_mouse.state == eye_zoom_mouse.STATE_SLEEP):
    308         actions.mouse_scroll(by_lines=False, y=int(scroll_amount / 10))
    309 
    310 
    311 def start_scroll():
    312     global scroll_job
    313     scroll_job = cron.interval("60ms", scroll_continuous_helper)
    314     # if eye_zoom_mouse.zoom_mouse.enabled and eye_mouse.mouse.attached_tracker is not None:
    315     #    eye_zoom_mouse.zoom_mouse.sleep(True)
    316 
    317 
    318 def gaze_scroll():
    319     # print("gaze_scroll")
    320     if (
    321         eye_zoom_mouse.zoom_mouse.state == eye_zoom_mouse.STATE_IDLE
    322     ):  # or eye_zoom_mouse.zoom_mouse.state == eye_zoom_mouse.STATE_SLEEP:
    323         x, y = ctrl.mouse_pos()
    324 
    325         # the rect for the window containing the mouse
    326         rect = None
    327 
    328         # on windows, check the active_window first since ui.windows() is not z-ordered
    329         if app.platform == "windows" and ui.active_window().rect.contains(x, y):
    330             rect = ui.active_window().rect
    331         else:
    332             windows = ui.windows()
    333             for w in windows:
    334                 if w.rect.contains(x, y):
    335                     rect = w.rect
    336                     break
    337 
    338         if rect is None:
    339             # print("no window found!")
    340             return
    341 
    342         midpoint = rect.y + rect.height / 2
    343         amount = int(((y - midpoint) / (rect.height / 10)) ** 3)
    344         actions.mouse_scroll(by_lines=False, y=amount)
    345 
    346     # print(f"gaze_scroll: {midpoint} {rect.height} {amount}")
    347 
    348 
    349 def stop_scroll():
    350     global scroll_amount, scroll_job, gaze_job
    351     scroll_amount = 0
    352     if scroll_job:
    353         cron.cancel(scroll_job)
    354 
    355     if gaze_job:
    356         cron.cancel(gaze_job)
    357 
    358     global control_mouse_forced
    359     if control_mouse_forced and config.control_mouse:
    360         toggle_control(False)
    361         control_mouse_forced = False
    362 
    363     scroll_job = None
    364     gaze_job = None
    365     gui_wheel.hide()
    366 
    367     # if eye_zoom_mouse.zoom_mouse.enabled and eye_mouse.mouse.attached_tracker is not None:
    368     #    eye_zoom_mouse.zoom_mouse.sleep(False)
    369 
    370 
    371 def start_cursor_scrolling():
    372     global scroll_job, gaze_job
    373     stop_scroll()
    374     gaze_job = cron.interval("60ms", gaze_scroll)
    375     # if eye_zoom_mouse.zoom_mouse.enabled and eye_mouse.mouse.attached_tracker is not None:
    376     #    eye_zoom_mouse.zoom_mouse.sleep(True)
    377 
    378 
    379 if app.platform == "mac":
    380     from talon import tap
    381 
    382     def on_move(e):
    383         if not config.control_mouse:
    384             buttons = ctrl.mouse_buttons_down()
    385             # print(str(ctrl.mouse_buttons_down()))
    386             if not e.flags & tap.DRAG and buttons:
    387                 e.flags |= tap.DRAG
    388                 # buttons is a set now
    389                 e.button = list(buttons)[0]
    390                 e.modify()
    391 
    392     tap.register(tap.MMOVE | tap.HOOK, on_move)