def observeNotifications(elem, notificationNames, callback, reactor=None): pid = elementPID(elem) err, observer = AXObserverCreateWithInfoCallback(pid, createCallback(callback), None) source = AXObserverGetRunLoopSource(observer) if reactor: CFRunLoopAddSource(reactor._cfrunloop, source, kCFRunLoopCommonModes) else: CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes) for name in notificationNames: AXObserverAddNotification(observer, elem, name, None) if reactor: reactor.run() else: handle_signals() CFRunLoopRun()
def run(self): source = CFMachPortCreateRunLoopSource(None, self._tap, 0) handler_thread = threading.Thread(target=self._event_handler, name="KeyEventDispatcher") handler_thread.start() self._loop = CFRunLoopGetCurrent() CFRunLoopAddSource(self._loop, source, kCFRunLoopCommonModes) CGEventTapEnable(self._tap, True) CFRunLoopRun() # Wake up event handler. self._event_queue.put_nowait(None) handler_thread.join() CFMachPortInvalidate(self._tap) CFRelease(self._tap) CFRunLoopSourceInvalidate(source)
def handle_signals(): def stop(cffd, cbt, info): CFRunLoopStop(CFRunLoopGetCurrent()) r, w = os.pipe() cffd = CFFileDescriptorCreate(None, r, False, stop, None) CFFileDescriptorEnableCallBacks(cffd, kCFFileDescriptorReadCallBack) cfrlsrc = CFFileDescriptorCreateRunLoopSource(None, cffd, 0) CFRunLoopAddSource(CFRunLoopGetCurrent(), cfrlsrc, kCFRunLoopDefaultMode) def nop(signum, stackframe): pass import signal signal.set_wakeup_fd(w) signal.signal(signal.SIGINT, nop) signal.signal(signal.SIGTERM, nop)
def run_mac(self): from Quartz import ( CGEventTapCreate, CFMachPortCreateRunLoopSource, CFRunLoopAddSource, CFRunLoopGetCurrent, CGEventTapEnable, CGEventMaskBit, CFRunLoopRun, CGEventGetIntegerValueField, CGEventPostToPid, kCGEventKeyDown, kCGEventKeyUp, kCGEventFlagsChanged, kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTargetUnixProcessID, kCFAllocatorDefault, kCFRunLoopDefaultMode, ) pid = QCoreApplication.applicationPid() def callback(proxy, type, event, refcon): if self.pid == CGEventGetIntegerValueField( event, kCGEventTargetUnixProcessID): CGEventPostToPid(pid, event) return event tap = CGEventTapCreate( kCGSessionEventTap, kCGHeadInsertEventTap, 0, CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventKeyUp) | CGEventMaskBit(kCGEventFlagsChanged), callback, None) if tap: source = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, tap, 0) self.runLoop = CFRunLoopGetCurrent() CFRunLoopAddSource(self.runLoop, source, kCFRunLoopDefaultMode) CGEventTapEnable(tap, True) CFRunLoopRun()
def run(self): self._running_thread = CFRunLoopGetCurrent() CFRunLoopAddSource(self._running_thread, self._source, kCFRunLoopCommonModes) CGEventTapEnable(self._tap, True) CFRunLoopRun()
def _make_run_loop_source(port): source = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, port, 0) assert source is not None CFRunLoopAddSource(CFRunLoopGetCurrent(), source, kCFRunLoopCommonModes) return source