예제 #1
0
파일: _xorg.py 프로젝트: robocorp/pynput
    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))
예제 #2
0
파일: _xorg.py 프로젝트: robocorp/pynput
    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
예제 #3
0
파일: _xorg.py 프로젝트: robocorp/pynput
    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)
예제 #4
0
 def _release(self, button):
     with display_manager(self._display) as dm:
         Xlib.ext.xtest.fake_input(dm, Xlib.X.ButtonRelease, button.value)
예제 #5
0
 def _press(self, button):
     with display_manager(self._display) as dm:
         Xlib.ext.xtest.fake_input(dm, Xlib.X.ButtonPress, button.value)
예제 #6
0
 def _position_set(self, pos):
     px, py = self._check_bounds(*pos)
     with display_manager(self._display) as dm:
         Xlib.ext.xtest.fake_input(dm, Xlib.X.MotionNotify, x=px, y=py)
예제 #7
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)
예제 #8
0
파일: _xorg.py 프로젝트: robocorp/pynput
 def _update_keyboard_mapping(self):
     """Updates the keyboard mapping.
     """
     with display_manager(self._display) as dm:
         self._keyboard_mapping = keyboard_mapping(dm)