Beispiel #1
0
    def _send_key(self, event, keycode, shift_state):
        """Sends a single keyboard event.

        :param event: The *X* keyboard event.

        :param int keycode: The calculated keycode.

        :param int shift_state: The shift state. The actual value used is
            :attr:`shift_state` or'd with this value.
        """
        with display_manager(self._display) as dm, self.modifiers as modifiers:
            # Under certain cimcumstances, such as when running under Xephyr,
            # the value returned by dm.get_input_focus is an int
            window = dm.get_input_focus().focus
            send_event = getattr(
                window,
                'send_event',
                lambda event: dm.send_event(window, event))
            send_event(event(
                detail=keycode,
                state=shift_state | self._shift_mask(modifiers),
                time=0,
                root=dm.screen().root,
                window=window,
                same_screen=0,
                child=Xlib.X.NONE,
                root_x=0, root_y=0, event_x=0, event_y=0))
Beispiel #2
0
    def _resolve_borrowing(self, key):
        """Tries to resolve a key by modifying the layout temporarily.

        A borrowed *keysym* does not exist on the keyboard, but is temporarily
        added to the layout.

        :param KeyCode key: The key to resolve.
        """
        keysym = self._key_to_keysym(key)
        if keysym is None:
            return None

        mapping = self._display.get_keyboard_mapping(8, 255 - 8)

        def i2kc(index):
            return index + 8

        def kc2i(keycode):
            return keycode - 8

        #: Finds a keycode and index by looking at already used keycodes
        def reuse():
            for _, (keycode, _, _) in self._borrows.items():
                keycodes = mapping[kc2i(keycode)]

                # Only the first four items are addressable by X
                for index in range(4):
                    if not keycodes[index]:
                        return keycode, index

        #: Finds a keycode and index by using a new keycode
        def borrow():
            for i, keycodes in enumerate(mapping):
                if not any(keycodes):
                    return i2kc(i), 0

        #: Finds a keycode and index by reusing an old, unused one
        def overwrite():
            for keysym, (keycode, index, count) in self._borrows.items():
                if count < 1:
                    del self._borrows[keysym]
                    return keycode, index

        #: Registers a keycode for a specific key and modifier state
        def register(dm, keycode, index):
            i = kc2i(keycode)
            mapping[i][index] = keysym
            dm.change_keyboard_mapping(keycode, mapping[i:i + 1])
            self._borrows[keysym] = (keycode, index, 0)

        try:
            with display_manager(self._display) as dm, self._borrow_lock as _:
                # First try an already used keycode, then try a new one, and
                # fall back on reusing one that is not currently pressed
                register(dm, *(reuse() or borrow() or overwrite()))
            return keysym

        except TypeError:
            return None
Beispiel #3
0
    def _send_key(self, keycode, is_press):
        """Sends single key event.

        :param int keycode: The calculated keycode.

        :param bool is_press: Whether this is a press event.
        """
        with display_manager(self._display) as dm:
            Xlib.ext.xtest.fake_input(
                dm, Xlib.X.KeyPress if is_press else Xlib.X.KeyRelease,
                keycode)
Beispiel #4
0
    def _handle(self, key, is_press):
        """Resolves a key identifier and sends a keyboard event.

        :param event: The *X* keyboard event.

        :param int keysym: The keysym to handle.
        """
        event = Xlib.display.event.KeyPress if is_press \
            else Xlib.display.event.KeyRelease
        keysym = self._keysym(key)

        # Make sure to verify that the key was resolved
        if keysym is None:
            raise self.InvalidKeyException(key)

        # If the key has a virtual key code, use that immediately with
        # fake_input; fake input,being an X server extension, has access to more
        # internal state that we
        if key.vk is not None:
            with display_manager(self._display) as dm:
                Xlib.ext.xtest.fake_input(
                    dm,
                    Xlib.X.KeyPress if is_press else Xlib.X.KeyRelease,
                    dm.keysym_to_keycode(key.vk))

        # Otherwise use XSendEvent; we need to use this in the general case to
        # work around problems with keyboard layouts
        else:
            try:
                keycode, shift_state = self.keyboard_mapping[keysym]
                self._send_key(event, keycode, shift_state)

            except KeyError:
                with self._borrow_lock:
                    keycode, index, count = self._borrows[keysym]
                    self._send_key(
                        event,
                        keycode,
                        index_to_shift(self._display, index))
                    count += 1 if is_press else -1
                    self._borrows[keysym] = (keycode, index, count)

        # Notify any running listeners
        self._emit('_on_fake_event', key, is_press)
Beispiel #5
0
    def _send_modifier(self, mod_state, is_press):
        """Sends modifier keys.

        :param int mod_mask: A mask defining which modifier keys to use.

        :param bool is_press: Whether this is a press event.
        """
        is_press_ = Xlib.X.KeyPress if is_press else Xlib.X.KeyRelease
        with display_manager(self._display) as dm, self.modifiers as modifiers:
            mod_mask = mod_state | self._shift_mask(modifiers)
            if not mod_mask:
                return
            mod_mapping = dm.get_modifier_mapping()
            for mod_idx, mod_arr in enumerate(mod_mapping):
                if mod_mask & (1 << mod_idx):
                    for keycode in mod_arr:
                        if keycode:
                            Xlib.ext.xtest.fake_input(dm, is_press_, keycode)
                            break
Beispiel #6
0
    def _send_key(self, event, keycode, shift_state):
        """Sends a single keyboard event.

        :param event: The *X* keyboard event.

        :param int keycode: The keycode.

        :param int shift_state: The shift state. The actual value used is
            :attr:`shift_state` or'd with this value.
        """
        with display_manager(self._display) as dm, self.modifiers as modifiers:
            window = dm.get_input_focus().focus
            window.send_event(event(
                detail=keycode,
                state=shift_state | self._shift_mask(modifiers),
                time=0,
                root=dm.screen().root,
                window=window,
                same_screen=0,
                child=Xlib.X.NONE,
                root_x=0, root_y=0, event_x=0, event_y=0))
Beispiel #7
0
    def _handle(self, key, is_press):
        """Resolves a key identifier and sends a keyboard event.

        :param event: The *X* keyboard event.

        :param int keysym: The keysym to handle.
        """
        keysym = self._keysym(key)

        # Make sure to verify that the key was resolved
        if keysym is None:
            raise self.InvalidKeyException(key)

        # If the key has a virtual key code, use that immediately with
        # fake_input; fake input,being an X server extension, has access to more
        # internal state than we
        if key.vk is not None:
            with display_manager(self._display) as dm:
                Xlib.ext.xtest.fake_input(
                    dm, Xlib.X.KeyPress if is_press else Xlib.X.KeyRelease,
                    dm.keysym_to_keycode(key.vk))

        # Otherwise send the required modifier keys and the desired key with
        # fake_input.
        else:
            try:
                keycode, mod_state = self.keyboard_mapping[keysym]
                self._send_modifier(mod_state, is_press)
                self._send_key(keycode, is_press)
            except KeyError:
                with self._borrow_lock:
                    keycode, index, count = self._borrows[keysym]
                    mod_state = index_to_shift(self._display, index)
                    self._send_modifier(mod_state, is_press)
                    self._send_key(keycode, is_press)
                    count += 1 if is_press else -1
                    self._borrows[keysym] = (keycode, index, count)

        # Notify any running listeners
        self._emit('_on_fake_event', key, is_press)
Beispiel #8
0
 def _release(self, button):
     with display_manager(self._display) as dm:
         Xlib.ext.xtest.fake_input(dm, Xlib.X.ButtonRelease, button.value)
Beispiel #9
0
 def _press(self, button):
     with display_manager(self._display) as dm:
         Xlib.ext.xtest.fake_input(dm, Xlib.X.ButtonPress, button.value)
Beispiel #10
0
 def _position_set(self, pos):
     self._check_bounds(*pos)
     px, py = pos
     with display_manager(self._display) as dm:
         Xlib.ext.xtest.fake_input(dm, Xlib.X.MotionNotify, x=px, y=py)
Beispiel #11
0
 def _position_get(self):
     with display_manager(self._display) as dm:
         qp = dm.screen().root.query_pointer()
         return (qp.root_x, qp.root_y)
Beispiel #12
0
 def _update_keyboard_mapping(self):
     """Updates the keyboard mapping.
     """
     with display_manager(self._display) as dm:
         self._keyboard_mapping = keyboard_mapping(dm)