使用touchesBeganWithEvent、touchesEndedWithEvent等方法,您可以从多点触控触摸板获取触摸数据,但是否有一种方法可以阻止该触摸数据移动鼠标/激活系统范围手势(类似于中文文本输入中所做的操作)?
使用touchesBeganWithEvent、touchesEndedWithEvent等方法,您可以从多点触控触摸板获取触摸数据,但是否有一种方法可以阻止该触摸数据移动鼠标/激活系统范围手势(类似于中文文本输入中所做的操作)?使用touchesBeganWithEvent、touchesEndedWithEvent等方法,您可以从多点触控触摸板获取触摸数据,但是否有一种方法可以阻止该触摸数据移动鼠标/激活系统范围手势(类似于中文文本输入中所做的操作)?
使用touchesBeganWithEvent、touchesEndedWithEvent等方法,您可以从多点触控触摸板获取触摸数据,但是否有一种方法可以阻止该触摸数据移动鼠标/激活系统范围手势(类似于中文文本输入中所做的操作)?kCGEventMaskForAllEvents
并在回调函数中将CGEventRef转换为NSEvent:NSEventMask eventMask = NSEventMaskGesture|NSEventMaskMagnify|NSEventMaskSwipe|NSEventMaskRotate|NSEventMaskBeginGesture|NSEventMaskEndGesture;
CGEventRef eventTapCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef eventRef, void *refcon) {
// convert the CGEventRef to an NSEvent
NSEvent *event = [NSEvent eventWithCGEvent:eventRef];
// filter out events which do not match the mask
if (!(eventMask & NSEventMaskFromType([event type]))) { return [event CGEvent]; }
// do stuff
NSLog(@"eventTapCallback: [event type] = %d", [event type]);
// return the CGEventRef
return [event CGEvent];
}
void initCGEventTap() {
CFMachPortRef eventTap = CGEventTapCreate(kCGSessionEventTap, kCGHeadInsertEventTap, kCGEventTapOptionListenOnly, kCGEventMaskForAllEvents, eventTapCallback, nil);
CFRunLoopAddSource(CFRunLoopGetCurrent(), CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0), kCFRunLoopCommonModes);
CGEventTapEnable(eventTap, true);
CFRunLoopRun();
}
CFRunLoopRun()
是因为这段代码片段来自一个不能使用 NSApplication 但是必须使用基本的 CFRunLoop 的项目中。如果你使用 NSApplication,则可以省略该调用。更新:下面的答案不再适用。请参见此处的答案。
通常,您需要使用Quartz事件点击才能实现此操作,尽管触摸事件似乎并没有被CGEvent API“官方”支持。NSEvent.h中的非多点触控事件类型似乎映射到CGEventTypes.h中的CGEvent类型,因此即使它们没有记录,多点触控事件也可能有效。
为了阻止事件传播,您需要从事件点击回调中返回NULL。
您需要像这样的代码:
#import <ApplicationServices/ApplicationServices.h>
//assume CGEventTap eventTap is an ivar or other global
void createEventTap(void)
{
CFRunLoopSourceRef runLoopSource;
//listen for touch events
//this is officially unsupported/undocumented
//but the NSEvent masks seem to map to the CGEvent types
//for all other events, so it should work.
CGEventMask eventMask = (
NSEventMaskGesture |
NSEventMaskMagnify |
NSEventMaskSwipe |
NSEventMaskRotate |
NSEventMaskBeginGesture |
NSEventMaskEndGesture
);
// Keyboard event taps need Universal Access enabled,
// I'm not sure about multi-touch. If necessary, this code needs to
// be here to check whether we're allowed to attach an event tap
if (!AXAPIEnabled()&&!AXIsProcessTrusted()) {
// error dialog here
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
[alert addButtonWithTitle:@"OK"];
[alert setMessageText:@"Could not start event monitoring."];
[alert setInformativeText:@"Please enable \"access for assistive devices\" in the Universal Access pane of System Preferences."];
[alert runModal];
return;
}
//create the event tap
eventTap = CGEventTapCreate(kCGHIDEventTap, //this intercepts events at the lowest level, where they enter the window server
kCGHeadInsertEventTap,
kCGEventTapOptionDefault,
eventMask,
myCGEventCallback, //this is the callback that we receive when the event fires
nil);
// Create a run loop source.
runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);
// Add to the current run loop.
CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
// Enable the event tap.
CGEventTapEnable(eventTap, true);
}
//the CGEvent callback that does the heavy lifting
CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef theEvent, void *refcon)
{
//handle the event here
//if you want to capture the event and prevent it propagating as normal, return NULL.
//if you want to let the event process as normal, return theEvent.
return theEvent;
}