123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130 |
- # -*- coding: utf-8 -*-
- import struct
- from subprocess import check_output
- import re
- from ._nixcommon import EV_KEY, EV_REL, EV_MSC, EV_SYN, EV_ABS, aggregate_devices, ensure_root
- from ._mouse_event import ButtonEvent, WheelEvent, MoveEvent, LEFT, RIGHT, MIDDLE, X, X2, UP, DOWN
- import ctypes
- import ctypes.util
- from ctypes import c_uint32, c_uint, c_int, byref
- display = None
- window = None
- x11 = None
- def build_display():
- global display, window, x11
- if display and window and x11: return
- x11 = ctypes.cdll.LoadLibrary(ctypes.util.find_library('X11'))
- # Required because we will have multiple threads calling x11,
- # such as the listener thread and then main using "move_to".
- x11.XInitThreads()
- display = x11.XOpenDisplay(None)
- # Known to cause segfault in Fedora 23 64bits, no known workarounds.
- # http://stackoverflow.com/questions/35137007/get-mouse-position-on-linux-pure-python
- window = x11.XDefaultRootWindow(display)
- def get_position():
- build_display()
- root_id, child_id = c_uint32(), c_uint32()
- root_x, root_y, win_x, win_y = c_int(), c_int(), c_int(), c_int()
- mask = c_uint()
- ret = x11.XQueryPointer(display, c_uint32(window), byref(root_id), byref(child_id),
- byref(root_x), byref(root_y),
- byref(win_x), byref(win_y), byref(mask))
- return root_x.value, root_y.value
- def move_to(x, y):
- build_display()
- x11.XWarpPointer(display, None, window, 0, 0, 0, 0, x, y)
- x11.XFlush(display)
- REL_X = 0x00
- REL_Y = 0x01
- REL_Z = 0x02
- REL_HWHEEL = 0x06
- REL_WHEEL = 0x08
- ABS_X = 0x00
- ABS_Y = 0x01
- BTN_MOUSE = 0x110
- BTN_LEFT = 0x110
- BTN_RIGHT = 0x111
- BTN_MIDDLE = 0x112
- BTN_SIDE = 0x113
- BTN_EXTRA = 0x114
- button_by_code = {
- BTN_LEFT: LEFT,
- BTN_RIGHT: RIGHT,
- BTN_MIDDLE: MIDDLE,
- BTN_SIDE: X,
- BTN_EXTRA: X2,
- }
- code_by_button = {button: code for code, button in button_by_code.items()}
- device = None
- def build_device():
- global device
- if device: return
- ensure_root()
- device = aggregate_devices('mouse')
- init = build_device
- def listen(queue):
- build_device()
- while True:
- time, type, code, value, device_id = device.read_event()
- if type == EV_SYN or type == EV_MSC:
- continue
- event_type = None
- arg = None
- if type == EV_KEY:
- event = ButtonEvent(DOWN if value else UP, button_by_code.get(code, '?'), time)
- elif type == EV_REL:
- value, = struct.unpack('i', struct.pack('I', value))
- if code == REL_WHEEL:
- event = WheelEvent(value, time)
- elif code in (REL_X, REL_Y):
- x, y = get_position()
- event = MoveEvent(x, y, time)
- if event is None:
- # Unknown event type.
- continue
- queue.put(event)
- def press(button=LEFT):
- build_device()
- device.write_event(EV_KEY, code_by_button[button], 0x01)
- def release(button=LEFT):
- build_device()
- device.write_event(EV_KEY, code_by_button[button], 0x00)
- def move_relative(x, y):
- build_device()
- # Note relative events are not in terms of pixels, but millimeters.
- if x < 0:
- x += 2**32
- if y < 0:
- y += 2**32
- device.write_event(EV_REL, REL_X, x)
- device.write_event(EV_REL, REL_Y, y)
- def wheel(delta=1):
- build_device()
- if delta < 0:
- delta += 2**32
- device.write_event(EV_REL, REL_WHEEL, delta)
- if __name__ == '__main__':
- #listen(print)
- move_to(100, 200)
|