first commit
This commit is contained in:
212
myenv/lib/python3.10/site-packages/pynput/mouse/_darwin.py
Normal file
212
myenv/lib/python3.10/site-packages/pynput/mouse/_darwin.py
Normal file
@@ -0,0 +1,212 @@
|
||||
# coding=utf-8
|
||||
# pynput
|
||||
# Copyright (C) 2015-2024 Moses Palmér
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Lesser General Public License as published by the Free
|
||||
# Software Foundation, either version 3 of the License, or (at your option) any
|
||||
# later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but WITHOUT
|
||||
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
"""
|
||||
The mouse implementation for *macOS*.
|
||||
"""
|
||||
|
||||
# pylint: disable=C0111
|
||||
# The documentation is extracted from the base classes
|
||||
|
||||
# pylint: disable=R0903
|
||||
# We implement stubs
|
||||
|
||||
import enum
|
||||
import Quartz
|
||||
|
||||
from AppKit import NSEvent
|
||||
|
||||
from pynput._util.darwin import (
|
||||
ListenerMixin)
|
||||
from . import _base
|
||||
|
||||
|
||||
def _button_value(base_name, mouse_button):
|
||||
"""Generates the value tuple for a :class:`Button` value.
|
||||
|
||||
:param str base_name: The base name for the button. This should be a string
|
||||
like ``'kCGEventLeftMouse'``.
|
||||
|
||||
:param int mouse_button: The mouse button ID.
|
||||
|
||||
:return: a value tuple
|
||||
"""
|
||||
return (
|
||||
tuple(
|
||||
getattr(Quartz, '%sMouse%s' % (base_name, name))
|
||||
for name in ('Down', 'Up', 'Dragged')),
|
||||
mouse_button)
|
||||
|
||||
|
||||
class Button(enum.Enum):
|
||||
"""The various buttons.
|
||||
"""
|
||||
unknown = None
|
||||
left = _button_value('kCGEventLeft', 0)
|
||||
middle = _button_value('kCGEventOther', 2)
|
||||
right = _button_value('kCGEventRight', 1)
|
||||
|
||||
|
||||
class Controller(_base.Controller):
|
||||
#: The scroll speed
|
||||
_SCROLL_SPEED = 10
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Controller, self).__init__(*args, **kwargs)
|
||||
self._click = None
|
||||
self._drag_button = None
|
||||
|
||||
def _position_get(self):
|
||||
pos = NSEvent.mouseLocation()
|
||||
|
||||
return pos.x, Quartz.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_button = 0
|
||||
|
||||
Quartz.CGEventPost(
|
||||
Quartz.kCGHIDEventTap,
|
||||
Quartz.CGEventCreateMouseEvent(
|
||||
None,
|
||||
mouse_type,
|
||||
pos,
|
||||
mouse_button))
|
||||
|
||||
def _scroll(self, dx, dy):
|
||||
dx = int(dx)
|
||||
dy = int(dy)
|
||||
|
||||
Quartz.CGEventPost(
|
||||
Quartz.kCGHIDEventTap,
|
||||
Quartz.CGEventCreateScrollWheelEvent(
|
||||
None,
|
||||
Quartz.kCGScrollEventUnitPixel,
|
||||
2,
|
||||
dy * self._SCROLL_SPEED,
|
||||
dx * self._SCROLL_SPEED))
|
||||
|
||||
def _press(self, button):
|
||||
(press, _, _), mouse_button = button.value
|
||||
event = Quartz.CGEventCreateMouseEvent(
|
||||
None,
|
||||
press,
|
||||
self.position,
|
||||
mouse_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(
|
||||
event,
|
||||
Quartz.kCGMouseEventClickState,
|
||||
self._click)
|
||||
|
||||
Quartz.CGEventPost(Quartz.kCGHIDEventTap, event)
|
||||
|
||||
# Store the button to enable dragging
|
||||
self._drag_button = button
|
||||
|
||||
def _release(self, button):
|
||||
(_, release, _), mouse_button = button.value
|
||||
event = Quartz.CGEventCreateMouseEvent(
|
||||
None,
|
||||
release,
|
||||
self.position,
|
||||
mouse_button)
|
||||
|
||||
# If we are performing a click, we need to set this state flag
|
||||
if self._click is not None:
|
||||
Quartz.CGEventSetIntegerValueField(
|
||||
event,
|
||||
Quartz.kCGMouseEventClickState,
|
||||
self._click)
|
||||
|
||||
Quartz.CGEventPost(Quartz.kCGHIDEventTap, event)
|
||||
|
||||
if button == self._drag_button:
|
||||
self._drag_button = None
|
||||
|
||||
def __enter__(self):
|
||||
self._click = 0
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, value, traceback):
|
||||
self._click = None
|
||||
|
||||
|
||||
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))
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(Listener, self).__init__(*args, **kwargs)
|
||||
self._intercept = self._options.get(
|
||||
'intercept',
|
||||
None)
|
||||
|
||||
def _handle_message(self, _proxy, event_type, event, _refcon, injected):
|
||||
"""The callback registered with *macOS* for mouse events.
|
||||
|
||||
This method will call the callbacks registered on initialisation.
|
||||
"""
|
||||
try:
|
||||
(px, py) = Quartz.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:
|
||||
self.on_move(px, py, injected)
|
||||
|
||||
elif event_type == Quartz.kCGEventScrollWheel:
|
||||
dx = Quartz.CGEventGetIntegerValueField(
|
||||
event,
|
||||
Quartz.kCGScrollWheelEventDeltaAxis2)
|
||||
dy = Quartz.CGEventGetIntegerValueField(
|
||||
event,
|
||||
Quartz.kCGScrollWheelEventDeltaAxis1)
|
||||
self.on_scroll(px, py, dx, dy, injected)
|
||||
|
||||
else:
|
||||
for button in Button:
|
||||
try:
|
||||
(press, release, drag), _ = button.value
|
||||
except TypeError:
|
||||
# Button.unknown cannot be enumerated
|
||||
continue
|
||||
|
||||
# Press and release generate click events, and drag
|
||||
# generates move events
|
||||
if event_type in (press, release):
|
||||
self.on_click(px, py, button, event_type == press, injected)
|
||||
elif event_type == drag:
|
||||
self.on_move(px, py, injected)
|
||||
Reference in New Issue
Block a user