当我的应用运行时,我正在使用CGEventTapCreate
从iTunes中“窃取”媒体密钥。我传递给CGEventTapCreate
的回调内部代码检查事件,如果发现它是媒体密钥之一,则向默认通知中心发布适当的通知。
现在,如果我发布“key up”事件的通知,这样可以正常工作。如果我为“关键”事件这样做,最终我的应用程序停止获取媒体键事件和iTunes接管。关于什么可能导致这个的任何想法?代码的相关部分在下面
enum {
...
PlayPauseKeyDown = 0x100A00,
PlayPauseKeyUp = 0x100B00,
...
};
static CGEventRef event_tap_callback(CGEventTapProxy proxy,
CGEventType type,
CGEventRef event,
void *refcon)
{
if (!(type == NX_SYSDEFINED) || (type == NX_KEYUP) || (type == NX_KEYDOWN))
return event;
NSEvent* keyEvent = [NSEvent eventWithCGEvent: event];
if (keyEvent.type != NSSystemDefined) return event;
switch(keyEvent.data1)
{
case PlayPauseKeyUp: // <--- this works reliably
//case PlayPauseKeyDown: // <--- this will break eventually
post_notification(@"PlayPauseMediaKeyPressed", nil, nil);
return NULL;
... and so on ...
答案 0 :(得分:9)
如果回调花费的时间太长,会不会触发我的事件?
有些人怀疑Snow Leopard有一个错误,有时会禁用事件点击,即使他们不花太长时间。要处理此问题,您可以查看事件类型kCGEventTapDisabledByTimeout
,并通过CGEventTapEnable
重新启用您的点按来回复。
答案 1 :(得分:3)
首先,为什么你的第一个“if”允许关键和关键事件通过?你的第二个“如果”只允许系统事件通过。因此,对于所有按键/向上事件,您创建一个NSEvent,只是为了将事件向下放一行。这没什么意义。事件点击应该始终尽可能快,否则会减慢整个系统的所有事件处理速度。甚至不应该为key-down / -up事件调用你的回调,因为系统事件不是key-down / -up事件,它们是系统事件。如果它们是关键事件,您肯定永远不会访问data1,而是使用“type”和“keyCode”方法从它们获取相关信息。
static CGEventRef event_tap_callback(CGEventTapProxy proxy,
CGEventType type,
CGEventRef event,
void *refcon)
{
NSEvent * sysEvent;
// No event we care for? return ASAP
if (type != NX_SYSDEFINED) return event;
sysEvent = [NSEvent eventWithCGEvent:event];
// No need to test event type, we know it is NSSystemDefined,
// becuase that is the same as NX_SYSDEFINED
此外,您无法通过查看数据来确定这是否是正确类型的事件,您还必须验证子类型,对于此类事件必须为8:
if ([sysEvent subtype] != 8) return event;
下一个合乎逻辑的步骤是将数据拆分为其组件:
int data = [sysEvent data1];
int keyCode = (data & 0xFFFF0000) >> 16;
int keyFlags = (data & 0xFFFF);
int keyState = (keyFlags & 0xFF00) >> 8;
BOOL keyIsRepeat = (keyFlags & 0x1) > 0;
你可能并不关心重复按键事件(也就是说我按下按键并且它会一遍又一遍地发送同一事件)。
// You probably won't care for repeating events
if (keyIsRepeat) return event;
最后你不应该定义任何自己的常量,系统已准备好使用这些键的常量:
// Analyze the key
switch (keyCode) {
case NX_KEYTYPE_PLAY:
// Play/Pause key
if (keyState == 0x0A) {
// Key down
// ...do your stuff here...
return NULL;
} else if (keyState == 0x0B) {
// Key Up
// ...do your stuff here...
return NULL;
}
// If neither down nor up, we don't know
// what it is and better ignore it
break;
case NX_KEYTYPE_FAST:
// (Fast) Forward
break;
case NX_KEYTYPE_REWIND:
// Rewind key
break;
}
// If we get here, we have not handled
// the event and want system to handle it
return event;
}
如果这仍然不起作用,我的下一个问题是你的post_notification函数是什么样的,如果你不在那里调用post_notification,你也会看到所描述的问题,但只是对你刚刚看到的事件进行NSLog调用?
答案 2 :(得分:0)
在处理程序中,检查以下类型,然后重新启用侦听器。
if (type == kCGEventTapDisabledByTimeout) {
NSLog(@"Event Taps Disabled! Re-enabling");
CGEventTapEnable(eventTap, true);
return event;
}