diff --git a/lib/pynput/_util/darwin.py b/lib/pynput/_util/darwin.py index b58c49a1..b8644c7b 100644 --- a/lib/pynput/_util/darwin.py +++ b/lib/pynput/_util/darwin.py @@ -28,7 +28,9 @@ import six import objc -import HIServices +from HIServices import ( + AXIsProcessTrusted +) from CoreFoundation import ( CFRelease @@ -36,18 +38,19 @@ from Quartz import ( CFMachPortCreateRunLoopSource, + CFRunLoopGetCurrent, CFRunLoopAddSource, - CFRunLoopGetCurrent, + kCFRunLoopDefaultMode, + CGEventTapEnable, CFRunLoopRunInMode, + kCFRunLoopRunTimedOut, CFRunLoopStop, CGEventTapCreate, - CGEventTapEnable, - kCFRunLoopDefaultMode, - kCFRunLoopRunTimedOut, - kCGEventTapOptionDefault, - kCGEventTapOptionListenOnly, + kCGSessionEventTap, kCGHeadInsertEventTap, - kCGSessionEventTap) + kCGEventTapOptionListenOnly, + kCGEventTapOptionDefault +) from . import AbstractListener @@ -77,6 +80,7 @@ def _wrapped(value): yield value finally: CFRelease(wrapped_value) + CFRelease(wrapped_value) class CarbonExtra(object): @@ -204,7 +208,7 @@ class ListenerMixin(object): IS_TRUSTED = False def _run(self): - self.IS_TRUSTED = HIServices.AXIsProcessTrusted() + self.IS_TRUSTED = AXIsProcessTrusted() if not self.IS_TRUSTED: self._log.warning( 'This process is not trusted! Input event monitoring will not ' diff --git a/lib/pynput/keyboard/_darwin.py b/lib/pynput/keyboard/_darwin.py index d51d8175..03d4b154 100644 --- a/lib/pynput/keyboard/_darwin.py +++ b/lib/pynput/keyboard/_darwin.py @@ -268,12 +268,12 @@ def __init__(self, *args, **kwargs): None) def _run(self): - with keycode_context() as context: - self._context = context - try: - super(Listener, self)._run() - finally: - self._context = None + context = keycode_context() + self._context = context + try: + super(Listener, self)._run() + finally: + self._context = None def _handle(self, _proxy, event_type, event, _refcon): # Convert the event to a KeyCode; this may fail, and in that case we diff --git a/lib/pynput/keyboard/_win32.py b/lib/pynput/keyboard/_win32.py index 5ff1d2da..a634c68b 100644 --- a/lib/pynput/keyboard/_win32.py +++ b/lib/pynput/keyboard/_win32.py @@ -196,6 +196,7 @@ class Listener(ListenerMixin, _base.Listener): #: The Windows hook ID for low level keyboard events, ``WH_KEYBOARD_LL`` _EVENTS = 13 + _WM_INPUTLANGCHANGEREQUEST = 0x0050 _WM_INPUTLANGCHANGE = 0x0051 _WM_KEYDOWN = 0x0100 _WM_KEYUP = 0x0101 @@ -218,6 +219,7 @@ class Listener(ListenerMixin, _base.Listener): #: Additional window messages to propagate to the subclass handler. _WM_NOTIFICATIONS = ( _WM_INPUTLANGCHANGE, + _WM_INPUTLANGCHANGEREQUEST, ) #: A mapping from keysym to special key @@ -298,9 +300,11 @@ def _receive(self): # pylint: enable=R0201 def _on_notification(self, code, wparam, lparam): - """Receives ``WM_INPUTLANGCHANGE`` and updates the cached layout. + """Receives ``WM_INPUTLANGCHANGE`` or ``WM_INPUTLANGCHANGE_REQUEST'' + and updates the cached layout. """ - if code == self._WM_INPUTLANGCHANGE: + if code == self._WM_INPUTLANGCHANGE \ + or code == self._WM_INPUTLANGCHANGEREQUEST: self._translator.update_layout() def _event_to_key(self, msg, vk): diff --git a/lib/pynput/mouse/_darwin.py b/lib/pynput/mouse/_darwin.py index 78d7d7ad..f3687c58 100644 --- a/lib/pynput/mouse/_darwin.py +++ b/lib/pynput/mouse/_darwin.py @@ -26,6 +26,32 @@ import enum import Quartz +from Quartz import ( + CGDisplayPixelsHigh, + kCGEventMouseMoved, + CGEventPost, + kCGHIDEventTap, + CGEventCreateMouseEvent, + CGEventCreateScrollWheelEvent, + kCGScrollEventUnitPixel, + CGEventSetIntegerValueField, + kCGMouseEventClickState, + CGEventMaskBit, + kCGEventLeftMouseDown, + kCGEventLeftMouseUp, + kCGEventLeftMouseDragged, + kCGEventRightMouseUp, + kCGEventRightMouseDown, + kCGEventOtherMouseDown, + kCGEventRightMouseDragged, + kCGEventOtherMouseUp, + kCGEventOtherMouseDragged, + kCGEventScrollWheel, + CGEventGetLocation, + CGEventGetIntegerValueField, + kCGScrollWheelEventDeltaAxis2, + kCGScrollWheelEventDeltaAxis1 +) from AppKit import NSEvent @@ -72,18 +98,18 @@ def __init__(self, *args, **kwargs): def _position_get(self): pos = NSEvent.mouseLocation() - return pos.x, Quartz.CGDisplayPixelsHigh(0) - pos.y + return pos.x, CGDisplayPixelsHigh(0) - pos.y def _position_set(self, pos): try: (_, _, mouse_type), mouse_button = self._drag_button.value except AttributeError: - mouse_type = Quartz.kCGEventMouseMoved + mouse_type = kCGEventMouseMoved mouse_button = 0 - Quartz.CGEventPost( - Quartz.kCGHIDEventTap, - Quartz.CGEventCreateMouseEvent( + CGEventPost( + kCGHIDEventTap, + CGEventCreateMouseEvent( None, mouse_type, pos, @@ -93,18 +119,18 @@ def _scroll(self, dx, dy): dx = int(dx) dy = int(dy) - Quartz.CGEventPost( - Quartz.kCGHIDEventTap, - Quartz.CGEventCreateScrollWheelEvent( + CGEventPost( + kCGHIDEventTap, + CGEventCreateScrollWheelEvent( None, - Quartz.kCGScrollEventUnitPixel, + kCGScrollEventUnitPixel, 2, dy * self._SCROLL_SPEED, dx * self._SCROLL_SPEED)) def _press(self, button): (press, _, _), mouse_button = button.value - event = Quartz.CGEventCreateMouseEvent( + event = CGEventCreateMouseEvent( None, press, self.position, @@ -113,19 +139,19 @@ def _press(self, button): # If we are performing a click, we need to set this state flag if self._click is not None: self._click += 1 - Quartz.CGEventSetIntegerValueField( + CGEventSetIntegerValueField( event, - Quartz.kCGMouseEventClickState, + kCGMouseEventClickState, self._click) - Quartz.CGEventPost(Quartz.kCGHIDEventTap, event) + CGEventPost(kCGHIDEventTap, event) # Store the button to enable dragging self._drag_button = button def _release(self, button): (_, release, _), mouse_button = button.value - event = Quartz.CGEventCreateMouseEvent( + event = CGEventCreateMouseEvent( None, release, self.position, @@ -133,12 +159,12 @@ def _release(self, button): # If we are performing a click, we need to set this state flag if self._click is not None: - Quartz.CGEventSetIntegerValueField( + CGEventSetIntegerValueField( event, - Quartz.kCGMouseEventClickState, + kCGMouseEventClickState, self._click) - Quartz.CGEventPost(Quartz.kCGHIDEventTap, event) + CGEventPost(kCGHIDEventTap, event) if button == self._drag_button: self._drag_button = None @@ -154,17 +180,17 @@ def __exit__(self, exc_type, value, traceback): class Listener(ListenerMixin, _base.Listener): #: The events that we listen to _EVENTS = ( - Quartz.CGEventMaskBit(Quartz.kCGEventMouseMoved) | - Quartz.CGEventMaskBit(Quartz.kCGEventLeftMouseDown) | - Quartz.CGEventMaskBit(Quartz.kCGEventLeftMouseUp) | - Quartz.CGEventMaskBit(Quartz.kCGEventLeftMouseDragged) | - Quartz.CGEventMaskBit(Quartz.kCGEventRightMouseDown) | - Quartz.CGEventMaskBit(Quartz.kCGEventRightMouseUp) | - Quartz.CGEventMaskBit(Quartz.kCGEventRightMouseDragged) | - Quartz.CGEventMaskBit(Quartz.kCGEventOtherMouseDown) | - Quartz.CGEventMaskBit(Quartz.kCGEventOtherMouseUp) | - Quartz.CGEventMaskBit(Quartz.kCGEventOtherMouseDragged) | - Quartz.CGEventMaskBit(Quartz.kCGEventScrollWheel)) + CGEventMaskBit(kCGEventMouseMoved) | + CGEventMaskBit(kCGEventLeftMouseDown) | + CGEventMaskBit(kCGEventLeftMouseUp) | + CGEventMaskBit(kCGEventLeftMouseDragged) | + CGEventMaskBit(kCGEventRightMouseDown) | + CGEventMaskBit(kCGEventRightMouseUp) | + CGEventMaskBit(kCGEventRightMouseDragged) | + CGEventMaskBit(kCGEventOtherMouseDown) | + CGEventMaskBit(kCGEventOtherMouseUp) | + CGEventMaskBit(kCGEventOtherMouseDragged) | + CGEventMaskBit(kCGEventScrollWheel)) def __init__(self, *args, **kwargs): super(Listener, self).__init__(*args, **kwargs) @@ -178,22 +204,22 @@ def _handle(self, _proxy, event_type, event, _refcon): This method will call the callbacks registered on initialisation. """ try: - (px, py) = Quartz.CGEventGetLocation(event) + (px, py) = CGEventGetLocation(event) except AttributeError: # This happens during teardown of the virtual machine return # Quickly detect the most common event type - if event_type == Quartz.kCGEventMouseMoved: + if event_type == kCGEventMouseMoved: self.on_move(px, py) - elif event_type == Quartz.kCGEventScrollWheel: - dx = Quartz.CGEventGetIntegerValueField( + elif event_type == kCGEventScrollWheel: + dx = CGEventGetIntegerValueField( event, - Quartz.kCGScrollWheelEventDeltaAxis2) - dy = Quartz.CGEventGetIntegerValueField( + kCGScrollWheelEventDeltaAxis2) + dy = CGEventGetIntegerValueField( event, - Quartz.kCGScrollWheelEventDeltaAxis1) + kCGScrollWheelEventDeltaAxis1) self.on_scroll(px, py, dx, dy) else: