2012-02-08 15 views
14

Sto scrivendo un'applicazione della riga di comando che ascolta gli eventi di rilascio dei tasti di controllo in X Windows e avvisa un altro processo quando li rileva.Ascoltare eventi della tastiera senza intrappolarli?

Essendo nuovo a GNU/Linux, preferirei evitare di armeggiare con GCC e quindi sto cercando una soluzione basata su script. Dato che conosco un po 'di Python, mi è sembrato naturale optare per una soluzione basata su Python, e dopo aver scavato Internet per gli esempi e aver letto i documenti Python Xlib, ho messo insieme questi programmi che funzionano, ma con un avvertimento: sono trappole eventi invece di limitarsi ad ascoltarli (intendo che tali eventi non vengono più trasmessi all'applicazione a cui sono stati indirizzati in primo luogo).

Ho rintracciato i codici dei tasti di controllo eseguendo "xev". Poiché ho rimappato i miei tasti modificatori, sul tuo sistema potrebbero essere diversi.

Per semplificare le cose, ho omesso il codice relativo al processo esterno.

Grazie per il vostro aiuto.

Software:

  • Python 2.7.2

  • Python Xlib 0.15 RC1

  • Perl v5.10.1

    versione
  • Debian GNU/Linux: 6.0.3

  • Kernel v ersion: Linux Debian 2.6.32-5-686

EDIT: Quello che non riesco a capire è che gli eventi della tastiera non vengono intrappolati salvo se vengono lavorate (nei miei programmi, questo significa che la linea 'di stampa "KeyRelease" viene eseguito). Dato che nel mio codice non chiamo alcun metodo né su Xlib né sull'oggetto evento, non capisco dove si trova la differenza nell'elaborazione.

EDIT2: Sono benvenuti anche suggerimenti su soluzioni alternative oltre all'utilizzo di Xlib.

Edit3: Lo so Perl troppo, e suggerimenti su librerie Perl che potrebbero aiutare sono i benvenuti, a patto che non richiedono le versioni recenti di librerie di sistema, dal momento che Debian ritardo notoriamente indietro quando si tratta di pacchetti disponibili nella sua i repository e la compilazione e l'installazione delle ultime versioni delle librerie possono essere difficili se hanno molte dipendenze (ho provato a installare PyGTK, ma mi sono arreso dopo aver mancato di fare riferimento a un GLib aggiornato che avevo installato).

#!/usr/bin/env python 

    from Xlib.display import Display 
    from Xlib import X 

    Control_R = 64 # Keycode for right Control. 
    Control_L = 108 # Keycode for left Control. 
    keycodes = [Control_R, Control_L] # Keycodes we are listening for. 

    # Handle X events. 
    def handle_event(event): 
     # Let us know whether this event is about a Key Release of 
     # one of the key we are interest in. 
     if event.type == X.KeyRelease: 
      keycode = event.detail 
      if keycode in keycodes: 
       print "KeyRelease" 

    # Objects needed to call Xlib. 
    display = Display() 
    root = display.screen().root 

    # Tell the X server we want to catch KeyRelease events. 
    root.change_attributes(event_mask = X.KeyReleaseMask) 

    # Grab those keys. 
    for keycode in keycodes: 
     root.grab_key(keycode, X.AnyModifier, 1, X.GrabModeAsync, X.GrabModeAsync) 

    # Event loop. 
    while 1: 
     event = root.display.next_event() 
     handle_event(event) 

risposta

2

È necessario utilizzare l'estensione xtipo. Può essere usato con pyxlib (il pykeylogger menzionato nell'altra risposta usa questo), o avvolgendo libX11 e libXtst via ctypes (come ho fatto in synaptiks).

Nota comunque che la programmazione con xrecord (e in parte anche con XLib in generale) è un po 'dura, perché l'API è mal documentata, piuttosto barocca e contro-intuitiva.

+0

Grazie. Guarderò XRecord. Tuttavia, ho aggiunto un paio di note alla mia domanda perché mi sembra che una soluzione sia dietro l'angolo, dal momento che il mio codice non intercetta tutti gli eventi. –

11

grazie alla libreria pykeylogger citato da Croad Langshan, e al codice di esempio utile fornito da Tim Alexander, l'autore di tale biblioteca, sono stato in grado di cambiare il mio programma per:

#!/usr/bin/env python 

    from pyxhook import HookManager 

    watched_keys = ["Control_R", "Control_L"] 

    def handle_event (event): 
     if event.Key in watched_keys: 
      print "KeyRelease" 


    hm = HookManager() 
    hm.HookKeyboard() 
    hm.KeyUp = handle_event 
    hm.start() 

Questo programma realizza il mio obiettivo senza alcun problema. Puoi leggere i campi dell'oggetto "evento" per ulteriori informazioni sull'evento (vedi il codice sorgente di "pyxhook.py").

1

Si noti che l'estensione XRecord continua a essere interrotta in alcune distribuzioni. Il motivo per cui non ero tornato indietro e ho aggiornato quella libreria per un po 'era perché era rotto in Ubuntu per più versioni. C'è un modo per farlo anche con un overlay XInput, (mi hanno detto) ma non l'ho mai perseguito perché non volevo affrontare una sovrapposizione piuttosto che agganciare direttamente gli eventi di X.

Commenta se ci sono problemi con l'uso del codice nella lib pyxhook, ho cercato di renderlo il più semplice/robusto possibile, ma potrei essermi perso qualcosa quando lo metto insieme. È stato un po 'di tempo fa.

Problemi correlati