346 lines
10 KiB
Python
346 lines
10 KiB
Python
from talon import Context, Module, actions, app, clip, cron, ctrl, imgui, settings, ui
|
|
from talon_plugins import eye_zoom_mouse
|
|
|
|
key = actions.key
|
|
self = actions.self
|
|
scroll_amount = 0
|
|
click_job = None
|
|
scroll_job = None
|
|
gaze_job = None
|
|
cancel_scroll_on_pop = True
|
|
control_mouse_forced = False
|
|
hiss_scroll_up = False
|
|
|
|
mod = Module()
|
|
ctx = Context()
|
|
|
|
mod.list(
|
|
"mouse_button",
|
|
desc="List of mouse button words to mouse_click index parameter",
|
|
)
|
|
mod.setting(
|
|
"mouse_enable_pop_click",
|
|
type=int,
|
|
default=0,
|
|
desc="Pop noise clicks left mouse button. 0 = off, 1 = on with eyetracker but not with zoom mouse mode, 2 = on but not with zoom mouse mode",
|
|
)
|
|
mod.setting(
|
|
"mouse_enable_pop_stops_scroll",
|
|
type=bool,
|
|
default=False,
|
|
desc="When enabled, pop stops continuous scroll modes (wheel upper/downer/gaze)",
|
|
)
|
|
mod.setting(
|
|
"mouse_enable_pop_stops_drag",
|
|
type=bool,
|
|
default=False,
|
|
desc="When enabled, pop stops mouse drag",
|
|
)
|
|
mod.setting(
|
|
"mouse_enable_hiss_scroll",
|
|
type=bool,
|
|
default=False,
|
|
desc="Hiss noise scrolls down when enabled",
|
|
)
|
|
mod.setting(
|
|
"mouse_wake_hides_cursor",
|
|
type=bool,
|
|
default=False,
|
|
desc="When enabled, mouse wake will hide the cursor. mouse_wake enables zoom mouse.",
|
|
)
|
|
mod.setting(
|
|
"mouse_hide_mouse_gui",
|
|
type=bool,
|
|
default=False,
|
|
desc="When enabled, the 'Scroll Mouse' GUI will not be shown.",
|
|
)
|
|
mod.setting(
|
|
"mouse_continuous_scroll_amount",
|
|
type=int,
|
|
default=80,
|
|
desc="The default amount used when scrolling continuously",
|
|
)
|
|
mod.setting(
|
|
"mouse_wheel_down_amount",
|
|
type=int,
|
|
default=120,
|
|
desc="The amount to scroll up/down (equivalent to mouse wheel on Windows by default)",
|
|
)
|
|
mod.setting(
|
|
"mouse_wheel_horizontal_amount",
|
|
type=int,
|
|
default=40,
|
|
desc="The amount to scroll left/right",
|
|
)
|
|
|
|
continuous_scroll_mode = ""
|
|
|
|
|
|
@imgui.open(x=700, y=0)
|
|
def gui_wheel(gui: imgui.GUI):
|
|
gui.text(f"Scroll mode: {continuous_scroll_mode}")
|
|
gui.line()
|
|
if gui.button("Wheel Stop [stop scrolling]"):
|
|
actions.user.mouse_scroll_stop()
|
|
|
|
|
|
@mod.action_class
|
|
class Actions:
|
|
def zoom_close():
|
|
"""Closes an in-progress zoom. Talon will move the cursor position but not click."""
|
|
if eye_zoom_mouse.zoom_mouse.state == eye_zoom_mouse.STATE_OVERLAY:
|
|
actions.tracking.zoom_cancel()
|
|
|
|
def mouse_wake():
|
|
"""Enable control mouse, zoom mouse, and disables cursor"""
|
|
actions.tracking.control_zoom_toggle(True)
|
|
|
|
if settings.get("user.mouse_wake_hides_cursor"):
|
|
actions.user.mouse_cursor_hide()
|
|
|
|
def mouse_drag(button: int):
|
|
"""Press and hold/release a specific mouse button for dragging"""
|
|
# Clear any existing drags
|
|
actions.user.mouse_drag_end()
|
|
|
|
# Start drag
|
|
ctrl.mouse_click(button=button, down=True)
|
|
|
|
def mouse_drag_end():
|
|
"""Releases any held mouse buttons"""
|
|
for button in ctrl.mouse_buttons_down():
|
|
ctrl.mouse_click(button=button, up=True)
|
|
|
|
def mouse_drag_toggle(button: int):
|
|
"""If the button is held down, release the button, else start dragging"""
|
|
if button in list(ctrl.mouse_buttons_down()):
|
|
ctrl.mouse_click(button=button, up=True)
|
|
else:
|
|
actions.user.mouse_drag(button=button)
|
|
|
|
def mouse_sleep():
|
|
"""Disables control mouse, zoom mouse, and re-enables cursor"""
|
|
actions.tracking.control_zoom_toggle(False)
|
|
actions.tracking.control_toggle(False)
|
|
actions.tracking.control1_toggle(False)
|
|
|
|
actions.user.mouse_cursor_show()
|
|
stop_scroll()
|
|
actions.user.mouse_drag_end()
|
|
|
|
def mouse_scroll_down(amount: float = 1):
|
|
"""Scrolls down"""
|
|
mouse_scroll(amount * settings.get("user.mouse_wheel_down_amount"))()
|
|
|
|
def mouse_scroll_down_continuous():
|
|
"""Scrolls down continuously"""
|
|
global continuous_scroll_mode
|
|
continuous_scroll_mode = "scroll down continuous"
|
|
mouse_scroll(settings.get("user.mouse_continuous_scroll_amount"))()
|
|
|
|
if scroll_job is None:
|
|
start_scroll()
|
|
|
|
if not settings.get("user.mouse_hide_mouse_gui"):
|
|
gui_wheel.show()
|
|
|
|
def mouse_scroll_up(amount: float = 1):
|
|
"""Scrolls up"""
|
|
mouse_scroll(-amount * settings.get("user.mouse_wheel_down_amount"))()
|
|
|
|
def mouse_scroll_up_continuous():
|
|
"""Scrolls up continuously"""
|
|
global continuous_scroll_mode
|
|
continuous_scroll_mode = "scroll up continuous"
|
|
mouse_scroll(-settings.get("user.mouse_continuous_scroll_amount"))()
|
|
|
|
if scroll_job is None:
|
|
start_scroll()
|
|
if not settings.get("user.mouse_hide_mouse_gui"):
|
|
gui_wheel.show()
|
|
|
|
def mouse_scroll_left(amount: float = 1):
|
|
"""Scrolls left"""
|
|
actions.mouse_scroll(
|
|
0, -amount * settings.get("user.mouse_wheel_horizontal_amount")
|
|
)
|
|
|
|
def mouse_scroll_right(amount: float = 1):
|
|
"""Scrolls right"""
|
|
actions.mouse_scroll(
|
|
0, amount * settings.get("user.mouse_wheel_horizontal_amount")
|
|
)
|
|
|
|
def mouse_scroll_stop():
|
|
"""Stops scrolling"""
|
|
stop_scroll()
|
|
|
|
def mouse_gaze_scroll():
|
|
"""Starts gaze scroll"""
|
|
global continuous_scroll_mode
|
|
# this calls stop_scroll, which resets continuous_scroll_mode
|
|
start_cursor_scrolling()
|
|
|
|
continuous_scroll_mode = "gaze scroll"
|
|
|
|
if not settings.get("user.mouse_hide_mouse_gui"):
|
|
gui_wheel.show()
|
|
|
|
# enable 'control mouse' if eye tracker is present and not enabled already
|
|
global control_mouse_forced
|
|
if not actions.tracking.control_enabled():
|
|
actions.tracking.control_toggle(True)
|
|
control_mouse_forced = True
|
|
|
|
def mouse_gaze_scroll_toggle():
|
|
"""If not scrolling, start gaze scroll, else stop scrolling."""
|
|
if continuous_scroll_mode == "":
|
|
actions.user.mouse_gaze_scroll()
|
|
else:
|
|
actions.user.mouse_scroll_stop()
|
|
|
|
def copy_mouse_position():
|
|
"""Copy the current mouse position coordinates"""
|
|
position = ctrl.mouse_pos()
|
|
clip.set_text(repr(position))
|
|
|
|
def mouse_move_center_active_window():
|
|
"""move the mouse cursor to the center of the currently active window"""
|
|
rect = ui.active_window().rect
|
|
ctrl.mouse_move(rect.left + (rect.width / 2), rect.top + (rect.height / 2))
|
|
|
|
def hiss_scroll_up():
|
|
"""Change mouse hiss scroll direction to up"""
|
|
global hiss_scroll_up
|
|
hiss_scroll_up = True
|
|
|
|
def hiss_scroll_down():
|
|
"""Change mouse hiss scroll direction to down"""
|
|
global hiss_scroll_up
|
|
hiss_scroll_up = False
|
|
|
|
|
|
@ctx.action_class("user")
|
|
class UserActions:
|
|
def noise_trigger_pop():
|
|
if (
|
|
settings.get("user.mouse_enable_pop_stops_drag")
|
|
and ctrl.mouse_buttons_down()
|
|
):
|
|
actions.user.mouse_drag_end()
|
|
elif settings.get("user.mouse_enable_pop_stops_scroll") and (
|
|
gaze_job or scroll_job
|
|
):
|
|
# Allow pop to stop scroll
|
|
stop_scroll()
|
|
else:
|
|
# Otherwise respect the mouse_enable_pop_click setting
|
|
setting_val = settings.get("user.mouse_enable_pop_click")
|
|
|
|
is_using_eye_tracker = (
|
|
actions.tracking.control_zoom_enabled()
|
|
or actions.tracking.control_enabled()
|
|
or actions.tracking.control1_enabled()
|
|
)
|
|
should_click = (
|
|
setting_val == 2 and not actions.tracking.control_zoom_enabled()
|
|
) or (
|
|
setting_val == 1
|
|
and is_using_eye_tracker
|
|
and not actions.tracking.control_zoom_enabled()
|
|
)
|
|
if should_click:
|
|
ctrl.mouse_click(button=0, hold=16000)
|
|
|
|
def noise_trigger_hiss(active: bool):
|
|
if settings.get("user.mouse_enable_hiss_scroll"):
|
|
if active:
|
|
if hiss_scroll_up:
|
|
actions.user.mouse_scroll_up_continuous()
|
|
else:
|
|
actions.user.mouse_scroll_down_continuous()
|
|
else:
|
|
actions.user.mouse_scroll_stop()
|
|
|
|
|
|
def mouse_scroll(amount):
|
|
def scroll():
|
|
global scroll_amount
|
|
if continuous_scroll_mode:
|
|
if (scroll_amount >= 0) == (amount >= 0):
|
|
scroll_amount += amount
|
|
else:
|
|
scroll_amount = amount
|
|
actions.mouse_scroll(y=int(amount))
|
|
|
|
return scroll
|
|
|
|
|
|
def scroll_continuous_helper():
|
|
global scroll_amount
|
|
# print("scroll_continuous_helper")
|
|
if scroll_amount and (eye_zoom_mouse.zoom_mouse.state == eye_zoom_mouse.STATE_IDLE):
|
|
actions.mouse_scroll(by_lines=False, y=int(scroll_amount / 10))
|
|
|
|
|
|
def start_scroll():
|
|
global scroll_job
|
|
scroll_job = cron.interval("60ms", scroll_continuous_helper)
|
|
|
|
|
|
def gaze_scroll():
|
|
# print("gaze_scroll")
|
|
if (
|
|
eye_zoom_mouse.zoom_mouse.state == eye_zoom_mouse.STATE_IDLE
|
|
): # or eye_zoom_mouse.zoom_mouse.state == eye_zoom_mouse.STATE_SLEEP:
|
|
x, y = ctrl.mouse_pos()
|
|
|
|
# the rect for the window containing the mouse
|
|
rect = None
|
|
|
|
# on windows, check the active_window first since ui.windows() is not z-ordered
|
|
if app.platform == "windows" and ui.active_window().rect.contains(x, y):
|
|
rect = ui.active_window().rect
|
|
else:
|
|
windows = ui.windows()
|
|
for w in windows:
|
|
if w.rect.contains(x, y):
|
|
rect = w.rect
|
|
break
|
|
|
|
if rect is None:
|
|
# print("no window found!")
|
|
return
|
|
|
|
midpoint = rect.y + rect.height / 2
|
|
amount = int(((y - midpoint) / (rect.height / 10)) ** 3)
|
|
actions.mouse_scroll(by_lines=False, y=amount)
|
|
|
|
# print(f"gaze_scroll: {midpoint} {rect.height} {amount}")
|
|
|
|
|
|
def stop_scroll():
|
|
global scroll_amount, scroll_job, gaze_job, continuous_scroll_mode
|
|
scroll_amount = 0
|
|
if scroll_job:
|
|
cron.cancel(scroll_job)
|
|
|
|
if gaze_job:
|
|
cron.cancel(gaze_job)
|
|
|
|
global control_mouse_forced
|
|
if control_mouse_forced:
|
|
actions.tracking.control_toggle(False)
|
|
control_mouse_forced = False
|
|
|
|
scroll_job = None
|
|
gaze_job = None
|
|
gui_wheel.hide()
|
|
|
|
continuous_scroll_mode = ""
|
|
|
|
|
|
def start_cursor_scrolling():
|
|
global scroll_job, gaze_job
|
|
stop_scroll()
|
|
gaze_job = cron.interval("60ms", gaze_scroll)
|