def phantom_release(dpy, kev): if not xlib.XPending(dpy): return False ev = xlib.XEvent() xlib.XPeekEvent(dpy, xlib.byref(ev)) return (ev.type == xlib.KeyPress and \ ev.xkey.state == kev.state and \ ev.xkey.keycode == kev.keycode and \ ev.xkey.time == kev.time)
def read_pending_events(self): """Read all the new event datas. Return: An array contains all event data with event type and valuator values. Sample format: { 'deviceid': 11, 'evtype': 17, 'time': 406752437L, 'valuators': { 0: (396.0, -38.0), 1: (578.0, -21.0), 2: (22802890.0, 22802890.0), 3: (26145746.0, 26145746.0) } } """ data = [] while xlib.XPending(self._display): xevent = xlib.XEvent() xlib.XNextEvent(self._display, ctypes.pointer(xevent)) cookie = xevent.xcookie # Get event valuator_data result = xlib.XGetEventData(self._display, ctypes.pointer(cookie)) if (not result or cookie.type != xlib.GenericEvent): continue raw_event_ptr = ctypes.cast(cookie.data, ctypes.POINTER(xi2.XIRawEvent)) raw_event = raw_event_ptr.contents valuator_state = raw_event.valuators # Two value arrays val_ptr = valuator_state.values val_idx = 0 raw_val_ptr = raw_event.raw_values raw_val_idx = 0 valuator_data = {} for i in range(valuator_state.mask_len): if xi2.XIMaskIsSet(valuator_state.mask, i): valuator_data[i] = (val_ptr[val_idx], raw_val_ptr[raw_val_idx]) val_idx += 1 raw_val_idx += 1 data.append({ 'deviceid': raw_event.deviceid, 'evtype': cookie.evtype, 'time': raw_event.time, 'valuators': valuator_data }) return data
def run(self): # control connection self.control_dpy = xlib.XOpenDisplay(None) xlib.XSynchronize(self.control_dpy, True) # unmapped replay window self.replay_dpy = xlib.XOpenDisplay(None) self.custom_atom = xlib.XInternAtom(self.replay_dpy, b"SCREENKEY", False) replay_fd = xlib.XConnectionNumber(self.replay_dpy) self.replay_win = create_replay_window(self.replay_dpy) if self.input_types & InputType.keyboard: self._kbd_init() # initialize recording context ev_ranges = [] dev_ranges = [] if self.input_types & InputType.keyboard: ev_ranges.append([xlib.FocusIn, xlib.FocusOut]) dev_ranges.append([xlib.KeyPress, xlib.KeyRelease]) if self.input_types & InputType.button: dev_ranges.append([xlib.ButtonPress, xlib.ButtonRelease]) if self.input_types & InputType.movement: dev_ranges.append([xlib.MotionNotify, xlib.MotionNotify]) self.record_ctx = record_context(self.control_dpy, ev_ranges, dev_ranges) record_dpy = xlib.XOpenDisplay(None) record_fd = xlib.XConnectionNumber(record_dpy) # we need to keep the record_ref alive(!) record_ref = record_enable(record_dpy, self.record_ctx, self._event_received) # event loop self.lock.release() while True: with self.lock: if self.stopped: break r_fd = [] if xlib.XPending(record_dpy): r_fd.append(record_fd) if xlib.XPending(self.replay_dpy): r_fd.append(replay_fd) if not r_fd: r_fd, _, _ = select.select([record_fd, replay_fd], [], []) if not r_fd: break if record_fd in r_fd: xlib.XRecordProcessReplies(record_dpy) xlib.XFlush(self.replay_dpy) if replay_fd in r_fd: ev = xlib.XEvent() xlib.XNextEvent(self.replay_dpy, xlib.byref(ev)) if self.input_types & InputType.keyboard: self._kbd_process(ev) # finalize xlib.XRecordFreeContext(self.control_dpy, self.record_ctx) xlib.XCloseDisplay(self.control_dpy) xlib.XCloseDisplay(record_dpy) del record_ref if self.input_types & InputType.keyboard: self._kbd_del() xlib.XDestroyWindow(self.replay_dpy, self.replay_win) xlib.XCloseDisplay(self.replay_dpy)
def run(self): self.control_dpy = xlib.XOpenDisplay(None) xlib.XSynchronize(self.control_dpy, True) self.record_ctx = record_context(self.control_dpy, [xlib.FocusIn, xlib.FocusOut], [xlib.KeyPress, xlib.KeyRelease]) record_dpy = xlib.XOpenDisplay(None) record_fd = xlib.XConnectionNumber(record_dpy) # note that we never ever map the window self.replay_dpy = xlib.XOpenDisplay(None) self.custom_atom = xlib.XInternAtom(self.replay_dpy, "SCREENKEY", False) replay_fd = xlib.XConnectionNumber(self.replay_dpy) self.replay_win = create_replay_window(self.replay_dpy) if self.compose: style = xlib.XIMPreeditNothing | xlib.XIMStatusNothing else: style = xlib.XIMPreeditNone | xlib.XIMStatusNone # TODO: implement preedit callbacks for on-the-spot composition # (this would fix focus-stealing for the global IM state) replay_xim = xlib.XOpenIM(self.replay_dpy, None, None, None) if not replay_xim: raise Exception("Cannot initialize input method") self.replay_xic = xlib.XCreateIC(replay_xim, xlib.XNClientWindow, self.replay_win, xlib.XNInputStyle, style, None) xlib.XSetICFocus(self.replay_xic) # we need to keep the proc_ref alive proc_ref = record_enable(record_dpy, self.record_ctx, self._event_received) last_ev = xlib.XEvent() self.lock.release() while True: with self.lock: if self.stopped: break r_fd = [] if xlib.XPending(record_dpy): r_fd.append(record_fd) if xlib.XPending(self.replay_dpy): r_fd.append(replay_fd) if not r_fd: r_fd, _, _ = select.select([record_fd, replay_fd], [], []) if not r_fd: break if record_fd in r_fd: xlib.XRecordProcessReplies(record_dpy) xlib.XFlush(self.replay_dpy) if replay_fd in r_fd: ev = xlib.XEvent() xlib.XNextEvent(self.replay_dpy, xlib.byref(ev)) if ev.type == xlib.ClientMessage and \ ev.xclient.message_type == self.custom_atom: if ev.xclient.data[0] in [xlib.FocusIn, xlib.FocusOut]: # We do not keep track of multiple XICs, just reset xic = xlib.Xutf8ResetIC(self.replay_xic) if xic is not None: xlib.XFree(xic) continue elif ev.type in [xlib.KeyPress, xlib.KeyRelease]: ev.xkey.send_event = False ev.xkey.window = self.replay_win filtered = bool(xlib.XFilterEvent(ev, 0)) if ev.type not in [xlib.KeyPress, xlib.KeyRelease]: continue if ev.type == xlib.KeyRelease and \ phantom_release(self.replay_dpy, ev.xkey): continue data = KeyData() data.filtered = filtered data.pressed = (ev.type == xlib.KeyPress) data.repeated = (ev.type == last_ev.type and \ ev.xkey.state == last_ev.xkey.state and \ ev.xkey.keycode == last_ev.xkey.keycode) data.mods_mask = ev.xkey.state self._event_modifiers(ev.xkey, data) if not data.filtered and data.pressed and self.translate: self._event_keypress(ev.xkey, data) else: self._event_lookup(ev.xkey, data) self._event_processed(data) last_ev = ev xlib.XRecordFreeContext(self.control_dpy, self.record_ctx) xlib.XCloseDisplay(self.control_dpy) xlib.XCloseDisplay(record_dpy) del proc_ref xlib.XDestroyIC(self.replay_xic) xlib.XCloseIM(replay_xim) xlib.XDestroyWindow(self.replay_dpy, self.replay_win) xlib.XCloseDisplay(self.replay_dpy)