2009-12-07 8 views
4

J'ai créé un script python dans lequel un événement doit être exécuté chaque fois que j'appuie sur Super (ou WinKey) sur mon clavier.Vérifiez si la touche est pressée en utilisant python (un démon en arrière-plan)

Comment peut-on y parvenir sans que le processus python soit "focalisé" - car il fonctionne en arrière-plan en attendant que la touche soit pressée pour exécuter l'événement? J'ai vu beaucoup de messages sur le web me montrant comment lire les entrées - mais ils en ont tous besoin pour que le processus soit "concentré" et aucun ne m'a montré comment capturer le Super (ou WinKey) en utilisant un script python.

Je cours sous Ubuntu 9.10.

Répondre

5

Cela me permet d'obtenir l'état de modificateur touches de mon * nix système.

#!/usr/bin/env python 
# -*- coding: utf-8 -*- 
"""OSD Neo2 
    ======== 
    On screen display for learning the keyboard layout Neo2 
    Copyright (c) 2009 Martin Zuther (http://www.mzuther.de/) 
    This program is free software: you can redistribute it and/or modify 
    it under the terms of the GNU General Public License as published by 
    the Free Software Foundation, either version 3 of the License, or 
    (at your option) any later version. 
    This program is distributed in the hope that it will be useful, 
    but WITHOUT ANY WARRANTY; without even the implied warranty of 
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
    GNU General Public License for more details. 
    You should have received a copy of the GNU General Public License 
    along with this program. If not, see <http://www.gnu.org/licenses/>. 
    Thank you for using free software! 
""" 
# Here follows a plea in German to keep the comments in English so 
# that you may understand them, dear visitor ... 
# 
# Meine Kommentare in den Quellcodes sind absichtlich auf Englisch 
# gehalten, damit Leute, die im Internet nach Lösungen suchen, den 
# Code nachvollziehen können. Daher bitte ich darum, zusätzliche 
# Kommentare ebenfalls auf Englisch zu schreiben. Vielen Dank! 
import ctypes 
import ctypes.util 
import gettext 
import os 
import types 
# initialise localisation settings 
module_path = os.path.dirname(os.path.realpath(__file__)) 
gettext.bindtextdomain('OSDneo2', os.path.join(module_path, 'po/')) 
gettext.textdomain('OSDneo2') 
_ = gettext.lgettext 
class SimpleXkbWrapper: 
    """ 
    Far from complete wrapper for the "X Keyboard Extension" (well, to 
    be honest, it just wraps what I need using Python's "ctypes" 
    library <g>). 
    """ 
    # set this to true to get lots of debugging information (and 
    # considerably slow things down) 
    DEBUG_XKB = False 
    # "C defines" from file /usr/include/X11/extensions/XKB.h (Ubuntu 9.04): 
    # $XFree86: xc/include/extensions/XKB.h,v 1.5tsi Exp $ 
    # 
    # XkbUseCoreKbd is used to specify the core keyboard without having to 
    # look up its X input extension identifier. 
    XkbUseCoreKbd   = 0x0100 
    # "C defines" from file /usr/include/X11/XKBlib.h (Ubuntu 9.04): 
    # $XFree86: xc/lib/X11/XKBlib.h,v 3.5 2003/04/17 02:06:31 dawes Exp $ # 
    # 
    # XkbOpenDisplay error codes 
    XkbOD_Success   = 0 
    XkbOD_BadLibraryVersion = 1 
    XkbOD_ConnectionRefused = 2 
    XkbOD_NonXkbServer  = 3 
    XkbOD_BadServerVersion = 4 
    # "C typedef" from file /usr/include/X11/extensions/XKBstr.h (Ubuntu 9.04): 
    # $Xorg: XKBstr.h,v 1.3 2000/08/18 04:05:45 coskrey Exp $ 
    # 
    # Common data structures and access macros 
    # 
    # typedef struct _XkbStateRec { 
    #   unsigned char group; 
    #   unsigned char locked_group; 
    #   unsigned short base_group; 
    #   unsigned short latched_group; 
    #   unsigned char mods; 
    #   unsigned char base_mods; 
    #   unsigned char latched_mods; 
    #   unsigned char locked_mods; 
    #   unsigned char compat_state; 
    #   unsigned char grab_mods; 
    #   unsigned char compat_grab_mods; 
    #   unsigned char lookup_mods; 
    #   unsigned char compat_lookup_mods; 
    #   unsigned short ptr_buttons; 
    # } XkbStateRec,*XkbStatePtr; 
    class XkbStateRec(ctypes.Structure): 
     _fields_ = [ 
         ('group',    ctypes.c_ubyte), \ 
         ('locked_group',  ctypes.c_ubyte), \ 
         ('base_group',   ctypes.c_ushort), \ 
         ('latched_group',  ctypes.c_ushort), \ 
         ('mods',    ctypes.c_ubyte), \ 
         ('base_mods',   ctypes.c_ubyte), \ 
         ('latched_mods',  ctypes.c_ubyte), \ 
         ('locked_mods',  ctypes.c_ubyte), \ 
         ('compat_state',  ctypes.c_ubyte), \ 
         ('grab_mods',   ctypes.c_ubyte), \ 
         ('compat_grab_mods', ctypes.c_ubyte), \ 
         ('lookup_mods',  ctypes.c_ubyte), \ 
         ('compat_lookup_mods', ctypes.c_ubyte), \ 
         ('ptr_buttons',  ctypes.c_ushort) \ 
        ] 
    # "C defines" from file /usr/include/X11/X.h (Ubuntu 9.04): 
    # $XFree86: xc/include/X.h,v 1.6 2003/07/09 15:27:28 tsi Exp $ 
    # 
    # Key masks. Used as modifiers to GrabButton and GrabKey, results of 
    # QueryPointer, state in various key-, mouse-, and button-related 
    # events. 
    ShiftMask    = 1 
    LockMask     = 2 
    ControlMask    = 4 
    Mod1Mask     = 8 
    Mod2Mask     = 16 
    Mod3Mask     = 32 
    Mod4Mask     = 64 
    Mod5Mask     = 128 
    def __init__(self): 
     # dynamically link to "X Keyboard Extension" library 
     library_xf86misc = ctypes.CDLL(ctypes.util.find_library('Xxf86misc')) 
     # print debugging information if requested 
     if self.DEBUG_XKB: 
      print 
      print ' %s' % library_xf86misc 
     # define "ctypes" prototype for the function 
     # 
     # Display *XkbOpenDisplay(display_name, event_rtrn, error_rtrn, 
     #        major_in_out, minor_in_out, reason_rtrn) 
     # 
     # char * display_name; 
     # int * event_rtrn; 
     # int * error_rtrn; 
     # int * major_in_out; 
     # int * minor_in_out; 
     # int * reason_rtrn; 
     paramflags_xkbopendisplay = \ 
      (1, 'display_name'), \ 
      (2, 'event_rtrn'), \ 
      (2, 'error_rtrn'), \ 
      (3, 'major_in_out'), \ 
      (3, 'minor_in_out'), \ 
      (2, 'reason_rtrn') 
     prototype_xkbopendisplay = ctypes.CFUNCTYPE(\ 
      ctypes.c_uint, \ 
       ctypes.c_char_p, \ 
       ctypes.POINTER(ctypes.c_int), \ 
       ctypes.POINTER(ctypes.c_int), \ 
       ctypes.POINTER(ctypes.c_int), \ 
       ctypes.POINTER(ctypes.c_int), \ 
       ctypes.POINTER(ctypes.c_int) \ 
       ) 
     # set-up function (low-level) 
     self.__XkbOpenDisplay__ = prototype_xkbopendisplay(\ 
      ('XkbOpenDisplay', library_xf86misc), \ 
       paramflags_xkbopendisplay \ 
       ) 
     # define error handler 
     def errcheck_xkbopendisplay(result, func, args): 
      # print debugging information if requested 
      if self.DEBUG_XKB: 
       print 
       print ' [XkbOpenDisplay]' 
       print ' Display:  %#010x' % result 
       print ' display_name: %s' % args[0].value 
       print ' event_rtrn: %d' % args[1].value 
       print ' error_rtrn: %d' % args[2].value 
       print ' major_in_out: %d' % args[3].value 
       print ' minor_in_out: %d' % args[4].value 
       print ' reason_rt:  %d' % args[5].value 
      # function didn't return display handle, so let's see why 
      # not 
      if result == 0: 
       # values were taken from file /usr/include/X11/XKBlib.h (Ubuntu 9.04): 
       # $XFree86: xc/lib/X11/XKBlib.h,v 3.5 2003/04/17 02:06:31 dawes Exp $ # 
       error_id = args[5].value 
       if error_id == self.XkbOD_Success: 
        error_name = 'XkbOD_Success' 
       elif error_id == self.XkbOD_BadLibraryVersion: 
        error_name = 'XkbOD_BadLibraryVersion' 
       elif error_id == self.XkbOD_ConnectionRefused: 
        error_name = 'XkbOD_ConnectionRefused' 
       elif error_id == self.XkbOD_NonXkbServer: 
        error_name = 'XkbOD_NonXkbServer' 
       elif error_id == self.XkbOD_BadServerVersion: 
        error_name = 'XkbOD_BadServerVersion' 
       else: 
        error_name = _('undefined') 
       error_message = \ 
        _('"XkbOpenDisplay" reported an error (%(error_name)s).') % \ 
        {'error_name': error_name} 
       raise OSError(error_message) 
      # return display handle and all function arguments 
      return (ctypes.c_uint(result), args) 
     # connect error handler to function 
     self.__XkbOpenDisplay__.errcheck = errcheck_xkbopendisplay 
     # define "ctypes" prototype for the function 
     # 
     # Bool XkbGetState(display, device_spec, state_return) 
     # 
     #  Display *    display; 
     #  unsigned int   device_spec; 
     #  XkbStatePtr   state_return; 
     paramflags_xkbgetstate = \ 
      (1, 'display'), \ 
      (1, 'device_spec'), \ 
      (3, 'state_return') 
     prototype_xkbgetstate = ctypes.CFUNCTYPE(\ 
      ctypes.c_int, # Python 2.5 doesn't yet know c_bool \ 
       ctypes.c_uint, \ 
       ctypes.c_uint, \ 
       ctypes.POINTER(self.XkbStateRec) \ 
       ) 
     # set-up function (low-level) 
     self.__XkbGetState__ = prototype_xkbgetstate(\ 
      ('XkbGetState', library_xf86misc), \ 
       paramflags_xkbgetstate \ 
       ) 
     # define error handler 
     def errcheck_xkbgetstate(result, func, args): 
      # print debugging information if requested 
      if self.DEBUG_XKB: 
       print 
       print ' [XkbGetState]' 
       print ' Status:  %s' % result 
       print ' display:  %#010x' % args[0].value 
       print ' device_spec: %d\n' % args[1].value 
       print ' state_return.group:    %d' % \ 
        args[2].group 
       print ' state_return.locked_group:  %d' % \ 
        args[2].locked_group 
       print ' state_return.base_group:   %d' % \ 
        args[2].base_group 
       print ' state_return.latched_group:  %d' % \ 
        args[2].latched_group 
       print ' state_return.mods:    %d' % \ 
        args[2].mods 
       print ' state_return.base_mods:   %d' % \ 
        args[2].base_mods 
       print ' state_return.latched_mods:  %d' % \ 
        args[2].latched_mods 
       print ' state_return.locked_mods:   %d' % \ 
        args[2].locked_mods 
       print ' state_return.compat_state:  %d' % \ 
        args[2].compat_state 
       print ' state_return.grab_mods:   %d' % \ 
        args[2].grab_mods 
       print ' state_return.compat_grab_mods: %d' % \ 
        args[2].compat_grab_mods 
       print ' state_return.lookup_mods:   %d' % \ 
        args[2].lookup_mods 
       print ' state_return.compat_lookup_mods: %d' % \ 
        args[2].compat_lookup_mods 
       print ' state_return.ptr_buttons:   %d\n' % \ 
        args[2].ptr_buttons 
       print ' Mask   mods base_mods latched_mods locked_mods compat_state' 
       print ' --------------------------------------------------------------------------' 
       print ' ShiftMask  %-5s %-5s  %-5s   %-5s   %-5s' % \ 
        ((args[2].mods   & self.ShiftMask) != 0, \ 
        (args[2].base_mods & self.ShiftMask) != 0, \ 
        (args[2].latched_mods & self.ShiftMask) != 0, \ 
        (args[2].locked_mods & self.ShiftMask) != 0, \ 
        (args[2].compat_state & self.ShiftMask) != 0) 
       print ' LockMask  %-5s %-5s  %-5s   %-5s   %-5s' % \ 
        ((args[2].mods   & self.LockMask) != 0, \ 
        (args[2].base_mods & self.LockMask) != 0, \ 
        (args[2].latched_mods & self.LockMask) != 0, \ 
        (args[2].locked_mods & self.LockMask) != 0, \ 
        (args[2].compat_state & self.LockMask) != 0) 
       print ' ControlMask %-5s %-5s  %-5s   %-5s   %-5s' % \ 
        ((args[2].mods   & self.ControlMask) != 0, \ 
        (args[2].base_mods & self.ControlMask) != 0, \ 
        (args[2].latched_mods & self.ControlMask) != 0, \ 
        (args[2].locked_mods & self.ControlMask) != 0, \ 
        (args[2].compat_state & self.ControlMask) != 0) 
       print ' Mod1Mask  %-5s %-5s  %-5s   %-5s   %-5s' % \ 
        ((args[2].mods   & self.Mod1Mask) != 0, \ 
        (args[2].base_mods & self.Mod1Mask) != 0, \ 
        (args[2].latched_mods & self.Mod1Mask) != 0, \ 
        (args[2].locked_mods & self.Mod1Mask) != 0, \ 
        (args[2].compat_state & self.Mod1Mask) != 0) 
       print ' Mod2Mask  %-5s %-5s  %-5s   %-5s   %-5s' % \ 
        ((args[2].mods   & self.Mod2Mask) != 0, \ 
        (args[2].base_mods & self.Mod2Mask) != 0, \ 
        (args[2].latched_mods & self.Mod2Mask) != 0, \ 
        (args[2].locked_mods & self.Mod2Mask) != 0, \ 
        (args[2].compat_state & self.Mod2Mask) != 0) 
       print ' Mod3Mask  %-5s %-5s  %-5s   %-5s   %-5s' % \ 
        ((args[2].mods   & self.Mod3Mask) != 0, \ 
        (args[2].base_mods & self.Mod3Mask) != 0, \ 
        (args[2].latched_mods & self.Mod3Mask) != 0, \ 
        (args[2].locked_mods & self.Mod3Mask) != 0, \ 
        (args[2].compat_state & self.Mod3Mask) != 0) 
       print ' Mod4Mask  %-5s %-5s  %-5s   %-5s   %-5s' % \ 
        ((args[2].mods   & self.Mod4Mask) != 0, \ 
        (args[2].base_mods & self.Mod4Mask) != 0, \ 
        (args[2].latched_mods & self.Mod4Mask) != 0, \ 
        (args[2].locked_mods & self.Mod4Mask) != 0, \ 
        (args[2].compat_state & self.Mod4Mask) != 0) 
       print ' Mod5Mask  %-5s %-5s  %-5s   %-5s   %-5s' % \ 
        ((args[2].mods   & self.Mod5Mask) != 0, \ 
        (args[2].base_mods & self.Mod5Mask) != 0, \ 
        (args[2].latched_mods & self.Mod5Mask) != 0, \ 
        (args[2].locked_mods & self.Mod5Mask) != 0, \ 
        (args[2].compat_state & self.Mod5Mask) != 0) 
      # return function return value and all function arguments 
      return (result, args) 
     # connect error handler to function 
     self.__XkbGetState__.errcheck = errcheck_xkbgetstate 
    # define high-level version of "XkbOpenDisplay" 
    def XkbOpenDisplay(self, display_name, major_in_out, minor_in_out): 
     # if we don't do type checking, nobody ever will 
     assert (type(display_name) == types.NoneType) or \ 
      (type(display_name) == types.StringType) 
     assert type(major_in_out) == types.IntType 
     assert type(minor_in_out) == types.IntType 
     # convert function arguments to "ctypes", ... 
     __display_name__ = ctypes.c_char_p(display_name) 
     __major_in_out__ = ctypes.c_int(major_in_out) 
     __minor_in_out__ = ctypes.c_int(minor_in_out) 
     # ... call low-level function ... 
     ret = self.__XkbOpenDisplay__(__display_name__, __major_in_out__, \ 
             __minor_in_out__) 
     # ... and return converted return value and function arguments 
     return {'display_handle': ret[0].value, \ 
        'server_major_version': ret[1][3].value, \ 
        'server_minor_version': ret[1][4].value} 
    # define high-level version of "XkbGetState" 
    def XkbGetState(self, display_handle, device_spec): 
     # if we don't do type checking, nobody ever will 
     assert type(display_handle) == types.LongType 
     assert type(device_spec) == types.IntType 
     # convert function arguments to "ctypes", ... 
     __display_handle__ = ctypes.c_uint(display_handle) 
     __device_spec__ = ctypes.c_uint(device_spec) 
     __xkbstaterec__ = self.XkbStateRec() 
     # ... call low-level function ... 
     ret = self.__XkbGetState__(__display_handle__, __device_spec__, \ 
            __xkbstaterec__) 
     # ... and return converted function argument 
     xkbstaterec = ret[1][2] 
     return xkbstaterec 
    # extract modifier status using bitmasks 
    def ExtractLocks(self, xkbstaterec): 
     return {'group': xkbstaterec.group, \ 
       'shift': \ 
        (xkbstaterec.base_mods & self.ShiftMask) != 0, \ 
       'shift_lock': \ 
        (xkbstaterec.locked_mods & self.ShiftMask) != 0, \ 
       'lock': \ 
        (xkbstaterec.base_mods & self.LockMask) != 0, \ 
       'lock_lock': \ 
        (xkbstaterec.locked_mods & self.LockMask) != 0, \ 
       'control': \ 
        (xkbstaterec.base_mods & self.ControlMask) != 0, \ 
       'control_lock': \ 
        (xkbstaterec.locked_mods & self.ControlMask) != 0, \ 
       'mod1': \ 
        (xkbstaterec.base_mods & self.Mod1Mask) != 0, \ 
       'mod1_lock': \ 
        (xkbstaterec.locked_mods & self.Mod1Mask) != 0, \ 
       'mod2': \ 
        (xkbstaterec.base_mods & self.Mod2Mask) != 0, \ 
       'mod2_lock': \ 
        (xkbstaterec.locked_mods & self.Mod2Mask) != 0, \ 
       'mod3': \ 
        (xkbstaterec.base_mods & self.Mod3Mask) != 0, \ 
       'mod3_lock': \ 
        (xkbstaterec.locked_mods & self.Mod3Mask) != 0, \ 
       'mod4': \ 
        (xkbstaterec.base_mods & self.Mod4Mask) != 0, \ 
       'mod4_lock': \ 
        (xkbstaterec.locked_mods & self.Mod4Mask) != 0, \ 
       'mod5': \ 
        (xkbstaterec.base_mods & self.Mod5Mask) != 0, \ 
       'mod5_lock': \ 
        (xkbstaterec.locked_mods & self.Mod5Mask) != 0} 

Pour appeler l'état à un dictionnaire, d'un autre fichier, il suffit d'appeler from FILENAME import * et procédez comme suit:

# simple demonstration of this wrapper 
xkb = SimpleXkbWrapper() 
# initialise wrapper for the X Keyboard Extension (v1.0) and 
# open connection to default X display 
display_name = None 
major_in_out = 1 
minor_in_out = 0 
try: 
    ret = xkb.XkbOpenDisplay(display_name, major_in_out, minor_in_out) 
except OSError, error: 
    print 
    print ' Error: %s' % error 
    print 
    exit(1) 
# ... get modifier state of core keyboard ... 
display_handle = ret['display_handle'] 
device_spec = xkb.XkbUseCoreKbd 
xkbstaterec = xkb.XkbGetState(display_handle, device_spec) 
# ... and extract and the information we need 
print xkb.ExtractLocks(xkbstaterec) 

Vive au créateur dont le code peut être trouvé here, et Jason Orendorffl pour dessiner mon attention à cela.

0

Si vous avez besoin de travailler sur Linux, je pense que vous devez surveiller les événements X en quelque sorte.

Vous pouvez voir tous les événements si vous exécutez la commande "xev" - donc je suis sûr que X fournit une interface à tous les événements. Un google rapide trouve Python X library qui vous donne probablement les choses dont vous avez besoin.

Vous pouvez download it here.

+2

Il faut se concentrer pour écouter clavier. – jfs

+0

Vous avez raison, donc la réponse était tout simplement erronée, désolé. Posté un nouveau qui devrait fonctionner :) – Kimvais

+1

XQueryPointer vous permet d'interroger l'état de clé de modification du clavier sans avoir besoin de mise au point, si ce code doit être cru: http://synergy2.cvs.sourceforge.net/viewvc/synergy2/synergy/ lib/platform/CXWindowsKeyState.cpp? revision = 1.7 & view = markup (voir CXWindowsKeyState :: pollActiveModifiers) –

2

Ma précédente réponse était apparemment complètement faux, désolé. Je pense que la bonne approche serait de lire/dev/input/event1

Ce test court a montré scancodes pour moi, même si le terminal n'a pas eu mise au point (?):

from struct import unpack 
port = open("/dev/input/event1","rb")  

while 1:  
    a,b,c,d = unpack("4B",port.read(4))  
    print a,b,c,d 

je sais pas si/dev/input/event1 est toujours le clavier ou comment déterminer lequel est, mais au moins pour moi, il a travaillé

+0

Ok J'ai utilisé un fichier sur mon clavier USB pour le trouver lié à event3. Je reçois également une série de codes de balayage - mais ils ne sont jamais les mêmes. Je suis allé googler XD. – torger

+0

Je n'ai aucune idée de scancodes. – torger

0

Vous pouvez utiliser PyUserInput à cette fin, ce qui est une solution multi-plateforme, compatible, dans votre cas, avec X11.

Exemple avec super:

from pykeyboard import PyKeyboardEvent 

class MonitorSuper(PyKeyboardEvent): 
    def tap(self, keycode, character, press): 
     '''Monitor Super key.''' 
     if character == 'Super_L': 
      if press: 
       print('Super pressed') 
      else: 
       print('Super released') 
mon = MonitorSuper() 
mon.run() 
Questions connexes