From d20af8bf17f17cbd4e7a21a67d15886ef7649b37 Mon Sep 17 00:00:00 2001 From: Lars Date: Mon, 11 Mar 2024 17:48:00 +0100 Subject: [PATCH 1/8] Attempt to fix issue #133: Touch class * Added class Touch similar to Pointer * Renamed exceptions (put Event to the end) * Added touch.h to ffi_build.py --- wlroots/ffi_build.py | 57 +++++++++++++++++++++++++++ wlroots/wlr_types/touch.py | 80 +++++++++++++++++++------------------- 2 files changed, 98 insertions(+), 39 deletions(-) diff --git a/wlroots/ffi_build.py b/wlroots/ffi_build.py index db10297d..5e01a3bc 100644 --- a/wlroots/ffi_build.py +++ b/wlroots/ffi_build.py @@ -2213,6 +2213,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 +2878,7 @@ def has_xwayland() -> bool: #include #include #include +#include #include #include #include diff --git a/wlroots/wlr_types/touch.py b/wlroots/wlr_types/touch.py index 8a412410..03129189 100644 --- a/wlroots/wlr_types/touch.py +++ b/wlroots/wlr_types/touch.py @@ -1,34 +1,50 @@ # Copyright (c) Matt Colligan 2021 +from __future__ import annotations -from wlroots import Ptr, ffi +import warnings + +from wlroots import Ptr, ffi, lib, str_or_none + +from weakref import WeakKeyDictionary 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 +54,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 +68,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) - - @property - def device(self) -> InputDevice: - return InputDevice(self._ptr.device) + self._ptr = ffi.cast("struct wlr_event_touch_up *", ptr) - @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 +86,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 From 7af909546c0bd191153d54b5c6c0f98e1cd5bc5d Mon Sep 17 00:00:00 2001 From: Lars Date: Mon, 11 Mar 2024 18:02:55 +0100 Subject: [PATCH 2/8] Removed unused import -> made ruff happy --- wlroots/wlr_types/touch.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/wlroots/wlr_types/touch.py b/wlroots/wlr_types/touch.py index 03129189..37895e71 100644 --- a/wlroots/wlr_types/touch.py +++ b/wlroots/wlr_types/touch.py @@ -1,12 +1,10 @@ # Copyright (c) Matt Colligan 2021 from __future__ import annotations -import warnings +from weakref import WeakKeyDictionary from wlroots import Ptr, ffi, lib, str_or_none -from weakref import WeakKeyDictionary - from .input_device import InputDevice _weakkeydict: WeakKeyDictionary = WeakKeyDictionary() From 97977c04a761d5324c64f8e494aab1d980716a17 Mon Sep 17 00:00:00 2001 From: Lars Date: Mon, 11 Mar 2024 18:05:42 +0100 Subject: [PATCH 3/8] Added whitespace to line comment --- wlroots/ffi_build.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wlroots/ffi_build.py b/wlroots/ffi_build.py index 5e01a3bc..fce3702a 100644 --- a/wlroots/ffi_build.py +++ b/wlroots/ffi_build.py @@ -2213,7 +2213,7 @@ def has_xwayland() -> bool: struct wlr_server_decoration_manager *manager, uint32_t default_mode); """ -#types/wlr_touch.h +# types/wlr_touch.h CDEF += """ struct wlr_touch { struct wlr_input_device base; From c3523b5fb9148bc5411fcd42fd9ef117b685c0e0 Mon Sep 17 00:00:00 2001 From: Lars Date: Mon, 11 Mar 2024 19:13:25 +0100 Subject: [PATCH 4/8] cursor.py: Use new touch event names --- wlroots/wlr_types/cursor.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/wlroots/wlr_types/cursor.py b/wlroots/wlr_types/cursor.py index fe00c015..bf2cefc6 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,19 @@ 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, ) @property From 44f54f606fcb738d84e718c5817151e4b8ef943e Mon Sep 17 00:00:00 2001 From: Lars Date: Mon, 11 Mar 2024 22:26:41 +0100 Subject: [PATCH 5/8] Added missing wlr_cursor.touch_frame event --- wlroots/wlr_types/cursor.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/wlroots/wlr_types/cursor.py b/wlroots/wlr_types/cursor.py index bf2cefc6..c8bd07a6 100644 --- a/wlroots/wlr_types/cursor.py +++ b/wlroots/wlr_types/cursor.py @@ -117,6 +117,9 @@ def __init__(self, output_layout: OutputLayout) -> None: ptr=ffi.addressof(self._ptr.events.touch_cancel), data_wrapper=TouchCancelEvent, ) + self.touch_frame_event = Signal( + ptr=ffi.addressof(self._ptr.events.touch_frame), + ) @property def x(self) -> float: From 95e36b72ddbb24e8b0518e9fb26068e3fb679433 Mon Sep 17 00:00:00 2001 From: Lars Date: Tue, 12 Mar 2024 21:56:40 +0100 Subject: [PATCH 6/8] Added several touch methods to Seat, only the grab functions are missing --- wlroots/ffi_build.py | 21 ++++++++++++--- wlroots/wlr_types/seat.py | 54 ++++++++++++++++++++++++++++++++++++--- 2 files changed, 68 insertions(+), 7 deletions(-) diff --git a/wlroots/ffi_build.py b/wlroots/ffi_build.py index fce3702a..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); diff --git a/wlroots/wlr_types/seat.py b/wlroots/wlr_types/seat.py index 85f53fa4..1e5e88b2 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,7 +233,7 @@ 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) @@ -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 From ce34996cf0705d7f9b068d929df6a7e507e0e806 Mon Sep 17 00:00:00 2001 From: Lars Date: Tue, 12 Mar 2024 22:12:31 +0100 Subject: [PATCH 7/8] Changed return statement of Seat.pointer_has_grab to boolean --- wlroots/wlr_types/seat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wlroots/wlr_types/seat.py b/wlroots/wlr_types/seat.py index 1e5e88b2..afe8adb4 100644 --- a/wlroots/wlr_types/seat.py +++ b/wlroots/wlr_types/seat.py @@ -235,7 +235,7 @@ def pointer_notify_frame(self) -> None: 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 From a91c03d3d5a4ca17172b706d096bd49a31cdd6b2 Mon Sep 17 00:00:00 2001 From: Lars Date: Wed, 13 Mar 2024 12:03:05 +0100 Subject: [PATCH 8/8] Fixed typo: Surface class vs. surface instance --- wlroots/wlr_types/seat.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wlroots/wlr_types/seat.py b/wlroots/wlr_types/seat.py index afe8adb4..859ca67d 100644 --- a/wlroots/wlr_types/seat.py +++ b/wlroots/wlr_types/seat.py @@ -361,7 +361,7 @@ def touch_point_clear_focus( ) -> 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 + self._ptr, surface._ptr, time_msec, touch_id, surface_x, surface_y ) def touch_notify_cancel(self, surface: Surface):