Comment surveiller l'état de la clé de modification globale (dans n'importe quelle application)?

StackOverflow https://stackoverflow.com/questions/1603030

  •  05-07-2019
  •  | 
  •  

Question

J'utilise du code carbone dans mon projet Cocoa pour gérer les événements clés globaux (raccourcis) à partir d'autres applications. Actuellement, j'ai configuré un gestionnaire d'événements kEventHotKeyReleased et je peux obtenir des touches de raccourci avec succès lorsque mon application n'est pas active. Cela déclenche une opération dans mon application.

Le problème que j'ai avec le comportement de kEventHotKeyReleased est:

Supposons, par exemple, que j'appuie sur la combinaison de touches Cmd-Shift-P. Dès que je relâche le "P" key l'événement de raccourci clavier est déclenché. Je dois pouvoir déclencher l'événement (ou le déclencher manuellement) lorsque toutes les touches ne sont pas pressées (les touches Cmd et Shift sont également relâchées).

Il est facile de surveiller les touches de raccourci, mais je n’ai rien vu pour contrôler les frappes individuelles. Si je pouvais surveiller la touche de modification, je serais en affaires.

Avez-vous des conseils sur la manière de procéder?

Merci d'avance!

UPDATE:

J'ai essayé d'utiliser kEventRawKeyUp et kEventRawKeyModifiersChanged mais alors que kEventHotKeyReleased ne fonctionne pas, même si je les ai configurés exactement de la même manière que 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

La méthode globalHotKeyHandler est appelée pour kEventHotKeyReleased , mais pas pour kEventRawKeyUp pour une raison quelconque, je n'arrive pas à saisir. Voici à quoi ressemble ma méthode globalHotKeyHandler :

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

Y a-t-il un appel supplémentaire à faire ou quelque chose que j'ai oublié?

N.B: À première vue, il semblerait que l'accès pour dispositifs d'assistance soit désactivé mais il ne l'est pas . Donc, je suis assez désemparé.

UPDATE 2:

J'ai un peu exploré le CGEventTap suggéré par Leibowitzn et j'ai proposé cette configuration:

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

... et le rappel:

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

Comme vous pouvez le constater, j'utilise kCGEventKeyUp comme masque pour la sélection d'événement, mais je reçois en quelque sorte des événements survolés avec la souris ? ?! ??

UPDATE 3:

Ok, oubliez ça, j'ai oublié la ligne dans la doc qui disait d'utiliser CGEventMaskBit (kCGEventKeyUp) pour ce paramètre, donc le bon appel est:

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

Je rencontre toujours un problème: les touches de modification ne déclenchent pas kCGEventKeyUp ...

MISE À JOUR 4:

Ok, oublie ça encore une fois ... Je suis obligé de répondre à mes propres questions 5 minutes après leur avoir posé la question aujourd'hui, hein!

Pour intercepter les touches de modification, utilisez kCGEventFlagsChanged :

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

Donc, en gros, la détection de l'état de la clé et du modificateur fonctionnait, mais je suis toujours intéressé par savoir pourquoi kEventRawKeyUp ne fonctionne pas ...

N.B: Notez également que je développe sur Tiger dans le but de prendre en charge autant que possible les versions nouvelles et anciennes du système d'exploitation. CGEventTap n’ayant que 10.4+, j’utiliserai cette solution pour le moment, mais une solution rétro-compatible serait la bienvenue.

scroll top