Domanda

Sto usando del codice Carbon nel mio progetto Cocoa per gestire eventi chiave globali (scorciatoie) da altre applicazioni. Attualmente ho impostato un gestore eventi kEventHotKeyReleased e posso ottenere con successo tasti di scelta rapida quando la mia applicazione non è attiva. Ciò innesca alcune operazioni nella mia applicazione.

Il problema che ho con il comportamento di kEventHotKeyReleased è:

Dire ad esempio che premo la combinazione di tasti Cmd-Maiusc-P. Non appena rilascerò la "P" tasto viene attivato l'evento tasto di scelta rapida. Devo essere in grado di attivare l'evento (o attivarlo manualmente) quando tutti dei tasti non sono compressi (ovvero: vengono rilasciati anche i tasti Cmd e Shift).

È facile monitorare i tasti di scelta rapida, ma non ho visto nulla per monitorare i singoli tasti. Se potessi monitorare gli stati chiave del modificatore sarei in affari.

Qualche suggerimento su come farlo?

Grazie in anticipo!


UPDATE:

Ho provato a usare kEventRawKeyUp e kEventRawKeyModifiersChanged ma mentre kEventHotKeyReleased funziona quei due, anche se non li ho impostati esattamente allo stesso modo di kEventHotKeyReleased .

EventTypeSpec eventTypes[] = {{kEventClassKeyboard, kEventHotKeyReleased}, {kEventClassKeyboard, kEventRawKeyUp}};
// Changing the order in the list does not help, nor does removing kEventHotKeyReleased
OSStatus err = InstallApplicationEventHandler(&globalHotkeyHandler, GetEventTypeCount(eventTypes), eventTypes, NULL, NULL);
// err == noErr after this line

Il metodo globalHotKeyHandler viene chiamato per kEventHotKeyReleased , ma non per kEventRawKeyUp per qualche motivo che non riesco a capire. Ecco come appare il mio metodo globalHotKeyHandler :

OSStatus globalHotkeyHandler(EventHandlerCallRef nextHandler, EventRef anEvent, void *userData) {
    NSLog(@"Something happened!");
}

È necessario effettuare una chiamata aggiuntiva o qualcos'altro che ho dimenticato?

N.B: a prima vista, sembra che Access for Assistive Devices sia disabilitato ma non lo è . Quindi sono abbastanza all'oscuro.


AGGIORNAMENTO 2:

Ho studiato un po 'il CGEventTap suggerito da Leibowitzn e ho ideato questa configurazione:

CFMachPortRef keyUpEventTap = CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,kCGEventKeyUp,&keyUpCallback,NULL);
CFRunLoopSourceRef keyUpRunLoopSourceRef = CFMachPortCreateRunLoopSource(NULL, keyUpEventTap, 0);
CFRelease(keyUpEventTap);
CFRunLoopAddSource(CFRunLoopGetCurrent(), keyUpRunLoopSourceRef, kCFRunLoopDefaultMode);
CFRelease(keyUpRunLoopSourceRef);

... e il callback:

CGEventRef keyUpCallback (CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon) {
    NSLog(@"KeyUp event tapped!");
    return event;
}

Come puoi vedere sto usando kCGEventKeyUp come maschera per il tap dell'evento ma in qualche modo sto ricevendo eventi down del mouse ? ?! ??


AGGIORNAMENTO 3:

Ok dimentica quello, ho trascurato la riga nel documento che diceva di usare CGEventMaskBit (kCGEventKeyUp) per questo parametro, quindi la chiamata corretta è:

CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventKeyUp),&keyUpCallback,NULL);

Sto ancora riscontrando un problema: i tasti modificatori non attivano kCGEventKeyUp ...


AGGIORNAMENTO 4:

Ok dimenticalo di nuovo ... Sono obbligato a rispondere alle mie domande 5 minuti dopo averle poste oggi eh!

Per intercettare le chiavi del modificatore, usa kCGEventFlagsChanged :

CGEventTapCreate(kCGHIDEventTap,kCGHeadInsertEventTap,kCGEventTapOptionListenOnly,CGEventMaskBit(kCGEventFlagsChanged),&callbackFunction,NULL);

Quindi, in sostanza, ho fatto in modo che il rilevamento dello stato della chiave e del modificatore funzionasse, ma sono ancora interessato a sapere perché kEventRawKeyUp non funziona ...


N.B: nota anche che sto sviluppando su Tiger con l'obiettivo di avere il più possibile supporto per versioni nuove e precedenti del sistema operativo. CGEventTap è solo 10.4+ quindi lo userò per ora, ma una soluzione compatibile con le versioni precedenti sarebbe benvenuta.

È stato utile?

Soluzione

Un'opzione è usare EventTaps. Ciò consente di monitorare tutti gli eventi della tastiera. Vedere: http://developer.apple.com/mac/library/documentation/Carbon/Reference/QuartzEventServicesRef/Reference/reference.html#//apple_ref/c/func/CGEventTapCreate

Sfortunatamente i tocchi degli eventi smetteranno di funzionare se un'applicazione richiede input sicuri. Ad esempio Quicken.

Altri suggerimenti

OSStatus err = InstallApplicationEventHandler(&globalHotkeyHandler, GetEventTypeCount(eventTypes), eventTypes, NULL, NULL);

Questo non è globale. Questo installa il gestore solo quando la tua applicazione è attiva e (credo) dopo i filtri degli eventi di Carbon Event Manager.

È necessario utilizzare InstallEventHandler , che accetta una destinazione dell'evento come primo parametro ( InstallApplicationEventHandler è una macro che supera la destinazione dell'evento dell'applicazione).

Per gli eventi che si verificano mentre l'applicazione non è attiva, la destinazione desiderata è GetEventMonitorTarget () . Per gli eventi che si verificano mentre l'applicazione è attiva, la destinazione desiderata è GetEventDispatcherTarget () . Per rilevare eventi indipendentemente dall'applicazione attiva, installa il gestore su entrambe le destinazioni.

Al giorno d'oggi, però, userei CGEventTaps, come suggerito da Leibowitzn.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top