diff options
Diffstat (limited to 'Python/venv1/Lib/site-packages/keyboard/_winmouse.py')
| -rw-r--r-- | Python/venv1/Lib/site-packages/keyboard/_winmouse.py | 201 |
1 files changed, 201 insertions, 0 deletions
diff --git a/Python/venv1/Lib/site-packages/keyboard/_winmouse.py b/Python/venv1/Lib/site-packages/keyboard/_winmouse.py new file mode 100644 index 0000000..ef16dd4 --- /dev/null +++ b/Python/venv1/Lib/site-packages/keyboard/_winmouse.py @@ -0,0 +1,201 @@ +# -*- coding: utf-8 -*- +import ctypes +import time +from ctypes import c_short, c_char, c_uint8, c_int32, c_int, c_uint, c_uint32, c_long, byref, Structure, CFUNCTYPE, POINTER +from ctypes.wintypes import DWORD, BOOL, HHOOK, MSG, LPWSTR, WCHAR, WPARAM, LPARAM +LPMSG = POINTER(MSG) + +import atexit + +from ._mouse_event import ButtonEvent, WheelEvent, MoveEvent, LEFT, RIGHT, MIDDLE, X, X2, UP, DOWN, DOUBLE, WHEEL, HORIZONTAL, VERTICAL + +#https://github.com/boppreh/mouse/issues/1 +#user32 = ctypes.windll.user32 +user32 = ctypes.WinDLL('user32', use_last_error = True) + +class MSLLHOOKSTRUCT(Structure): + _fields_ = [("x", c_long), + ("y", c_long), + ('data', c_int32), + ('reserved', c_int32), + ("flags", DWORD), + ("time", c_int), + ] + +LowLevelMouseProc = CFUNCTYPE(c_int, WPARAM, LPARAM, POINTER(MSLLHOOKSTRUCT)) + +SetWindowsHookEx = user32.SetWindowsHookExA +#SetWindowsHookEx.argtypes = [c_int, LowLevelMouseProc, c_int, c_int] +SetWindowsHookEx.restype = HHOOK + +CallNextHookEx = user32.CallNextHookEx +#CallNextHookEx.argtypes = [c_int , c_int, c_int, POINTER(MSLLHOOKSTRUCT)] +CallNextHookEx.restype = c_int + +UnhookWindowsHookEx = user32.UnhookWindowsHookEx +UnhookWindowsHookEx.argtypes = [HHOOK] +UnhookWindowsHookEx.restype = BOOL + +GetMessage = user32.GetMessageW +GetMessage.argtypes = [LPMSG, c_int, c_int, c_int] +GetMessage.restype = BOOL + +TranslateMessage = user32.TranslateMessage +TranslateMessage.argtypes = [LPMSG] +TranslateMessage.restype = BOOL + +DispatchMessage = user32.DispatchMessageA +DispatchMessage.argtypes = [LPMSG] + +# Beware, as of 2016-01-30 the official docs have a very incomplete list. +# This one was compiled from experience and may be incomplete. +WM_MOUSEMOVE = 0x200 +WM_LBUTTONDOWN = 0x201 +WM_LBUTTONUP = 0x202 +WM_LBUTTONDBLCLK = 0x203 +WM_RBUTTONDOWN = 0x204 +WM_RBUTTONUP = 0x205 +WM_RBUTTONDBLCLK = 0x206 +WM_MBUTTONDOWN = 0x207 +WM_MBUTTONUP = 0x208 +WM_MBUTTONDBLCLK = 0x209 +WM_MOUSEWHEEL = 0x20A +WM_XBUTTONDOWN = 0x20B +WM_XBUTTONUP = 0x20C +WM_XBUTTONDBLCLK = 0x20D +WM_NCXBUTTONDOWN = 0x00AB +WM_NCXBUTTONUP = 0x00AC +WM_NCXBUTTONDBLCLK = 0x00AD +WM_MOUSEHWHEEL = 0x20E +WM_LBUTTONDOWN = 0x0201 +WM_LBUTTONUP = 0x0202 +WM_MOUSEMOVE = 0x0200 +WM_MOUSEWHEEL = 0x020A +WM_MOUSEHWHEEL = 0x020E +WM_RBUTTONDOWN = 0x0204 +WM_RBUTTONUP = 0x0205 + +buttons_by_wm_code = { + WM_LBUTTONDOWN: (DOWN, LEFT), + WM_LBUTTONUP: (UP, LEFT), + WM_LBUTTONDBLCLK: (DOUBLE, LEFT), + + WM_RBUTTONDOWN: (DOWN, RIGHT), + WM_RBUTTONUP: (UP, RIGHT), + WM_RBUTTONDBLCLK: (DOUBLE, RIGHT), + + WM_MBUTTONDOWN: (DOWN, MIDDLE), + WM_MBUTTONUP: (UP, MIDDLE), + WM_MBUTTONDBLCLK: (DOUBLE, MIDDLE), + + WM_XBUTTONDOWN: (DOWN, X), + WM_XBUTTONUP: (UP, X), + WM_XBUTTONDBLCLK: (DOUBLE, X), +} + +MOUSEEVENTF_ABSOLUTE = 0x8000 +MOUSEEVENTF_MOVE = 0x1 +MOUSEEVENTF_WHEEL = 0x800 +MOUSEEVENTF_HWHEEL = 0x1000 +MOUSEEVENTF_LEFTDOWN = 0x2 +MOUSEEVENTF_LEFTUP = 0x4 +MOUSEEVENTF_RIGHTDOWN = 0x8 +MOUSEEVENTF_RIGHTUP = 0x10 +MOUSEEVENTF_MIDDLEDOWN = 0x20 +MOUSEEVENTF_MIDDLEUP = 0x40 +MOUSEEVENTF_XDOWN = 0x0080 +MOUSEEVENTF_XUP = 0x0100 + +simulated_mouse_codes = { + (WHEEL, HORIZONTAL): MOUSEEVENTF_HWHEEL, + (WHEEL, VERTICAL): MOUSEEVENTF_WHEEL, + + (DOWN, LEFT): MOUSEEVENTF_LEFTDOWN, + (UP, LEFT): MOUSEEVENTF_LEFTUP, + + (DOWN, RIGHT): MOUSEEVENTF_RIGHTDOWN, + (UP, RIGHT): MOUSEEVENTF_RIGHTUP, + + (DOWN, MIDDLE): MOUSEEVENTF_MIDDLEDOWN, + (UP, MIDDLE): MOUSEEVENTF_MIDDLEUP, + + (DOWN, X): MOUSEEVENTF_XDOWN, + (UP, X): MOUSEEVENTF_XUP, +} + +NULL = c_int(0) + +WHEEL_DELTA = 120 + +init = lambda: None + +def listen(queue): + def low_level_mouse_handler(nCode, wParam, lParam): + struct = lParam.contents + # Can't use struct.time because it's usually zero. + t = time.time() + + if wParam == WM_MOUSEMOVE: + event = MoveEvent(struct.x, struct.y, t) + elif wParam == WM_MOUSEWHEEL: + event = WheelEvent(struct.data / (WHEEL_DELTA * (2<<15)), t) + elif wParam in buttons_by_wm_code: + type, button = buttons_by_wm_code.get(wParam, ('?', '?')) + if wParam >= WM_XBUTTONDOWN: + button = {0x10000: X, 0x20000: X2}[struct.data] + event = ButtonEvent(type, button, t) + + queue.put(event) + return CallNextHookEx(NULL, nCode, wParam, lParam) + + WH_MOUSE_LL = c_int(14) + mouse_callback = LowLevelMouseProc(low_level_mouse_handler) + mouse_hook = SetWindowsHookEx(WH_MOUSE_LL, mouse_callback, NULL, NULL) + + # Register to remove the hook when the interpreter exits. Unfortunately a + # try/finally block doesn't seem to work here. + atexit.register(UnhookWindowsHookEx, mouse_hook) + + msg = LPMSG() + while not GetMessage(msg, NULL, NULL, NULL): + TranslateMessage(msg) + DispatchMessage(msg) + +def _translate_button(button): + if button == X or button == X2: + return X, {X: 0x10000, X2: 0x20000}[button] + else: + return button, 0 + +def press(button=LEFT): + button, data = _translate_button(button) + code = simulated_mouse_codes[(DOWN, button)] + user32.mouse_event(code, 0, 0, data, 0) + +def release(button=LEFT): + button, data = _translate_button(button) + code = simulated_mouse_codes[(UP, button)] + user32.mouse_event(code, 0, 0, data, 0) + +def wheel(delta=1): + code = simulated_mouse_codes[(WHEEL, VERTICAL)] + user32.mouse_event(code, 0, 0, int(delta * WHEEL_DELTA), 0) + +def move_to(x, y): + user32.SetCursorPos(int(x), int(y)) + +def move_relative(x, y): + user32.mouse_event(MOUSEEVENTF_MOVE, int(x), int(y), 0, 0) + +class POINT(Structure): + _fields_ = [("x", c_long), ("y", c_long)] + +def get_position(): + point = POINT() + user32.GetCursorPos(byref(point)) + return (point.x, point.y) + +if __name__ == '__main__': + def p(e): + print(e) + listen(p) |
