2009-09-05 14 views
11

Za pomocą dotknięćBeganWithEvent, touchesEndedWithEvent itp. Można uzyskać dane dotykowe z gładzika wielodotykowego, ale czy istnieje sposób blokowania danych dotykowych przed poruszeniem myszą/aktywowaniem gestów w całym systemie (podobne do tego, co robi się w chińskim wpisie tekstowym)?Przechwytywanie wszystkich wielodotykowych danych wprowadzanych za pomocą gładzika w kakao

+1

Sugeruję aktualizację zaakceptowanej odpowiedzi. – ArtOfWarfare

Odpowiedz

6

Jak zauważył valexa korzystając NSEventMask dla CGEventTap jest hack. Tarmes zauważa również, że odpowiedź Rob'a Kenigera już nie działa (OS X> = 10,8). Na szczęście, Apple przedstawił sposób to zrobić bardzo łatwo za pomocą kCGEventMaskForAllEvents i przekształcenie CGEventRef do NSEvent w callback:

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(); 
} 

Note, że wezwanie do CFRunLoopRun() wliczone jest od tego fragment został zaczerpnięty z projektu, który nie może korzystać z aplikacji NSA, ale zamiast tego miał CFRunLoop. Pomiń go, jeśli korzystasz z NSApplication.

2

AKTUALIZACJA: Moja odpowiedź poniżej nie działa. Zobacz odpowiedź here.

Zwykle w tym celu trzeba użyć kwarcowego kranu zdarzeń, chociaż wydarzenia dotykowe nie wydają się "oficjalnie" obsługiwane przez interfejs API CGEvent. Zdarzenia typu multitouch w pliku NSEvent.h wydają się być odwzorowane na typy CGEvent w CGEventTypes.h, więc te multitouch prawdopodobnie zadziałają, nawet jeśli nie są udokumentowane.

Aby zablokować rozprzestrzenianie się zdarzeń, należy zwrócić wartość NULL z wywołania zwrotnego zdarzenia dotykowego.

należałoby trochę kodu:

#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; 
} 
+0

to jest błędne, że mapa NSEventMasks do CGEventMasks co faktycznie się dzieje, że ustawienie maski do nich jest taki sam, jak ustawienie maski do kCGEventMaskForAllEvents i jest to wynik jest uzyskiwanie pary o zaledwie NSEventTypeGesture wydarzeń dla każdego dotyku na touchpadzie, tłumienie który, zwracając NULL, faktycznie blokuje każdy gest. – valexa

+0

Próbowałem ten bieg pod 10.8 i nie wydają się działać - gesty nie są przepuszczane przez EventTap już w ogóle. Nie sądzę, że znalazłeś inne rozwiązanie? – tarmes

+0

-1: Nie działa pod 10,8. Proponuję za pomocą tej odpowiedzi zamiast: http://stackoverflow.com/a/13755292/901641 – ArtOfWarfare

Powiązane problemy