如何在OSX命令行工具CoreFoundation,C API中捕获进程空间键事件?

问题描述 投票:0回答:1

我正在研究如何在C中仅使用CoreFoundation在其处理空间内实现OSX无GUI 命令行工具key event捕获和回调, (没有Cocoa,没有NSEvents)。通过一些研究,我可以轻松地将此MCVE放在“全局级别”上(这需要以root特权运行该程序),但无法弄清楚该如何捕获和处理程序<仅。我也没有找到有关如何完成此操作的文档。我从SO的这一领域发现了一些问题,但所有问题都是基于Cocoa API的。我很乐意提供所需的任何其他信息。

// gcc -Wall -o test test.c -framework ApplicationServices // sudo test #include <ApplicationServices/ApplicationServices.h> CGEventRef testEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) { printf( " Event Type: %d\n", type ); return event; } int main(int argc, char *argv[]) { CFMachPortRef eventPort; CFRunLoopSourceRef eventSrc; CFRunLoopRef runLoop; CGEventMask mask = CGEventMaskBit(kCGEventKeyDown) | CGEventMaskBit(kCGEventKeyUp); eventPort = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionListenOnly, mask, testEventCallback, NULL ); if ( eventPort == NULL ){ printf( "NULL eventPort\n" ); return 1; } eventSrc = CFMachPortCreateRunLoopSource(NULL, eventPort, 0); if ( eventSrc == NULL ){ printf( "NULL eventSrc\n" ); return 1; } runLoop = CFRunLoopGetCurrent(); if ( runLoop == NULL ){ printf( "NULL runLoop\n" ); return 1; } CFRunLoopAddSource(runLoop, eventSrc, kCFRunLoopDefaultMode); CFRunLoopRun(); return 0; }
c macos core-foundation
1个回答
0
投票
这是一些在Terminal中运行的Swift命令行工具中的代码。它点击通常会路由到Terminal.app的事件,或者点击该工具开始运行时最前端的任何事件。它避免了使用命令键,因此您可以根据需要轻松地在命令周期内终止程序。由于GetFrontProcess()现在已被弃用,因此它使用NSWorkspace来定位前端进程。

let lock = DispatchQueue(label: "lock") var events = [CGEvent]() // track keyboard events using an event tap. let callback: CGEventTapCallBack = { (tapProxy, eventType, event, _) -> Unmanaged<CGEvent>? in // don't consume command keys. if !event.flags.contains(.maskCommand) { if eventType == .keyDown { lock.sync { events.append(event) } } return nil } return Unmanaged<CGEvent>.passUnretained(event) } let eventMask = CGEventMask((1 << CGEventType.keyDown.rawValue) | (1 << CGEventType.keyUp.rawValue)) if let frontmostProcess = NSWorkspace.shared.frontmostApplication?.processIdentifier, let eventTap = CGEvent.tapCreateForPid(pid: frontmostProcess, place: .headInsertEventTap, options: .defaultTap, eventsOfInterest: eventMask, callback: callback, userInfo: nil) { let source = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0) CFRunLoopAddSource(CFRunLoopGetCurrent(), source, .commonModes) CGEvent.tapEnable(tap: eventTap, enable: true) CFRunLoopRun() }

© www.soinside.com 2019 - 2024. All rights reserved.