Domanda

Sto usando quarzo CGEventTap nel tentativo di globalmente presse capslock intercetta e bloccarli (per farli fare qualcosa di utile, invece). I successo rilevare presse capslock ma sono stati finora in grado di bloccarli. Il mio codice (provenienti da questa risposta StackOverflow ) è qualcosa di simile a questo:

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

Se ho capito bene il ritorno NULL dovrebbe bloccare in modo efficace la pressione del tasto di propagarsi. In effetti lo fa anche per keyup "normale" e gli eventi -down. Tuttavia capslock alterna a prescindere. Tutte le idee perché? Sto facendo presupposti errati? E / o come posso fare le cose in modo diverso per raggiungere il mio obiettivo?

Grazie,

Thor

È stato utile?

Soluzione

Non si può bloccare capslock così. Capslock è una condizione, che viene gestita dal driver della tastiera, non dalla finestra Server o le singole applicazioni. A propaga evento Pressione in OS X del genere:

Keyboard Driver -> Windows Server -> sessione utente -> Applicazione Attiva

Ad ogni propagazione di livello (indicato da "->") è possibile effettuare un tap evento e di blocco e / o modificare gli eventi chiave. Driver di tastiera e Windows Server sono due componenti privilegiati, gli altri due sono normali componenti a livello di utente.

La prima si può prendere un evento di tastiera è quando si propaga evento dal driver (spazio del kernel) al Window Server (dello spazio utente, ma ancora privilegiati). Tuttavia, come notato sopra, lo stato capslock viene gestito internamente nel driver, catturando così un evento è già troppo tardi. L'autista avrà già permesso alla luce capslock sulla tastiera (se necessario a tutti e non eseguiti dall'hardware sola) e ricordato lo stato capslock essere su, che ha un effetto su tutti i tasti futuro.

È possibile spegnere la luce capslock di programmazione per i dispositivi HID (Apple ha anche il codice di esempio per questo ), ma questo non sarà turn-off capslock, si scopre appena fuori la luce.

L'unico modo di vedere di attuare tale utilizzo rubinetti evento è manualmente riscrivere ogni tasto con capslock ad una pressa chiave senza capslock (quella in cui non è impostato il flag capslock e la lettera allegata, se esiste, è inferiore Astuccio). Inoltre, da non confondere l'utente, che ci si spegne la luce capslock come mostrato da codice di esempio di Apple.

Altre alternative sono: Scrivi la tua driver della tastiera, che prende il controllo sopra la tastiera al posto del driver standard di Apple (non è così difficile come si pensa, ma ancora difficile abbastanza difficile) o hackerare la tua strada verso il driver (il male, ma le opere ). Per esempio. alcuni remappers tastiera sostituire i metodi solo singoli del driver (driver sono C ++ in OS X, quindi sono OO-oggetti e si può ignorare in modo dinamico i metodi C ++ in fase di esecuzione; in realtà non li ignorare, ma piuttosto manipolare le tabelle di metodo). I problemi con queste due soluzioni sono: la prima significa che a meno che il driver è buono come quello di Apple, alcune tastiere USB potrebbero non funzionare con il driver, mentre gli altri fanno, la seconda significa che se si fanno alcun errore, il sistema punisce questo errore con un kernel panic.

Sono me stesso alla ricerca di un modo per CapsLock programmazione levetta su Mac, senza successo finora. Ma vi posso assicurare, rubinetti di eventi non sono la strada da percorrere.

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