Example #1
0
    def _on_device_event(self, event):
        """
        Handler for XI2 events.
        """
        event_type = event.xi_type
        device_id  = event.device_id

        log = self._log_event_stub
        if _logger.isEnabledFor(logging.DEBUG) and \
            event_type != XIEventType.Motion and \
            event_type != XIEventType.TouchUpdate:
            self._log_device_event(event)
            log = self.log_event

        # re-select devices on changes to the device hierarchy
        if event_type in XIEventType.HierarchyEvents or \
           event_type == XIEventType.DeviceChanged:
            self.select_xinput_devices()
            return

        log("_on_device_event1")

        if event_type == XIEventType.KeyPress or \
           event_type == XIEventType.KeyRelease:
            return

        # check device_id, discard duplicate and unknown events
        if event_type == XIEventType.Enter or \
           event_type == XIEventType.Leave:

            log("_on_device_event2 {} {}", device_id, self._master_device_id)
            # enter/leave are only expected from the master device
            if not device_id == self._master_device_id:
                log("_on_device_event3")
                return

        else:
            # all other pointer/touch events have to come from slaves
            log("_on_device_event4 {} {}", event.device_id, self._slave_device_ids)
            if not event.device_id in self._slave_device_ids:
                log("_on_device_event5")
                return

        # bail if the window isn't realized yet
        win = self.get_window()
        if not win:
            log("_on_device_event6")
            return

        # scale coordinates in response to changes to
        # org.gnome.desktop.interface scaling-factor
        try:
            scale = win.get_scale_factor()  # from Gdk 3.10
            log("_on_device_event7 {}", scale)
            if scale and scale != 1.0:
                scale = 1.0 / scale
                event.x = event.x * scale
                event.y = event.y * scale
                event.x_root = event.x_root * scale
                event.y_root = event.y_root * scale
        except AttributeError:
            pass

        # Slaves aren't grabbed for moving/resizing when simulating a drag
        # operation (drag click button), or when multiple slave devices are
        # involved (one for button press, another for motion).
        # -> Simulate pointer grab, select root events we can track even
        #    outside the keyboard window.
        # None of these problems are assumed to exist for touch devices.
        log("_on_device_event8 {}", self._xi_grab_active)
        if self._xi_grab_active and \
           (event_type == XIEventType.Motion or \
            event_type == XIEventType.ButtonRelease):
            if not self._xi_grab_events_selected:
                self._select_xi_grab_events(True)

            log("_on_device_event9")

            # We only get root window coordinates for root window events,
            # so convert them to our target window's coordinates.
            rx, ry = win.get_root_coords(0, 0)
            event.x = event.x_root - rx
            event.y = event.y_root - ry

        else:
            # Is self the hit window?
            # We need this only for the multi-touch case with open
            # long press popup, e.g. while shift is held down with
            # one finger, touching anything in a long press popup must
            # not also affect the keyboard below.
            xid_event = event.xid_event
            xid_win = win.get_xid()
            log("_on_device_event10 {} {}", xid_event, xid_win)
            if xid_event != 0 and \
                xid_event != xid_win:
                log("_on_device_event11")
                return

        # Dispatch events
        self._xi_event_handled = False
        if event_type == XIEventType.Motion:
            self._on_motion_event(self, event)

        elif event_type == XIEventType.TouchUpdate or \
             event_type == XIEventType.TouchBegin or \
             event_type == XIEventType.TouchEnd:
            self._on_touch_event(self, event)

        elif event_type == XIEventType.ButtonPress:
            self._on_button_press_event(self, event)

        elif event_type == XIEventType.ButtonRelease:
            self._on_button_release_event(self, event)

            # Notify CSButtonMapper, end remapped click.
            if not self._xi_event_handled:
                EventSource.emit(self, "button-release", event)

        elif event_type == XIEventType.Enter:
            self._on_enter_notify(self, event)

        elif event_type == XIEventType.Leave:
            self._on_leave_notify(self, event)
Example #2
0
    def _on_device_event(self, event):
        """
        Handler for XI2 events.
        """
        event_type = event.xi_type
        device_id = event.device_id

        log = self._log_event_stub
        if _logger.isEnabledFor(logging.DEBUG) and \
            event_type != XIEventType.Motion and \
            event_type != XIEventType.TouchUpdate:
            self._log_device_event(event)
            log = self.log_event

        # re-select devices on changes to the device hierarchy
        if event_type in XIEventType.HierarchyEvents or \
           event_type == XIEventType.DeviceChanged:
            self.select_xinput_devices()
            return

        log("_on_device_event1")

        if event_type == XIEventType.KeyPress or \
           event_type == XIEventType.KeyRelease:
            return

        # check device_id, discard duplicate and unknown events
        if event_type == XIEventType.Enter or \
           event_type == XIEventType.Leave:

            log("_on_device_event2 {} {}", device_id, self._master_device_id)
            # enter/leave are only expected from the master device
            if not device_id == self._master_device_id:
                log("_on_device_event3")
                return

        else:
            # all other pointer/touch events have to come from slaves
            log("_on_device_event4 {} {}", event.device_id,
                self._slave_device_ids)
            if not event.device_id in self._slave_device_ids:
                log("_on_device_event5")
                return

        # bail if the window isn't realized yet
        win = self.get_window()
        if not win:
            log("_on_device_event6")
            return

        # scale coordinates in response to changes to
        # org.gnome.desktop.interface scaling-factor
        try:
            scale = win.get_scale_factor()  # from Gdk 3.10
            log("_on_device_event7 {}", scale)
            if scale and scale != 1.0:
                scale = 1.0 / scale
                event.x = event.x * scale
                event.y = event.y * scale
                event.x_root = event.x_root * scale
                event.y_root = event.y_root * scale
        except AttributeError:
            pass

        # Slaves aren't grabbed for moving/resizing when simulating a drag
        # operation (drag click button), or when multiple slave devices are
        # involved (one for button press, another for motion).
        # -> Simulate pointer grab, select root events we can track even
        #    outside the keyboard window.
        # None of these problems are assumed to exist for touch devices.
        log("_on_device_event8 {}", self._xi_grab_active)
        if self._xi_grab_active and \
           (event_type == XIEventType.Motion or
            event_type == XIEventType.ButtonRelease):
            if not self._xi_grab_events_selected:
                self._select_xi_grab_events(True)

            log("_on_device_event9")

            # We only get root window coordinates for root window events,
            # so convert them to our target window's coordinates.
            rx, ry = win.get_root_coords(0, 0)
            event.x = event.x_root - rx
            event.y = event.y_root - ry

        else:
            # Is self the hit window?
            # We need this only for the multi-touch case with open
            # long press popup, e.g. while shift is held down with
            # one finger, touching anything in a long press popup must
            # not also affect the keyboard below.
            xid_event = event.xid_event
            xid_win = self.get_xid()
            log("_on_device_event10 {} {}", xid_event, xid_win)
            if xid_event != 0 and \
               xid_event != xid_win:
                log("_on_device_event11")
                return

        # Dispatch events
        self._xi_event_handled = False
        if event_type == XIEventType.Motion:
            self._on_motion_event(self, event)

        elif event_type == XIEventType.TouchUpdate or \
             event_type == XIEventType.TouchBegin or \
             event_type == XIEventType.TouchEnd:
            self._on_touch_event(self, event)

        elif event_type == XIEventType.ButtonPress:
            self._on_button_press_event(self, event)

        elif event_type == XIEventType.ButtonRelease:
            self._on_button_release_event(self, event)

            # Notify CSButtonMapper, end remapped click.
            if not self._xi_event_handled:
                EventSource.emit(self, "button-release", event)

        elif event_type == XIEventType.Enter:
            self._on_enter_notify(self, event)

        elif event_type == XIEventType.Leave:
            self._on_leave_notify(self, event)