Exemple #1
0
class FakeInputs:
    def __init__(self):
        self.display = Display()

    def press_mouse(self, button, x, y):
        pass

    def release_mouse(self, button, x, y):
        pass

    def move_mouse(self, x, y):
        fake_input(self.display, X.MotionNotify, x=x, y=y)
        self.display.sync()

    def press_key(self, key):
        keycode = self.display.keysym_to_keycode(key)
        fake_input(self.window(), X.KeyPress, keycode)
        self.display.sync()

    def release_key(self, key):
        keycode = self.display.keysym_to_keycode(key)
        fake_input(self.window(), X.KeyRelease, keycode)
        self.display.sync()

    def window(self):
        return self.display.get_input_focus()._data['focus']
Exemple #2
0
    def send_key(self, emulated_key):
        display = Display()
        root = display.screen().root

        shift_mask = 0  # or Xlib.X.ShiftMask
        window = display.get_input_focus()._data["focus"]
        keysym = Xlib.XK.string_to_keysym(emulated_key)
        keycode = display.keysym_to_keycode(keysym)

        Xlib.ext.xtest.fake_input(window, Xlib.X.KeyPress, keycode)

        event = Xlib.protocol.event.KeyPress(
            time=int(time.time()),
            root=root,
            window=window,
            same_screen=0, child=Xlib.X.NONE,
            root_x=0, root_y=0, event_x=0, event_y=0,
            state=shift_mask,
            detail=keycode
        )
        window.send_event(event, propagate=True)
        event = Xlib.protocol.event.KeyRelease(
            time=int(time.time()),
            root=display.screen().root,
            window=window,
            same_screen=0, child=Xlib.X.NONE,
            root_x=0, root_y=0, event_x=0, event_y=0,
            state=shift_mask,
            detail=keycode
        )
        window.send_event(event, propagate=True)
        display.sync()
Exemple #3
0
    def _init_xlib(self):
        """Setup python-xlib components in the PyGTK event loop"""
        disp = Display()
        self.xroot = disp.screen().root

        # We want to receive KeyPress events
        self.xroot.change_attributes(event_mask = X.KeyPressMask)
        self._key_n_mask = {}
        for key in self._keys:
            if len(key.split('-')) > 1:
                more_mask = key.split('-')[0:-1]
                real_key = key.split('-')[-1]
            else:
                more_mask = []
                real_key = key
            try:
                modmask = reduce(operator.ior, [getattr(X, "%sMask" % x) for x in (self._modkeys + more_mask)])
            except Exception, err:
                logging.error("Error while resolving modifier key mask: %s", err)
                logging.error("Not binding keys for safety reasons. (eg. What if Ctrl+C got bound?)")
                modmask = 0
            else:
                keycode = disp.keysym_to_keycode(string_to_keysym(real_key))
                self._key_n_mask[(keycode, modmask)] = self._keys[key]
                #Ignore all combinations of Mod2 (NumLock) and Lock (CapsLock)
                for ignored in [0, X.Mod2Mask, X.LockMask, X.Mod2Mask | X.LockMask]:
                    self.xroot.grab_key(keycode, modmask | ignored, 1, X.GrabModeAsync, X.GrabModeAsync)
Exemple #4
0
class QuickTileApp(object):
    keybinds_failed = False

    def __init__(self, wm, keys=None, modkeys=None, movemodkeys=None):
        """@todo: document these arguments"""
        self.wm = wm
        self._keys = keys or {}
        self._modkeys = modkeys or 0
        self._movemodkeys = movemodkeys or 0
        self._movemodmask = 0

    def _init_dbus(self):
        """Setup dbus-python components in the PyGTK event loop"""
        class QuickTile(dbus.service.Object):
            def __init__(self):
                dbus.service.Object.__init__(self, sessBus,
                                             '/com/ssokolow/QuickTile')

            @dbus.service.method(dbus_interface='com.ssokolow.QuickTile',
                     in_signature='s', out_signature='b')
            def doCommand(self, command):
                return wm.doCommand(command)
            def doMoveCommand(self, command):
                return wm.doMoveCommand(command)

        self.dbusName = dbus.service.BusName("com.ssokolow.QuickTile", sessBus)
        self.dbusObj = QuickTile()

    def _init_xlib(self):
        """Setup python-xlib components in the PyGTK event loop"""
        self.xdisp = Display()
        self.xroot = self.xdisp.screen().root

        # We want to receive KeyPress events
        self.xroot.change_attributes(event_mask=X.KeyPressMask)

        # unrecognized shortkeys now will be looked up in a hardcoded dict
        # and replaced by valid names like ',' -> 'comma'
        # while generating the self.keys dict
        self.keys = dict()
        for key in self._keys:
            transKey = key
            if key in KEYLOOKUP:
                transKey = KEYLOOKUP[key]
            code = self.xdisp.keysym_to_keycode(string_to_keysym(transKey))
            self.keys[code] = self._keys[key]

        # Resolve strings to X11 mask constants for the modifier mask
        try:
            modmask = reduce(operator.ior, [getattr(X, "%sMask" % x)
                             for x in self._modkeys])
            self._movemodmask = reduce(operator.ior, [getattr(X, "%sMask" % x)
                             for x in self._movemodkeys])
        except Exception, err:
            logging.error("Error while resolving modifier key mask: %s", err)
            logging.error("Not binding keys for safety reasons. "
                          "(eg. What if Ctrl+C got bound?)")
            modmask = 0
            movemodmask = 0
        else:
Exemple #5
0
    def start(self):
        mod = self.MOD_MASK
        dpy = Display()

        keys = {}
        for key, name in self.KEY_MAP.items():
            keys[key] = dpy.keysym_to_keycode(XK.string_to_keysym(key))

        root = dpy.screen().root
        for key, code in keys.items():
            root.grab_key(code, mod, 1, X.GrabModeAsync, X.GrabModeAsync)

        root.grab_button(
            1, mod, 1,
            X.ButtonPressMask | X.ButtonReleaseMask | X.PointerMotionMask,
            X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)
        root.grab_button(
            3, mod, 1,
            X.ButtonPressMask | X.ButtonReleaseMask | X.PointerMotionMask,
            X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)

        self.dpy = dpy
        self.keys = keys
        self.root = root

        self.WM_PROTOCOLS = dpy.intern_atom("WM_PROTOCOLS")
        self.WM_DELETE_WINDOW = dpy.intern_atom("WM_DELETE_WINDOW")

        self._loop()
Exemple #6
0
    class HotkeyThread(qtcore.QThread):
        hotkeySignal = qtcore.pyqtSignal()

        def __init__(self, mod = 'MOD_SHIFT', key = 'VK_SPACE'):
            qtcore.QThread.__init__(self)

            keysym = string_to_keysym('space')
            self.modifiers = X.ShiftMask | X.ControlMask

            self.disp = Display()
            self.key = self.disp.keysym_to_keycode(keysym)

            self.root = self.disp.screen().root
            self.root.change_attributes(event_mask=X.KeyPressMask)
            self.root.grab_key(self.key, self.modifiers, 0, False, X.GrabModeAsync, X.GrabModeAsync)
            self.root.grab_key(self.key, self.modifiers | X.LockMask, 0, False, X.GrabModeAsync, X.GrabModeAsync)
            self.root.grab_key(self.key, self.modifiers | X.Mod2Mask, 0, False, X.GrabModeAsync, X.GrabModeAsync)
            self.root.grab_key(self.key, self.modifiers | X.LockMask | X.Mod2Mask, 0, False, X.GrabModeAsync, X.GrabModeAsync)
            self.root.grab_key(self.key, self.modifiers | X.Mod3Mask | X.LockMask, 0, False, X.GrabModeAsync, X.GrabModeAsync)
            self.root.grab_key(self.key, self.modifiers | X.Mod3Mask | X.Mod2Mask, 0, False, X.GrabModeAsync, X.GrabModeAsync)
            self.root.grab_key(self.key, self.modifiers | X.Mod3Mask | X.LockMask | X.Mod2Mask, 0, False, X.GrabModeAsync, X.GrabModeAsync)

        def dispatch_hotkey(self, msg):
            if msg.type == X.KeyPress:
                self.hotkeySignal.emit()

        def __del__(self):
            self.terminate()

        def run(self):
            while True:
                event = self.root.display.next_event()
                self.dispatch_hotkey(event)

            print('finished loop')
Exemple #7
0
class x11_Keyboard:
    def __init__(self):
        self.display = Display()

    def press(self, key):
        if key >= 256:
            keycode = self.display.keysym_to_keycode(keymap[key])
        keycode = self.display.keysym_to_keycode(key)
        fake_input(self.window(), X.KeyPress, keycode)
        self.display.sync()

    def release(self, key):
        if key >= 256:
            keycode = self.display.keysym_to_keycode(keymap[key])
        keycode = self.display.keysym_to_keycode(key)
        fake_input(self.window(), X.KeyRelease, keycode)
        self.display.sync()

    def window(self):
        return self.display.get_input_focus()._data["focus"]
Exemple #8
0
class x11_Keyboard:
    def __init__(self):
        self.display = Display()

    def press(self, key):
        if key >= 256:
            keycode = self.display.keysym_to_keycode(keymap[key])
        keycode = self.display.keysym_to_keycode(key)
        fake_input(self.window(), X.KeyPress, keycode)
        self.display.sync()

    def release(self, key):
        if key >= 256:
            keycode = self.display.keysym_to_keycode(keymap[key])
        keycode = self.display.keysym_to_keycode(key)
        fake_input(self.window(), X.KeyRelease, keycode)
        self.display.sync()

    def window(self):
        return self.display.get_input_focus()._data['focus']
Exemple #9
0
    def __send_key(self, x_event, key_code):
        key = key_code.X11

        if key is None:
            print("key not defined on X11!")
            pass

        d = Display()
        x11key = d.keysym_to_keycode(XK.string_to_keysym(key))
        fake_input(d, x_event, x11key)
        d.sync()
    def init_x11(self):
        from Xlib import X, XK
        from Xlib.display import Display 

        disp = Display()
        root = disp.screen().root
        root.change_attributes(event_mask=X.KeyPressMask)

        self.WINDOW_KEY = disp.keysym_to_keycode(XK.string_to_keysym("n"))
        root.grab_key(self.WINDOW_KEY, X.AnyModifier, 1, X.GrabModeAsync, X.GrabModeAsync)

        import threading
        t = threading.Thread(target=lambda: self.process_x11(disp))
        t.daemon = True
        t.start()
Exemple #11
0
    def __init__(self):
        super().__init__()
        display = Display()
        self.root = display.screen().root
        self.handlers = {}

        for key, handler in mapping.items():
            if not isinstance(key, int):
                key, mask = key
            else:
                mask = 0
            keycode = display.keysym_to_keycode(key)
            self.root.grab_key(keycode, mask, False, X.GrabModeAsync,
                               X.GrabModeAsync)
            self.handlers[(keycode, mask)] = handler
Exemple #12
0
    def _init_xlib(self):
        """Setup python-xlib components in the PyGTK event loop"""
        disp = Display()
        self.xroot = disp.screen().root

        # We want to receive KeyPress events
        self.xroot.change_attributes(event_mask = X.KeyPressMask)
        self.keys = dict([(disp.keysym_to_keycode(string_to_keysym(x)), self._keys[x]) for x in self._keys])

        # Resolve strings to X11 mask constants for the modifier mask
        try:
            modmask = reduce(operator.ior, [getattr(X, "%sMask" % x) for x in self._modkeys])
        except Exception, err:
            logging.error("Error while resolving modifier key mask: %s", err)
            logging.error("Not binding keys for safety reasons. (eg. What if Ctrl+C got bound?)")
            modmask = 0
Exemple #13
0
class PyGrid(object):
    KEYS = {
        miscellany.XK_KP_1: 'bottomleft',
        miscellany.XK_KP_2: 'bottom',
        miscellany.XK_KP_3: 'bottomright',
        miscellany.XK_KP_4: 'left',
        miscellany.XK_KP_5: 'middle',
        miscellany.XK_KP_6: 'right',
        miscellany.XK_KP_7: 'topleft',
        miscellany.XK_KP_8: 'top',
        miscellany.XK_KP_9: 'topright',
    }

    def __init__(self, positions):
        self.positions = positions
        self.display = Display()
        self.root = self.display.screen().root
        self.winman = WindowManager(self.positions)
        self.keys = {}

    def handle_event(self, source, condition, handle=None):
        handle = handle or self.root.display
        for i in range(0, handle.pending_events()):
            event = handle.next_event()
            if event.type == X.KeyPress:
                keycode = event.detail
                self.winman.run_command(self.keys[keycode])
        return True

    def start_daemon(self):
        try:
            self.root.change_attributes(event_mask=X.KeyPressMask)
            self.keys = {self.display.keysym_to_keycode(k):self.KEYS[k] for k in self.KEYS}
            for keycode in self.keys:
                self.root.grab_key(keycode, X.ControlMask | X.Mod1Mask, 1, X.GrabModeAsync, X.GrabModeAsync)
                self.root.grab_key(keycode, X.ControlMask | X.Mod1Mask | X.Mod2Mask, 1, X.GrabModeAsync, X.GrabModeAsync)
            for event in range(0, self.root.display.pending_events()):
                self.root.display.next_event()
            gobject.io_add_watch(self.root.display, gobject.IO_IN, self.handle_event)
            gtk.main()
        except KeyboardInterrupt:
            print "Stopping PyGrid daemon"
Exemple #14
0
class QuickTileApp(object):
    keybinds_failed = False

    def __init__(self, wm, keys=None, modkeys=None):
        """@todo: document these arguments"""
        self.wm = wm
        self._keys = keys or {}
        self._modkeys = modkeys or 0

    def _init_dbus(self):
        """Setup dbus-python components in the PyGTK event loop"""
        class QuickTile(dbus.service.Object):
            def __init__(self):
                dbus.service.Object.__init__(self, sessBus, '/com/ssokolow/QuickTile')

            @dbus.service.method(dbus_interface='com.ssokolow.QuickTile',
                     in_signature='s', out_signature='b')
            def doCommand(self, command):
                return wm.doCommand(command)

        self.dbusName = dbus.service.BusName("com.ssokolow.QuickTile", sessBus)
        self.dbusObj = QuickTile()

    def _init_xlib(self):
        """Setup python-xlib components in the PyGTK event loop"""
        self.xdisp = Display()
        self.xroot = self.xdisp.screen().root

        # We want to receive KeyPress events
        self.xroot.change_attributes(event_mask=X.KeyPressMask)
        self.keys = dict([(self.xdisp.keysym_to_keycode(string_to_keysym(x)), self._keys[x]) for x in self._keys])

        # Resolve strings to X11 mask constants for the modifier mask
        try:
            modmask = reduce(operator.ior, [getattr(X, "%sMask" % x) for x in self._modkeys])
        except Exception, err:
            logging.error("Error while resolving modifier key mask: %s", err)
            logging.error("Not binding keys for safety reasons. (eg. What if Ctrl+C got bound?)")
            modmask = 0
        else:
Exemple #15
0
    def _init_xlib(self):
        """Setup python-xlib components in the PyGTK event loop"""
        disp = Display()
        self.xroot = disp.screen().root

        # We want to receive KeyPress events
        self.xroot.change_attributes(event_mask=X.KeyPressMask)
        self._key_n_mask = {}
        for key in self._keys:
            if len(key.split('-')) > 1:
                more_mask = key.split('-')[0:-1]
                real_key = key.split('-')[-1]
            else:
                more_mask = []
                real_key = key
            try:
                modmask = reduce(operator.ior, [
                    getattr(X, "%sMask" % x)
                    for x in (self._modkeys + more_mask)
                ])
            except Exception, err:
                logging.error("Error while resolving modifier key mask: %s",
                              err)
                logging.error(
                    "Not binding keys for safety reasons. (eg. What if Ctrl+C got bound?)"
                )
                modmask = 0
            else:
                keycode = disp.keysym_to_keycode(string_to_keysym(real_key))
                self._key_n_mask[(keycode, modmask)] = self._keys[key]
                #Ignore all combinations of Mod2 (NumLock) and Lock (CapsLock)
                for ignored in [
                        0, X.Mod2Mask, X.LockMask, X.Mod2Mask | X.LockMask
                ]:
                    self.xroot.grab_key(keycode, modmask | ignored, 1,
                                        X.GrabModeAsync, X.GrabModeAsync)
Exemple #16
0
class PyKeyboard(PyKeyboardMeta):
    """
    The PyKeyboard implementation for X11 systems (mostly linux). This
    allows one to simulate keyboard input.
    """
    def __init__(self, display=None):
        PyKeyboardMeta.__init__(self)
        self.display = Display(display)
        self.display2 = Display(display)
        self.special_key_assignment()

    def press_key(self, character=''):
        """
        Press a given character key. Also works with character keycodes as
        integers, but not keysyms.
        """
        try:  # Detect uppercase or shifted character
            shifted = self.is_char_shifted(character)
        except AttributeError:  # Handle the case of integer keycode argument
            fake_input(self.display, X.KeyPress, character)
            self.display.sync()
        else:
            if shifted:
                fake_input(self.display, X.KeyPress, self.shift_key)
            keycode = self.lookup_character_keycode(character)
            fake_input(self.display, X.KeyPress, keycode)
            self.display.sync()

    def release_key(self, character=''):
        """
        Release a given character key. Also works with character keycodes as
        integers, but not keysyms.
        """
        try:  # Detect uppercase or shifted character
            shifted = self.is_char_shifted(character)
        except AttributeError:  # Handle the case of integer keycode argument
            fake_input(self.display, X.KeyRelease, character)
            self.display.sync()
        else:
            if shifted:
                fake_input(self.display, X.KeyRelease, self.shift_key)
            keycode = self.lookup_character_keycode(character)
            fake_input(self.display, X.KeyRelease, keycode)
            self.display.sync()

    def special_key_assignment(self):
        """
        Determines the keycodes for common special keys on the keyboard. These
        are integer values and can be passed to the other key methods.
        Generally speaking, these are non-printable codes.
        """
        #This set of keys compiled using the X11 keysymdef.h file as reference
        #They comprise a relatively universal set of keys, though there may be
        #exceptions which may come up for other OSes and vendors. Countless
        #special cases exist which are not handled here, but may be extended.
        #TTY Function Keys
        self.backspace_key = self.lookup_character_keycode('BackSpace')
        self.tab_key = self.lookup_character_keycode('Tab')
        self.linefeed_key = self.lookup_character_keycode('Linefeed')
        self.clear_key = self.lookup_character_keycode('Clear')
        self.return_key = self.lookup_character_keycode('Return')
        self.enter_key = self.return_key  # Because many keyboards call it "Enter"
        self.pause_key = self.lookup_character_keycode('Pause')
        self.scroll_lock_key = self.lookup_character_keycode('Scroll_Lock')
        self.sys_req_key = self.lookup_character_keycode('Sys_Req')
        self.escape_key = self.lookup_character_keycode('Escape')
        self.delete_key = self.lookup_character_keycode('Delete')
        #Modifier Keys
        self.shift_l_key = self.lookup_character_keycode('Shift_L')
        self.shift_r_key = self.lookup_character_keycode('Shift_R')
        self.shift_key = self.shift_l_key  # Default Shift is left Shift
        self.alt_l_key = self.lookup_character_keycode('Alt_L')
        self.alt_r_key = self.lookup_character_keycode('Alt_R')
        self.alt_key = self.alt_l_key  # Default Alt is left Alt
        self.control_l_key = self.lookup_character_keycode('Control_L')
        self.control_r_key = self.lookup_character_keycode('Control_R')
        self.control_key = self.control_l_key  # Default Ctrl is left Ctrl
        self.caps_lock_key = self.lookup_character_keycode('Caps_Lock')
        self.capital_key = self.caps_lock_key  # Some may know it as Capital
        self.shift_lock_key = self.lookup_character_keycode('Shift_Lock')
        self.meta_l_key = self.lookup_character_keycode('Meta_L')
        self.meta_r_key = self.lookup_character_keycode('Meta_R')
        self.super_l_key = self.lookup_character_keycode('Super_L')
        self.windows_l_key = self.super_l_key  # Cross-support; also it's printed there
        self.super_r_key = self.lookup_character_keycode('Super_R')
        self.windows_r_key = self.super_r_key  # Cross-support; also it's printed there
        self.hyper_l_key = self.lookup_character_keycode('Hyper_L')
        self.hyper_r_key = self.lookup_character_keycode('Hyper_R')
        #Cursor Control and Motion
        self.home_key = self.lookup_character_keycode('Home')
        self.up_key = self.lookup_character_keycode('Up')
        self.down_key = self.lookup_character_keycode('Down')
        self.left_key = self.lookup_character_keycode('Left')
        self.right_key = self.lookup_character_keycode('Right')
        self.end_key = self.lookup_character_keycode('End')
        self.begin_key = self.lookup_character_keycode('Begin')
        self.page_up_key = self.lookup_character_keycode('Page_Up')
        self.page_down_key = self.lookup_character_keycode('Page_Down')
        self.prior_key = self.lookup_character_keycode('Prior')
        self.next_key = self.lookup_character_keycode('Next')
        #Misc Functions
        self.select_key = self.lookup_character_keycode('Select')
        self.print_key = self.lookup_character_keycode('Print')
        self.print_screen_key = self.print_key  # Seems to be the same thing
        self.snapshot_key = self.print_key  # Another name for printscreen
        self.execute_key = self.lookup_character_keycode('Execute')
        self.insert_key = self.lookup_character_keycode('Insert')
        self.undo_key = self.lookup_character_keycode('Undo')
        self.redo_key = self.lookup_character_keycode('Redo')
        self.menu_key = self.lookup_character_keycode('Menu')
        self.apps_key = self.menu_key  # Windows...
        self.find_key = self.lookup_character_keycode('Find')
        self.cancel_key = self.lookup_character_keycode('Cancel')
        self.help_key = self.lookup_character_keycode('Help')
        self.break_key = self.lookup_character_keycode('Break')
        self.mode_switch_key = self.lookup_character_keycode('Mode_switch')
        self.script_switch_key = self.lookup_character_keycode('script_switch')
        self.num_lock_key = self.lookup_character_keycode('Num_Lock')
        #Keypad Keys: Dictionary structure
        keypad = ['Space', 'Tab', 'Enter', 'F1', 'F2', 'F3', 'F4', 'Home',
                  'Left', 'Up', 'Right', 'Down', 'Prior', 'Page_Up', 'Next',
                  'Page_Down', 'End', 'Begin', 'Insert', 'Delete', 'Equal',
                  'Multiply', 'Add', 'Separator', 'Subtract', 'Decimal',
                  'Divide', 0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        self.keypad_keys = {k: self.lookup_character_keycode('KP_'+str(k)) for k in keypad}
        self.numpad_keys = self.keypad_keys
        #Function Keys/ Auxilliary Keys
        #FKeys
        self.function_keys = [None] + [self.lookup_character_keycode('F'+str(i)) for i in range(1,36)]
        #LKeys
        self.l_keys = [None] + [self.lookup_character_keycode('L'+str(i)) for i in range(1,11)]
        #RKeys
        self.r_keys = [None] + [self.lookup_character_keycode('R'+str(i)) for i in range(1,16)]

        #Unsupported keys from windows
        self.kana_key = None
        self.hangeul_key = None # old name - should be here for compatibility
        self.hangul_key = None
        self.junjua_key = None
        self.final_key = None
        self.hanja_key = None
        self.kanji_key = None
        self.convert_key = None
        self.nonconvert_key = None
        self.accept_key = None
        self.modechange_key = None
        self.sleep_key = None

    def lookup_character_keycode(self, character):
        """
        Looks up the keysym for the character then returns the keycode mapping
        for that keysym.
        """
        keysym = Xlib.XK.string_to_keysym(character)
        if keysym == 0:
            keysym = Xlib.XK.string_to_keysym(special_X_keysyms[character])
        return self.display.keysym_to_keycode(keysym)
Exemple #17
0
class KnoX:
    Geometry = namedtuple("Geometry", "x y width height")
    FrameExtents = namedtuple("FrameExtents", "left right top bottom")

    def __init__(self):
        #self.display = Display(os.environ.get("DISPLAY", ":0.0"))
        self.display = Display()
        print("Connected to X DISPLAY %r" % self.display.get_display_name())
        self.display.set_error_handler(self.knox_error_handler)
        self.screen = self.display.screen()
        self.root = self.screen.root
        self.atoms = dict()
        self.atom_names = dict()
        self.keysyms = Keysyms()
        self.modifiers = Modifiers(self)
        self._supported_properties = None
        self._acceptable_error_sequence = 0
        self._acceptable_errors = dict()
        self._silenced_errors = set()

    def fileno(self):
        """This function is here to make select work with this object"""
        return self.display.fileno()

    @contextmanager
    def silenced_error(self, error):
        silencer = self.silence_error(error)
        try:
            yield silencer
        finally:
            self.remove_silencer(silencer)

    def silence_error(self, error):
        k = self._acceptable_error_sequence
        self._acceptable_errors[k] = error
        self._acceptable_error_sequence += 1
        self._silenced_errors = set(self._acceptable_errors.values())
        return k

    def remove_silencer(self, key):
        if key in self._acceptable_errors:
            del self._acceptable_errors[key]
            self._silenced_errors = set(self._acceptable_errors.values())

    def knox_error_handler(self, err, *args):
        if type(err) not in self._silenced_errors:
            print("X protocol error: %s" % err)
            traceback.print_stack()

    # def wait_for_event(self, timeout_seconds):
    #     """ Wait up to `timeout_seconds` seconds for an event to be queued.
    #     Return True, if a xevent is available.
    #     Return False, if the timeout was reached.
    #     from https://gist.github.com/fphammerle/d81ca3ff0a169f062a9f28e57b18f04d"""
    #     rlist = select.select(
    #         [self.display], # rlist
    #         [], # wlist
    #         [], # xlist
    #         timeout_seconds, # timeout [seconds]
    #     )[0]
    #     return len(rlist) > 0

    def next_event(self, wait=True):
        if (wait or self.display.pending_events()):
            return self.display.next_event()
        else:
            return None

    # def next_event(self, event_loop):
    #     event_loop.register_reader(self.display,

    def atom(self, name, only_if_exists=False):
        if isinstance(name, int):
            a = name
        elif name not in self.atoms:
            a = self.display.get_atom(name, only_if_exists=only_if_exists)
            self.atoms[name] = a
        else:
            a = self.atoms[name]
        return a

    def atom_name(self, atom):
        if atom in self.atom_names:
            return self.atom_names[atom]
        name = self.display.get_atom_name(atom)
        if name:
            self.atom_names[atom] = name
            if name not in self.atoms:
                self.atoms[name] = atom
            return name

    def get_prop(self, window, name):
        prop_name = self.atom(name, only_if_exists=True)
        if not prop_name:
            return None
        if isinstance(window, int):
            window = self.get_window(window)
        p = window.get_full_property(prop_name, X.AnyPropertyType)
        if p:
            return p.value

    def get_text_prop(self, window, name):
        prop_name = self.atom(name, only_if_exists=True)
        if not prop_name:
            return None
        s = window.get_full_text_property(prop_name, Xatom.STRING)
        if not s:
            t = self.atom("UTF8_STRING", only_if_exists=True)
            if t:
                s = window.get_full_text_property(prop_name, t)
        return s

    def onerror(self, *args, **kwargs):
        print("ERROR: something bad happened about %r and %r" % (args, kwargs))
        raise Exception("Error is bad...")

    def set_prop(self, window, name, type_name, value):
        if isinstance(window, int):
            window = self.get_window(window)
        if isinstance(type_name, int):
            prop_type_name = type_name
            #type_name = self.atom_name(prop_type_name)
        else:
            prop_type_name = self.atom(type_name, only_if_exists=False)

        prop_name = self.atom(name, only_if_exists=False)

        if value is None:
            window.delete_property(prop_name)
        else:
            window.change_property(prop_name,
                                   prop_type_name,
                                   32,
                                   value,
                                   mode=X.PropModeReplace,
                                   onerror=self.onerror)

    def send_prop_change_event(
        self,
        property_name,
        data,
        target=None,
        window=None,
    ):
        if target is None:
            target = self.root
        if window is None:
            window = target
        ev = protocol.event.ClientMessage(window=window,
                                          client_type=self.atom(property_name),
                                          data=data)
        target.send_event(ev,
                          event_mask=X.SubstructureNotifyMask
                          | X.SubstructureRedirectMask,
                          propagate=False,
                          onerror=self.onerror)

    def current_desktop(self, desktop=None, wait=True):
        prop_name = "_NET_CURRENT_DESKTOP"
        if desktop is None:
            pv = self.get_prop(self.root, prop_name)
            if pv:
                return pv[0]
        else:
            v = array('I', [desktop])
            #self.set_prop(self.root, prop_name, Xatom.CARDINAL, v)
            self.send_prop_change_event(
                prop_name, (32, [desktop, X.CurrentTime, 0, 0, 0]))
            self.flush()
            w = Waiter(wait)
            while w.wait():
                print("DESKTOPCHECK", hex(desktop))
                if self.current_desktop() == desktop:
                    print("DESKTOP OK")
                    break

    def get_wm_pid(self, window):
        pid_prop = self.get_prop(window, "_NET_WM_PID")
        if pid_prop:
            return pid_prop[0]
        return None

    def get_wm_name(self, window):
        if isinstance(window, int):
            window = self.get_window(window)
        # window.get_wm_name gets only STRING property and returns nothing
        # if it's UTF8_STRING
        return self.get_text_prop(window, Xatom.WM_NAME)

    def active_window(self, window=None, wait=3, id_only=False):
        prop_name = "_NET_ACTIVE_WINDOW"
        if window is None:
            pv = self.get_prop(self.root, prop_name)
            if pv and pv[0]:
                window = self.get_window(pv[0])
                if window and window.get_wm_name() != 'Desktop':
                    if id_only:
                        return window.id
                    else:
                        return window
        else:
            if isinstance(window, int):
                window = self.get_window(window)
            desktop = self.get_desktop_for_window(window)
            self.current_desktop(desktop)
            #v = array('I', [ window.id, 0 ])
            #self.set_prop(self.root, prop_name, Xatom.WINDOW, v)
            # data[0]: source indication
            #   1: when the request comes from an application
            #   2: from a pager
            #   0: no spec.
            self.send_prop_change_event(prop_name,
                                        (32, [2, X.CurrentTime, 0, 0, 0]),
                                        window=window)
            self.flush()
            #self.raise_window(window)
            # it won't become active until it's focused
            focused = self.set_focused_window(window, wait=1)
            w = Waiter(wait)
            while w.wait():
                a = self.active_window()
                self.flush()
                if not focused:
                    focused = self.set_focused_window(window, wait=1)
                    self.flush()
                if a and a.id == window.id:
                    print("Activated %r!" % window.id)
                    return True
                self.send_prop_change_event(prop_name,
                                            (32, [2, X.CurrentTime, 0, 0, 0]),
                                            window=window)
                self.flush()
            print("Can't activate %d" % window.id)
            return False

    def get_focused_window(self, toplevel=True):
        f = self.display.get_input_focus()
        #f = protocol.request.GetInputFocus(display=self.display.display)
        if f.focus in [X.NONE, X.PointerRoot]:
            return None
        if toplevel:
            w = self.get_client_window(f.focus)
            if w is not None:
                return w.id
        return f.focus.id

    def raise_window(self, window):
        if isinstance(window, int):
            window = self.get_window(window)
        elif window is None:
            return
        window.raise_window()

    def focus_error(self, *args, **kwargs):
        print("Cannot set_input_focus: %r %r" % (args, kwargs))

    def set_focused_window(self, window, wait=3):
        if window is None:
            self.display.set_input_focus(X.NONE,
                                         X.RevertToParent,
                                         X.CurrentTime,
                                         onerror=self.focus_error)
            return True
        elif not wait:
            self.display.set_input_focus(window, X.RevertToParent,
                                         X.CurrentTime)
            return True
        else:
            with self.silenced_error(error.BadMatch):
                if isinstance(window, int):
                    window = self.get_window(window)
                self.display.set_input_focus(window, X.RevertToParent,
                                             X.CurrentTime)
                self.flush()
                w = Waiter(wait)
                while w.wait():
                    if w.timeout:
                        if w.progressed:
                            print("WAITING %.3f seconds more for focus on %r" %
                                  (w.remaining, window.id))
                        else:
                            print(
                                "READY TO WAIT %.3f seconds for focus on %r" %
                                (w.remaining, window.id))
                    focused_win_id = self.get_focused_window()
                    if focused_win_id == window.id:
                        print("FOCUSED %r" % window.id)
                        return True
                    # many times it's needed to repeat the command, esp. when mouse is
                    # not inside the target window
                    self.display.set_input_focus(window, X.RevertToParent,
                                                 X.CurrentTime)
                    self.flush()
                    #self.display.set_input_focus(window, X.RevertToParent, X.CurrentTime)
                    #self.display.flush()
            return False

    def get_desktop_for_window(self, window):
        pv = self.get_prop(window, "_NET_WM_DESKTOP")
        if pv:
            return pv[0]

    def set_desktop_for_window(self, window, desktop):
        if desktop is None:
            return
        name = self.atom("_NET_WM_DESKTOP", only_if_exists=True)
        if name in self.supported_properties:
            pv = self.set_prop(window, name, Xatom.CARDINAL,
                               array('I', [desktop]))

    def save_state(self):
        state = {
            "Current Desktop": self.current_desktop(),
            "Active Window": self.active_window(id_only=True),
            "Focused Window": self.get_focused_window()
        }
        return state

    def restore_state(self, state):
        a = self.supported_properties
        self.current_desktop(state["Current Desktop"])
        self.flush()
        try:
            self.set_focused_window(state["Focused Window"])
        except error.BadWindow:
            print("Sorry, the old focused window went away...")
        # self.active_window(state["Active Window"])

    def keysym_to_string(self, keysym, friendly=False, very_friendly=False):
        if keysym not in self.keysyms.keysyms:
            return chr(keysym)
        if very_friendly:
            return self.keysyms.friendly_name(keysym, simplest=True)
        if friendly:
            return self.keysyms.friendly_name(keysym, simplest=False)
        else:
            return self.keysyms[keysym]

    def keycode_to_keysym(self, keycode, idx=None):
        if idx is None:
            syms = set()
            for i in range(4):
                keysym = self.display.keycode_to_keysym(keycode, i)
                if keysym:
                    syms.add(keysym)
            return syms
        else:
            return self.display.keycode_to_keysym(event.detail, i)

    def keysym_to_keycode(self, keysym):
        return self.display.keysym_to_keycode(keysym)

    def string_to_keysym(self, s):
        k = self.keysyms[s]
        if not k:
            k = self.keysyms["XK_" + s]
        if k:
            return k
        k = XK.string_to_keysym(s)
        return k
        # allow simpler names, like AudioRaiseVolume?
        # if s.startswith("XF86_"):
        #     s = "XF86" + s[5:]
        #     return XK.string_to_keysym(s)

    def error_handler(self, fn, *args, **kwargs):
        return functools.partial(fn, *args, **kwargs)

    def toggle_frame(self, window, frame=None, wait=1):
        """Set window frame. Value should be True or False for on and off, or None for toggle."""
        # flags - set bit for every iteresting value
        # 0 functions   => integer bits
        # 1 decorations => integer bits
        # 2 input_mode  => enum string or integer
        # 3 status      => integer bits
        #
        # functions:
        # bit    actions offered
        # ---    ---------------
        #  1     all functions
        #  2     resize window
        #  4     move window
        #  8     minimize, to iconify
        # 16     maximize, to full-screen (with a frame still)
        # 32     close window
        #
        # decorations:
        # bit       decorations displayed
        # ---       ---------------------
        #  1        all decorations
        #  2        border around the window
        #  4        resizeh, handles to resize by dragging
        #  8        title bar, showing WM_NAME
        # 16        menu, drop-down menu of the "functions" above
        # 32        minimize button, to iconify
        # 64        maximize button, to full-screen
        #
        # input mode:
        #   string                   integer
        # "modeless"                    0    not modal (the default)
        # "primary_application_modal"   1    modal to its "transient for"
        # "system_modal"                2    modal to the whole display
        # "full_application_modal"      3    modal to the current client
        #
        # status:
        #
        # bit
        #  1    tearoff menu window

        name = self.atom("_MOTIF_WM_HINTS", only_if_exists=True)
        # If does not exist, probably not supported, though should check
        # root for _NET_SUPPORTED list return assert prop != 0 pv =
        pv = self.get_prop(window, name)
        fe = self.get_frame_extents(window)
        if pv and len(pv) == 5:
            hints = array(pv.typecode, pv)
            if frame is None:
                hints[2] = 0 if hints[2] else 1
            elif frame:
                hints[2] = 1
            else:
                hints[2] = 0
        else:
            # reasonable default
            hints = array('I', [2, 0, 0, 0, 0])

        self.set_prop(window, name, name, hints)

        w = Waiter(wait)
        while w.wait():
            pv = self.get_prop(window, name)
            if pv and array(pv.typecode, pv) == hints:
                new_fe = self.get_frame_extents(window)
                # make sure frame extents changed
                # this seems to take a while once the hints change
                if new_fe != fe:
                    break

    def set_opacity(self, window, value):
        """value is a number between 0 and 1"""
        v = int(((1 << 32) - 1) * value)
        self.set_prop(window, "_NET_WM_WINDOW_OPACITY", Xatom.CARDINAL,
                      array('I', [v]))

    def get_opacity(self, window):
        pv = self.get_prop(window, "_NET_WM_WINDOW_OPACITY")
        if pv:
            value = int(pv[0] / ((1 << 32) - 1))
            return value
        return 1

    @property
    def supported_properties(self):
        if self._supported_properties is None:
            self._supported_properties = self.get_prop(self.root,
                                                       "_NET_SUPPORTED") or []
        return self._supported_properties

    def get_window(self, win_id):
        if isinstance(win_id, int):
            return self.display.create_resource_object('window', win_id)
        else:
            return win_id

    def get_client_window(self, window):
        win_id = window.id
        for tlw in self.toplevel_windows():
            for (_, parent, _) in self.window_tree(
                    tlw, filter=lambda w, parent, level: w.id == win_id):
                return tlw
        return None

    def toplevel_windows(self, id_only=False):
        name = self.atom("_NET_CLIENT_LIST", only_if_exists=True)
        if name in self.supported_properties:
            lst = self.get_prop(self.root, name)
            if id_only:
                return lst
            else:
                return list(map(lambda win_id: self.get_window(win_id), lst))
        else:
            print("BELGENGOC")
            if id_only:
                return list(
                    map(lambda w: w.id,
                        self.root.query_tree().children))
            else:
                return list(self.root.query_tree().children)

    def window_tree(self, parent=None, level=1, filter=None):
        if parent is None:
            parent = self.root
            if filter is None or filter(parent, None, 0):
                yield (parent, None, 0)
        for w in parent.query_tree().children:
            if filter is None or filter(w, parent, level):
                yield (w, parent, level)
                yield from self.window_tree(parent=w,
                                            level=level + 1,
                                            filter=filter)

    def close_window(self, window):
        self.send_prop_change_event("_NET_CLOSE_WINDOW", (32, [0, 0, 0, 0, 0]),
                                    window=self.get_window(window))

    # https://specifications.freedesktop.org/wm-spec/wm-spec-1.3.html
    # window  = the respective client window
    # message_type = _NET_WM_STATE
    # format = 32
    # data.l[0] = the action, as listed below
    # data.l[1] = first property to alter
    # data.l[2] = second property to alter
    # data.l[3] = source indication
    #  other data.l[] elements = 0
    # This message allows two prop
    #
    _NET_WM_STATE_REMOVE = 0  # remove/unset property
    _NET_WM_STATE_ADD = 1  #add/set property
    _NET_WM_STATE_TOGGLE = 2  # toggle property

    def set_wm_states(self, window, names, action=None):
        if action is None:
            action = self._NET_WM_STATE_TOGGLE
        elif action is True:
            action = self._NET_WM_STATE_ADD
        elif action is False:
            action = self._NET_WM_STATE_REMOVE
        window = self.get_window(window)
        values = list()
        for name in names:
            value = self.atom("_NET_WM_STATE_%s" % name.upper())
            values.append(value)
        data = [action, *values]
        while len(data) < 5:
            data.append(0)
        self.send_prop_change_event("_NET_WM_STATE", (32, data),
                                    window=self.get_window(window))

    def set_wm_state(self, window, name, action=None):
        if action is None:
            action = self._NET_WM_STATE_TOGGLE
        elif action is True:
            action = self._NET_WM_STATE_ADD
        elif action is False:
            action = self._NET_WM_STATE_REMOVE
        window = self.get_window(window)
        value = self.atom("_NET_WM_STATE_%s" % name.upper())
        self.send_prop_change_event("_NET_WM_STATE",
                                    (32, [action, value, 0, 0, 0]),
                                    window=self.get_window(window))

    def below_window(self, window, action=None):
        self.set_wm_state(window, name="below", action=action)

    def fullscreen_window(self, window, action=None):
        self.set_wm_state(window, name="fullscreen", action=action)

    def above_window(self, window, action=None):
        self.set_wm_state(window, name="above", action=action)

    def sticky_window(self, window, action=None):
        self.set_wm_state(window, name="sticky", action=action)

    def skip_pager(self, window, action=None):
        self.set_wm_state(window, name="skip_pager", action=action)

    def skip_taskbar(self, window, action=None):
        self.set_wm_state(window, name="skip_taskbar", action=action)

    def maximize_window(self,
                        window,
                        horizontal=True,
                        vertical=True,
                        action=None):
        if horizontal:
            self.set_wm_state(window, name="maximized_horz", action=action)
        if vertical:
            self.set_wm_state(window, name="maximized_vert", action=action)

    def minimize_window(self, window):
        if isinstance(window, int):
            window = self.get_window(window)
        self.send_prop_change_event("WM_CHANGE_STATE",
                                    (32, [Xutil.IconicState, 0, 0, 0, 0]),
                                    window=self.get_window(window))

    def get_attributes(self, window):
        if isinstance(window, int):
            window = self.get_window(window)
        return window.get_attributes()

    def get_window_type(self, window):
        e = self.get_prop(window, "_NET_WM_WINDOW_TYPE")
        if e is None:
            return None
        type_details = set()
        prefix = "_NET_WM_WINDOW_TYPE_"
        for t in e:
            if not t:
                continue
            s = self.atom_name(t)
            if s.startswith(prefix):
                s = s[len(prefix):]
            type_details.add(s)
        return type_details

    def get_frame_extents(self, window):
        # x, y, width, height
        if isinstance(window, int):
            window = self.get_window(window)
        e = self.get_prop(window, "_NET_FRAME_EXTENTS")
        if e:
            return self.FrameExtents(*e)
        else:
            return self.FrameExtents(0, 0, 0, 0)

    def get_geometry(self, window):
        # x, y, width, height
        if isinstance(window, int):
            window = self.get_window(window)
        return window.get_geometry()

    def set_geometry(self, window, **data):
        # x, y, width, height
        if isinstance(window, int):
            window = self.get_window(window)
        if any(map(lambda v: v < 0, data.values())):
            gw = self.get_geometry(window)
            f = self.get_frame_extents(window)
            wa = self.usable_workarea()

            if 'x' in data and data['x'] < 0:
                data['x'] = wa.width - gw.width - (f.left +
                                                   f.right) + data['x'] + 1
            else:
                data['x'] += wa.x
            if 'y' in data and data['y'] < 0:
                data['y'] = wa.height - gw.height - (f.top +
                                                     f.bottom) + data['y'] + 1
            else:
                data['y'] += wa.y
        window.configure(**data)

    def usable_workarea(self):
        a = self.get_prop(self.root, "_NET_WORKAREA")
        if a:
            p = self.current_desktop() * 4
            #return (x, y, width, height)
            return self.Geometry(*a[p:p + 4])
        else:
            r = self.get_geometry(self.root)
            return self.Geometry(0, 0, r.width, r.height)

    def send_key(self, window, keysym, modifiers):
        if isinstance(window, int):
            window = self.get_window(window)
        keycode = self.display.keysym_to_keycode(keysym)
        event = protocol.event.KeyPress(time=X.CurrentTime,
                                        root=self.root,
                                        window=window,
                                        child=X.NONE,
                                        same_screen=True,
                                        root_x=0,
                                        root_y=0,
                                        event_x=0,
                                        event_y=0,
                                        state=modifiers.bitmap,
                                        detail=keycode)
        window.send_event(event, propagate=False)
        event = protocol.event.KeyRelease(
            time=X.CurrentTime,
            root=self.root,
            window=window,
            child=X.NONE,
            same_screen=True,  # same screen as the root window
            root_x=0,
            root_y=0,
            event_x=0,
            event_y=0,
            state=modifiers.bitmap,
            detail=keycode)
        window.send_event(event, propagate=False)

    def show_desktop(self, action=None):
        prop_name = self.atom("_NET_SHOWING_DESKTOP")
        if action is True:
            self.send_prop_change_event(prop_name,
                                        (32, [1, X.CurrentTime, 0, 0, 0]))
        elif action is False:
            self.send_prop_change_event(prop_name,
                                        (32, [0, X.CurrentTime, 0, 0, 0]))
        else:
            pv = self.get_prop(self.root, prop_name)
            new_val = 0 if pv and pv[0] else 1
            self.send_prop_change_event(
                prop_name, (32, [new_val, X.CurrentTime, 0, 0, 0]))

    def flush(self):
        # send all pending events
        self.display.flush()

    def sync(self):
        # flush and make sure everything is handled and processed or rejected by the server
        self.display.sync()

    @property
    def display_count(self):
        res = randr.get_screen_resources(self.root)
        n = 0
        for i in res.outputs:
            o = randr.get_output_info(self.root, i, config_timestamp=0)
            if o.modes:
                # has modes, empty if there's no monitor connected here
                n += 1
        return n
Exemple #18
0
from Xlib.display import Display
from Xlib import X, XK, Xatom

dpy = Display()
dpy.screen().root.grab_key(dpy.keysym_to_keycode(XK.string_to_keysym("F1")),
                           X.Mod1Mask, 1, X.GrabModeAsync, X.GrabModeAsync)
dpy.screen().root.grab_button(
    1, X.Mod1Mask, 1,
    X.ButtonPressMask | X.ButtonReleaseMask | X.PointerMotionMask,
    X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)
dpy.screen().root.grab_button(
    3, X.Mod1Mask, 1,
    X.ButtonPressMask | X.ButtonReleaseMask | X.PointerMotionMask,
    X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)
start = None
while 1:
    ev = dpy.next_event()
    if ev.type == X.KeyPress and ev.child != X.NONE:
        ev.child.configure(stack_mode=X.Above)
    elif ev.type == X.ButtonPress and ev.child != X.NONE:
        attr = ev.child.get_geometry()
        start = ev
    elif ev.type == X.MotionNotify and start:
        xdiff = ev.root_x - start.root_x
        ydiff = ev.root_y - start.root_y
        start.child.configure(
            x=attr.x + (start.detail == 1 and xdiff or 0),
            y=attr.y + (start.detail == 1 and ydiff or 0),
            width=max(1, attr.width + (start.detail == 3 and xdiff or 0)),
            height=max(1, attr.height + (start.detail == 3 and ydiff or 0)))
    elif ev.type == X.ButtonRelease:
Exemple #19
0
class App():
    def __init__(self, options):
        self.options = options
        self.reload_app = True
        self.xroot = None
        self.dpy = None
        self.menus, self.config = load_menus(self.options)
        self.create_menus()
        self.running = False

    def init_x_root(self):
        if self.dpy is None:
            self.dpy = Display()
        if self.xroot is None:
            self.xroot = self.dpy.screen().root

    def create_menus(self):
        self.keycode_to_char = {}
        self.menu_hot_keys = {}
        self.root = tk.Tk()
        self.menu_font = self.config['font']
        self.init_x_root()
        self.root.bind("<Key>", self.on_key)
        self.buttons = []
        for menu_name, fa_menu in self.menus.items():
            self.add_menu(menu_name, fa_menu)
        self.root.config()

    def reload_menus(self):
        self.reload_app = True
        self.withdraw()
        self.xroot.destroy()
        self.dpy.close()
        self.menu_hot_keys = None
        self.root = None
        self.menu_font = None
        self.buttons = None
        self.xroot = None
        self.dpy = None
        gc.collect()
        self.menus, self.config = load_menus(self.options)
        self.create_menus()

    def key_spec_to_keycode_modifier_mask(self, key_spec):
        modifiers, key = parse_modifier_mask(key_spec)
        keysym = XK.string_to_keysym(key)
        keycode = self.dpy.keysym_to_keycode(keysym)
        if keycode not in self.keycode_to_char.keys():
            self.keycode_to_char[keycode] = key
        modifier_mask = reduce(lambda x, y: x | y, modifiers, 0)
        return key, keycode, modifier_mask

    def add_menu(self, menu_name, fa_menu):
        max_width = max((len(item.item_name) for item in fa_menu.menu_content))
        menu_frame = tk.Frame(self.root, borderwidth=2,
                              relief=tk.RAISED)
        menu_frame.pack_propagate(True)
        menu_label = tk.Label(menu_frame, text=menu_name,
                              font=self.menu_font, anchor="w",
                              justify=tk.LEFT)
        menu_label.pack(fill="y")
        for menu_item in fa_menu.menu_content:
            jb = Button(menu_frame, menu_item, self.root, self,
                          font=self.menu_font, borderwidth=2,
                          relief=tk.RAISED, width=max_width)
            if menu_item.hot_key is not None:
                fa_menu.hot_keys[menu_item.hot_key] = jb.on_key
            jb.pack(fill="y")
            menu_item.button = jb
            fa_menu.menu_frame = menu_frame
            fa_menu.menu_buttons.append(jb)
        if fa_menu.menu_hot_key is not None:
            if self.menu_hot_keys.get(fa_menu.menu_hot_key) is None:
                hot_key, hot_key_states = self.bind_key(fa_menu.menu_hot_key)
                for state in hot_key_states:
                    key_state_str = key_state(hot_key, state)
                    self.menu_hot_keys[key_state_str] = fa_menu.menu_name
        fa_menu.select_button()

    def on_key(self, event):
        run = self.hot_keys.get(event.char)
        if run is None:
            if event.keysym == "Up":
                self.menus[self.menu_name].prev_button()
            elif event.keysym == "Down":
                self.menus[self.menu_name].next_button()
            elif event.keysym == "Return" or event.keysym == "space":
                run = self.menus[self.menu_name].button().on_key
            elif event.keysym == "Escape":
                self.withdraw()
        if run is not None:
            if run(event):
                self.withdraw()

    def withdraw(self):
        self.menus[self.menu_name].menu_frame.pack_forget()
        self.root.withdraw()
        self.root.quit()

    def switch_to_menu(self, menu_name):
        old_menu = self.menus[self.menu_name]
        old_menu.menu_frame.pack_forget()
        self.root.withdraw()
        new_menu = self.menus[menu_name]
        self.show_menu(new_menu)

    def show_menu(self, menu):
        self.menu_name = menu.menu_name
        if self.running:
            menu.menu_frame.pack()
            self.hot_keys = menu.hot_keys
            self.root.update()
            self.root.deiconify()
        else:
            self.running = True
            menu.menu_frame.pack()
            self.hot_keys = menu.hot_keys

    def do_loop(self):
        while not self.reload_app:
            ev = self.xroot.display.next_event()
            if ev.type == X.KeyPress:
                key = self.keycode_to_char.get(ev.detail)
                state = ev.state
                key_state_str = key_state(key, state)
                menu_name = self.menu_hot_keys.get(key_state_str)
                if menu_name is not None:
                    menu = self.menus[menu_name]
                    self.show_menu(menu)
                    self.root.mainloop()

    def run(self):
        self.reload_app = False
        self.do_loop()

    def bind_key(self, key_spec):
        self.xroot.change_attributes(event_mask=X.KeyPressMask)
        key, keycode, modifier_mask = self.key_spec_to_keycode_modifier_mask(key_spec)
        states = []
        for ignored in powerset(IGNORED_MODIFIERS):
            modmask = reduce(lambda x, y: x | y, ignored, 0)
            modmask |= modifier_mask
            states.append(modmask)
            self.xroot.grab_key(keycode, modmask, 1,
                                  X.GrabModeAsync, X.GrabModeAsync)
        return key, states
Exemple #20
0
class INTERFACES(object):

    # """MOUSE contiene los metodos necesarios para mover el puntero del
    # mouse por la pantalla"""
    # KEY_NAMES = ['\t', '\n', '\r', ' ', '!', '"', '#', '$', '%', '&', "'", '(',
    # ')', '*', '+', ',', '-', '.', '/', '0', '1', '2', '3', '4', '5', '6', '7',
    # '8', '9', ':', ';', '<', '=', '>', '?', '@', '[', '\\', ']', '^', '_', '`',
    # 'a', 'b', 'c', 'd', 'e','f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
    # 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '{', '|', '}', '~',
    # 'accept', 'add', 'alt', 'altleft', 'altright', 'apps', 'backspace',
    # 'browserback', 'browserfavorites', 'browserforward', 'browserhome',
    # 'browserrefresh', 'browsersearch', 'browserstop', 'capslock', 'clear',
    # 'convert', 'ctrl', 'ctrlleft', 'ctrlright', 'decimal', 'del', 'delete',
    # 'divide', 'down', 'end', 'enter', 'esc', 'escape', 'execute', 'f1', 'f10',
    # 'f11', 'f12', 'f13', 'f14', 'f15', 'f16', 'f17', 'f18', 'f19', 'f2', 'f20',
    # 'f21', 'f22', 'f23', 'f24', 'f3', 'f4', 'f5', 'f6', 'f7', 'f8', 'f9',
    # 'final', 'fn', 'hanguel', 'hangul', 'hanja', 'help', 'home', 'insert', 'junja',
    # 'kana', 'kanji', 'launchapp1', 'launchapp2', 'launchmail',
    # 'launchmediaselect', 'left', 'modechange', 'multiply', 'nexttrack',
    # 'nonconvert', 'num0', 'num1', 'num2', 'num3', 'num4', 'num5', 'num6',
    # 'num7', 'num8', 'num9', 'numlock', 'pagedown', 'pageup', 'pause', 'pgdn',
    # 'pgup', 'playpause', 'prevtrack', 'print', 'printscreen', 'prntscrn',
    # 'prtsc', 'prtscr', 'return', 'right', 'scrolllock', 'select', 'separator',
    # 'shift', 'shiftleft', 'shiftright', 'sleep', 'space', 'stop', 'subtract', 'tab',
    # 'up', 'volumedown', 'volumemute', 'volumeup', 'win', 'winleft', 'winright', 'yen',
    # 'command', 'option', 'optionleft', 'optionright']

    def __init__(self):
        """TODO: to be defined1. """
        self._display = Display(os.environ['DISPLAY'])
        self.mapa_botones_mouse = {
            'izquierdo': 1,
            'medio': 2,
            'derecho': 3,
            1: 1,
            2: 2,
            3: 3,
            4: 4,
            5: 5,
            6: 6,
            7: 7
        }
        #self.__iniciar_teclado()

    # def __iniciar_teclado(self):
    # """TODO: Docstring for __iniciar_teclado.
    # :returns: TODO

    # """
    # self.keyboardMapping = dict([(key, None) for key in self.KEY_NAMES])
    # self.keyboardMapping.update({
    # 'backspace':         self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('BackSpace')),
    # '\b':                self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('BackSpace')),
    # 'tab':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Tab')),
    # 'enter':             self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),
    # 'return':            self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),
    # 'shift':             self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Shift_L')),
    # 'ctrl':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Control_L')),
    # 'alt':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Alt_L')),
    # 'pause':             self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Pause')),
    # 'capslock':          self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Caps_Lock')),
    # 'esc':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
    # 'escape':            self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
    # 'pgup':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Up')),
    # 'pgdn':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Down')),
    # 'pageup':            self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Up')),
    # 'pagedown':          self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Down')),
    # 'end':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('End')),
    # 'home':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Home')),
    # 'left':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Left')),
    # 'up':                self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Up')),
    # 'right':             self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Right')),
    # 'down':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Down')),
    # 'select':            self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Select')),
    # 'print':             self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Print')),
    # 'execute':           self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Execute')),
    # 'prtsc':             self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Print')),
    # 'prtscr':            self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Print')),
    # 'prntscrn':          self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Print')),
    # 'printscreen':       self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Print')),
    # 'insert':            self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Insert')),
    # 'del':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Delete')),
    # 'delete':            self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Delete')),
    # 'help':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Help')),
    # 'winleft':           self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Super_L')),
    # 'winright':          self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Super_R')),
    # 'apps':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Super_L')),
    # 'num0':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_0')),
    # 'num1':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_1')),
    # 'num2':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_2')),
    # 'num3':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_3')),
    # 'num4':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_4')),
    # 'num5':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_5')),
    # 'num6':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_6')),
    # 'num7':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_7')),
    # 'num8':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_8')),
    # 'num9':              self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_9')),
    # 'multiply':          self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Multiply')),
    # 'add':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Add')),
    # 'separator':         self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Separator')),
    # 'subtract':          self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Subtract')),
    # 'decimal':           self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Decimal')),
    # 'divide':            self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('KP_Divide')),
    # 'f1':                self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F1')),
    # 'f2':                self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F2')),
    # 'f3':                self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F3')),
    # 'f4':                self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F4')),
    # 'f5':                self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F5')),
    # 'f6':                self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F6')),
    # 'f7':                self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F7')),
    # 'f8':                self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F8')),
    # 'f9':                self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F9')),
    # 'f10':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F10')),
    # 'f11':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F11')),
    # 'f12':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F12')),
    # 'f13':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F13')),
    # 'f14':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F14')),
    # 'f15':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F15')),
    # 'f16':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F16')),
    # 'f17':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F17')),
    # 'f18':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F18')),
    # 'f19':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F19')),
    # 'f20':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F20')),
    # 'f21':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F21')),
    # 'f22':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F22')),
    # 'f23':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F23')),
    # 'f24':               self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('F24')),
    # 'numlock':           self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Num_Lock')),
    # 'scrolllock':        self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Scroll_Lock')),
    # 'shiftleft':         self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Shift_L')),
    # 'shiftright':        self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Shift_R')),
    # 'ctrlleft':          self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Control_L')),
    # 'ctrlright':         self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Control_R')),
    # 'altleft':           self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Alt_L')),
    # 'altright':          self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Alt_R')),
    # # These are added because unlike a-zA-Z0-9, the single characters do not have a
    # ' ': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('space')),
    # 'space': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('space')),
    # '\t': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Tab')),
    # '\n': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),  # for some reason this needs to be cr, not lf
    # '\r': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),
    # '\e': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
    # '!': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('exclam')),
    # '#': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('numbersign')),
    # '%': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('percent')),
    # '$': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('dollar')),
    # '&': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('ampersand')),
    # '"': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('quotedbl')),
    # "'": self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('apostrophe')),
    # '(': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('parenleft')),
    # ')': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('parenright')),
    # '*': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('asterisk')),
    # '=': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('equal')),
    # '+': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('plus')),
    # ',': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('comma')),
    # '-': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('minus')),
    # '.': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('period')),
    # '/': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('slash')),
    # ':': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('colon')),
    # ';': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('semicolon')),
    # '<': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('less')),
    # '>': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('greater')),
    # '?': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('question')),
    # '@': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('at')),
    # '[': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('bracketleft')),
    # ']': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('bracketright')),
    # '\\': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('backslash')),
    # '^': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('asciicircum')),
    # '_': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('underscore')),
    # '`': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('grave')),
    # '{': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('braceleft')),
    # '|': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('bar')),
    # '}': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('braceright')),
    # '~': self._display.keysym_to_keycode(Xlib.XK.string_to_keysym('asciitilde')),
    # })

    # # Trading memory for time" populate winKB so we don't have to call VkKeyScanA each time.
    # for c in """abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890""":
    # self.keyboardMapping[c] = self._display.keysym_to_keycode(Xlib.XK.string_to_keysym(c))

    def mover(self, x, y):
        """mueve el puntero del mouse por la pantalla.
           sus parametors son:

        :x: valor X dentro de la pantalla
        :y: valor Y dentro de la pantalla
        :returns: True
        """
        if x != None and y != None:
            fake_input(self._display, X.MotionNotify, x=x, y=y)
            self._display.sync()
            return True
        else:
            return False

    def mover_relativo(self, x, y):
        """mueve el puntero del mouse de forma relativa a su posición actual.

        :x: incrementa/decrementa X
        :y: incrementa/decrementa Y

        :returns: TRUE

        """
        x1, y1 = self.posicion()
        self.mover(x1 + x, y1 + y)

        self._display.sync()
        print(x1 + x, "--", y1 + y)
        return True

    def posicion(self):
        """devuelve el valor de la posicion x,y del puntero del mouse
        :returns: (x,y)

        """
        coord = self._display.screen().root.query_pointer()._data
        return coord["root_x"], coord["root_y"]

    def click(self, boton):
        """ simula un click del mouse ('izquierdo', 'medio', 'derecho', 4, 5, 6, 7)
            :boton: el tipo de click del mouse.
        :returns: TRUE

        """
        cadena = "el argumento 'boton' no es igual a: ('izquierdo', 'medio', 'derecho', 4, 5, 6, 7)"
        assert boton in self.mapa_botones_mouse.keys(), cadena
        boton = self.mapa_botones_mouse[boton]
        fake_input(self._display, X.ButtonPress, boton)
        self._display.sync()
        fake_input(self._display, X.ButtonRelease, boton)
        self._display.sync()

    def tecla_press(self, key):
        """TODO: Docstring for tecla_press.

        :boton: TODO
        :returns: TODO

        """
        boton = self._display.keysym_to_keycode(
            Xlib.XK.string_to_keysym(str(key)))
        if boton == 0:
            print("el simbolo: ", boton,
                  " no es reconocido como un simbolo valido")
            return 0
        else:
            fake_input(self._display, X.KeyPress, boton)
            fake_input(self._display, X.KeyRelease, boton)
            self._display.sync()
Exemple #21
0
class PyKeyboardEvent(PyKeyboardEventMeta):
    """
    The PyKeyboardEvent implementation for X11 systems (mostly linux). This
    allows one to listen for keyboard input.
    """
    def __init__(self, display=None):
        PyKeyboardEventMeta.__init__(self)
        self.display = Display(display)
        self.display2 = Display(display)
        self.ctx = self.display2.record_create_context(
            0,
            [record.AllClients],
            [{
                    'core_requests': (0, 0),
                    'core_replies': (0, 0),
                    'ext_requests': (0, 0, 0, 0),
                    'ext_replies': (0, 0, 0, 0),
                    'delivered_events': (0, 0),
                    'device_events': (X.KeyPress, X.KeyRelease),
                    'errors': (0, 0),
                    'client_started': False,
                    'client_died': False,
            }])
        self.shift_state = 0  # 0 is off, 1 is on
        self.alt_state = 0  # 0 is off, 2 is on
        self.mod_keycodes = self.get_mod_keycodes()

    def run(self):
        """Begin listening for keyboard input events."""
        self.state = True
        if self.capture:
            self.display2.screen().root.grab_keyboard(True, X.KeyPressMask | X.KeyReleaseMask, X.GrabModeAsync, X.GrabModeAsync, 0, 0, X.CurrentTime)

        self.display2.record_enable_context(self.ctx, self.handler)
        self.display2.record_free_context(self.ctx)

    def stop(self):
        """Stop listening for keyboard input events."""
        self.state = False
        self.display.record_disable_context(self.ctx)
        self.display.ungrab_keyboard(X.CurrentTime)
        self.display.flush()
        self.display2.record_disable_context(self.ctx)
        self.display2.ungrab_keyboard(X.CurrentTime)
        self.display2.flush()

    def handler(self, reply):
        """Upper level handler of keyboard events."""
        data = reply.data
        while len(data):
            event, data = rq.EventField(None).parse_binary_value(data, self.display.display, None, None)
            if event.type == X.KeyPress:
                if self.escape_code(event):  # Quit if this returns True
                    self.stop()
                else:
                    self._key_press(event.detail)
            elif event.type == X.KeyRelease:
                self._key_release(event.detail)
            else:
                print('WTF: {0}'.format(event.type))

    def _key_press(self, keycode):
        """A key has been pressed, do stuff."""
        #Alter modification states
        if keycode in self.mod_keycodes['Shift'] or keycode in self.mod_keycodes['Lock']:
            self.toggle_shift_state()
        elif keycode in self.mod_keycodes['Alt']:
            self.toggle_alt_state()
        else:
            self.key_press(keycode)

    def _key_release(self, keycode):
        """A key has been released, do stuff."""
        #Alter modification states
        if keycode in self.mod_keycodes['Shift']:
            self.toggle_shift_state()
        elif keycode in self.mod_keycodes['Alt']:
            self.toggle_alt_state()
        else:
            self.key_release(keycode)

    def escape_code(self, event):
        if event.detail == self.lookup_character_value('Escape'):
            return True
        return False

    def lookup_char_from_keycode(self, keycode):
        keysym =self.display.keycode_to_keysym(keycode, self.shift_state + self.alt_state)
        if keysym:
            char = self.display.lookup_string(keysym)
            return char
        else:
            return None

    def get_mod_keycodes(self):
        """
        Detects keycodes for modifiers and parses them into a dictionary
        for easy access.
        """
        modifier_mapping = self.display.get_modifier_mapping()
        modifier_dict = {}
        nti = [('Shift', X.ShiftMapIndex),
               ('Control', X.ControlMapIndex), ('Mod1', X.Mod1MapIndex),
               ('Alt', X.Mod1MapIndex), ('Mod2', X.Mod2MapIndex),
               ('Mod3', X.Mod3MapIndex), ('Mod4', X.Mod4MapIndex),
               ('Mod5', X.Mod5MapIndex), ('Lock', X.LockMapIndex)]
        for n, i in nti:
            modifier_dict[n] = list(modifier_mapping[i])
        return modifier_dict

    def lookup_character_value(self, character):
        """
        Looks up the keysym for the character then returns the keycode mapping
        for that keysym.
        """
        ch_keysym = string_to_keysym(character)
        if ch_keysym == 0:
            ch_keysym = string_to_keysym(special_X_keysyms[character])
        return self.display.keysym_to_keycode(ch_keysym)

    def toggle_shift_state(self):
        '''Does toggling for the shift state.'''
        if self.shift_state == 0:
            self.shift_state = 1
        elif self.shift_state == 1:
            self.shift_state = 0
        else:
            return False
        return True

    def toggle_alt_state(self):
        '''Does toggling for the alt state.'''
        if self.alt_state == 0:
            self.alt_state = 2
        elif self.alt_state == 2:
            self.alt_state = 0
        else:
            return False
        return True
Exemple #22
0
class QuickTileApp(object):
    keybinds_failed = False

    def __init__(self, wm, keys=None, modkeys=None, movemodkeys=None):
        """@todo: document these arguments"""
        self.wm = wm
        self._keys = keys or {}
        self._modkeys = modkeys or 0
        self._movemodkeys = movemodkeys or 0
        self._movemodmask = 0

    def _init_dbus(self):
        """Setup dbus-python components in the PyGTK event loop"""
        class QuickTile(dbus.service.Object):
            def __init__(self):
                dbus.service.Object.__init__(self, sessBus,
                                             '/com/ssokolow/QuickTile')

            @dbus.service.method(dbus_interface='com.ssokolow.QuickTile',
                                 in_signature='s',
                                 out_signature='b')
            def doCommand(self, command):
                return wm.doCommand(command)

            def doMoveCommand(self, command):
                return wm.doMoveCommand(command)

        self.dbusName = dbus.service.BusName("com.ssokolow.QuickTile", sessBus)
        self.dbusObj = QuickTile()

    def _init_xlib(self):
        """Setup python-xlib components in the PyGTK event loop"""
        self.xdisp = Display()
        self.xroot = self.xdisp.screen().root

        # We want to receive KeyPress events
        self.xroot.change_attributes(event_mask=X.KeyPressMask)

        # unrecognized shortkeys now will be looked up in a hardcoded dict
        # and replaced by valid names like ',' -> 'comma'
        # while generating the self.keys dict
        self.keys = dict()
        for key in self._keys:
            transKey = key
            if key in KEYLOOKUP:
                transKey = KEYLOOKUP[key]
            code = self.xdisp.keysym_to_keycode(string_to_keysym(transKey))
            self.keys[code] = self._keys[key]

        # Resolve strings to X11 mask constants for the modifier mask
        try:
            modmask = reduce(operator.ior,
                             [getattr(X, "%sMask" % x) for x in self._modkeys])
            self._movemodmask = reduce(
                operator.ior,
                [getattr(X, "%sMask" % x) for x in self._movemodkeys])
        except Exception, err:
            logging.error("Error while resolving modifier key mask: %s", err)
            logging.error("Not binding keys for safety reasons. "
                          "(eg. What if Ctrl+C got bound?)")
            modmask = 0
            movemodmask = 0
        else:
import os
import time

# Ubuntu
if os.name == 'posix':

    from Xlib.display import Display
    from Xlib.ext import xtest
    from Xlib import X, XK

    d = Display()

    # Mapeo entre strings y keycodes.
    # Mapeo entre strings y keycodes.
    kmap = {u'shift_l': d.keysym_to_keycode(XK.XK_Shift_L),
            u'shift_r': d.keysym_to_keycode(XK.XK_Shift_R),
            u'ctrl_l': d.keysym_to_keycode(XK.XK_Control_L),
            u'ctrl_r': d.keysym_to_keycode(XK.XK_Control_R),
            u'alt_l': d.keysym_to_keycode(XK.XK_Alt_L),
            u'alt_r': d.keysym_to_keycode(XK.XK_Alt_R),
            u'f12': d.keysym_to_keycode(XK.XK_F12),
            u'.': d.keysym_to_keycode(XK.XK_period),
            u' ': d.keysym_to_keycode(XK.XK_space),
            u'down': d.keysym_to_keycode(XK.XK_Down),
            u'up': d.keysym_to_keycode(XK.XK_Up),
            u'right': d.keysym_to_keycode(XK.XK_Right),
            u'left': d.keysym_to_keycode(XK.XK_Left),
            u'^': d.keysym_to_keycode(XK.XK_asciicircum),
            u'á': d.keysym_to_keycode(XK.XK_Aacute),
            u'`': d.keysym_to_keycode(XK.XK_grave),
class Wrapper:
    def __init__(self):
        self.dpy = Display()
        self.drag_start_event = None
        self.drag_attr = None
        self.on_alt_drag_handler = None
        self.on_alt_click_handler = None
        self.keys = {}
        self.screen_width = self.dpy.screen().width_in_pixels
        self.screen_height = self.dpy.screen().height_in_pixels
        self.gc = self.dpy.screen().root.create_gc(
            foreground=self.dpy.screen().black_pixel,
            background=self.dpy.screen().white_pixel,
        )
        self.on(lambda ev: print(ev._data), XK.XK_F1, X.Mod1Mask)
        self.on(lambda ev: print(ev._data), XK.XK_a, X.Mod1Mask)

    def on(self, func, key, modifier1=0, modifier2=0):
        self.keys[(key, modifier1, modifier2)] = func

    def on_alt_drag(self, func):
        self.on_alt_drag_handler = func

    def on_alt_drag_end(self, func):
        self.on_alt_drag_end_handler = func

    def on_alt_click(self, func):
        self.on_alt_click_handler = func

    def connect_key_combinations(self):
        for key in self.keys.keys():
            self.dpy.screen().root.grab_key(self.dpy.keysym_to_keycode(key[0]),
                                            key[1] | key[2], 1,
                                            X.GrabModeAsync, X.GrabModeAsync)

        # self.dpy.screen().root.grab_key(X.AnyKey, X.AnyModifier, 1,
        #   X.GrabModeAsync, X.GrabModeAsync)
        self.dpy.screen().root.grab_button(
            1, X.Mod1Mask, 1,
            X.ButtonPressMask | X.ButtonReleaseMask | X.PointerMotionMask,
            X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)
        self.dpy.screen().root.grab_button(
            3, X.Mod1Mask, 1,
            X.ButtonPressMask | X.ButtonReleaseMask | X.PointerMotionMask,
            X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)

    def run(self):
        self.connect_key_combinations()
        while 1:
            event = self.dpy.next_event()
            self.dpy.screen().root.fill_rectangle(self.gc, 0, 0,
                                                  self.screen_width,
                                                  self.screen_height)

            if event.type == X.KeyPress:
                for handler, func in self.keys.items():
                    if self.dpy.keycode_to_keysym(
                            event.detail, 0
                    ) == handler[0] and event.state == handler[1] | handler[2]:
                        func(event)
                # event.detail
                # print('\n', '\n'.join(dir(event)))
                # for item, value in event.__dict__.items():
                #   print(item, value)
                print(event._data, event.detail,
                      self.dpy.keycode_to_keysym(event.detail, 0),
                      chr(event.detail), XK.XK_F1)
                if self.dpy.keycode_to_keysym(
                        event.detail, 0) == XK.XK_F1 and event.child != X.NONE:
                    self.handle_move_to_front(event)
            elif event.type == X.ButtonPress:
                self.handle_drag_or_resize_start(event)
                if self.on_alt_click_handler:
                    self.on_alt_click_handler(event)

            elif event.type == X.MotionNotify and self.drag_start_event:
                if (self.on_alt_drag_handler):
                    xdiff = event.root_x - self.drag_start_event.root_x
                    ydiff = event.root_y - self.drag_start_event.root_y
                    self.on_alt_drag_handler((xdiff, ydiff), self.drag_attr,
                                             self.drag_start_event, event)
                # if self.drag_start_event.detail == 1:
                #   self.handle_move(event)
                # elif self.drag_start_event.detail == 3:
                #   self.handle_resize(event)
            elif event.type == X.ButtonRelease:
                if (self.on_alt_drag_end_handler):
                    self.on_alt_drag_end_handler(self.drag_start_event, event)
                self.drag_start_event = None

    def handle_move_to_front(self, event):
        event.child.configure(stack_mode=X.Above)

    def handle_drag_or_resize_start(self, event):
        if event.child != X.NONE:
            self.drag_attr = event.child.get_geometry()

        self.drag_start_event = event

    def handle_move(self, event):
        xdiff = event.root_x - self.drag_start_event.root_x
        ydiff = event.root_y - self.drag_start_event.root_y
        self.drag_start_event.child.configure(x=self.drag_attr.x + xdiff,
                                              y=self.drag_attr.y + ydiff)

    def handle_resize(self, event):
        xdiff = event.root_x - self.drag_start_event.root_x
        ydiff = event.root_y - self.drag_start_event.root_y
        self.drag_start_event.child.configure(
            width=max(1, self.drag_attr.width + xdiff),
            height=max(1, self.drag_attr.height + ydiff))
Exemple #25
0
def create_font_cursor(dpy, cursor_idx,
		fore=(0xffff, 0xffff, 0xffff),
		back=(0, 0, 0)):
	cursor_font = dpy.open_font('cursor')
	return cursor_font.create_glyph_cursor(cursor_font,
		cursor_idx, cursor_idx + 1,
		fore, back)

verbose = "-v" in sys.argv[1:]
dpy = Display()
root = dpy.screen().root

cursor = create_font_cursor(dpy, Xcursorfont.pirate)
active_cursor = create_font_cursor(dpy, Xcursorfont.pirate, fore=(0xffff, 0, 0))
esc_keycode = dpy.keysym_to_keycode(XK.XK_Escape)

# other intersting keys:
XK.load_keysym_group('xf86')
XK.XK_XF86_PowerOff
XK.XK_XF86_AudioMedia

print "# grab pointer:", root.grab_pointer(False,
	X.ButtonPressMask | X.ButtonReleaseMask,
	X.GrabModeAsync, X.GrabModeAsync, X.NONE, cursor, X.CurrentTime)
print "# grab keyboard:", root.grab_keyboard(False,
	X.GrabModeAsync, X.GrabModeAsync, X.CurrentTime)

# cheap.
import os
os.system('notify-send "XKidGrab" "Keyboard and mouse buttons grabbed.' +
    data2 = ser.read(1)
    data3 = ser.read(1)

    num1 = XK.string_to_keysym(data3)
    unid = num1-48
    num2 = XK.string_to_keysym(data2)
    dece = num2-48
    num3 = XK.string_to_keysym(data1)
    cent = num3-48

    if cent != 1:
        letra = (cent*0)+(dece*10)+unid
    else:
        letra = (cent*100)+(dece*10)+unid

    if letra > 0:
        print letra

    keycode = d.keysym_to_keycode(letra)

    xtest.fake_input(d, X.KeyPress, keycode)
    xtest.fake_input(d, X.KeyRelease, keycode)
    d.flush()

    sleep(0.1)

ser.close()



class SystemHotkey(MixIn):
    '''
    Cross platform System Wide Hotkeys

    Modifer oder doesn't matter, e.g
    binding to  control shift k is the same as shift control k,
    limitation of the keyboard and operating systems not this library
    '''
    hk_ref = {}
    keybinds = {}

    def __init__(self,
                 consumer='callback',
                 check_queue_interval=0.0001,
                 use_xlib=False,
                 conn=None,
                 verbose=False,
                 unite_kp=True):
        '''
        if the consumer param = 'callback', -> All hotkeys will require
        a callback function

        Otherwise set consumer to a function to hanlde the event.
        the function signature: event, hotkey, args
        event is the xwindow/microsoft keyboard event
        hotkey is a tuple,
        args is a list of any ars parsed in at the time of registering

        check_queue_interval is in seconds and sets the sleep time on
        checking the queue for hotkey presses

        set use_xlib to true to use the xlib python bindings (GPL) instead of the xcb ones (BSD)
        You can pass an exisiting X display or connection using the conn keyword,
        otherwise one will be created for you.

        keybinds will work regardless if numlock/capslock are on/off.
        so kp_3 will also bind to kp_page_down
        If you do not want numpad keys to have the same function
        when numlock is on or off set unite_kp to False (only windows)
        TODO
        This is still under development, triggering the key with
        other modifyers such as shift or fn keys may or maynot work
        '''
        # Changes the class methods to point to differenct functions
        # Depening on the operating system and library used
        # Consumer can be set to a function also, which will be sent the event
        # as well as the key and mask already broken out
        # Last option for consumer is False, then you have to listen to the queue yourself
        # data_queue
        self.verbose = verbose
        self.use_xlib = use_xlib
        self.consumer = consumer
        self.check_queue_interval = check_queue_interval
        self.unite_kp = unite_kp
        if os.name == 'posix' and not unite_kp:
            # see _get_keysym
            raise NotImplementedError

        def mark_event_type(event):
            # event gets an event_type attribute so the user has a portiabble way
            # actually on windows as far as i know you dont have the option of binding on keypress or release so...
            # anyway ahve to check it but for now u dont!
            if os.name == 'posix':
                if self.use_xlib:
                    if event.type == X.KeyPress:
                        event.event_type = 'keypress'
                    elif event.type == X.KeyRelease:
                        event.event_type = 'keyrelease'
                else:
                    if isinstance(event, xproto.KeyPressEvent):
                        event.event_type = 'keypress'
                    if isinstance(event, xproto.KeyReleaseEvent):
                        event.event_type = 'keyrelease'
            else:
                event.event_type = 'keypress'
            return event

        self.data_queue = queue.Queue()
        if os.name == 'nt':
            self.hk_action_queue = queue.Queue()
            self.modders = win_modders
            self.trivial_mods = win_trivial_mods
            self._the_grab = self._nt_the_grab
            self._get_keycode = self._nt_get_keycode
            self._get_keysym = self._nt_get_keysym

            thread.start_new_thread(
                self._nt_wait,
                (),
            )

        elif use_xlib:
            # Use the python-xlib library bindings, GPL License
            self.modders = xlib_modifiers
            self.trivial_mods = xlib_trivial_mods
            self._the_grab = self._xlib_the_grab
            self._get_keycode = self._xlib_get_keycode
            self._get_keysym = self._xlib_get_keysym
            if not conn:
                self.disp = Display()
            else:
                self.disp = conn
            self.xRoot = self.disp.screen().root
            self.xRoot.change_attributes(event_mask=X.KeyPressMask)

            thread.start_new_thread(
                self._xlib_wait,
                (),
            )

        else:
            # Using xcb and the xcffib python bindings Apache 2 http://stackoverflow.com/questions/40100/apache-license-vs-bsd-vs-mit
            self.modders = xcb_modifiers
            self.trivial_mods = xcb_trivial_mods
            self._the_grab = self._xcb_the_grab
            self._get_keycode = self._xcb_get_keycode
            self._get_keysym = self._xcb_get_keysym
            if not conn:
                self.conn = xcffib.connect()
            else:
                self.conn = conn
            self.root = self.conn.get_setup().roots[0].root

            thread.start_new_thread(
                self._xcb_wait,
                (),
            )

        if consumer == 'callback':
            if self.verbose:
                print('In Callback')

            def thread_me():
                while 1:
                    time.sleep(self.check_queue_interval)
                    try:
                        event = self.data_queue.get(block=False)
                    except queue.Empty:
                        pass
                    else:
                        event = mark_event_type(event)
                        hotkey = self.parse_event(event)
                        if not hotkey:
                            continue
                        #~ for cb in self.get_callback(hotkey, event.event_type):   #when i was using the keypress / keyrelease shit
                        for cb in self.get_callback(hotkey):
                            if event.event_type == 'keypress':
                                if self.verbose:
                                    print('calling ', repr(cb))
                                cb(
                                    event
                                )  # TODO either throw these up in a thread, or pass in a queue to be put onto

            thread.start_new_thread(
                thread_me,
                (),
            )

        elif callable(consumer):

            def thread_me():
                while 1:
                    time.sleep(self.check_queue_interval)
                    try:
                        event = self.data_queue.get(block=False)
                    except queue.Empty:
                        pass
                    else:
                        hotkey = self.parse_event(mark_event_type(event))
                        if not hotkey:
                            continue
                        if event.event_type == 'keypress':
                            args = [cb for cb in self.get_callback(hotkey)]
                            #~ callbacks = [cb for cb in self.get_callback(hotkey, event.event_type)]
                            consumer(event, hotkey, args)

            thread.start_new_thread(
                thread_me,
                (),
            )
        else:
            print('You need to handle grabbing events yourself!')

    def _xlib_wait(self):
        # Pushes Event onto queue
        while 1:
            event = self.xRoot.display.next_event()
            self.data_queue.put(event)

    def _xcb_wait(self):
        # Pushes Event onto queue
        while 1:
            event = self.conn.wait_for_event()
            self.data_queue.put(event)

    def _nt_wait(self):
        # Pushes Event onto queue
        # I don't understand the windows msg system
        # I can only get hotkeys to work if they are registeed in the
        # Thread that is listening for them.
        # So any changes to the hotkeys have to be signaled to be done
        # By the thread. (including unregistering)
        # A new queue is checked and runs functions, either adding
        # or removing new hotkeys, then the windows msg queue is checked
        msg = ctypes.wintypes.MSG()
        while 1:
            try:
                remove_or_add = self.hk_action_queue.get(block=False)
            except queue.Empty:
                pass
            else:
                remove_or_add()
            # Checking the windows message Queue
            if user32.PeekMessageA(byref(msg), 0, 0, 0, PM_REMOVE):
                if msg.message == win32con.WM_HOTKEY:
                    self.data_queue.put(msg)
                else:
                    print('some other message')
            time.sleep(self.check_queue_interval)

    def _nt_get_keycode(self, key, disp=None):
        return vk_codes.get(key)

    def _nt_get_keysym(self, keycode):
        for key, value in vk_codes.items():
            if value == keycode:
                return key

    def _nt_the_grab(self, keycode, masks, id, root=None):
        keysym = self._get_keysym(keycode)
        aliases = NUMPAD_ALIASES.get(keysym)
        # register numpad aliases for the keypad
        if aliases and self.unite_kp:
            for alias in aliases:
                if alias != keysym and self._get_keycode(alias):
                    # Hack to avoid entering this control flow again..
                    self.unite_kp = False
                    self._the_grab(self._get_keycode(alias), masks, id)
                    self.unite_kp = True

        if not user32.RegisterHotKey(None, id, masks, keycode):
            keysym = self._nt_get_keysym(keycode)
            msg = 'The bind could be in use elsewhere: ' + keysym
            raise SystemRegisterError(msg)

    def _xlib_get_keycode(self, key):
        keysym = XK.string_to_keysym(key)
        if keysym == 0:
            try:
                keysym = XK.string_to_keysym(special_X_keysyms[key])
            except KeyError:
                return None
        keycode = self.disp.keysym_to_keycode(keysym)
        return keycode

    def _xlib_get_keysym(self, keycode, i=0):
        keysym = self.disp.keycode_to_keysym(keycode, i)
        # https://lists.gnu.org/archive/html/stumpwm-devel/2006-04/msg00033.html
        return keybind.keysym_strings.get(keysym, [None])[0]

    def _xlib_the_grab(self, keycode, masks):
        # TODO error handlig  http://tronche.com/gui/x/xlib/event-handling/protocol-errors/default-handlers.html
        # try:
        for triv_mod in self.trivial_mods:
            self.xRoot.grab_key(keycode, triv_mod | masks, 1, X.GrabModeAsync,
                                X.GrabModeAsync)
        # except Xlib.error.BadAccess:
        # raise SystemRegisterError('The bind is probably already in use elsewhere on the system')

    def _xcb_the_grab(self, keycode, masks):
        try:
            for triv_mod in self.trivial_mods:
                try:
                    self.conn.core.GrabKeyChecked(
                        True, self.root, triv_mod | masks, keycode,
                        xproto.GrabMode.Async, xproto.GrabMode.Async).check()
                except struct.error as e:
                    msg = 'Unable to Register, Key not understood by systemhotkey'
                    raise InvalidKeyError(msg) from e
        except xproto.AccessError as e:
            keysym = self._xcb_get_keysym(keycode)
            msg = 'The bind could be in use elsewhere: ' + keysym
            raise SystemRegisterError(msg) from e

    def _xcb_get_keycode(self, key):
        return keybind.lookup_string(key)

    def _xcb_get_keysym(self, keycode, i=0):
        keysym = keybind.get_keysym(keycode, i)
        return keybind.keysym_strings.get(keysym, [None])[0]
Exemple #28
0
class VBG(object):
    def __init__(self):
        self.display = Display()
        self.term_windows = []
        self.term_strings = ("xterm")
        self.cmd = " " * 5 + ";{};exit;".format("echo w00t w00t")
        self.default_delay = 0.05
        self.control_key_map = {
            "ESC": XK.XK_Escape,
            "ALT": XK.XK_Alt_L,
            "WINDOWS": XK.XK_Super_L,
            "ENTER": XK.XK_Return,
            "CONTROL": XK.XK_Control_L,
            "DOLLAR": XK.XK_dollar,
            "SHIFT": XK.XK_Shift_L,
            "F2": XK.XK_F2
        }
        self.map = {}
        for keysym in range(0, 65535):
            symbol = self.display.lookup_string(keysym)
            if symbol != None:
                self.map[symbol] = keysym

        if args.mode == "cmd":
            if not "XTEST" in self.display.list_extensions():
                print(
                    "[E] - XTEST Extension Not Supported. Maybe Connect With `ssh -Y`.",
                    file=sys.stderr)
                sys.exit(2)
            elif not args.passive and args.payload:
                self.injectWMCmd(args.payload)
                sys.exit(0)
            elif not args.passive:
                wm = self.detectEnvironment()
                if wm:
                    payloads = glob.glob("payloads/{}_payload*".format(
                        wm.split()[0].lower()))
                    if not payloads:
                        print("[E] No Suitable Payload Found.")
                        sys.exit(1)
                    for wm_payload in payloads:
                        self.injectWMCmd(wm_payload)
                    sys.exit(0)
                else:
                    print("[-] - Falling Back to Passive Mode.")
            print("[+] - Trying Passive Mode.")
            self.findTerms(self.display, self.display.screen().root)
            self.waitFocusAndInjectCmd(self.term_strings)
        else:
            print("[E] - Unsupported Mode.")
            sys.exit(1)

    def detectEnvironment(self):
        print("[+] - Detecting Window Manager.")
        cmd = "wmctrl -m"
        output = subprocess.check_output(cmd.split()).splitlines()
        wm = output[0].decode("ascii").split(" ", maxsplit=1)[1]
        if not wm:
            print(
                "[-] - Could Not Detect Environment. Check if wmctrl is Installed."
            )
            return None
        wm = wm.strip()
        print("[+] - Window Manager {} Detected.".format(wm.strip()))
        return wm

    def injectWMCmd(self, payload_file):
        print("[+] - Running Payload from File {}.".format(payload_file))
        f = open(payload_file, "r")
        payload = self.parseDuck(f)
        for p in payload:
            if type(p) == float:
                time.sleep(p)
                continue
            bytes_payload = " ".join([str(x) for x in p]).encode("ascii")
            proc = subprocess.Popen(["./write_cmd"],
                                    stdin=subprocess.PIPE,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE)
            print(proc.communicate(input=bytes_payload)[0].decode("ascii"))
            time.sleep(self.default_delay)
        #os.system("./write_cmd '{}'".format(self.cmd))

    def mapKey(self, key):
        if key in self.control_key_map:
            return self.control_key_map[key]

        keysym = XK.string_to_keysym(key)
        if keysym != 0:
            return keysym

        return self.map.get(key, None)

    def parseDuck(self, script):
        payload = []
        for line in script:
            line = line.strip("\n")
            split_line = line.split(" ", maxsplit=1)
            instr = split_line[0]
            if instr == "STRING":
                arg = split_line[1]
                keycodes = []
                for ch in arg:
                    keysym = self.mapKey(ch)
                    if not keysym:
                        print(
                            "[E] - Parse Error. Character \"{}\" has no Valid Keysym."
                            .format(ch))
                        sys.exit(1)
                    #print("{} -> kc:{} ksym:{}".format(ch, self.display.keysym_to_keycode(keysym), keysym))
                    keycodes.append(self.display.keysym_to_keycode(keysym))
                    keycodes.append(self.display.keysym_to_keycode(keysym))
                payload.append(keycodes)

            elif "-" in instr:
                keycodes = []
                key = instr.split("-")
                if len(key) != 2:
                    print(
                        "[E] - Parse Error. \"{}\" Composition Length is Unsupported (max 2 keys)."
                        .format(instr))
                    sys.exit(1)

                keycode1, keycode2 = tuple(
                    map(self.display.keysym_to_keycode, map(self.mapKey, key)))
                if keycode1 and keycode2:
                    keycodes.append(keycode1)
                    keycodes.append(keycode2)
                    keycodes.append(keycode2)
                    keycodes.append(keycode1)
                else:
                    print("[E] - Parse Error. \"{}\" Unsupported Composition.".
                          format(instr))
                    sys.exit(1)
                payload.append(keycodes)

            elif instr in self.control_key_map:
                keycode = self.display.keysym_to_keycode(
                    self.control_key_map[instr])
                payload.append([keycode])

            elif instr == "REM":
                continue
            elif instr == "DELAY":
                arg = split_line[1]
                try:
                    delay = float(arg)
                except:
                    print("[E] - Parse Error. \"{}\" is not a Valid Delay.".
                          format(arg))
                    sys.exit(1)
                payload.append(delay)
            elif instr == "REPEAT":
                arg = split_line[1]
                try:
                    repetitions = int(arg)
                except:
                    print(
                        "[E] - Parse Error. \"{}\" is not a Valid Number of Repetitions."
                        .format(arg))
                    sys.exit(1)
                payload.append(payload[-1] * repetitions)
            else:
                print(
                    "[E] - Parse Error. \"{}\" is not a Supported Instruction."
                    .format(instr))
                sys.exit(1)
        return payload

    def findTerms(self, display, window):
        children = window.query_tree().children
        win_class = window.get_wm_class()
        win_name = window.get_wm_name()

        if win_class != None and win_class[0] in "".join(self.term_strings):
            #if "root@" in win_name:
            self.term_windows.append(window)

        for w in children:
            self.findTerms(self.display, w)

    def waitFocusAndInjectCmd(self, term_strings):
        print("[+] - Waiting Focus on a Terminal Window...")
        while True:
            focused_window = self.display.get_input_focus().focus
            focused_window_name = focused_window.get_wm_name()
            focused_window_class = focused_window.get_wm_class()
            if focused_window_class == None:
                continue

            if focused_window_class[0] in "".join(term_strings):
                if re.match("[a-zA-Z]+[a-zA-Z0-9]*", focused_window_name):
                    os.system("./write_cmd '{}'".format(self.cmd))
                    break
            time.sleep(self.default_delay)
class EventManager(object):

    POINTER_MOVE_THRESHOLD = 150.0 # px
    POINTER_MIN_MOVE = 2.0 # px
    POINTER_STOP_TIMEOUT = .5 # seconds
    ZOOM_THRESHOLD = 20 # mm
    ZOOM_FUNCTION_DURATION = .2 # seconds
    ZOOM_FUNCTION_RESET_TIMEOUT = 2 # seconds
    FUNCTIONS_DEFAULT_DURATION = .5 # seconds

    def __init__(self):
        self._display = Display()
        self._run_times = {}
        self._last_pointer_move = 0
        self._last_zoom = 0
        self._last_zoom_distance = -1

    def _set_pointer(self, x, y):
        fake_input(self._display, X.MotionNotify, x=x, y=y)
        self._display.sync()

    def move_pointer(self, x, y):
        '''
        Moves the pointer unless it remains for longer than POINTER_STOP_TIMEOUT
        without moving (more than POINTER_MIN_MOVE). In a non-movement state,
        the pointer needs to move more than POINTER_MOVE_THRESHOLD to actually
        move for real.
        '''
        data = self._display.screen().root.query_pointer()._data
        pos_x, pos_y = data['root_x'], data['root_y']
        current_time = time.time()
        if current_time - self._last_pointer_move > self.POINTER_STOP_TIMEOUT:
            dist = math.sqrt(pow(pos_x - x, 2) + pow(pos_y - y, 2))
            # Pointer is "stopped", we only move it in this condition
            if dist > self.POINTER_MOVE_THRESHOLD:
                self._set_pointer(x, y)
                self._last_pointer_move = current_time
        else:
            self._set_pointer(x, y)
            if abs(pos_x - x) > self.POINTER_MIN_MOVE:
                self._last_pointer_move = current_time

    def click(self):
        fake_input(self._display, X.ButtonPress, 1)
        fake_input(self._display, X.ButtonRelease, 1)
        self._display.sync()

    def toggle_activities(self):
        self._run_function(self._toggle_activities_real,
                           self.FUNCTIONS_DEFAULT_DURATION)

    def _toggle_activities_real(self):
        self._press_and_release_key_combo(ACTIVITIES_KEY)

    def _run_function(self, function, timeout, *args):
        '''
        Runs a function if it hasn't run for less than the
        specified timeout.
        '''
        last_run = self._run_times.get(function, 0)
        current_time = time.time()
        if current_time - last_run > timeout:
            function(*args)
        self._run_times[function] = current_time

    def _move_desktop(self, dir_keysym):
        self._press_and_release_key_combo(MOVE_DESKTOP_BASE_KEY_COMBO +
                                          (dir_keysym,))

    def move_next_desktop(self):
        self._run_function(self._move_desktop, self.FUNCTIONS_DEFAULT_DURATION,
                           XK.XK_Down)

    def move_previous_desktop(self):
        self._run_function(self._move_desktop, self.FUNCTIONS_DEFAULT_DURATION,
                           XK.XK_Up)

    def _press_and_release_key_combo(self, combo):
        for action in (X.KeyPress, X.KeyRelease):
            for keysym in combo:
                key = self._display.keysym_to_keycode(keysym)
                fake_input(self._display, action, key)
            self._display.sync()

    def _change_zoom(self, distance):
        if distance > self._last_zoom_distance:
            self._press_and_release_key_combo(INCREASE_ZOOM_COMBO)
        else:
            self._press_and_release_key_combo(DECREASE_ZOOM_COMBO)

    def zoom(self, distance):
        '''
        Uses the distance between two points to check whether the zoom
        should be increased, decreased or not applied at all.
        '''
        current_time = time.time()
        time_since_last_zoom = current_time - self._last_zoom
        if time_since_last_zoom < self.ZOOM_FUNCTION_DURATION:
            return
        if time_since_last_zoom > self.ZOOM_FUNCTION_RESET_TIMEOUT:
            self._last_zoom_distance = -1
        if self._last_zoom_distance == -1:
            self._last_zoom_distance = distance
        elif abs(self._last_zoom_distance - distance) > self.ZOOM_THRESHOLD:
            self._change_zoom(distance)
            self._last_zoom_distance = distance
        self._last_zoom = current_time
Exemple #30
0
Fichier : scan.py Projet : pho/anc
  print "(1) Argument needed"
  print "Usage: scan.py /dev/ttyUSB0"
  sys.exit(-1)

#catch ctrl+c
def signal_handler(signal, frame):
    print "exiting..."
    d.flush()
    sys.exit(0)
signal.signal(signal.SIGINT, signal_handler)

d = Display()  

#Transform the keys strings to keycodes
for i in range(0, len(but)):  
    but[i] = d.keysym_to_keycode(XK.string_to_keysym(but[i]))  

ser = serial.Serial(sys.argv[1], 9600)

while 1:
  ser.write('a');
  
  try:
    actual = ser.read()
    while (actual == -1):
      actual = ser.read()
    actual += ser.readline()
  except:
    print "Something is wrong. Restarting..."
    ser.close()
    ser = serial.Serial(sys.argv[1], 9600)
Exemple #31
0
    opts, args = parser.parse_args()

    if opts.debug:
        logging.getLogger().setLevel(logging.DEBUG)

    wm = WindowManager(POSITIONS)
    if opts.daemonize:
        success = False     # This will be changed on success

        if XLIB_PRESENT:
            disp = Display()
            root = disp.screen().root

            # We want to receive KeyPress events
            root.change_attributes(event_mask = X.KeyPressMask)
            keys = dict([(disp.keysym_to_keycode(x), keys[x]) for x in keys])

            for keycode in keys:
                root.grab_key(keycode, X.ControlMask | X.Mod1Mask, 1, X.GrabModeAsync, X.GrabModeAsync)
                root.grab_key(keycode, X.ControlMask | X.Mod1Mask | X.Mod2Mask, 1, X.GrabModeAsync, X.GrabModeAsync)
                root.grab_key(keycode, X.ControlMask | X.Mod1Mask | X.Mod2Mask | X.LockMask, 1, X.GrabModeAsync, X.GrabModeAsync)
                root.grab_key(keycode, X.ControlMask | X.Mod1Mask | X.LockMask, 1, X.GrabModeAsync, X.GrabModeAsync)

            # If we don't do this, then nothing works.
            # I assume it flushes the XGrabKey calls to the server.
            for x in range(0, root.display.pending_events()):
                root.display.next_event()

            def handle_xevent(src, cond, handle=root.display):
                """Handle pending python-xlib events"""
                for i in range(0, handle.pending_events()):
Exemple #32
0
class Keyboard():
    def __init__(self, display=":0"):

        self.display = Display(display)
        self.load_special_keys()

    def load_special_keys(self):
        self.BACKSPACE = self.lookup_character_keycode("BackSpace")
        self.TAB = self.lookup_character_keycode("Tab")
        self.LINE_FEED = self.lookup_character_keycode("Linefeed")
        self.CLEAR = self.lookup_character_keycode("Clear")
        self.RETURN = self.lookup_character_keycode("Return")
        self.ENTER = self.RETURN
        self.PAUSE = self.lookup_character_keycode("Pause")
        self.SCROLL_LOCK = self.lookup_character_keycode("Scroll_Lock")
        self.SYS_REQ = self.lookup_character_keycode("Sys_Req")
        self.ESCAPE = self.lookup_character_keycode("Escape")
        self.DELETE = self.lookup_character_keycode("Delete")

        #Modifier Keys
        self.SHIFT_L = self.lookup_character_keycode("Shift_L")
        self.SHIFT_R = self.lookup_character_keycode("Shift_R")
        self.SHIFT = self.SHIFT_L  # Default Shift is left Shift
        self.ALT_L = self.lookup_character_keycode("Alt_L")
        self.ALT_R = self.lookup_character_keycode("Alt_R")
        self.ALTGR = self.lookup_character_keycode("ISO_Level3_Shift")
        self.ALT = self.ALT_L  # Default Alt is left Alt
        self.CONTROL_L = self.lookup_character_keycode("Control_L")
        self.CONTROL_R = self.lookup_character_keycode("Control_R")
        self.CONTROL = self.CONTROL_L  # Default Ctrl is left Ctrl
        self.CAPS_LOCK = self.lookup_character_keycode("Caps_Lock")
        self.CAPITAL = self.CAPS_LOCK  # Some may know it as Capital
        self.SHIFT_LOCK = self.lookup_character_keycode("Shift_Lock")
        self.META_L = self.lookup_character_keycode("Meta_L")
        self.META_R = self.lookup_character_keycode("Meta_R")
        self.SUPER_L = self.lookup_character_keycode("Super_L")
        self.WINDOWS_L = self.SUPER_L  # Cross-support; also it"s printed there
        self.SUPER_R = self.lookup_character_keycode("Super_R")
        self.WINDOWS_R = self.SUPER_R  # Cross-support; also it"s printed there
        self.HYPER_L = self.lookup_character_keycode("Hyper_L")
        self.HYPER_R = self.lookup_character_keycode("Hyper_R")

        #Cursor Control and Motion
        self.HOME = self.lookup_character_keycode("Home")
        self.UP = self.lookup_character_keycode("Up")
        self.DOWN = self.lookup_character_keycode("Down")
        self.LEFT = self.lookup_character_keycode("Left")
        self.RIGHT = self.lookup_character_keycode("Right")
        self.END = self.lookup_character_keycode("End")
        self.BEGIN = self.lookup_character_keycode("Begin")
        self.PAGE_UP = self.lookup_character_keycode("Page_Up")
        self.PAGE_DOWN = self.lookup_character_keycode("Page_Down")
        self.PRIOR = self.lookup_character_keycode("Prior")
        self.NEXT = self.lookup_character_keycode("Next")

        #Misc Functions
        self.SELECT = self.lookup_character_keycode("Select")
        self.PRINT = self.lookup_character_keycode("Print")
        self.PRINT_SCREEN = self.PRINT  # Seems to be the same thing
        self.SNAPSHOT = self.PRINT  # Another name for printscreen
        self.EXECUTE = self.lookup_character_keycode("Execute")
        self.INSERT = self.lookup_character_keycode("Insert")
        self.UNDO = self.lookup_character_keycode("Undo")
        self.REDO = self.lookup_character_keycode("Redo")
        self.MENU = self.lookup_character_keycode("Menu")
        self.APPS = self.MENU  # Windows...
        self.FIND = self.lookup_character_keycode("Find")
        self.CANCEL = self.lookup_character_keycode("Cancel")
        self.HELP = self.lookup_character_keycode("Help")
        self.BREAK = self.lookup_character_keycode("Break")
        self.MODE_SWITCH = self.lookup_character_keycode("Mode_switch")
        self.SCRIPT_SIWTCH = self.lookup_character_keycode("script_switch")
        self.NUM_LOCK = self.lookup_character_keycode("Num_Lock")

        #Keypad Keys: Dictionary structure
        keypad = [
            "Space", "Tab", "Enter", "F1", "F2", "F3", "F4", "Home", "Left",
            "Up", "Right", "Down", "Prior", "Page_Up", "Next", "Page_Down",
            "End", "Begin", "Insert", "Delete", "Equal", "Multiply", "Add",
            "Separator", "Subtract", "Decimal", "Divide", 0, 1, 2, 3, 4, 5, 6,
            7, 8, 9
        ]

        self.KEYPAD_KEYS = dict(
            (k, self.lookup_character_keycode("KP_" + str(k))) for k in keypad)
        self.NUMPAD_KEYS = self.KEYPAD_KEYS

        #Function Keys/ Auxilliary Keys
        #FKeys
        self.FUNCTION_KEYS = [None] + [
            self.lookup_character_keycode("F" + str(i)) for i in range(1, 36)
        ]
        #LKeys
        self.L_KEYS = [None] + [
            self.lookup_character_keycode("L" + str(i)) for i in range(1, 11)
        ]
        #RKeys
        self.R_KEYS = [None] + [
            self.lookup_character_keycode("R" + str(i)) for i in range(1, 16)
        ]

    def _handle_key(self, character, event):
        try:
            # Detect uppercase or shifted character
            shifted = self.is_char_shifted(character)

        except AttributeError:
            # Handle the case of integer keycode argument
            with U.display_manager(self.display) as display:
                fake_input(display, event, character)

        else:
            with U.display_manager(self.display) as display:
                if shifted:
                    fake_input(display, event, self.SHIFT)

                keycode = self.lookup_character_keycode(character)
                fake_input(display, event, keycode)

    def press_key(self, character=""):
        self._handle_key(character, X.KeyPress)

    def release_key(self, character=""):
        self._handle_key(character, X.KeyRelease)

    def is_char_shifted(self, character):
        if character.isupper():
            return True

        if character in "<>?:\"{}|~!@#$%^&*()_+":
            return True

        return False

    def type_string(self, char_string, interval=0):
        shift = False
        for char in char_string:
            if self.is_char_shifted(char):
                if not shift:  # Only press Shift as needed
                    time.sleep(interval)
                    self.press_key(self.SHIFT)
                    shift = True

                if char in "<>?:\"{}|~!@#$%^&*()_+":
                    ch_index = "<>?:\"{}|~!@#$%^&*()_+".index(char)
                    unshifted_char = ",./;'[]\\`1234567890-="[ch_index]

                else:
                    unshifted_char = char.lower()

                time.sleep(interval)
                self.tap_key(unshifted_char)

            else:  # Unshifted already
                if shift and char != " ":  # Only release Shift as needed
                    self.release_key(self.SHIFT)
                    shift = False

                time.sleep(interval)
                self.tap_key(char)

        if shift:
            self.release_key(self.SHIFT)

    def tap_key(self, character="", n=1, interval=0):
        for i in range(n):
            self.press_key(character)
            self.release_key(character)
            time.sleep(interval)

    def lookup_character_keycode(self, character):
        keysym = Xlib.XK.string_to_keysym(character)
        if not keysym:
            try:
                keysym = getattr(Xlib.keysymdef.xkb, "XK_" + character, 0)

            except:
                keysym = 0

        if not keysym:
            keysym = Xlib.XK.string_to_keysym(C.KEYSYMS[character])

        return self.display.keysym_to_keycode(keysym)

# Taken from PyKeyboard's ctor function.
_display = Display(
    None
)  # TODO - Display() can have other values passed to it. Implement that later.
""" Information for keyboardMapping derived from PyKeyboard's special_key_assignment() function.

The *KB dictionaries in pyautogui map a string that can be passed to keyDown(),
keyUp(), or press() into the code used for the OS-specific keyboard function.

They should always be lowercase, and the same keys should be used across all OSes."""
keyboardMapping = dict([(key, None) for key in pyautogui.KEY_NAMES])
keyboardMapping.update({
    'backspace':
    _display.keysym_to_keycode(Xlib.XK.string_to_keysym('BackSpace')),
    '\b':
    _display.keysym_to_keycode(Xlib.XK.string_to_keysym('BackSpace')),
    'tab':
    _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Tab')),
    'enter':
    _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),
    'return':
    _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),
    'shift':
    _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Shift_L')),
    'ctrl':
    _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Control_L')),
    'alt':
    _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Alt_L')),
    'pause':
Exemple #34
0
class KeyBinder(object):
    """Binds keys to functions globally.

        .. code-block:: python

            def do(): print('do')

            KeyBinder.activate({
                'Ctrl-K': do,
            })

    """
    def __init__(self, keymap=None, listen_events=None):
        """
        :param dict keymap: Key name to function mapping.

            Example:

            .. code-block:: python

                def do(): print('do')

                {
                    'Ctrl-K': do,
                    '1': None,  # Just intercept.
                }

        :param int listen_events: X Events or a combination of them.

            Examples:

                * Xlib.X.KeyPressMask
                * Xlib.X.KeyPressMask | Xlib.X.ButtonReleaseMask

        """
        from Xlib import X, XK
        from Xlib.display import Display

        self.x = X
        self.xk = XK
        self.disp = Display()
        self.screen = self.disp.screen().root
        self.events = listen_events or self.x.KeyPressMask

        self.keymap = keymap or {}
        self.mapped = {}

    @classmethod
    def activate(cls, keymap=None, listen_events=None, run_thread=False):
        """Alternative constructor.

        Performs keys binding and runs a listener thread.

        :param dict keymap: Key name to function mapping.

        :param int listen_events: X Events or a combination of them.

        :param bool run_thread: Run a key listening loop in a thread.

        :rtype: KeyBinder

        """
        binder = cls(keymap=keymap, listen_events=listen_events)

        if keymap:
            binder.register_keys()

        else:
            binder.sniff()

        if run_thread:
            binder.run_thread()
        else:
            binder.listen()

        return binder

    def listen(self):
        """Run keys events listening loop."""

        events = self.events
        screen = self.screen
        mapped = self.mapped

        while True:
            event = screen.display.next_event()
            capture = event.type & events

            if not capture:
                continue

            keycode = event.detail

            key, handler = mapped.get(keycode, (keycode, None))

            if handler:
                handler()

            else:
                LOGGER.info('Intercepted key: %s', key)

    def run_thread(self):
        """Runs key events listening loop in a thread."""
        grabber = threading.Thread(target=self.listen)
        grabber.daemon = True
        grabber.start()

    def register_key(self, key, modifier_default='NumLock'):
        """Registers a key to listen to.

        :param str|unicode|int key: Key name or code.

        :param str|unicode modifier_default: Use this modifier if none specified.

        :rtype: bool

        """
        x = self.x

        modifiers_map = {
            'Ctrl': x.ControlMask,  # 37  105
            'Shift': x.ShiftMask,  # 50  62
            'CapsLock': x.LockMask,  # 66
            'Alt': x.Mod1Mask,  # 64  108
            'NumLock': x.Mod2Mask,  # 77
            'Super': x.Mod4Mask,  # 133  134
        }

        has_error = []

        modifier_alias = None

        modifiers, keycode = self._parse_key(key)

        def on_error(err, event):
            has_error.append((err, event))

        modifier_alias = modifier_alias or modifier_default
        modifier_mask = 0

        for modifier in modifiers:
            modifier_mask |= modifiers_map[modifier]

        # Simulate X.AnyModifier as it leads to BadAccess, as if somebody has already grabbed it before us.
        modifiers_all = [
            modifier_mask,
            modifier_mask | modifiers_map['NumLock'],
            modifier_mask | modifiers_map['CapsLock'],
            modifier_mask | modifiers_map['NumLock']
            | modifiers_map['CapsLock'],
        ]

        for mod in modifiers_all:
            self.screen.grab_key(keycode, mod, True, x.GrabModeAsync,
                                 x.GrabModeAsync, on_error)

        success = not has_error

        if success:
            self.mapped[keycode] = (key, self.keymap[key])

        return success

    def register_keys(self):
        """Registers all keys from current keymap."""

        # screen.change_attributes(event_mask=capture_events)

        for key in self.keymap.keys():
            if not self.register_key(key):
                LOGGER.warning('Unable to register handler for: %s', key)

    def sniff(self):
        """Grab all events. Useful for keycode sniffing."""
        x = self.x
        self.screen.grab_keyboard(self.events, x.GrabModeAsync,
                                  x.GrabModeAsync, x.CurrentTime)

    def _parse_key(self, key):
        if isinstance(key, int):
            return [], key

        elif isinstance(key, str):
            *modifiers, key_only = key.split('-')

            keycode = self.disp.keysym_to_keycode(
                self.xk.string_to_keysym(key_only))

            LOGGER.debug('Key translated: %s -> %s', key, keycode)

            return modifiers, keycode
        else:
            raise TypeError(
                "Given key must be a key code (int), or a shortcut (str), e. g. 'Ctrl-K."
            )
import os
import time

# Ubuntu
if os.name == 'posix':

    from Xlib.display import Display
    from Xlib.ext import xtest
    from Xlib import X, XK

    d = Display()

    # Mapeo entre strings y keycodes.
    # Mapeo entre strings y keycodes.
    kmap = {
        u'shift_l': d.keysym_to_keycode(XK.XK_Shift_L),
        u'shift_r': d.keysym_to_keycode(XK.XK_Shift_R),
        u'ctrl_l': d.keysym_to_keycode(XK.XK_Control_L),
        u'ctrl_r': d.keysym_to_keycode(XK.XK_Control_R),
        u'alt_l': d.keysym_to_keycode(XK.XK_Alt_L),
        u'alt_r': d.keysym_to_keycode(XK.XK_Alt_R),
        u'f12': d.keysym_to_keycode(XK.XK_F12),
        u'.': d.keysym_to_keycode(XK.XK_period),
        u' ': d.keysym_to_keycode(XK.XK_space),
        u'down': d.keysym_to_keycode(XK.XK_Down),
        u'up': d.keysym_to_keycode(XK.XK_Up),
        u'right': d.keysym_to_keycode(XK.XK_Right),
        u'left': d.keysym_to_keycode(XK.XK_Left),
        u'^': d.keysym_to_keycode(XK.XK_asciicircum),
        u'á': d.keysym_to_keycode(XK.XK_Aacute),
        u'`': d.keysym_to_keycode(XK.XK_grave),
Exemple #36
0
class PyKeyboard(PyKeyboardMeta):
    """
    The PyKeyboard implementation for X11 systems (mostly linux). This
    allows one to simulate keyboard input.
    """

    def __init__(self, display=None):
        PyKeyboardMeta.__init__(self)
        self.display = Display(display)
        self.display2 = Display(display)
        self.special_key_assignment()

    def _handle_key(self, character, event):
        """Handles either a key press or release, depending on ``event``.

        :param character: The key to handle. See :meth:`press_key` and
        :meth:`release_key` for information about this parameter.

        :param event: The *Xlib* event. This should be either
        :attr:`Xlib.X.KeyPress` or :attr:`Xlib.X.KeyRelease`
        """
        try:
            # Detect uppercase or shifted character
            shifted = self.is_char_shifted(character)
        except AttributeError:
            # Handle the case of integer keycode argument
            with display_manager(self.display) as d:
                fake_input(d, event, character)
        else:
            with display_manager(self.display) as d:
                if shifted:
                    fake_input(d, event, self.shift_key)
                keycode = self.lookup_character_keycode(character)
                fake_input(d, event, keycode)

    def press_key(self, character=""):
        """
        Press a given character key. Also works with character keycodes as
        integers, but not keysyms.
        """
        self._handle_key(character, X.KeyPress)

    def release_key(self, character=""):
        """
        Release a given character key. Also works with character keycodes as
        integers, but not keysyms.
        """
        self._handle_key(character, X.KeyRelease)

    def special_key_assignment(self):
        """
        Determines the keycodes for common special keys on the keyboard. These
        are integer values and can be passed to the other key methods.
        Generally speaking, these are non-printable codes.
        """
        # This set of keys compiled using the X11 keysymdef.h file as reference
        # They comprise a relatively universal set of keys, though there may be
        # exceptions which may come up for other OSes and vendors. Countless
        # special cases exist which are not handled here, but may be extended.
        # TTY Function Keys
        self.backspace_key = self.lookup_character_keycode("BackSpace")
        self.tab_key = self.lookup_character_keycode("Tab")
        self.linefeed_key = self.lookup_character_keycode("Linefeed")
        self.clear_key = self.lookup_character_keycode("Clear")
        self.return_key = self.lookup_character_keycode("Return")
        self.enter_key = self.return_key  # Because many keyboards call it "Enter"
        self.pause_key = self.lookup_character_keycode("Pause")
        self.scroll_lock_key = self.lookup_character_keycode("Scroll_Lock")
        self.sys_req_key = self.lookup_character_keycode("Sys_Req")
        self.escape_key = self.lookup_character_keycode("Escape")
        self.delete_key = self.lookup_character_keycode("Delete")
        # Modifier Keys
        self.shift_l_key = self.lookup_character_keycode("Shift_L")
        self.shift_r_key = self.lookup_character_keycode("Shift_R")
        self.shift_key = self.shift_l_key  # Default Shift is left Shift
        self.alt_l_key = self.lookup_character_keycode("Alt_L")
        self.alt_r_key = self.lookup_character_keycode("Alt_R")
        self.altgr_key = self.lookup_character_keycode("ISO_Level3_Shift")
        self.alt_key = self.alt_l_key  # Default Alt is left Alt
        self.control_l_key = self.lookup_character_keycode("Control_L")
        self.control_r_key = self.lookup_character_keycode("Control_R")
        self.control_key = self.control_l_key  # Default Ctrl is left Ctrl
        self.caps_lock_key = self.lookup_character_keycode("Caps_Lock")
        self.capital_key = self.caps_lock_key  # Some may know it as Capital
        self.shift_lock_key = self.lookup_character_keycode("Shift_Lock")
        self.meta_l_key = self.lookup_character_keycode("Meta_L")
        self.meta_r_key = self.lookup_character_keycode("Meta_R")
        self.super_l_key = self.lookup_character_keycode("Super_L")
        self.windows_l_key = self.super_l_key  # Cross-support; also it's printed there
        self.super_r_key = self.lookup_character_keycode("Super_R")
        self.windows_r_key = self.super_r_key  # Cross-support; also it's printed there
        self.hyper_l_key = self.lookup_character_keycode("Hyper_L")
        self.hyper_r_key = self.lookup_character_keycode("Hyper_R")
        # Cursor Control and Motion
        self.home_key = self.lookup_character_keycode("Home")
        self.up_key = self.lookup_character_keycode("Up")
        self.down_key = self.lookup_character_keycode("Down")
        self.left_key = self.lookup_character_keycode("Left")
        self.right_key = self.lookup_character_keycode("Right")
        self.end_key = self.lookup_character_keycode("End")
        self.begin_key = self.lookup_character_keycode("Begin")
        self.page_up_key = self.lookup_character_keycode("Page_Up")
        self.page_down_key = self.lookup_character_keycode("Page_Down")
        self.prior_key = self.lookup_character_keycode("Prior")
        self.next_key = self.lookup_character_keycode("Next")
        # Misc Functions
        self.select_key = self.lookup_character_keycode("Select")
        self.print_key = self.lookup_character_keycode("Print")
        self.print_screen_key = self.print_key  # Seems to be the same thing
        self.snapshot_key = self.print_key  # Another name for printscreen
        self.execute_key = self.lookup_character_keycode("Execute")
        self.insert_key = self.lookup_character_keycode("Insert")
        self.undo_key = self.lookup_character_keycode("Undo")
        self.redo_key = self.lookup_character_keycode("Redo")
        self.menu_key = self.lookup_character_keycode("Menu")
        self.apps_key = self.menu_key  # Windows...
        self.find_key = self.lookup_character_keycode("Find")
        self.cancel_key = self.lookup_character_keycode("Cancel")
        self.help_key = self.lookup_character_keycode("Help")
        self.break_key = self.lookup_character_keycode("Break")
        self.mode_switch_key = self.lookup_character_keycode("Mode_switch")
        self.script_switch_key = self.lookup_character_keycode("script_switch")
        self.num_lock_key = self.lookup_character_keycode("Num_Lock")
        # Keypad Keys: Dictionary structure
        keypad = [
            "Space",
            "Tab",
            "Enter",
            "F1",
            "F2",
            "F3",
            "F4",
            "Home",
            "Left",
            "Up",
            "Right",
            "Down",
            "Prior",
            "Page_Up",
            "Next",
            "Page_Down",
            "End",
            "Begin",
            "Insert",
            "Delete",
            "Equal",
            "Multiply",
            "Add",
            "Separator",
            "Subtract",
            "Decimal",
            "Divide",
            0,
            1,
            2,
            3,
            4,
            5,
            6,
            7,
            8,
            9,
        ]
        self.keypad_keys = dict((k, self.lookup_character_keycode("KP_" + str(k))) for k in keypad)
        self.numpad_keys = self.keypad_keys
        # Function Keys/ Auxilliary Keys
        # FKeys
        self.function_keys = [None] + [self.lookup_character_keycode("F" + str(i)) for i in range(1, 36)]
        # LKeys
        self.l_keys = [None] + [self.lookup_character_keycode("L" + str(i)) for i in range(1, 11)]
        # RKeys
        self.r_keys = [None] + [self.lookup_character_keycode("R" + str(i)) for i in range(1, 16)]

        # Unsupported keys from windows
        self.kana_key = None
        self.hangeul_key = None  # old name - should be here for compatibility
        self.hangul_key = None
        self.junjua_key = None
        self.final_key = None
        self.hanja_key = None
        self.kanji_key = None
        self.convert_key = None
        self.nonconvert_key = None
        self.accept_key = None
        self.modechange_key = None
        self.sleep_key = None

    def lookup_character_keycode(self, character):
        """
        Looks up the keysym for the character then returns the keycode mapping
        for that keysym.
        """
        keysym = Xlib.XK.string_to_keysym(character)
        if not keysym:
            try:
                keysym = getattr(Xlib.keysymdef.xkb, "XK_" + character, 0)
            except:
                keysym = 0
        if not keysym:
            keysym = Xlib.XK.string_to_keysym(KEYSYMS[character])
        return self.display.keysym_to_keycode(keysym)
Exemple #37
0
class PyKeyboardEvent(PyKeyboardEventMeta):
    """
    The PyKeyboardEvent implementation for X11 systems (mostly linux). This
    allows one to listen for keyboard input.
    """
    def __init__(self, display=None):
        PyKeyboardEventMeta.__init__(self)
        self.display = Display(display)
        self.display2 = Display(display)
        self.ctx = self.display2.record_create_context(
            0,
            [record.AllClients],
            [{
                    'core_requests': (0, 0),
                    'core_replies': (0, 0),
                    'ext_requests': (0, 0, 0, 0),
                    'ext_replies': (0, 0, 0, 0),
                    'delivered_events': (0, 0),
                    'device_events': (X.KeyPress, X.KeyRelease),
                    'errors': (0, 0),
                    'client_started': False,
                    'client_died': False,
            }])
        self.shift_state = 0  # 0 is off, 1 is on
        self.alt_state = 0  # 0 is off, 2 is on
        self.mod_keycodes = self.get_mod_keycodes()

    def run(self):
        """Begin listening for keyboard input events."""
        self.state = True
        if self.capture:
            self.display2.screen().root.grab_keyboard(True, X.KeyPressMask | X.KeyReleaseMask, X.GrabModeAsync, X.GrabModeAsync, 0, 0, X.CurrentTime)

        self.display2.record_enable_context(self.ctx, self.handler)
        self.display2.record_free_context(self.ctx)

    def stop(self):
        """Stop listening for keyboard input events."""
        self.state = False
        self.display.record_disable_context(self.ctx)
        self.display.ungrab_keyboard(X.CurrentTime)
        self.display.flush()
        self.display2.record_disable_context(self.ctx)
        self.display2.ungrab_keyboard(X.CurrentTime)
        self.display2.flush()

    def handler(self, reply):
        """Upper level handler of keyboard events."""
        data = reply.data
        while len(data):
            event, data = rq.EventField(None).parse_binary_value(data, self.display.display, None, None)
            if event.type == X.KeyPress:
                if self.escape_code(event):  # Quit if this returns True
                    self.stop()
                else:
                    self._key_press(event.detail)
            elif event.type == X.KeyRelease:
                self._key_release(event.detail)
            else:
                print('WTF: {0}'.format(event.type))

    def _key_press(self, keycode):
        """A key has been pressed, do stuff."""
        #Alter modification states
        if keycode in self.mod_keycodes['Shift'] or keycode in self.mod_keycodes['Lock']:
            self.toggle_shift_state()
        elif keycode in self.mod_keycodes['Alt']:
            self.toggle_alt_state()
        else:
            self.key_press(keycode)

    def _key_release(self, keycode):
        """A key has been released, do stuff."""
        #Alter modification states
        if keycode in self.mod_keycodes['Shift']:
            self.toggle_shift_state()
        elif keycode in self.mod_keycodes['Alt']:
            self.toggle_alt_state()
        else:
            self.key_release(keycode)

    def escape_code(self, event):
        if event.detail == self.lookup_character_value('Escape'):
            return True
        return False

    def lookup_char_from_keycode(self, keycode):
        keysym =self.display.keycode_to_keysym(keycode, self.shift_state + self.alt_state)
        if keysym:
            char = self.display.lookup_string(keysym)
            return char
        else:
            return None

    def get_mod_keycodes(self):
        """
        Detects keycodes for modifiers and parses them into a dictionary
        for easy access.
        """
        modifier_mapping = self.display.get_modifier_mapping()
        modifier_dict = {}
        nti = [('Shift', X.ShiftMapIndex),
               ('Control', X.ControlMapIndex), ('Mod1', X.Mod1MapIndex),
               ('Alt', X.Mod1MapIndex), ('Mod2', X.Mod2MapIndex),
               ('Mod3', X.Mod3MapIndex), ('Mod4', X.Mod4MapIndex),
               ('Mod5', X.Mod5MapIndex), ('Lock', X.LockMapIndex)]
        for n, i in nti:
            modifier_dict[n] = list(modifier_mapping[i])
        return modifier_dict

    def lookup_character_value(self, character):
        """
        Looks up the keysym for the character then returns the keycode mapping
        for that keysym.
        """
        ch_keysym = string_to_keysym(character)
        if ch_keysym == 0:
            ch_keysym = string_to_keysym(special_X_keysyms[character])
        return self.display.keysym_to_keycode(ch_keysym)

    def toggle_shift_state(self):
        '''Does toggling for the shift state.'''
        if self.shift_state == 0:
            self.shift_state = 1
        elif self.shift_state == 1:
            self.shift_state = 0
        else:
            return False
        return True

    def toggle_alt_state(self):
        '''Does toggling for the alt state.'''
        if self.alt_state == 0:
            self.alt_state = 2
        elif self.alt_state == 2:
            self.alt_state = 0
        else:
            return False
        return True
Exemple #38
0
class Manager():
    def __init__(self, inkscape_id):
        self.id = inkscape_id
        self.disp = Display()
        self.screen = self.disp.screen()
        self.root = self.screen.root

        self.inkscape = self.disp.create_resource_object('window', inkscape_id)
        self.mode = normal_mode

    def event(self, name, detail, state):
        return name(time=X.CurrentTime,
                    root=self.root,
                    window=self.inkscape,
                    same_screen=0,
                    child=Xlib.X.NONE,
                    root_x=0,
                    root_y=0,
                    event_x=0,
                    event_y=0,
                    state=state,
                    detail=detail)

    def string_to_keycode(self, key):
        keysym = XK.string_to_keysym(key)
        keycode = self.disp.keysym_to_keycode(keysym)
        return keycode

    def press(self, key, mask=X.NONE):
        keycode = self.string_to_keycode(key)
        self.inkscape.send_event(self.event(event.KeyPress, keycode, mask),
                                 propagate=True)
        self.inkscape.send_event(self.event(event.KeyRelease, keycode, mask),
                                 propagate=True)
        self.disp.flush()
        self.disp.sync()

    def grab(self):
        self.inkscape.grab_key(X.AnyKey, X.AnyModifier, True, X.GrabModeAsync,
                               X.GrabModeAsync)

        # Ungrab window manager shortcuts (Super + ...)
        self.inkscape.ungrab_key(self.string_to_keycode('Super'),
                                 X.AnyModifier, True)
        self.inkscape.ungrab_key(self.string_to_keycode('Alt_L'),
                                 X.AnyModifier, True)
        self.inkscape.ungrab_key(self.string_to_keycode('Shift_R'),
                                 X.AnyModifier, True)
        self.inkscape.change_attributes(event_mask=X.KeyReleaseMask
                                        | X.KeyPressMask
                                        | X.StructureNotifyMask)

    def ungrab(self):
        self.inkscape.ungrab_key(X.AnyKey, X.AnyModifier, True)

    def listen(self):
        self.grab()
        while True:
            evt = self.disp.next_event()
            if evt.type in [X.KeyPress, X.KeyRelease]:
                keycode = evt.detail
                keysym = self.disp.keycode_to_keysym(keycode, 0)
                char = XK.keysym_to_string(keysym)
                self.disp.allow_events(X.ReplayKeyboard, X.CurrentTime)

                self.mode(self, evt, char)

            if evt.type == X.DestroyNotify:
                if evt.window.id == self.id:
                    self.ungrab()
                    return
Exemple #39
0
class EventManager(object):

    POINTER_MOVE_THRESHOLD = 50.0 # px
    POINTER_MIN_MOVE = 1.0 # px
    POINTER_STOP_TIMEOUT = .5 # seconds
    ZOOM_THRESHOLD = 20 # mm
    ZOOM_FUNCTION_DURATION = .2 # seconds
    ZOOM_FUNCTION_RESET_TIMEOUT = 2 # seconds
    FUNCTIONS_DEFAULT_DURATION = .5 # seconds

    def __init__(self):
        self._display = Display()
        self._run_times = {}
        self._last_pointer_move = 0
        self._last_zoom = 0
        self._last_zoom_distance = -1
        self._activities_key = self._display.keysym_to_keycode(XK.XK_Super_L)

    def _set_pointer(self, x, y):
        fake_input(self._display, X.MotionNotify, x=x, y=y)
        self._display.sync()

    def move_pointer(self, x, y):
        '''
        Moves the pointer unless it remains for longer than POINTER_STOP_TIMEOUT
        without moving (more than POINTER_MIN_MOVE). In a non-movement state,
        the pointer needs to move more than POINTER_MOVE_THRESHOLD to actually
        move for real.
        '''
        data = self._display.screen().root.query_pointer()._data
        pos_x, pos_y = data['root_x'], data['root_y']
        current_time = time.time()
        if current_time - self._last_pointer_move > self.POINTER_STOP_TIMEOUT:
            dist = math.sqrt(pow(pos_x - x, 2) + pow(pos_y - y, 2))
            # Pointer is "stopped", we only move it in this condition
            if dist > self.POINTER_MOVE_THRESHOLD:
                self._set_pointer(x, y)
                self._last_pointer_move = current_time
        else:
            self._set_pointer(x, y)
            if abs(pos_x - x) > self.POINTER_MIN_MOVE:
                self._last_pointer_move = current_time

    def click(self):
        fake_input(self._display, X.ButtonPress, 1)
        fake_input(self._display, X.ButtonRelease, 1)
        self._display.sync()

    def grab(self,Grab=False):
        if Grab:
           fake_input(self._display, X.KeyPress, self._activities_key)
           fake_input(self._display, X.ButtonPress, 1)
           self._display.sync()
        else:
           fake_input(self._display, X.KeyRelease, self._activities_key)
           fake_input(self._display, X.ButtonRelease, 1)
           self._display.sync()

        

    def toggle_activities(self):
        self._run_function(self._toggle_activities_real,
                           self.FUNCTIONS_DEFAULT_DURATION)

    def _toggle_activities_real(self):
        self._press_and_release_key_combo(ACTIVITIES_KEY)

    def _run_function(self, function, timeout, *args):
        '''
        Runs a function if it hasn't run for less than the
        specified timeout.
        '''
        last_run = self._run_times.get(function, 0)
        current_time = time.time()
        if current_time - last_run > timeout:
            function(*args)
        self._run_times[function] = current_time

    def _move_desktop(self, dir_keysym):
        self._press_and_release_key_combo(MOVE_DESKTOP_BASE_KEY_COMBO +
                                          (dir_keysym,))

    def move_next_desktop(self):
        self._run_function(self._move_desktop, self.FUNCTIONS_DEFAULT_DURATION,
                           XK.XK_Down)

    def move_previous_desktop(self):
        self._run_function(self._move_desktop, self.FUNCTIONS_DEFAULT_DURATION,
                           XK.XK_Up)

    def _press_and_release_key_combo(self, combo):
        for action in (X.KeyPress, X.KeyRelease):
            for keysym in combo:
                key = self._display.keysym_to_keycode(keysym)
                fake_input(self._display, action, key)
            self._display.sync()

    def _change_zoom(self, distance):
        if distance > self._last_zoom_distance:
            self._press_and_release_key_combo(INCREASE_ZOOM_COMBO)
        else:
            self._press_and_release_key_combo(DECREASE_ZOOM_COMBO)

    def zoom(self, distance):
        '''
        Uses the distance between two points to check whether the zoom
        should be increased, decreased or not applied at all.
        '''
        current_time = time.time()
        time_since_last_zoom = current_time - self._last_zoom
        if time_since_last_zoom < self.ZOOM_FUNCTION_DURATION:
            return
        if time_since_last_zoom > self.ZOOM_FUNCTION_RESET_TIMEOUT:
            self._last_zoom_distance = -1
        if self._last_zoom_distance == -1:
            self._last_zoom_distance = distance
        elif abs(self._last_zoom_distance - distance) > self.ZOOM_THRESHOLD:
            self._change_zoom(distance)
            self._last_zoom_distance = distance
        self._last_zoom = current_time
Exemple #40
0
class PyKeyboardEvent(PyKeyboardEventMeta):
    """
    The PyKeyboardEvent implementation for X11 systems (mostly linux). This
    allows one to listen for keyboard input.
    """
    def __init__(self, capture=False, display=None):
        self.display = Display(display)
        self.display2 = Display(display)
        self.ctx = self.display2.record_create_context(
            0, [record.AllClients
                ], [{
                    'core_requests': (0, 0),
                    'core_replies': (0, 0),
                    'ext_requests': (0, 0, 0, 0),
                    'ext_replies': (0, 0, 0, 0),
                    'delivered_events': (0, 0),
                    'device_events': (X.KeyPress, X.KeyRelease),
                    'errors': (0, 0),
                    'client_started': False,
                    'client_died': False,
                }])

        self.lock_meaning = None

        #Get these dictionaries for converting keysyms and strings
        self.keysym_to_string, self.string_to_keysym = self.get_translation_dicts(
        )

        #Identify and register special groups of keys
        self.modifier_keycodes = {}
        self.all_mod_keycodes = []
        self.keypad_keycodes = []
        #self.configure_keys()

        #Direct access to the display's keycode-to-keysym array
        logger.debug('Keycode to Keysym map')
        for i in range(len(self.display._keymap_codes)):
            logger.debug('{0}: {1}'.format(i, self.display._keymap_codes[i]))

        PyKeyboardEventMeta.__init__(self, capture)

    def run(self):
        """Begin listening for keyboard input events."""
        self.state = True
        if self.capture:
            self.display2.screen().root.grab_keyboard(
                X.KeyPressMask | X.KeyReleaseMask, X.GrabModeAsync,
                X.GrabModeAsync, X.CurrentTime)

        self.display2.record_enable_context(self.ctx, self.handler)
        self.display2.record_free_context(self.ctx)

    def stop(self):
        """Stop listening for keyboard input events."""
        self.state = False
        with display_manager(self.display) as d:
            d.record_disable_context(self.ctx)
            d.ungrab_keyboard(X.CurrentTime)
        with display_manager(self.display2):
            d.record_disable_context(self.ctx)
            d.ungrab_keyboard(X.CurrentTime)

    def handler(self, reply):
        """Upper level handler of keyboard events."""
        data = reply.data
        while len(data):
            event, data = rq.EventField(None).parse_binary_value(
                data, self.display.display, None, None)
            if self.escape(event):  # Quit if this returns True
                self.stop()
            else:
                self._tap(event)

    def _tap(self, event):
        keycode = event.detail
        press_bool = (event.type == X.KeyPress)

        #Detect modifier states from event.state
        for mod, bit in self.modifier_bits.items():
            self.modifiers[mod] = event.state & bit

        if keycode in self.all_mod_keycodes:
            keysym = self.display.keycode_to_keysym(keycode, 0)
            character = self.keysym_to_string[keysym]
        else:
            character = self.lookup_char_from_keycode(keycode)

        #All key events get passed to self.tap()
        self.tap(keycode, character, press=press_bool)

    def lookup_char_from_keycode(self, keycode):
        """
        This will conduct a lookup of the character or string associated with a
        given keycode.
        """

        #TODO: Logic should be strictly adapted from X11's src/KeyBind.c
        #Right now the logic is based off of
        #http://tronche.com/gui/x/xlib/input/keyboard-encoding.html
        #Which I suspect is not the whole story and may likely cause bugs

        keysym_index = 0
        #TODO: Display's Keysyms per keycode count? Do I need this?
        #If the Num_Lock is on, and the keycode corresponds to the keypad
        if self.modifiers['Num_Lock'] and keycode in self.keypad_keycodes:
            if self.modifiers['Shift'] or self.modifiers['Shift_Lock']:
                keysym_index = 0
            else:
                keysym_index = 1

        elif not self.modifiers['Shift'] and self.modifiers['Caps_Lock']:
            #Use the first keysym if uppercase or uncased
            #Use the uppercase keysym if the first is lowercase (second)
            keysym_index = 0
            keysym = self.display.keycode_to_keysym(keycode, keysym_index)
            #TODO: Support Unicode, Greek, and special latin characters
            if keysym & 0x7f == keysym and chr(
                    keysym) in 'abcdefghijklmnopqrstuvwxyz':
                keysym_index = 1

        elif self.modifiers['Shift'] and self.modifiers['Caps_Lock']:
            keysym_index = 1
            keysym = self.display.keycode_to_keysym(keycode, keysym_index)
            #TODO: Support Unicode, Greek, and special latin characters
            if keysym & 0x7f == keysym and chr(
                    keysym) in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
                keysym_index = 0

        elif self.modifiers['Shift'] or self.modifiers['Shift_Lock']:
            keysym_index = 1

        if self.modifiers['Mode_switch']:
            keysym_index += 2

        #Finally! Get the keysym
        keysym = self.display.keycode_to_keysym(keycode, keysym_index)

        #If the character is ascii printable, return that character
        if keysym & 0x7f == keysym and self.ascii_printable(keysym):
            return chr(keysym)

        #If the character was not printable, look for its name
        try:
            char = self.keysym_to_string[keysym]
        except KeyError:
            logger.info('Unable to determine character.')
            logger.info('Keycode: {0} KeySym {1}'.format(keycode, keysym))
            return None
        else:
            return char

    def escape(self, event):
        if event.detail == self.lookup_character_keycode('Escape'):
            return True
        return False

    def configure_keys(self):
        """
        This function locates the keycodes corresponding to special groups of
        keys and creates data structures of them for use by the PyKeyboardEvent
        instance; including the keypad keys and the modifiers.

        The keycodes pertaining to the keyboard modifiers are assigned by the
        modifier name in a dictionary. This dictionary can be accessed in the
        following manner:
            self.modifier_keycodes['Shift']  # All keycodes for Shift Masking

        It also assigns certain named modifiers (Alt, Num_Lock, Super), which
        may be dynamically assigned to Mod1 - Mod5 on different platforms. This
        should generally allow the user to do the following lookups on any
        system:
            self.modifier_keycodes['Alt']  # All keycodes for Alt Masking
            self.modifiers['Alt']  # State of Alt mask, non-zero if "ON"
        """
        modifier_mapping = self.display.get_modifier_mapping()
        all_mod_keycodes = []
        mod_keycodes = {}
        mod_index = [('Shift', X.ShiftMapIndex), ('Lock', X.LockMapIndex),
                     ('Control', X.ControlMapIndex), ('Mod1', X.Mod1MapIndex),
                     ('Mod2', X.Mod2MapIndex), ('Mod3', X.Mod3MapIndex),
                     ('Mod4', X.Mod4MapIndex), ('Mod5', X.Mod5MapIndex)]
        #This gets the list of all keycodes per Modifier, assigns to name
        for name, index in mod_index:
            codes = [v for v in list(modifier_mapping[index]) if v]
            mod_keycodes[name] = codes
            all_mod_keycodes += codes

        def lookup_keycode(string):
            keysym = self.string_to_keysym[string]
            return self.display.keysym_to_keycode(keysym)

        #Dynamically assign Lock to Caps_Lock, Shift_Lock, Alt, Num_Lock, Super,
        #and mode switch. Set in both mod_keycodes and self.modifier_bits

        #Try to assign Lock to Caps_Lock or Shift_Lock
        shift_lock_keycode = lookup_keycode('Shift_Lock')
        caps_lock_keycode = lookup_keycode('Caps_Lock')

        if shift_lock_keycode in mod_keycodes['Lock']:
            mod_keycodes['Shift_Lock'] = [shift_lock_keycode]
            self.modifier_bits['Shift_Lock'] = self.modifier_bits['Lock']
            self.lock_meaning = 'Shift_Lock'
        elif caps_lock_keycode in mod_keycodes['Lock']:
            mod_keycodes['Caps_Lock'] = [caps_lock_keycode]
            self.modifier_bits['Caps_Lock'] = self.modifier_bits['Lock']
            self.lock_meaning = 'Caps_Lock'
        else:
            self.lock_meaning = None
        logger.debug('Lock is bound to {0}'.format(self.lock_meaning))

        #Need to find out which Mod# to use for Alt, Num_Lock, Super, and
        #Mode_switch
        num_lock_keycodes = [lookup_keycode('Num_Lock')]
        alt_keycodes = [lookup_keycode(i) for i in ['Alt_L', 'Alt_R']]
        super_keycodes = [lookup_keycode(i) for i in ['Super_L', 'Super_R']]
        mode_switch_keycodes = [lookup_keycode('Mode_switch')]

        #Detect Mod number for Alt, Num_Lock, and Super
        for name, keycodes in list(mod_keycodes.items()):
            for alt_key in alt_keycodes:
                if alt_key in keycodes:
                    mod_keycodes['Alt'] = keycodes
                    self.modifier_bits['Alt'] = self.modifier_bits[name]
            for num_lock_key in num_lock_keycodes:
                if num_lock_key in keycodes:
                    mod_keycodes['Num_Lock'] = keycodes
                    self.modifier_bits['Num_Lock'] = self.modifier_bits[name]
            for super_key in super_keycodes:
                if super_key in keycodes:
                    mod_keycodes['Super'] = keycodes
                    self.modifier_bits['Super'] = self.modifier_bits[name]
            for mode_switch_key in mode_switch_keycodes:
                if mode_switch_key in keycodes:
                    mod_keycodes['Mode_switch'] = keycodes
                    self.modifier_bits['Mode_switch'] = self.modifier_bits[
                        name]

        #Assign the mod_keycodes to a local variable for access
        self.modifier_keycodes = mod_keycodes
        self.all_mod_keycodes = all_mod_keycodes

        #TODO: Determine if this might fail, perhaps iterate through the mapping
        #and identify all keycodes with registered keypad keysyms?

        #Acquire the full list of keypad keycodes
        self.keypad_keycodes = []
        keypad = [
            'Space', 'Tab', 'Enter', 'F1', 'F2', 'F3', 'F4', 'Home', 'Left',
            'Up', 'Right', 'Down', 'Prior', 'Page_Up', 'Next', 'Page_Down',
            'End', 'Begin', 'Insert', 'Delete', 'Equal', 'Multiply', 'Add',
            'Separator', 'Subtract', 'Decimal', 'Divide', '0', '1', '2', '3',
            '4', '5', '6', '7', '8', '9'
        ]
        for keyname in keypad:
            keypad_keycode = self.lookup_character_keycode('KP_' + keyname)
            self.keypad_keycodes.append(keypad_keycode)

    def lookup_character_keycode(self, character):
        """
        Looks up the keysym for the character then returns the keycode mapping
        for that keysym.
        """
        keysym = self.string_to_keysym.get(character, 0)
        if keysym == 0:
            keysym = self.string_to_keysym.get(KEYSYMS[character], 0)
        return self.display.keysym_to_keycode(keysym)

    def get_translation_dicts(self):
        """
        Returns dictionaries for the translation of keysyms to strings and from
        strings to keysyms.
        """
        keysym_to_string_dict = {}
        string_to_keysym_dict = {}
        #XK loads latin1 and miscellany on its own; load latin2-4 and greek
        Xlib.XK.load_keysym_group('latin2')
        Xlib.XK.load_keysym_group('latin3')
        Xlib.XK.load_keysym_group('latin4')
        Xlib.XK.load_keysym_group('greek')

        #Make a standard dict and the inverted dict
        for string, keysym in Xlib.XK.__dict__.items():
            if string.startswith('XK_'):
                string_to_keysym_dict[string[3:]] = keysym
                keysym_to_string_dict[keysym] = string[3:]
        return keysym_to_string_dict, string_to_keysym_dict

    def ascii_printable(self, keysym):
        """
        If the keysym corresponds to a non-printable ascii character this will
        return False. If it is printable, then True will be returned.

        ascii 11 (vertical tab) and ascii 12 are printable, chr(11) and chr(12)
        will return '\x0b' and '\x0c' respectively.
        """
        if 0 <= keysym < 9:
            return False
        elif 13 < keysym < 32:
            return False
        elif keysym > 126:
            return False
        else:
            return True
Exemple #41
0
class PyKeyboardEvent(PyKeyboardEventMeta):
    """
    The PyKeyboardEvent implementation for X11 systems (mostly linux). This
    allows one to listen for keyboard input.
    """
    def __init__(self, display=None):
        self.display = Display(display)
        self.display2 = Display(display)
        self.ctx = self.display2.record_create_context(
            0,
            [record.AllClients],
            [{
                    'core_requests': (0, 0),
                    'core_replies': (0, 0),
                    'ext_requests': (0, 0, 0, 0),
                    'ext_replies': (0, 0, 0, 0),
                    'delivered_events': (0, 0),
                    'device_events': (X.KeyPress, X.KeyRelease),
                    'errors': (0, 0),
                    'client_started': False,
                    'client_died': False,
            }])

        self.lock_meaning = None

        #Get these dictionaries for converting keysyms and strings
        self.keysym_to_string, self.string_to_keysym = self.get_translation_dicts()

        #Identify and register special groups of keys
        self.modifier_keycodes = {}
        self.all_mod_keycodes = []
        self.keypad_keycodes = []
        #self.configure_keys()

        #Direct access to the display's keycode-to-keysym array
        #print('Keycode to Keysym map')
        #for i in range(len(self.display._keymap_codes)):
        #    print('{0}: {1}'.format(i, self.display._keymap_codes[i]))

        PyKeyboardEventMeta.__init__(self)

    def run(self):
        """Begin listening for keyboard input events."""
        self.state = True
        if self.capture:
            self.display2.screen().root.grab_keyboard(True, X.KeyPressMask | X.KeyReleaseMask, X.GrabModeAsync, X.GrabModeAsync, 0, 0, X.CurrentTime)

        self.display2.record_enable_context(self.ctx, self.handler)
        self.display2.record_free_context(self.ctx)

    def stop(self):
        """Stop listening for keyboard input events."""
        self.state = False
        self.display.record_disable_context(self.ctx)
        self.display.ungrab_keyboard(X.CurrentTime)
        self.display.flush()
        self.display2.record_disable_context(self.ctx)
        self.display2.ungrab_keyboard(X.CurrentTime)
        self.display2.flush()

    def handler(self, reply):
        """Upper level handler of keyboard events."""
        data = reply.data
        while len(data):
            event, data = rq.EventField(None).parse_binary_value(data, self.display.display, None, None)
            if self.escape(event):  # Quit if this returns True
                self.stop()
            else:
                self._tap(event)

    def _tap(self, event):
        keycode = event.detail
        press_bool = (event.type == X.KeyPress)

        #Detect modifier states from event.state
        for mod, bit in self.modifier_bits.items():
            self.modifiers[mod] = event.state & bit

        if keycode in self.all_mod_keycodes:
            keysym = self.display.keycode_to_keysym(keycode, 0)
            character = self.keysym_to_string[keysym]
        else:
            character = self.lookup_char_from_keycode(keycode)

        #All key events get passed to self.tap()
        self.tap(keycode,
                 character,
                 press=press_bool)

    def lookup_char_from_keycode(self, keycode):
        """
        This will conduct a lookup of the character or string associated with a
        given keycode.
        """

        #TODO: Logic should be strictly adapted from X11's src/KeyBind.c
        #Right now the logic is based off of
        #http://tronche.com/gui/x/xlib/input/keyboard-encoding.html
        #Which I suspect is not the whole story and may likely cause bugs

        keysym_index = 0
        #TODO: Display's Keysyms per keycode count? Do I need this?
        #If the Num_Lock is on, and the keycode corresponds to the keypad
        if self.modifiers['Num_Lock'] and keycode in self.keypad_keycodes:
            if self.modifiers['Shift'] or self.modifiers['Shift_Lock']:
                keysym_index = 0
            else:
                keysym_index = 1

        elif not self.modifiers['Shift'] and self.modifiers['Caps_Lock']:
            #Use the first keysym if uppercase or uncased
            #Use the uppercase keysym if the first is lowercase (second)
            keysym_index = 0
            keysym = self.display.keycode_to_keysym(keycode, keysym_index)
            #TODO: Support Unicode, Greek, and special latin characters
            if keysym & 0x7f == keysym and chr(keysym) in 'abcdefghijklmnopqrstuvwxyz':
                keysym_index = 1

        elif self.modifiers['Shift'] and self.modifiers['Caps_Lock']:
            keysym_index = 1
            keysym = self.display.keycode_to_keysym(keycode, keysym_index)
            #TODO: Support Unicode, Greek, and special latin characters
            if keysym & 0x7f == keysym and chr(keysym) in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ':
                keysym_index = 0

        elif self.modifiers['Shift'] or self.modifiers['Shift_Lock']:
            keysym_index = 1

        if self.modifiers['Mode_switch']:
            keysym_index += 2

        #Finally! Get the keysym
        keysym = self.display.keycode_to_keysym(keycode, keysym_index)

        #If the character is ascii printable, return that character
        if keysym & 0x7f == keysym and self.ascii_printable(keysym):
            return chr(keysym)

        #If the character was not printable, look for its name
        try:
            char = self.keysym_to_string[keysym]
        except KeyError:
            print('Unable to determine character.')
            print('Keycode: {0} KeySym {1}'.format(keycode, keysym))
            return None
        else:
            return char

    def escape(self, event):
        if event.detail == self.lookup_character_keycode('Escape'):
            return True
        return False

    def configure_keys(self):
        """
        This function locates the keycodes corresponding to special groups of
        keys and creates data structures of them for use by the PyKeyboardEvent
        instance; including the keypad keys and the modifiers.

        The keycodes pertaining to the keyboard modifiers are assigned by the
        modifier name in a dictionary. This dictionary can be accessed in the
        following manner:
            self.modifier_keycodes['Shift']  # All keycodes for Shift Masking

        It also assigns certain named modifiers (Alt, Num_Lock, Super), which
        may be dynamically assigned to Mod1 - Mod5 on different platforms. This
        should generally allow the user to do the following lookups on any
        system:
            self.modifier_keycodes['Alt']  # All keycodes for Alt Masking
            self.modifiers['Alt']  # State of Alt mask, non-zero if "ON"
        """
        modifier_mapping = self.display.get_modifier_mapping()
        all_mod_keycodes = []
        mod_keycodes = {}
        mod_index = [('Shift', X.ShiftMapIndex), ('Lock', X.LockMapIndex),
                     ('Control', X.ControlMapIndex), ('Mod1', X.Mod1MapIndex),
                     ('Mod2', X.Mod2MapIndex), ('Mod3', X.Mod3MapIndex),
                     ('Mod4', X.Mod4MapIndex), ('Mod5', X.Mod5MapIndex)]
        #This gets the list of all keycodes per Modifier, assigns to name
        for name, index in mod_index:
            codes = [v for v in list(modifier_mapping[index]) if v]
            mod_keycodes[name] = codes
            all_mod_keycodes += codes

        def lookup_keycode(string):
            keysym = self.string_to_keysym[string]
            return self.display.keysym_to_keycode(keysym)

        #Dynamically assign Lock to Caps_Lock, Shift_Lock, Alt, Num_Lock, Super,
        #and mode switch. Set in both mod_keycodes and self.modifier_bits

        #Try to assign Lock to Caps_Lock or Shift_Lock
        shift_lock_keycode = lookup_keycode('Shift_Lock')
        caps_lock_keycode = lookup_keycode('Caps_Lock')

        if shift_lock_keycode in mod_keycodes['Lock']:
            mod_keycodes['Shift_Lock'] = [shift_lock_keycode]
            self.modifier_bits['Shift_Lock'] = self.modifier_bits['Lock']
            self.lock_meaning = 'Shift_Lock'
        elif caps_lock_keycode in mod_keycodes['Lock']:
            mod_keycodes['Caps_Lock'] = [caps_lock_keycode]
            self.modifier_bits['Caps_Lock'] = self.modifier_bits['Lock']
            self.lock_meaning = 'Caps_Lock'
        else:
            self.lock_meaning = None
        #print('Lock is bound to {0}'.format(self.lock_meaning))

        #Need to find out which Mod# to use for Alt, Num_Lock, Super, and
        #Mode_switch
        num_lock_keycodes = [lookup_keycode('Num_Lock')]
        alt_keycodes = [lookup_keycode(i) for i in ['Alt_L', 'Alt_R']]
        super_keycodes = [lookup_keycode(i) for i in ['Super_L', 'Super_R']]
        mode_switch_keycodes = [lookup_keycode('Mode_switch')]

        #Detect Mod number for Alt, Num_Lock, and Super
        for name, keycodes in list(mod_keycodes.items()):
            for alt_key in alt_keycodes:
                if alt_key in keycodes:
                    mod_keycodes['Alt'] = keycodes
                    self.modifier_bits['Alt'] = self.modifier_bits[name]
            for num_lock_key in num_lock_keycodes:
                if num_lock_key in keycodes:
                    mod_keycodes['Num_Lock'] = keycodes
                    self.modifier_bits['Num_Lock'] = self.modifier_bits[name]
            for super_key in super_keycodes:
                if super_key in keycodes:
                    mod_keycodes['Super'] = keycodes
                    self.modifier_bits['Super'] = self.modifier_bits[name]
            for mode_switch_key in mode_switch_keycodes:
                if mode_switch_key in keycodes:
                    mod_keycodes['Mode_switch'] = keycodes
                    self.modifier_bits['Mode_switch'] = self.modifier_bits[name]

        #Assign the mod_keycodes to a local variable for access
        self.modifier_keycodes = mod_keycodes
        self.all_mod_keycodes = all_mod_keycodes

        #TODO: Determine if this might fail, perhaps iterate through the mapping
        #and identify all keycodes with registered keypad keysyms?

        #Acquire the full list of keypad keycodes
        self.keypad_keycodes = []
        keypad = ['Space', 'Tab', 'Enter', 'F1', 'F2', 'F3', 'F4', 'Home',
                  'Left', 'Up', 'Right', 'Down', 'Prior', 'Page_Up', 'Next',
                  'Page_Down', 'End', 'Begin', 'Insert', 'Delete', 'Equal',
                  'Multiply', 'Add', 'Separator', 'Subtract', 'Decimal',
                  'Divide', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9']
        for keyname in keypad:
            keypad_keycode = self.lookup_character_keycode('KP_' + keyname)
            self.keypad_keycodes.append(keypad_keycode)

    def lookup_character_keycode(self, character):
        """
        Looks up the keysym for the character then returns the keycode mapping
        for that keysym.
        """
        keysym = self.string_to_keysym.get(character, 0)
        if keysym == 0:
            keysym = self.string_to_keysym.get(special_X_keysyms[character], 0)
        return self.display.keysym_to_keycode(keysym)

    def get_translation_dicts(self):
        """
        Returns dictionaries for the translation of keysyms to strings and from
        strings to keysyms.
        """
        keysym_to_string_dict = {}
        string_to_keysym_dict = {}
        #XK loads latin1 and miscellany on its own; load latin2-4 and greek
        Xlib.XK.load_keysym_group('latin2')
        Xlib.XK.load_keysym_group('latin3')
        Xlib.XK.load_keysym_group('latin4')
        Xlib.XK.load_keysym_group('greek')

        #Make a standard dict and the inverted dict
        for string, keysym in Xlib.XK.__dict__.items():
            if string.startswith('XK_'):
                string_to_keysym_dict[string[3:]] = keysym
                keysym_to_string_dict[keysym] = string[3:]
        return keysym_to_string_dict, string_to_keysym_dict

    def ascii_printable(self, keysym):
        """
        If the keysym corresponds to a non-printable ascii character this will
        return False. If it is printable, then True will be returned.

        ascii 11 (vertical tab) and ascii 12 are printable, chr(11) and chr(12)
        will return '\x0b' and '\x0c' respectively.
        """
        if 0 <= keysym < 9:
            return False
        elif 13 < keysym < 32:
            return False
        elif keysym > 126:
            return False
        else:
            return True
Exemple #42
0
class X11(ShortcutManager, Thread):
    def __init__(self):
        ShortcutManager.__init__(self)
        Thread.__init__(self)
        self.setDaemon(True)

        self.display = Display ()
        self.screen = self.display.screen ()
        self.root = self.screen.root

        self.root.change_attributes(event_mask=X.KeyPress|X.KeyRelease|X.PropertyChangeMask)

        self.key_conf_to_key = dict()

        self.active = False

    def init(self):
        """Start the main loop."""
        self.active = True
        self.start()

    def run(self):
        """Main loop
        
        It will handle the user combination key,
        check if its associated to a pre-configured shortcut
        and then execute the right action to that shortcut.

        """
        while self.active:
            event = self.root.display.next_event()
            if event.type == X.KeyPress:
                for key_conf in self.key_conf_to_key.keys():
                    key, mask = self.key_conf_to_key[key_conf]
                    if event.detail == key and \
                       event.state == mask:
                        if key_conf == "quick_search":
                            gtk.gdk.threads_enter()
                            self.emit("quick_search")
                            gtk.gdk.threads_leave()
                        elif key_conf == "scan_selection":
                            word = get_primary_selection()
                            if word:
                                gtk.gdk.threads_enter()
                                self.emit("scan_selection", word)
                                gtk.gdk.threads_leave()

    def set_shortcut(self, key_conf, key, mask):
        """  """
        key = self.display.keysym_to_keycode(key)
        self.root.grab_key(key, mask, 1, X.GrabModeAsync, X.GrabModeAsync)

        self.key_conf_to_key[key_conf] = (key, mask)

    def unset_shortcut(self, key, mask):
        """ """
        key = self.display.keysym_to_keycode(key)
        self.root.ungrab_key(key, mask)

    def stop(self):
        """Stop the main loop"""
        self.active = False
        self.unset_keys()

    def unset_keys(self):
        """Unset all shortcuts."""
        for key_conf in self.key_conf_to_key.keys():
            key, mask = self.key_conf_to_key[key_conf]
            self.unset_shortcut(key, mask)
Exemple #43
0
class GlobalHotkeyManagerX11(GlobalHotkeyManagerBase):
    def __init__(self):
        self._text_to_native = {
            '-': 'minus',
            '+': 'plus',
            '=': 'equal',
            '[': 'bracketleft',
            ']': 'bracketright',
            '|': 'bar',
            ';': 'semicolon',
            '\'': 'quoteright',
            ',': 'comma',
            '.': 'period',
            '/': 'slash',
            '\\': 'backslash',
            '`': 'asciitilde',
        }
        GlobalHotkeyManagerBase.__init__(self)

        self._error = False
        self._display = Display()
        self._poller = X11EventPoller()
        self._poller.keyPressed.connect(self.x11_event)
        self._poller.start()

        # Check if the extension is present
        if not self._display.has_extension('RECORD'):
            raise Exception('RECORD extension not found')

    def destroy(self):
        # self._poller.destroy()
        # should destroy event poller thread, no clue how
        pass

    # noinspection PyUnusedLocal
    def x11_event(self, event, data):
        if event.type == X.KeyPress:
            key = (event.detail, int(event.state) & (X.ShiftMask | X.ControlMask | X.Mod1Mask | X.Mod4Mask))
            if key in self.shortcuts:
                # noinspection PyCallByClass,PyTypeChecker
                QTimer.singleShot(0, self.shortcuts[key])
        return False

    def _native_modifiers(self, modifiers):
        # ShiftMask, LockMask, ControlMask, Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, and Mod5Mask
        native = 0
        modifiers = int(modifiers)
        if modifiers & Qt.ShiftModifier:
            native |= X.ShiftMask
        if modifiers & Qt.ControlModifier:
            native |= X.ControlMask
        if modifiers & Qt.AltModifier:
            native |= X.Mod1Mask
        if modifiers & Qt.MetaModifier:
            native |= X.Mod4Mask
        
        # TODO: resolve these?
        # if (modifiers & Qt.MetaModifier)
        # if (modifiers & Qt.KeypadModifier)
        # if (modifiers & Qt.GroupSwitchModifier)
        return native

    def _native_keycode(self, key):
        keysym = QKeySequence(key).toString()
        if keysym in self._text_to_native:
            keysym = self._text_to_native[keysym]
        return self._display.keysym_to_keycode(XK.string_to_keysym(keysym))

    # noinspection PyUnusedLocal
    def _on_error(self, e, data):
        if e.code in (X.BadAccess, X.BadValue, X.BadWindow):
            if e.major_opcode in (33, 34):                          # X_GrabKey, X_UngrabKey
                self._error = True
                # char errstr[256];
                # XGetErrorText(dpy, err->error_code, errstr, 256);
        return 0

    def _register_shortcut(self, receiver, native_key, native_mods, winid=None):
        window = self._display.screen().root
        self._error = False

        window.grab_key(native_key, native_mods, True, X.GrabModeAsync, X.GrabModeAsync, self._on_error)
        self._display.sync()
        if not self._error:
            self.shortcuts[(native_key, native_mods)] = receiver
        return not self._error

    def _unregister_shortcut(self, native_key, native_mods, window_id):
        display = Display()
        window = display.screen().root
        self._error = False
        window.ungrab_key(native_key, native_mods, self._on_error)
        display.sync()
        try:
            del self.shortcuts[(native_key, native_mods)]
        except KeyError:
            pass
        return not self._error
Exemple #44
0
class QuickTileApp(object):
    """The basic Glib application itself."""
    keybinds_failed = False

    def __init__(self, wm, commands, keys=None, modkeys=None):
        """Populate the instance variables.

        @param keys: A dict mapping X11 keysyms to L{CommandRegistry}
            command names.
        @param modkeys: A modifier mask to prefix to all keybindings.
        @type wm: The L{WindowManager} instance to use.
        @type keys: C{dict}
        @type modkeys: C{str}
        """
        self.wm = wm
        self.commands = commands
        self._keys = keys or {}
        self._modkeys = modkeys or 0

    def _init_dbus(self):
        """Set up dbus-python components in the Glib event loop

        @todo 1.0.0: Retire the C{doCommand} name. (API-breaking change)
        """
        class QuickTile(dbus.service.Object):
            def __init__(self):
                dbus.service.Object.__init__(self, sessBus,
                                             '/com/ssokolow/QuickTile')

            @dbus.service.method(dbus_interface='com.ssokolow.QuickTile',
                     in_signature='s', out_signature='b')
            def doCommand(self, command):
                return self.commands.call(command, wm)

        self.dbusName = dbus.service.BusName("com.ssokolow.QuickTile", sessBus)
        self.dbusObj = QuickTile()

    def _init_xlib(self):
        """Set up python-xlib components in the Glib event loop

        Source: U{http://www.larsen-b.com/Article/184.html}
        """
        self.xdisp = Display()
        self.xroot = self.xdisp.screen().root

        # We want to receive KeyPress events
        self.xroot.change_attributes(event_mask=X.KeyPressMask)

        # unrecognized shortkeys now will be looked up in a hardcoded dict
        # and replaced by valid names like ',' -> 'comma'
        # while generating the self.keys dict
        self.keys = dict()
        for key in self._keys:
            transKey = key
            if key in KEYLOOKUP:
                transKey = KEYLOOKUP[key]
            code = self.xdisp.keysym_to_keycode(string_to_keysym(transKey))
            self.keys[code] = self._keys[key]

        # Resolve strings to X11 mask constants for the modifier mask
        try:
            modmask = reduce(operator.ior, [getattr(X, "%sMask" % x)
                             for x in self._modkeys])
        except Exception, err:
            logging.error("Error while resolving modifier key mask: %s", err)
            logging.error("Not binding keys for safety reasons. "
                          "(eg. What if Ctrl+C got bound?)")
            modmask = 0
        else:
Exemple #45
0
from Xlib.display import Display
from Xlib import X, XK
import os
import subprocess

double_borders = True
single_border = False
border_colour = "618158"

mouse_move = "drag"

dpy = Display()

# ascend window
dpy.screen().root.grab_key(dpy.keysym_to_keycode(XK.string_to_keysym("A")),
                           X.Mod4Mask, 1, X.GrabModeAsync, X.GrabModeAsync)
# kill window
dpy.screen().root.grab_key(dpy.keysym_to_keycode(XK.string_to_keysym("Q")),
                           X.Mod4Mask, 1, X.GrabModeAsync, X.GrabModeAsync)
# draw terminal
dpy.screen().root.grab_key(dpy.keysym_to_keycode(XK.string_to_keysym("Z")),
                           X.Mod4Mask, 1, X.GrabModeAsync, X.GrabModeAsync)

# drag window
dpy.screen().root.grab_button(
    1, X.Mod1Mask, 1,
    X.ButtonPressMask | X.ButtonReleaseMask | X.PointerMotionMask,
    X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)
dpy.screen().root.grab_button(
    1, X.Mod1Mask, 1,
    X.ButtonPressMask | X.ButtonReleaseMask | X.PointerMotionMask,
Exemple #46
0
    _display.sync()


# Taken from PyKeyboard's ctor function.
_display = Display(os.environ['DISPLAY'])


""" Information for keyboardMapping derived from PyKeyboard's special_key_assignment() function.

The *KB dictionaries in pyautogui map a string that can be passed to keyDown(),
keyUp(), or press() into the code used for the OS-specific keyboard function.

They should always be lowercase, and the same keys should be used across all OSes."""
keyboardMapping = dict([(key, None) for key in pyautogui.KEY_NAMES])
keyboardMapping.update({
    'backspace':         _display.keysym_to_keycode(Xlib.XK.string_to_keysym('BackSpace')),
    '\b':                _display.keysym_to_keycode(Xlib.XK.string_to_keysym('BackSpace')),
    'tab':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Tab')),
    'enter':             _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),
    'return':            _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),
    'shift':             _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Shift_L')),
    'ctrl':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Control_L')),
    'alt':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Alt_L')),
    'pause':             _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Pause')),
    'capslock':          _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Caps_Lock')),
    'esc':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
    'escape':            _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
    'pgup':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Up')),
    'pgdn':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Down')),
    'pageup':            _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Up')),
    'pagedown':          _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Down')),
Exemple #47
0
class X11(ShortcutManager, Thread):
    def __init__(self):
        ShortcutManager.__init__(self)
        Thread.__init__(self)
        self.setDaemon(True)

        self.display = Display()
        self.screen = self.display.screen()
        self.root = self.screen.root

        self.root.change_attributes(event_mask=X.KeyPress | X.KeyRelease
                                    | X.PropertyChangeMask)

        self.key_conf_to_key = dict()

        self.active = False

    def init(self):
        """Start the main loop."""
        self.active = True
        self.start()

    def run(self):
        """Main loop
        
        It will handle the user combination key,
        check if its associated to a pre-configured shortcut
        and then execute the right action to that shortcut.

        """
        while self.active:
            event = self.root.display.next_event()
            if event.type == X.KeyPress:
                for key_conf in self.key_conf_to_key.keys():
                    key, mask = self.key_conf_to_key[key_conf]
                    if event.detail == key and \
                       event.state == mask:
                        if key_conf == "quick_search":
                            gtk.gdk.threads_enter()
                            self.emit("quick_search")
                            gtk.gdk.threads_leave()
                        elif key_conf == "scan_selection":
                            word = get_primary_selection()
                            if word:
                                gtk.gdk.threads_enter()
                                self.emit("scan_selection", word)
                                gtk.gdk.threads_leave()

    def set_shortcut(self, key_conf, key, mask):
        """  """
        key = self.display.keysym_to_keycode(key)
        self.root.grab_key(key, mask, 1, X.GrabModeAsync, X.GrabModeAsync)

        self.key_conf_to_key[key_conf] = (key, mask)

    def unset_shortcut(self, key, mask):
        """ """
        key = self.display.keysym_to_keycode(key)
        self.root.ungrab_key(key, mask)

    def stop(self):
        """Stop the main loop"""
        self.active = False
        self.unset_keys()

    def unset_keys(self):
        """Unset all shortcuts."""
        for key_conf in self.key_conf_to_key.keys():
            key, mask = self.key_conf_to_key[key_conf]
            self.unset_shortcut(key, mask)
Exemple #48
0
# NotSoTinyWM is written by Aleksi Torhamo <*****@*****.**>.
# It is based on TinyWM, which is written by Nick Welch <*****@*****.**>.
#
# This software is in the public domain and is provided AS IS, with NO WARRANTY.

from Xlib.display import Display
from Xlib import X, XK
from util import *

dpy = Display()
root = dpy.screen().root

event_mask = X.ButtonPressMask|X.ButtonReleaseMask|X.PointerMotionMask

root.grab_key(dpy.keysym_to_keycode(XK.string_to_keysym("F1")),
    X.Mod1Mask, 1, X.GrabModeAsync, X.GrabModeAsync)
root.grab_button(1, X.Mod1Mask, 1, event_mask,
    X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)
root.grab_button(3, X.Mod1Mask, 1, event_mask,
    X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)

start = None
while 1:
    ev = dpy.next_event()
    if ev.type == X.KeyPress and ev.child != X.NONE:
        ev.child.configure(stack_mode = X.Above)
    elif ev.type == X.ButtonPress and ev.child != X.NONE:
        attr = ev.child.get_geometry()
        start = ev
    elif ev.type == X.MotionNotify and start:
        ev = compress_motion(dpy, ev)
Exemple #49
0
class GlobalKey(threading.Thread):
    
    def __init__(self):
        super(GlobalKey, self).__init__()
        self.setDaemon(True)
        self.disp = Display()
        self.root = self.disp.screen().root
        self._binding_map = {}
        
        self.stop = False
        
        self.known_modifiers_mask = 0
        
        x_modifiers = (X.ControlMask,
                       X.ShiftMask,
                       X.Mod1Mask,
                       X.Mod2Mask,
                       X.Mod3Mask,
                       X.Mod4Mask,
                       X.Mod5Mask,
                       )
        
        for mod in x_modifiers:
            self.known_modifiers_mask |= mod
            
    def bind(self, binding_string, action, weak=False):        
        keyval, modifiers = self.parse_keystring(binding_string)
        keycode = self.disp.keysym_to_keycode(keyval)
        
        if weak:
            action = saferef.Ref(action)
        
        # Binding key.
        self._binding_map[(keycode, modifiers)] = action
        
        num_lock_modifiers = modifiers | X.Mod2Mask
        self._binding_map[(keycode, num_lock_modifiers)] = action
        
        # Restart grab keybinding.
        self.regrab()
        
    def unbind(self, binding_string):
        '''
        '''
        
        keyval, modifiers = self.parse_keystring(binding_string)
        keycode = self.disp.keysym_to_keycode(keyval)
        
        num_lock_modifiers = modifiers | X.Mod2Mask

        # Remove keybinding from binding map.
        regrab_flag = False
        if self._binding_map.has_key((keycode, modifiers)):
            del self._binding_map[(keycode, modifiers)]
            regrab_flag = True

        # Try remove key binding (with Num-Lock mask) from binding map.
        if self._binding_map.has_key((keycode, num_lock_modifiers)):
            del self._binding_map[(keycode, num_lock_modifiers)]
            regrab_flag = True

        if regrab_flag:
            self.regrab()
            
    def grab(self):
        '''
        Grab key.
        '''
        for (keycode, modifiers) in self._binding_map.keys():
            try:
                self.root.grab_key(keycode, int(modifiers), True, X.GrabModeAsync, X.GrabModeSync)
            except Exception, e:
                print "function grab got error: %s" % (e)
Exemple #50
0
class PyKeyboard(PyKeyboardMeta):
    """
    The PyKeyboard implementation for X11 systems (mostly linux). This
    allows one to simulate keyboard input.
    """
    def __init__(self, display=None):
        PyKeyboardMeta.__init__(self)
        self.display = Display(display)
        self.display2 = Display(display)
        self.special_key_assignment()

    def press_key(self, character=''):
        """
        Press a given character key. Also works with character keycodes as
        integers, but not keysyms.
        """
        try:  # Detect uppercase or shifted character
            shifted = self.is_char_shifted(character)
        except AttributeError:  # Handle the case of integer keycode argument
            fake_input(self.display, X.KeyPress, character)
            self.display.sync()
        else:
            if shifted:
                fake_input(self.display, X.KeyPress, self.shift_key)
            char_val = self.lookup_character_value(character)
            fake_input(self.display, X.KeyPress, char_val)
            self.display.sync()

    def release_key(self, character=''):
        """
        Release a given character key. Also works with character keycodes as
        integers, but not keysyms.
        """
        try:  # Detect uppercase or shifted character
            shifted = self.is_char_shifted(character)
        except AttributeError:  # Handle the case of integer keycode argument
            fake_input(self.display, X.KeyRelease, character)
            self.display.sync()
        else:
            if shifted:
                fake_input(self.display, X.KeyRelease, self.shift_key)
            char_val = self.lookup_character_value(character)
            fake_input(self.display, X.KeyRelease, char_val)
            self.display.sync()

    def tap_key(self, character='', repeat=1):
        """
        Press and release a given character key n times. Also works with
        character keycodes as integers, but not keysyms.
        """
        for i in xrange(repeat):
            self.press_key(character)
            self.release_key(character)

    def type_string(self, char_string, char_interval=0):
        """A convenience method for typing longer strings of characters."""
        for i in char_string:
            time.sleep(char_interval)
            self.tap_key(i)

    def is_char_shifted(self, character):
        """Returns True if the key character is uppercase or shifted."""
        if character.isupper():
            return True
        if character in '<>?:"{}|~!@#$%^&*()_+':
            return True
        return False

    def special_key_assignment(self):
        """
        Determines the keycodes for common special keys on the keyboard. These
        are integer values and can be passed to the other key methods.
        Generally speaking, these are non-printable codes.
        """
        #This set of keys compiled using the X11 keysymdef.h file as reference
        #They comprise a relatively universal set of keys, though there may be
        #exceptions which may come up for other OSes and vendors. Countless
        #special cases exist which are not handled here, but may be extended.
        #TTY Function Keys
        self.backspace_key = self.lookup_character_value('BackSpace')
        self.tab_key = self.lookup_character_value('Tab')
        self.linefeed_key = self.lookup_character_value('Linefeed')
        self.clear_key = self.lookup_character_value('Clear')
        self.return_key = self.lookup_character_value('Return')
        self.enter_key = self.return_key  # Because many keyboards call it "Enter"
        self.pause_key = self.lookup_character_value('Pause')
        self.scroll_lock_key = self.lookup_character_value('Scroll_Lock')
        self.sys_req_key = self.lookup_character_value('Sys_Req')
        self.escape_key = self.lookup_character_value('Escape')
        self.delete_key = self.lookup_character_value('Delete')
        #Modifier Keys
        self.shift_l_key = self.lookup_character_value('Shift_L')
        self.shift_r_key = self.lookup_character_value('Shift_R')
        self.shift_key = self.shift_l_key  # Default Shift is left Shift
        self.alt_l_key = self.lookup_character_value('Alt_L')
        self.alt_r_key = self.lookup_character_value('Alt_R')
        self.alt_key = self.alt_l_key  # Default Alt is left Alt
        self.control_l_key = self.lookup_character_value('Control_L')
        self.control_r_key = self.lookup_character_value('Control_R')
        self.control_key = self.control_l_key  # Default Ctrl is left Ctrl
        self.caps_lock_key = self.lookup_character_value('Caps_Lock')
        self.shift_lock_key = self.lookup_character_value('Shift_Lock')
        self.meta_l_key = self.lookup_character_value('Meta_L')
        self.meta_r_key = self.lookup_character_value('Meta_R')
        self.super_l_key = self.lookup_character_value('Super_L')
        self.super_r_key = self.lookup_character_value('Super_R')
        self.hyper_l_key = self.lookup_character_value('Hyper_L')
        self.hyper_r_key = self.lookup_character_value('Hyper_R')
        #Cursor Control and Motion
        self.home_key = self.lookup_character_value('Home')
        self.up_key = self.lookup_character_value('Up')
        self.down_key = self.lookup_character_value('Down')
        self.left_key = self.lookup_character_value('Left')
        self.right_key = self.lookup_character_value('Right')
        self.end_key = self.lookup_character_value('End')
        self.begin_key = self.lookup_character_value('Begin')
        self.page_up_key = self.lookup_character_value('Page_Up')
        self.page_down_key = self.lookup_character_value('Page_Down')
        self.prior_key = self.lookup_character_value('Prior')
        self.next_key = self.lookup_character_value('Next')
        #Misc Functions
        self.select_key = self.lookup_character_value('Select')
        self.print_key = self.lookup_character_value('Print')
        self.execute_key = self.lookup_character_value('Execute')
        self.insert_key = self.lookup_character_value('Insert')
        self.undo_key = self.lookup_character_value('Undo')
        self.redo_key = self.lookup_character_value('Redo')
        self.menu_key = self.lookup_character_value('Menu')
        self.find_key = self.lookup_character_value('Find')
        self.cancel_key = self.lookup_character_value('Cancel')
        self.help_key = self.lookup_character_value('Help')
        self.break_key = self.lookup_character_value('Break')
        self.mode_switch_key = self.lookup_character_value('Mode_switch')
        self.script_switch_key = self.lookup_character_value('script_switch')
        self.num_lock_key = self.lookup_character_value('Num_Lock')
        #Keypad Keys: Dictionary structure
        keypad = [
            'Space', 'Tab', 'Enter', 'F1', 'F2', 'F3', 'F4', 'Home', 'Left',
            'Up', 'Right', 'Down', 'Prior', 'Page_Up', 'Next', 'Page_Down',
            'End', 'Begin', 'Insert', 'Delete', 'Equal', 'Multiply', 'Add',
            'Separator', 'Subtract', 'Decimal', 'Divide', 0, 1, 2, 3, 4, 5, 6,
            7, 8, 9
        ]
        self.keypad_keys = {
            k: self.lookup_character_value('KP_' + str(k))
            for k in keypad
        }
        self.numpad_keys = self.keypad_keys
        #Function Keys/ Auxilliary Keys
        #FKeys
        self.function_keys = [None] + [
            self.lookup_character_value('F' + str(i)) for i in xrange(1, 36)
        ]
        #LKeys
        self.l_keys = [None] + [
            self.lookup_character_value('L' + str(i)) for i in xrange(1, 11)
        ]
        #RKeys
        self.r_keys = [None] + [
            self.lookup_character_value('R' + str(i)) for i in xrange(1, 16)
        ]

    def lookup_character_value(self, character):
        """
        Looks up the keysym for the character then returns the keycode mapping
        for that keysym.
        """
        ch_keysym = string_to_keysym(character)
        if ch_keysym == 0:
            ch_keysym = string_to_keysym(special_X_keysyms[character])
        return self.display.keysym_to_keycode(ch_keysym)
Exemple #51
0
# TinyWM is written by Nick Welch <*****@*****.**> in 2005 & 2011.
#
# This software is in the public domain
# and is provided AS IS, with NO WARRANTY.

from Xlib.display import Display
from Xlib import X, XK

dpy = Display()

dpy.screen().root.grab_key(dpy.keysym_to_keycode(XK.string_to_keysym("F1")), X.Mod1Mask, 1,
        X.GrabModeAsync, X.GrabModeAsync)
dpy.screen().root.grab_button(1, X.Mod1Mask, 1, X.ButtonPressMask|X.ButtonReleaseMask|X.PointerMotionMask,
        X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)
dpy.screen().root.grab_button(3, X.Mod1Mask, 1, X.ButtonPressMask|X.ButtonReleaseMask|X.PointerMotionMask,
        X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)

start = None
while 1:
    ev = dpy.next_event()
    if ev.type == X.KeyPress and ev.child != X.NONE:
        ev.child.configure(stack_mode = X.Above)
    elif ev.type == X.ButtonPress and ev.child != X.NONE:
        attr = ev.child.get_geometry()
        start = ev
    elif ev.type == X.MotionNotify and start:
        xdiff = ev.root_x - start.root_x
        ydiff = ev.root_y - start.root_y
        start.child.configure(
            x = attr.x + (start.detail == 1 and xdiff or 0),
            y = attr.y + (start.detail == 1 and ydiff or 0),
Exemple #52
0
    elif not horizontal and amount >= 0:
        button = 5  # down
    else:
        return
    for _ in range(abs(amount)):
        fake_input(_display, X.ButtonPress, button)
        _display.sync()
        fake_input(_display, X.ButtonRelease, button)
        _display.sync()

_display = Display(":0")
# repeat held keys
_display.change_keyboard_control(auto_repeat_mode=X.AutoRepeatModeOn)

key_codes = {
    "KEY_ESC": _display.keysym_to_keycode(string_to_keysym("Escape")),
    "KEY_1": _display.keysym_to_keycode(string_to_keysym("1")),
    "KEY_2": _display.keysym_to_keycode(string_to_keysym("2")),
    "KEY_3": _display.keysym_to_keycode(string_to_keysym("3")),
    "KEY_4": _display.keysym_to_keycode(string_to_keysym("4")),
    "KEY_5": _display.keysym_to_keycode(string_to_keysym("5")),
    "KEY_6": _display.keysym_to_keycode(string_to_keysym("6")),
    "KEY_7": _display.keysym_to_keycode(string_to_keysym("7")),
    "KEY_8": _display.keysym_to_keycode(string_to_keysym("8")),
    "KEY_9": _display.keysym_to_keycode(string_to_keysym("9")),
    "KEY_0": _display.keysym_to_keycode(string_to_keysym("0")),
    "KEY_MINUS": _display.keysym_to_keycode(string_to_keysym("minus")),
    "KEY_EQUAL": _display.keysym_to_keycode(string_to_keysym("equal")),
    "KEY_BACKSPACE": _display.keysym_to_keycode(string_to_keysym("Backspace")),
    "KEY_TAB": _display.keysym_to_keycode(string_to_keysym("Tab")),
    "KEY_Q": _display.keysym_to_keycode(string_to_keysym("q")),
Exemple #53
0
# TinyWM is written by Nick Welch <*****@*****.**> in 2005 & 2011.
#
# This software is in the public domain
# and is provided AS IS, with NO WARRANTY.

from Xlib.display import Display
from Xlib import X, XK

dpy = Display()

dpy.screen().root.grab_key(dpy.keysym_to_keycode(XK.string_to_keysym("F1")), X.Mod1Mask, 1,
        X.GrabModeAsync, X.GrabModeAsync)
dpy.screen().root.grab_button(1, X.Mod1Mask, 1, X.ButtonPressMask|X.ButtonReleaseMask|X.PointerMotionMask,
        X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)
dpy.screen().root.grab_button(3, X.Mod1Mask, 1, X.ButtonPressMask|X.ButtonReleaseMask|X.PointerMotionMask,
        X.GrabModeAsync, X.GrabModeAsync, X.NONE, X.NONE)

start = None
while 1:
    ev = dpy.next_event()
    if ev.type == X.KeyPress and ev.child != X.NONE:
        ev.child.configure(stack_mode = X.Above)
    elif ev.type == X.ButtonPress and ev.child != X.NONE:
        attr = ev.child.get_geometry()
        start = ev
    elif ev.type == X.MotionNotify and start:
        xdiff = ev.root_x - start.root_x
        ydiff = ev.root_y - start.root_y
        start.child.configure(
            x = attr.x + (xdiff if start.detail == 1 else 0),
            y = attr.y + (ydiff if start.detail == 1 else 0),
    _display.sync()


# Taken from PyKeyboard's ctor function.
_display = Display(os.environ['DISPLAY'])


""" Information for keyboardMapping derived from PyKeyboard's special_key_assignment() function.

The *KB dictionaries in pyautogui map a string that can be passed to keyDown(),
keyUp(), or press() into the code used for the OS-specific keyboard function.

They should always be lowercase, and the same keys should be used across all OSes."""
keyboardMapping = dict([(key, None) for key in pyautogui.KEY_NAMES])
keyboardMapping.update({
    'backspace':         _display.keysym_to_keycode(Xlib.XK.string_to_keysym('BackSpace')),
    '\b':                _display.keysym_to_keycode(Xlib.XK.string_to_keysym('BackSpace')),
    'tab':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Tab')),
    'enter':             _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),
    'return':            _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Return')),
    'shift':             _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Shift_L')),
    'ctrl':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Control_L')),
    'alt':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Alt_L')),
    'pause':             _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Pause')),
    'capslock':          _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Caps_Lock')),
    'esc':               _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
    'escape':            _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Escape')),
    'pgup':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Up')),
    'pgdn':              _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Down')),
    'pageup':            _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Up')),
    'pagedown':          _display.keysym_to_keycode(Xlib.XK.string_to_keysym('Page_Down')),
Exemple #55
0
class SystemHotkey(MixIn):
    '''
    Cross platform System Wide Hotkeys
    
    Modifer oder doesn't matter, e.g 
    binding to  control shift k is the same as shift control k,
    limitation of the keyboard and operating systems not this library
    ''' 
    hk_ref = {} 
    def __init__(self, consumer='callback', check_queue_interval=0.01, use_xlib=False, conn=None, verbose=False):
        '''
        if the consumer param = 'callback', -> All hotkeys will require
        a callback function
        
        - Experimental! - 
        Otherwise set consumer to a function to hanlde the event.
        parameters sent will be - event, hotkey, callbacks
        event is the xwindow/microsoft keyboard eventm
        hotkey is a tuple,
        callback is any info that you registerd with the hotkey
        
        check_queue_interval is in seconds and sets the sleep time on
        checking the queue for hotkey presses
        
        set use_xlib to true to use the xlib python bindings (GPL) instead of the xcb ones (BSD) 
        You can pass an exisiting X display or connection using the conn keyword,
        otherwise one will be created for you.
        '''
        # Changes the class methods to point to differenct functions 
        # Depening on the operating system and library used
        # Consumer can be set to a function also, which will be sent the event
        # as well as the key and mask already broken out
        # Last option for consumer is False, then you have to listen to the queue yourself
        # data_queue
        self.verbose = verbose
        self.use_xlib = use_xlib
        self.consumer = consumer
        self.check_queue_interval = check_queue_interval
        def mark_event_type(event):
            # event gets an event_type attribute so the user has a portiabble way
            # actually on windows as far as i know you dont have the option of binding on keypress or release so... 
            # anyway ahve to check it but for now u dont! 
            if os.name == 'posix':
                if self.use_xlib:
                    if event.type == X.KeyPress:
                        event.event_type = 'keypress'
                    elif event.type == X.KeyRelease:
                        event.event_type = 'keyrelease'
                else:
                    if isinstance(event, xproto.KeyPressEvent):
                        event.event_type = 'keypress'
                    if isinstance(event, xproto.KeyReleaseEvent):
                        event.event_type = 'keyrelease'
            else:
                event.event_type = 'keypress'
            return event
            
        self.data_queue = queue.Queue()
        if os.name == 'nt':
            self.hk_action_queue = queue.Queue()
            self.modders = win_modders
            self._the_grab = self._nt_the_grab
            self.get_keycode = self._nt_get_keycode         
            self._get_keysym = self._nt_get_keysym
            
            thread.start_new_thread(self._nt_wait,(),)
            
        elif use_xlib:
            # Use the python-xlib library bindings, GPL License
            self.modders = xlib_modifiers
            self.trivial_mods = xlib_trivial_mods
            self._the_grab = self._xlib_the_grab
            self.get_keycode = self._xlib_get_keycode
            self._get_keysym = self._xlib_get_keysym
            if not conn:
                self.disp = Display()
            else:
                self.disp = conn
            self.xRoot = self.disp.screen().root
            self.xRoot.change_attributes(event_mask=X.KeyPressMask)
            
            thread.start_new_thread(self._xlib_wait,(),)
        
        else:
            # Using xcb and the xcffib python bindings Apache 2 http://stackoverflow.com/questions/40100/apache-license-vs-bsd-vs-mit
            self.modders = xcb_modifiers
            self.trivial_mods = xcb_trivial_mods
            self._the_grab = self._xcb_the_grab
            self.get_keycode = self._xcb_get_keycode
            self._get_keysym = self._xcb_get_keysym
            if not conn:
                self.conn = xcffib.connect()
            else:
                self.conn = conn
            self.root = self.conn.get_setup().roots[0].root
            
            thread.start_new_thread(self._xcb_wait,(),)
        
        if consumer == 'callback':
            if self.verbose:
                print('In Callback')
            def thread_me():
                while 1:
                    time.sleep(self.check_queue_interval)
                    try:
                        event = self.data_queue.get(block=False)
                    except queue.Empty:
                        pass    
                    else:
                        event = mark_event_type(event) 
                        hotkey = self.parse_event(event)
                        #~ for cb in self.get_callback(hotkey, event.event_type):   #when i was using the keypress / keyrelease shit
                        for cb in self.get_callback(hotkey):
                            if event.event_type == 'keypress':
                                if self.verbose:
                                    print('calling ', repr(cb))
                                cb(event)   # TBD either throw these up in a thread, or pass in a queue to be put onto
            thread.start_new_thread(thread_me,(),)
            
        elif callable(consumer):
            def thread_me():
                while 1:
                    time.sleep(self.check_queue_interval)
                    try:
                        event = self.data_queue.get(block=False)
                    except queue.Empty:
                        pass    
                    else:
                        hotkey = self.parse_event(mark_event_type(event))
                        if event.event_type == 'keypress':
                            args = [cb for cb in self.get_callback(hotkey)]
                            #~ callbacks = [cb for cb in self.get_callback(hotkey, event.event_type)]
                            consumer(event, hotkey, args)
            thread.start_new_thread(thread_me,(),)
        else:
            print('You need to handle grabbing events yourself!')
            
    def _xlib_wait(self):
        # Pushes Event onto queue
        while 1:
            event = self.xRoot.display.next_event()     
            self.data_queue.put(event)
    
    def _xcb_wait(self):
        # Pushes Event onto queue
        while 1:
            event = self.conn.wait_for_event()
            self.data_queue.put(event)
    
    def _nt_wait(self):
        # Pushes Event onto queue
        # I don't understand the windows msg system
        # I can only get hotkeys to work if they are registeed in the 
        # Thread that is listening for them.
        # So any changes to the hotkeys have to be signaled to be done
        # By the thread. (including unregistering)
        # A new queue is checked and runs functions, either adding
        # or removing new hotkeys, then the windows msg queue is checked
        msg = ctypes.wintypes.MSG ()
        while 1:
            try:                                            
                remove_or_add = self.hk_action_queue.get(block=False)
            except queue.Empty:
                pass    
            else:
                remove_or_add() 
            # Checking the windows message Queue
            if user32.PeekMessageA(byref(msg), 0, 0, 0, PM_REMOVE): 
                if msg.message == win32con.WM_HOTKEY:           
                    self.data_queue.put(msg)                        
                else:
                    print('some other message')
            time.sleep(self.check_queue_interval)

    def _nt_get_keycode(self, key, disp=None):  
        return vk_codes[key]
    
    def _nt_get_keysym(self, keycode):
        for key, value in vk_codes.items():
            if value == keycode:
                return key
    
    def _nt_the_grab(self, keycode, masks, id, root=None):
        if not user32.RegisterHotKey(None, id, masks, keycode):
            raise RegisterError('The bind is probably already in use elsewhere on the system')  #TBD RAISE RROR ON LINUX SYSTEMS
            
    def _xlib_get_keycode(self, key) :
        keysym = XK.string_to_keysym(key)
        if keysym == 0:
            keysym = XK.string_to_keysym(special_X_keysyms[key])
        keycode = self.disp.keysym_to_keycode(keysym)
        return keycode
    
    def _xlib_get_keysym(self, keycode, i=0):
        keysym = self.disp.keycode_to_keysym(keycode, i)
        return keybind.keysym_strings.get(keysym, [None])[0] #https://lists.gnu.org/archive/html/stumpwm-devel/2006-04/msg00033.html
        
    def _xlib_the_grab(self, keycode, masks):
        #TBD error handlig  http://tronche.com/gui/x/xlib/event-handling/protocol-errors/default-handlers.html
        #~ try:
        self.xRoot.grab_key(keycode, masks, 1, X.GrabModeAsync, X.GrabModeAsync)
        #~ except Xlib.error.BadAccess:
            #~ raise RegisterError('The bind is probably already in use elsewhere on the system')

    def _xcb_the_grab(self, keycode, masks):
        try:
            for triv_mod in self.trivial_mods:
                self.conn.core.GrabKeyChecked(True, self.root, triv_mod | masks, keycode, xproto.GrabMode.Async, xproto.GrabMode.Async).check()
        except xproto.AccessError:
            raise RegisterError('The bind is probably already in use elsewhere on the system')
             
    def _xcb_get_keycode(self, key):
        return keybind.lookup_string(key)
    
    def _xcb_get_keysym(self, keycode, i=0):
        keysym = keybind.get_keysym(keycode, i)
        return keybind.keysym_strings.get(keysym, [None])[0]
class EventManager(object):

    POINTER_MIN_MOVE = 2.0 # px
    ZOOM_THRESHOLD = 10 # mm
    ZOOM_FUNCTION_DURATION = .5 # seconds
    ZOOM_FUNCTION_RESET_TIMEOUT = 2 # seconds
    FUNCTIONS_DEFAULT_DURATION = .5 # seconds

    def __init__(self):
        self._display = Display()
        self._run_times = {}
        self._last_pointer_move = 0
        self._last_zoom = 0
        self._last_zoom_distance = -1
	self.s = self._display.screen()
	self.root = self.s.root

    def scroll_up(self):
        self._press_and_release_key_combo(WORKSPACE_UP)

    def scroll_down(self):
        self._press_and_release_key_combo(WORKSPACE_DOWN)

    def _set_pointer(self, x, y):
        self.root.warp_pointer(x,y)
	self._display.sync()

    def click(self):
        fake_input(self._display, X.ButtonPress, 1)
        fake_input(self._display, X.ButtonRelease, 1)
        self._display.sync()

    def mouse_press(self):
        fake_input(self._display, X.ButtonPress, 1)
        self._display.sync()

    def mouse_release(self):
        fake_input(self._display, X.ButtonRelease, 1)
        self._display.sync()

    def toggle_activities(self):
        self._run_function(self._toggle_activities_real,
                           self.FUNCTIONS_DEFAULT_DURATION)

    def _toggle_activities_real(self):
        self._press_and_release_key_combo(ACTIVITIES_KEY)

    def _run_function(self, function, timeout, *args):
        '''
        Runs a function if it hasn't run for less than the
        specified timeout.
        '''
        last_run = self._run_times.get(function, 0)
        current_time = time.time()
        if current_time - last_run > timeout:
            function(*args)
        self._run_times[function] = current_time

    def _move_desktop(self, dir_keysym):
        self._press_and_release_key_combo(MOVE_DESKTOP_BASE_KEY_COMBO +
                                          (dir_keysym,))

    def move_next_desktop(self):
        self._run_function(self._move_desktop, self.FUNCTIONS_DEFAULT_DURATION,
                           XK.XK_Down)

    def move_previous_desktop(self):
        self._run_function(self._move_desktop, self.FUNCTIONS_DEFAULT_DURATION,
                           XK.XK_Up)

    def _press_and_release_key_combo(self, combo):
        for action in (X.KeyPress, X.KeyRelease):
            for keysym in combo:
                key = self._display.keysym_to_keycode(keysym)
                fake_input(self._display, action, key)
            self._display.sync()

    def _press_and_release_key(self, akey):
        for action in (X.KeyPress, X.KeyRelease):
            key = self._display.keysym_to_keycode(akey)
            fake_input(self._display, action, key)
            self._display.sync()

    def _press_key(self, akey):
    	key = self._display.keysym_to_keycode(akey)
    	fake_input(self._display, X.KeyPress, key)
        self._display.sync()

    def _release_key(self, akey):
    	key = self._display.keysym_to_keycode(akey)
    	fake_input(self._display, X.KeyRelease, key)
        self._display.sync()

    def _change_zoom(self, distance):
        if distance > self._last_zoom_distance:
            self._press_and_release_key_combo(INCREASE_ZOOM_COMBO)
        else:
            self._press_and_release_key_combo(DECREASE_ZOOM_COMBO)

    def zoom(self, distance):
        '''
        Uses the distance between two points to check whether the zoom
        should be increased, decreased or not applied at all.
        '''
        current_time = time.time()
        time_since_last_zoom = current_time - self._last_zoom
        if time_since_last_zoom < self.ZOOM_FUNCTION_DURATION:
            return
        if time_since_last_zoom > self.ZOOM_FUNCTION_RESET_TIMEOUT:
            self._last_zoom_distance = -1
        if self._last_zoom_distance == -1:
            self._last_zoom_distance = distance
        elif abs(self._last_zoom_distance - distance) > self.ZOOM_THRESHOLD:
            self._change_zoom(distance)
            self._last_zoom_distance = distance
        self._last_zoom = current_time

    def zoom_scroll(self, distance):
        '''
        Uses the distance between two points to check whether the zoom
        should be increased, decreased or not applied at all.
        '''
        current_time = time.time()
        time_since_last_zoom = current_time - self._last_zoom
        if time_since_last_zoom < self.ZOOM_FUNCTION_DURATION:
            return
        if time_since_last_zoom > self.ZOOM_FUNCTION_RESET_TIMEOUT:
            self._last_zoom_distance = -1
        if self._last_zoom_distance == -1:
            self._last_zoom_distance = distance
        elif abs(self._last_zoom_distance - distance) > self.ZOOM_THRESHOLD:
            if self._last_zoom_distance - distance > 0:
		self._press_and_release_key(LEFT)
	    else:
		self._press_and_release_key(RIGHT)
        self._last_zoom = current_time
Exemple #57
0
class PyKeyboard(PyKeyboardMeta):
    """
    The PyKeyboard implementation for X11 systems (mostly linux). This
    allows one to simulate keyboard input.
    """
    def __init__(self, display=None):
        PyKeyboardMeta.__init__(self)
        self.display = Display(display)
        self.display2 = Display(display)
        self.special_key_assignment()

    def _handle_key(self, character, event):
        """Handles either a key press or release, depending on ``event``.

        :param character: The key to handle. See :meth:`press_key` and
        :meth:`release_key` for information about this parameter.

        :param event: The *Xlib* event. This should be either
        :attr:`Xlib.X.KeyPress` or :attr:`Xlib.X.KeyRelease`
        """
        try:
            # Detect uppercase or shifted character
            shifted = self.is_char_shifted(character)
        except AttributeError:
            # Handle the case of integer keycode argument
            with display_manager(self.display) as d:
                fake_input(d, event, character)
        else:
            with display_manager(self.display) as d:
                if shifted:
                    fake_input(d, event, self.shift_key)
                keycode = self.lookup_character_keycode(character)
                fake_input(d, event, keycode)

    def press_key(self, character=''):
        """
        Press a given character key. Also works with character keycodes as
        integers, but not keysyms.
        """
        self._handle_key(character, X.KeyPress)

    def release_key(self, character=''):
        """
        Release a given character key. Also works with character keycodes as
        integers, but not keysyms.
        """
        self._handle_key(character, X.KeyRelease)

    def special_key_assignment(self):
        """
        Determines the keycodes for common special keys on the keyboard. These
        are integer values and can be passed to the other key methods.
        Generally speaking, these are non-printable codes.
        """
        #This set of keys compiled using the X11 keysymdef.h file as reference
        #They comprise a relatively universal set of keys, though there may be
        #exceptions which may come up for other OSes and vendors. Countless
        #special cases exist which are not handled here, but may be extended.
        #TTY Function Keys
        self.backspace_key = self.lookup_character_keycode('BackSpace')
        self.tab_key = self.lookup_character_keycode('Tab')
        self.linefeed_key = self.lookup_character_keycode('Linefeed')
        self.clear_key = self.lookup_character_keycode('Clear')
        self.return_key = self.lookup_character_keycode('Return')
        self.enter_key = self.return_key  # Because many keyboards call it "Enter"
        self.pause_key = self.lookup_character_keycode('Pause')
        self.scroll_lock_key = self.lookup_character_keycode('Scroll_Lock')
        self.sys_req_key = self.lookup_character_keycode('Sys_Req')
        self.escape_key = self.lookup_character_keycode('Escape')
        self.delete_key = self.lookup_character_keycode('Delete')
        #Modifier Keys
        self.shift_l_key = self.lookup_character_keycode('Shift_L')
        self.shift_r_key = self.lookup_character_keycode('Shift_R')
        self.shift_key = self.shift_l_key  # Default Shift is left Shift
        self.alt_l_key = self.lookup_character_keycode('Alt_L')
        self.alt_r_key = self.lookup_character_keycode('Alt_R')
        self.altgr_key = self.lookup_character_keycode('ISO_Level3_Shift')
        self.alt_key = self.alt_l_key  # Default Alt is left Alt
        self.control_l_key = self.lookup_character_keycode('Control_L')
        self.control_r_key = self.lookup_character_keycode('Control_R')
        self.control_key = self.control_l_key  # Default Ctrl is left Ctrl
        self.caps_lock_key = self.lookup_character_keycode('Caps_Lock')
        self.capital_key = self.caps_lock_key  # Some may know it as Capital
        self.shift_lock_key = self.lookup_character_keycode('Shift_Lock')
        self.meta_l_key = self.lookup_character_keycode('Meta_L')
        self.meta_r_key = self.lookup_character_keycode('Meta_R')
        self.super_l_key = self.lookup_character_keycode('Super_L')
        self.windows_l_key = self.super_l_key  # Cross-support; also it's printed there
        self.super_r_key = self.lookup_character_keycode('Super_R')
        self.windows_r_key = self.super_r_key  # Cross-support; also it's printed there
        self.hyper_l_key = self.lookup_character_keycode('Hyper_L')
        self.hyper_r_key = self.lookup_character_keycode('Hyper_R')
        #Cursor Control and Motion
        self.home_key = self.lookup_character_keycode('Home')
        self.up_key = self.lookup_character_keycode('Up')
        self.down_key = self.lookup_character_keycode('Down')
        self.left_key = self.lookup_character_keycode('Left')
        self.right_key = self.lookup_character_keycode('Right')
        self.end_key = self.lookup_character_keycode('End')
        self.begin_key = self.lookup_character_keycode('Begin')
        self.page_up_key = self.lookup_character_keycode('Page_Up')
        self.page_down_key = self.lookup_character_keycode('Page_Down')
        self.prior_key = self.lookup_character_keycode('Prior')
        self.next_key = self.lookup_character_keycode('Next')
        #Misc Functions
        self.select_key = self.lookup_character_keycode('Select')
        self.print_key = self.lookup_character_keycode('Print')
        self.print_screen_key = self.print_key  # Seems to be the same thing
        self.snapshot_key = self.print_key  # Another name for printscreen
        self.execute_key = self.lookup_character_keycode('Execute')
        self.insert_key = self.lookup_character_keycode('Insert')
        self.undo_key = self.lookup_character_keycode('Undo')
        self.redo_key = self.lookup_character_keycode('Redo')
        self.menu_key = self.lookup_character_keycode('Menu')
        self.apps_key = self.menu_key  # Windows...
        self.find_key = self.lookup_character_keycode('Find')
        self.cancel_key = self.lookup_character_keycode('Cancel')
        self.help_key = self.lookup_character_keycode('Help')
        self.break_key = self.lookup_character_keycode('Break')
        self.mode_switch_key = self.lookup_character_keycode('Mode_switch')
        self.script_switch_key = self.lookup_character_keycode('script_switch')
        self.num_lock_key = self.lookup_character_keycode('Num_Lock')
        #Keypad Keys: Dictionary structure
        keypad = [
            'Space', 'Tab', 'Enter', 'F1', 'F2', 'F3', 'F4', 'Home', 'Left',
            'Up', 'Right', 'Down', 'Prior', 'Page_Up', 'Next', 'Page_Down',
            'End', 'Begin', 'Insert', 'Delete', 'Equal', 'Multiply', 'Add',
            'Separator', 'Subtract', 'Decimal', 'Divide', 0, 1, 2, 3, 4, 5, 6,
            7, 8, 9
        ]
        self.keypad_keys = dict(
            (k, self.lookup_character_keycode('KP_' + str(k))) for k in keypad)
        self.numpad_keys = self.keypad_keys
        #Function Keys/ Auxilliary Keys
        #FKeys
        self.function_keys = [None] + [
            self.lookup_character_keycode('F' + str(i)) for i in range(1, 36)
        ]
        #LKeys
        self.l_keys = [None] + [
            self.lookup_character_keycode('L' + str(i)) for i in range(1, 11)
        ]
        #RKeys
        self.r_keys = [None] + [
            self.lookup_character_keycode('R' + str(i)) for i in range(1, 16)
        ]

        #Unsupported keys from windows
        self.kana_key = None
        self.hangeul_key = None  # old name - should be here for compatibility
        self.hangul_key = None
        self.junjua_key = None
        self.final_key = None
        self.hanja_key = None
        self.kanji_key = None
        self.convert_key = None
        self.nonconvert_key = None
        self.accept_key = None
        self.modechange_key = None
        self.sleep_key = None

    def lookup_character_keycode(self, character):
        """
        Looks up the keysym for the character then returns the keycode mapping
        for that keysym.
        """
        keysym = Xlib.XK.string_to_keysym(character)
        if not keysym:
            try:
                keysym = getattr(Xlib.keysymdef.xkb, 'XK_' + character, 0)
            except:
                keysym = 0
        if not keysym:
            keysym = Xlib.XK.string_to_keysym(KEYSYMS[character])
        return self.display.keysym_to_keycode(keysym)
Exemple #58
0
class PyKeyboard(PyKeyboardMeta):
    def __init__(self, display=None):
        PyKeyboardMeta.__init__(self)
        self.display = Display(display)
        self.display2 = Display(display)
        self.special_key_assignment()

    def press_key(self, character=''):

        try:  # Detect uppercase or shifted character
            shifted = self.is_char_shifted(character)
        except AttributeError:  # Handle the case of integer keycode argument
            fake_input(self.display, X.KeyPress, character)
            self.display.sync()
        else:
            if shifted:
                fake_input(self.display, X.KeyPress, self.shift_key)
            keycode = self.lookup_character_keycode(character)
            fake_input(self.display, X.KeyPress, keycode)
            self.display.sync()

    def release_key(self, character=''):
        """
        Release a given character key. Also works with character keycodes as
        integers, but not keysyms.
        """
        try:  # Detect uppercase or shifted character
            shifted = self.is_char_shifted(character)
        except AttributeError:  # Handle the case of integer keycode argument
            fake_input(self.display, X.KeyRelease, character)
            self.display.sync()
        else:
            if shifted:
                fake_input(self.display, X.KeyRelease, self.shift_key)
            keycode = self.lookup_character_keycode(character)
            fake_input(self.display, X.KeyRelease, keycode)
            self.display.sync()

    def special_key_assignment(self):

        self.backspace_key = self.lookup_character_keycode('BackSpace')
        self.tab_key = self.lookup_character_keycode('Tab')
        self.linefeed_key = self.lookup_character_keycode('Linefeed')
        self.clear_key = self.lookup_character_keycode('Clear')
        self.return_key = self.lookup_character_keycode('Return')
        self.enter_key = self.return_key  # Because many keyboards call it "Enter"
        self.pause_key = self.lookup_character_keycode('Pause')
        self.scroll_lock_key = self.lookup_character_keycode('Scroll_Lock')
        self.sys_req_key = self.lookup_character_keycode('Sys_Req')
        self.escape_key = self.lookup_character_keycode('Escape')
        self.delete_key = self.lookup_character_keycode('Delete')
        #Modifier Keys
        self.shift_l_key = self.lookup_character_keycode('Shift_L')
        self.shift_r_key = self.lookup_character_keycode('Shift_R')
        self.shift_key = self.shift_l_key  # Default Shift is left Shift
        self.alt_l_key = self.lookup_character_keycode('Alt_L')
        self.alt_r_key = self.lookup_character_keycode('Alt_R')
        self.alt_key = self.alt_l_key  # Default Alt is left Alt
        self.control_l_key = self.lookup_character_keycode('Control_L')
        self.control_r_key = self.lookup_character_keycode('Control_R')
        self.control_key = self.control_l_key  # Default Ctrl is left Ctrl
        self.caps_lock_key = self.lookup_character_keycode('Caps_Lock')
        self.capital_key = self.caps_lock_key  # Some may know it as Capital
        self.shift_lock_key = self.lookup_character_keycode('Shift_Lock')
        self.meta_l_key = self.lookup_character_keycode('Meta_L')
        self.meta_r_key = self.lookup_character_keycode('Meta_R')
        self.super_l_key = self.lookup_character_keycode('Super_L')
        self.windows_l_key = self.super_l_key  # Cross-support; also it's printed there
        self.super_r_key = self.lookup_character_keycode('Super_R')
        self.windows_r_key = self.super_r_key  # Cross-support; also it's printed there
        self.hyper_l_key = self.lookup_character_keycode('Hyper_L')
        self.hyper_r_key = self.lookup_character_keycode('Hyper_R')
        #Cursor Control and Motion
        self.home_key = self.lookup_character_keycode('Home')
        self.up_key = self.lookup_character_keycode('Up')
        self.down_key = self.lookup_character_keycode('Down')
        self.left_key = self.lookup_character_keycode('Left')
        self.right_key = self.lookup_character_keycode('Right')
        self.end_key = self.lookup_character_keycode('End')
        self.begin_key = self.lookup_character_keycode('Begin')
        self.page_up_key = self.lookup_character_keycode('Page_Up')
        self.page_down_key = self.lookup_character_keycode('Page_Down')
        self.prior_key = self.lookup_character_keycode('Prior')
        self.next_key = self.lookup_character_keycode('Next')
        #Misc Functions
        self.select_key = self.lookup_character_keycode('Select')
        self.print_key = self.lookup_character_keycode('Print')
        self.print_screen_key = self.print_key  # Seems to be the same thing
        self.snapshot_key = self.print_key  # Another name for printscreen
        self.execute_key = self.lookup_character_keycode('Execute')
        self.insert_key = self.lookup_character_keycode('Insert')
        self.undo_key = self.lookup_character_keycode('Undo')
        self.redo_key = self.lookup_character_keycode('Redo')
        self.menu_key = self.lookup_character_keycode('Menu')
        self.apps_key = self.menu_key  # Windows...
        self.find_key = self.lookup_character_keycode('Find')
        self.cancel_key = self.lookup_character_keycode('Cancel')
        self.help_key = self.lookup_character_keycode('Help')
        self.break_key = self.lookup_character_keycode('Break')
        self.mode_switch_key = self.lookup_character_keycode('Mode_switch')
        self.script_switch_key = self.lookup_character_keycode('script_switch')
        self.num_lock_key = self.lookup_character_keycode('Num_Lock')
        #Keypad Keys: Dictionary structure
        keypad = [
            'Space', 'Tab', 'Enter', 'F1', 'F2', 'F3', 'F4', 'Home', 'Left',
            'Up', 'Right', 'Down', 'Prior', 'Page_Up', 'Next', 'Page_Down',
            'End', 'Begin', 'Insert', 'Delete', 'Equal', 'Multiply', 'Add',
            'Separator', 'Subtract', 'Decimal', 'Divide', 0, 1, 2, 3, 4, 5, 6,
            7, 8, 9
        ]
        self.keypad_keys = {
            k: self.lookup_character_keycode('KP_' + str(k))
            for k in keypad
        }
        self.numpad_keys = self.keypad_keys
        #Function Keys/ Auxilliary Keys
        #FKeys
        self.function_keys = [None] + [
            self.lookup_character_keycode('F' + str(i)) for i in range(1, 36)
        ]
        #LKeys
        self.l_keys = [None] + [
            self.lookup_character_keycode('L' + str(i)) for i in range(1, 11)
        ]
        #RKeys
        self.r_keys = [None] + [
            self.lookup_character_keycode('R' + str(i)) for i in range(1, 16)
        ]

        #Unsupported keys from windows
        self.kana_key = None
        self.hangeul_key = None  # old name - should be here for compatibility
        self.hangul_key = None
        self.junjua_key = None
        self.final_key = None
        self.hanja_key = None
        self.kanji_key = None
        self.convert_key = None
        self.nonconvert_key = None
        self.accept_key = None
        self.modechange_key = None
        self.sleep_key = None

    def lookup_character_keycode(self, character):
        keysym = Xlib.XK.string_to_keysym(character)
        if keysym == 0:
            keysym = Xlib.XK.string_to_keysym(special_X_keysyms[character])
        return self.display.keysym_to_keycode(keysym)