diff --git a/wlroots/ffi_build.py b/wlroots/ffi_build.py index db10297d..0344596b 100644 --- a/wlroots/ffi_build.py +++ b/wlroots/ffi_build.py @@ -2162,13 +2162,26 @@ def has_xwayland() -> bool: void wlr_seat_set_keyboard(struct wlr_seat *seat, struct wlr_keyboard *keyboard); struct wlr_keyboard *wlr_seat_get_keyboard(struct wlr_seat *seat); +void wlr_seat_touch_point_focus(struct wlr_seat *seat, + struct wlr_surface *surface, uint32_t time_msec, + int32_t touch_id, double sx, double sy); +void wlr_seat_touch_point_clear_focus(struct wlr_seat *seat, uint32_t time_msec, + int32_t touch_id); uint32_t wlr_seat_touch_notify_down(struct wlr_seat *seat, - struct wlr_surface *surface, uint32_t time_msec, - int32_t touch_id, double sx, double sy); + struct wlr_surface *surface, uint32_t time_msec, + int32_t touch_id, double sx, double sy); void wlr_seat_touch_notify_up(struct wlr_seat *seat, uint32_t time_msec, - int32_t touch_id); + int32_t touch_id); void wlr_seat_touch_notify_motion(struct wlr_seat *seat, uint32_t time_msec, - int32_t touch_id, double sx, double sy); + int32_t touch_id, double sx, double sy); +void wlr_seat_touch_notify_cancel(struct wlr_seat *seat, + struct wlr_surface *surface); +void wlr_seat_touch_notify_frame(struct wlr_seat *seat); +int wlr_seat_touch_num_points(struct wlr_seat *seat); +void wlr_seat_touch_start_grab(struct wlr_seat *wlr_seat, + struct wlr_seat_touch_grab *grab); +void wlr_seat_touch_end_grab(struct wlr_seat *wlr_seat); +bool wlr_seat_touch_has_grab(struct wlr_seat *seat); void wlr_seat_keyboard_start_grab(struct wlr_seat *wlr_seat, struct wlr_seat_keyboard_grab *grab); @@ -2213,6 +2226,62 @@ def has_xwayland() -> bool: struct wlr_server_decoration_manager *manager, uint32_t default_mode); """ +# types/wlr_touch.h +CDEF += """ +struct wlr_touch { + struct wlr_input_device base; + const struct wlr_touch_impl *impl; + char *output_name; + double width_mm, height_mm; + struct { + struct wl_signal down; // struct wlr_touch_down_event + struct wl_signal up; // struct wlr_touch_up_event + struct wl_signal motion; // struct wlr_touch_motion_event + struct wl_signal cancel; // struct wlr_touch_cancel_event + struct wl_signal frame; + } events; + + void *data; + + ...; +}; + +struct wlr_touch_down_event { + struct wlr_touch *touch; + uint32_t time_msec; + int32_t touch_id; + // From 0..1 + double x, y; + ...; +}; + +struct wlr_touch_up_event { + struct wlr_touch *touch; + uint32_t time_msec; + int32_t touch_id; + ...; +}; + +struct wlr_touch_motion_event { + struct wlr_touch *touch; + uint32_t time_msec; + int32_t touch_id; + // From 0..1 + double x, y; + ...; +}; + +struct wlr_touch_cancel_event { + struct wlr_touch *touch; + uint32_t time_msec; + int32_t touch_id; + ...; +}; + +struct wlr_touch *wlr_touch_from_input_device( + struct wlr_input_device *input_device); +""" + # types/wlr_virtual_keyboard_v1.h CDEF += """ struct wlr_virtual_keyboard_manager_v1 { @@ -2822,6 +2891,7 @@ def has_xwayland() -> bool: #include #include #include +#include #include #include #include diff --git a/wlroots/wlr_types/cursor.py b/wlroots/wlr_types/cursor.py index fe00c015..c8bd07a6 100644 --- a/wlroots/wlr_types/cursor.py +++ b/wlroots/wlr_types/cursor.py @@ -26,10 +26,10 @@ ) from .surface import Surface from .touch import ( - TouchEventCancel, - TouchEventDown, - TouchEventMotion, - TouchEventUp, + TouchCancelEvent, + TouchDownEvent, + TouchMotionEvent, + TouchUpEvent, ) @@ -103,19 +103,22 @@ def __init__(self, output_layout: OutputLayout) -> None: ) self.touch_up_event = Signal( ptr=ffi.addressof(self._ptr.events.touch_up), - data_wrapper=TouchEventUp, + data_wrapper=TouchUpEvent, ) self.touch_down_event = Signal( ptr=ffi.addressof(self._ptr.events.touch_down), - data_wrapper=TouchEventDown, + data_wrapper=TouchDownEvent, ) self.touch_motion_event = Signal( ptr=ffi.addressof(self._ptr.events.touch_motion), - data_wrapper=TouchEventMotion, + data_wrapper=TouchMotionEvent, ) self.touch_cancel_event = Signal( ptr=ffi.addressof(self._ptr.events.touch_cancel), - data_wrapper=TouchEventCancel, + data_wrapper=TouchCancelEvent, + ) + self.touch_frame_event = Signal( + ptr=ffi.addressof(self._ptr.events.touch_frame), ) @property diff --git a/wlroots/wlr_types/seat.py b/wlroots/wlr_types/seat.py index 85f53fa4..859ca67d 100644 --- a/wlroots/wlr_types/seat.py +++ b/wlroots/wlr_types/seat.py @@ -32,7 +32,7 @@ def __enter__(self) -> KeyboardGrab: def __exit__(self, exc_type, exc_value, exc_tb) -> None: """End the grab of the keyboard of this seat""" - lib.wlr_seat_keyboard_end_grab(self._seat) + lib.wlr_seat_keyboard_end_grab(self._seat._ptr) class Seat(PtrHasData): @@ -170,7 +170,6 @@ def pointer_clear_focus(self) -> None: This function does not respect pointer grabs: you probably want `pointer_notify_clear_focus()` instead. """ - return lib.wlr_seat_pointer_clear_focus(self._ptr) def pointer_notify_clear_focus(self) -> None: @@ -234,9 +233,9 @@ def pointer_notify_frame(self) -> None: """ lib.wlr_seat_pointer_notify_frame(self._ptr) - def pointer_has_grab(self): + def pointer_has_grab(self) -> bool: """Whether or not the pointer has a grab other than the default grab""" - lib.wlr_seat_pointer_has_grab(self._ptr) + return lib.wlr_seat_pointer_has_grab(self._ptr) def set_keyboard(self, keyboard: Keyboard | None) -> None: """Set this keyboard as the active keyboard for the seat @@ -336,6 +335,55 @@ def touch_notify_motion( self._ptr, time_msec, touch_id, surface_x, surface_y ) + def touch_point_focus( + self, + surface: Surface, + time_msec: int, + touch_id: int, + surface_x: float, + surface_y: float, + ) -> None: + """ + Notify the seat that the touch point given by `touch_id` has entered a new + surface. The surface is required. To clear focus, use touch_point_clear_focus(). + """ + lib.wlr_seat_touch_point_focus( + self._ptr, surface._ptr, time_msec, touch_id, surface_x, surface_y + ) + + def touch_point_clear_focus( + self, + surface: Surface, + time_msec: int, + touch_id: int, + surface_x: float, + surface_y: float, + ) -> None: + """Clear the focused surface for the touch point given by `touch_id`.""" + lib.wlr_seat_touch_point_clear_focus( + self._ptr, surface._ptr, time_msec, touch_id, surface_x, surface_y + ) + + def touch_notify_cancel(self, surface: Surface): + """Notify the seat that this is a global gesture and the client should + cancel processing it. Defers to any grab of the touch device.""" + lib.wlr_seat_touch_notify_cancel(self._ptr, surface._ptr) + + def touch_notify_frame(self) -> None: + lib.wlr_seat_touch_notify_frame(self._ptr) + + def touch_num_points(self) -> int: + """ + How many touch points are currently down for the seat. + """ + return lib.wlr_seat_touch_num_points(self._ptr) + + def touch_has_grab(self) -> bool: + """ + Whether or not the seat has a touch grab other than the default grab. + """ + return lib.wlr_seat_touch_has_grab(self._ptr) + def set_selection(self, source, serial: int) -> None: """Sets the current selection for the seat diff --git a/wlroots/wlr_types/touch.py b/wlroots/wlr_types/touch.py index 8a412410..37895e71 100644 --- a/wlroots/wlr_types/touch.py +++ b/wlroots/wlr_types/touch.py @@ -1,34 +1,48 @@ # Copyright (c) Matt Colligan 2021 +from __future__ import annotations -from wlroots import Ptr, ffi +from weakref import WeakKeyDictionary + +from wlroots import Ptr, ffi, lib, str_or_none from .input_device import InputDevice +_weakkeydict: WeakKeyDictionary = WeakKeyDictionary() + -class TouchEventUp(Ptr): +class Touch(Ptr): def __init__(self, ptr) -> None: - self._ptr = ffi.cast("struct wlr_event_touch_up *", ptr) + self._ptr = ptr + + @staticmethod + def from_input_device(input_device: InputDevice) -> Touch: + return Touch(lib.wlr_touch_from_input_device(input_device._ptr)) @property - def device(self) -> InputDevice: - return InputDevice(self._ptr.device) + def base(self) -> InputDevice: + device_ptr = ffi.addressof(self._ptr.base) + _weakkeydict[device_ptr] = self._ptr + return InputDevice(device_ptr) @property - def time_msec(self) -> int: - return self._ptr.time_msec + def output_name(self) -> str | None: + """The name of any associated output""" + return str_or_none(self._ptr.output_name) @property - def touch_id(self) -> int: - return self._ptr.touch_id + def width_mm(self) -> float: + return self._ptr.width_mm + @property + def height_mm(self) -> float: + return self._ptr.height_mm -class TouchEventDown(Ptr): - def __init__(self, ptr) -> None: - self._ptr = ffi.cast("struct wlr_event_touch_down *", ptr) +class _TouchEvent(Ptr): @property - def device(self) -> InputDevice: - return InputDevice(self._ptr.device) + def touch(self) -> Touch: + """The touch device associated with the event""" + return Touch(self._ptr.touch) @property def time_msec(self) -> int: @@ -38,6 +52,11 @@ def time_msec(self) -> int: def touch_id(self) -> int: return self._ptr.touch_id + +class TouchDownEvent(_TouchEvent): + def __init__(self, ptr) -> None: + self._ptr = ffi.cast("struct wlr_event_touch_down *", ptr) + @property def x(self) -> float: return self._ptr.x @@ -47,21 +66,14 @@ def y(self) -> float: return self._ptr.y -class TouchEventMotion(Ptr): +class TouchUpEvent(_TouchEvent): def __init__(self, ptr) -> None: - self._ptr = ffi.cast("struct wlr_event_touch_motion *", ptr) + self._ptr = ffi.cast("struct wlr_event_touch_up *", ptr) - @property - def device(self) -> InputDevice: - return InputDevice(self._ptr.device) - @property - def time_msec(self) -> int: - return self._ptr.time_msec - - @property - def touch_id(self) -> int: - return self._ptr.touch_id +class TouchMotionEvent(_TouchEvent): + def __init__(self, ptr) -> None: + self._ptr = ffi.cast("struct wlr_event_touch_motion *", ptr) @property def x(self) -> float: @@ -72,18 +84,6 @@ def y(self) -> float: return self._ptr.y -class TouchEventCancel(Ptr): +class TouchCancelEvent(_TouchEvent): def __init__(self, ptr) -> None: self._ptr = ffi.cast("struct wlr_event_touch_cancel *", ptr) - - @property - def device(self) -> InputDevice: - return InputDevice(self._ptr.device) - - @property - def time_msec(self) -> int: - return self._ptr.time_msec - - @property - def touch_id(self) -> int: - return self._ptr.touch_id