Last active
October 5, 2023 02:36
-
-
Save adamberenzweig/a5bcff3edc42297bbf7f064dc13ee43d to your computer and use it in GitHub Desktop.
freeze_mouse_test.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import time | |
from threading import Thread | |
import HIServices | |
import Quartz | |
# Tested on Ventura 13.5.2 with python 3.8.15 | |
_EVENTS = ( | |
Quartz.CGEventMaskBit(Quartz.kCGEventMouseMoved) | | |
Quartz.CGEventMaskBit(Quartz.kCGEventLeftMouseDown) | | |
Quartz.CGEventMaskBit(Quartz.kCGEventLeftMouseUp) | | |
Quartz.CGEventMaskBit(Quartz.kCGEventLeftMouseDragged)) | |
class FreezeMouse: | |
def __init__(self): | |
self.running = False | |
def _handler(self, proxy, event_type, event, refcon): | |
if event_type == Quartz.kCGEventMouseMoved: | |
# Freeze the mouse to one location. | |
pos = (20, 20) | |
Quartz.CGEventSetLocation(event, pos) | |
#print('intercept', Quartz.CGEventGetLocation(event)) | |
return event | |
elif event_type in ( | |
Quartz.kCGEventLeftMouseDown, | |
Quartz.kCGEventLeftMouseUp, | |
Quartz.kCGEventLeftMouseDragged | |
): | |
# Suppress clicks | |
print('Suppressing event type ', event_type) | |
return None | |
return event | |
def stop(self): | |
self.running = False | |
def __call__(self): | |
tap = Quartz.CGEventTapCreate( | |
Quartz.kCGSessionEventTap, # Also tried Quartz.kCGHIDEventTap | |
Quartz.kCGHeadInsertEventTap, | |
Quartz.kCGEventTapOptionDefault, | |
_EVENTS, | |
self._handler, | |
None) | |
loop_source = Quartz.CFMachPortCreateRunLoopSource( | |
None, tap, 0) | |
_loop = Quartz.CFRunLoopGetCurrent() | |
Quartz.CFRunLoopAddSource(_loop, loop_source, Quartz.kCFRunLoopDefaultMode) | |
Quartz.CGEventTapEnable(tap, True) | |
self.running = True | |
try: | |
while self.running: | |
result = Quartz.CFRunLoopRunInMode( | |
Quartz.kCFRunLoopDefaultMode, 1, False) | |
try: | |
if result != Quartz.kCFRunLoopRunTimedOut: | |
break | |
except AttributeError: | |
# This happens during teardown of the virtual machine | |
break | |
except: | |
# This exception will have been passed to the main thread | |
pass | |
def main(): | |
if not HIServices.AXIsProcessTrusted(): | |
print( | |
"To run this script, you need to grant Accessibility permissions to the Terminal " + | |
"app. Opening System Preferences > Security & Privacy > Accessibility for you now." | |
) | |
os.system( | |
"open x-apple.systempreferences:com.apple.preference.security?Privacy_Accessibility" | |
) | |
return | |
try: | |
freeze_mouse = FreezeMouse() | |
freeze_thread = Thread(target=freeze_mouse) | |
freeze_thread.start() | |
except KeyboardInterrupt: | |
freeze_mouse.stop() | |
freeze_thread.join() | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment