Question

J'utilise Quartz CGEventTap dans une tentative d'interception à l'échelle mondiale et presses à Verr les bloquer (pour les faire faire quelque chose au lieu utile). Je détecte avec succès les presses Verr mais ont jusqu'à présent été incapable de les bloquer. Mon code (provenant cette réponse stackoverflow) est quelque chose comme ceci:

eventTap = CGEventTapCreate(kCGHIDEventTap,
                            kCGTailAppendEventTap, 
                            kCGEventTapOptionDefault, 
                            eventMask,
                            myCGEventCallback,
                            &oldFlags);

runLoopSource = CFMachPortCreateRunLoopSource(kCFAllocatorDefault, eventTap, 0);

CFRunLoopAddSource(CFRunLoopGetCurrent(), runLoopSource, kCFRunLoopCommonModes);
CGEventTapEnable(eventTap, true);

CGEventRef myCGEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef theEvent, void *refcon)
{
    CGEventFlags *oldFlags = (CGEventFlags *)refcon; 

    switch (type)
    {
        case kCGEventFlagsChanged:
        {
            CGEventFlags newFlags = CGEventGetFlags(theEvent);
            CGEventFlags changedFlags = *oldFlags ^ newFlags; 
            *oldFlags = newFlags;

            if (changedFlags == 65536)
            {
                NSLog(@"Capslock pressed. Let's not return the event");
                return NULL;
            }
            break;
        }
        default:
            break;
    }

    NSLog(@"Different modifier than capslock. Returning the event");
    return theEvent;
}

Si je comprends correctement le retour NULL devrait bloquer efficacement la propagation de keypress. En effet, il fait aussi pour keyup « normal » et les événements -Down. Cependant CAPSLOCK quel que soit bascule. Toutes les idées pourquoi? Suis-je faire des hypothèses erronées? Et / ou comment puis-je faire les choses différemment pour atteindre mon objectif?

Merci,

Thor

Était-ce utile?

La solution

Vous ne pouvez pas bloquer capslock comme ça. Capslock est une condition, qui est gérée par le pilote de clavier, pas par le serveur ou la fenêtre des applications individuelles. Un événement se propage dans keypress OS X comme ça:

Keyboard Driver -> Windows Server -> Session utilisateur -> Application active

A chaque propagation de niveau (indiqué par « -> ») vous pouvez placer un robinet d'événement et bloc et / ou modifier des événements clés. Pilote clavier et Windows Server sont les deux composants privilégiés, les deux autres sont des composants de niveau utilisateur normal.

Le plus tôt vous pouvez attraper un événement de clavier est lorsque l'événement se propage à partir du pilote (espace noyau) au serveur (fenêtre de l'espace utilisateur, mais toujours privilégié). Cependant, comme il est indiqué ci-dessus, l'état de capslock est géré en interne dans le pilote, attrapant donc un événement, il est déjà trop tard. Le pilote aura déjà permis à la lumière capslock sur le clavier (si nécessaire à tous et non exécutés par le matériel lui-même) et rappeler l'état capslock être sur, ce qui a un effet sur toutes les presses clés de l'avenir.

Vous pouvez éteindre la lumière capslock pour les appareils de programmation HID (Apple a même exemple de code pour cette ), mais cela ne capslock, il turn-off tourne juste à côté de la lumière.

La seule façon que je vois à mettre en œuvre que l'utilisation de robinets d'événements est de ré-écrire manuellement chaque pression de touche capslock à appuyer sur la touche sans capslock (celui où le drapeau capslock n'est pas défini et la lettre ci-jointe, le cas échéant, est plus faible Cas). En outre, de ne pas confondre l'utilisateur, vous souhaitez désactiver la lumière capslock comme le montre l'exemple de code d'Apple.

D'autres alternatives sont: Écrivez votre propre pilote de clavier, qui prend le contrôle du clavier au lieu du pilote standard d'Apple (pas aussi dur que vous le pensez, mais encore assez dur dur) ou le piratage de votre chemin dans le conducteur (le mal, mais des œuvres ). Par exemple. certains remappers clavier remplacent uniquement des méthodes simples du pilote (pilotes sont C ++ dans OS X, ils sont donc des objets OO et vous pouvez dynamiquement remplacer les méthodes de C à l'exécution, pas vraiment les remplacer, mais plutôt manipuler des tables de méthode). Les problèmes avec ces deux solutions sont: la première signifie que si votre pilote est aussi bon que celui d'Apple, certains claviers USB peuvent ne pas fonctionner avec votre pilote, alors que d'autres, le second moyen si vous faites une erreur, la système punit cette erreur avec une panique du noyau.

Je me cherche un moyen de capslock programme bascule sur Mac, sans succès jusqu'à présent. Mais je peux vous assurer, robinets d'événements ne sont pas la voie à suivre.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top