From 8e19199524b3fc0b7adbbc68427c1a9db98bd575 Mon Sep 17 00:00:00 2001 From: A Frederick Christensen Date: Sun, 14 Jan 2024 08:30:31 -0600 Subject: [PATCH] Add SIMPLE touchscreen handling This is based in part on original work by Bastien Brouant, "Unprex" at https://github.com/Unprex/dwl !!!!!!!!!!!!!!! This patch may be used with or without the pointer-constraints branch from anon_cvptw's repository https://codeberg.org/anon_cvptw/dwl/src/branch/main In maintaining this patch, be sure to watch for changes to the `motionabsolute` function in anon_cvptw's `main` branch: The `touchdown` function here incorporates the contents of the `motionabsolute` function, adds in the `wlr_cursor_warp_closest` call and then the button press If `motionabsolute` is modified, `touchdown` should [likely] mirror any of its modifications. If/when anon_cvptw's pointer-constraints pull request is merged into the upstream https://codeberg.org/dwl/dwl codebase, this remark will be removed from the simple-touch-input patch branch commit, and things will be significantly simplified. KNOWN BUGS: - Sometimes, the pointer moves to where the screen is pressed, but the button press doesn't occur until the screen is touched AGAIN. This means that if you touch to click button 'Q' on the screen (for instance), nothing happens; then you touch elsewhere on the screen and THEN button 'Q' registers a click. This is annoying, doesn't always happen, and I don't yet know how to fix it. !!!!!!!!!!!!!!! --- dwl.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/dwl.c b/dwl.c index a20c607..ce00134 100644 --- a/dwl.c +++ b/dwl.c @@ -45,6 +45,7 @@ #include #include #include +#include #include #include #include @@ -253,6 +254,7 @@ static void createlocksurface(struct wl_listener *listener, void *data); static void createmon(struct wl_listener *listener, void *data); static void createnotify(struct wl_listener *listener, void *data); static void createpointer(struct wlr_pointer *pointer); +static void createtouch(struct wlr_touch *touch); static void cursorframe(struct wl_listener *listener, void *data); static void destroydecoration(struct wl_listener *listener, void *data); static void destroydragicon(struct wl_listener *listener, void *data); @@ -319,6 +321,8 @@ static void togglefloating(const Arg *arg); static void togglefullscreen(const Arg *arg); static void toggletag(const Arg *arg); static void toggleview(const Arg *arg); +static void touchdown(struct wl_listener *listener, void *data); +static void touchup(struct wl_listener *listener, void *data); static void unlocksession(struct wl_listener *listener, void *data); static void unmaplayersurfacenotify(struct wl_listener *listener, void *data); static void unmapnotify(struct wl_listener *listener, void *data); @@ -1006,6 +1010,50 @@ createpointer(struct wlr_pointer *pointer) wlr_cursor_attach_input_device(cursor, &pointer->base); } +void +createtouch(struct wlr_touch *touch) +{ + if (wlr_input_device_is_libinput(&touch->base)) { + struct libinput_device *libinput_device = (struct libinput_device*) + wlr_libinput_get_device_handle(&touch->base); + + if (libinput_device_config_tap_get_finger_count(libinput_device)) { + libinput_device_config_tap_set_enabled(libinput_device, tap_to_click); + libinput_device_config_tap_set_drag_enabled(libinput_device, tap_and_drag); + libinput_device_config_tap_set_drag_lock_enabled(libinput_device, drag_lock); + libinput_device_config_tap_set_button_map(libinput_device, button_map); + } + + if (libinput_device_config_scroll_has_natural_scroll(libinput_device)) + libinput_device_config_scroll_set_natural_scroll_enabled(libinput_device, natural_scrolling); + + if (libinput_device_config_dwt_is_available(libinput_device)) + libinput_device_config_dwt_set_enabled(libinput_device, disable_while_typing); + + if (libinput_device_config_left_handed_is_available(libinput_device)) + libinput_device_config_left_handed_set(libinput_device, left_handed); + + if (libinput_device_config_middle_emulation_is_available(libinput_device)) + libinput_device_config_middle_emulation_set_enabled(libinput_device, middle_button_emulation); + + if (libinput_device_config_scroll_get_methods(libinput_device) != LIBINPUT_CONFIG_SCROLL_NO_SCROLL) + libinput_device_config_scroll_set_method (libinput_device, scroll_method); + + if (libinput_device_config_click_get_methods(libinput_device) != LIBINPUT_CONFIG_CLICK_METHOD_NONE) + libinput_device_config_click_set_method (libinput_device, click_method); + + if (libinput_device_config_send_events_get_modes(libinput_device)) + libinput_device_config_send_events_set_mode(libinput_device, send_events_mode); + + if (libinput_device_config_accel_is_available(libinput_device)) { + libinput_device_config_accel_set_profile(libinput_device, accel_profile); + libinput_device_config_accel_set_speed(libinput_device, accel_speed); + } + } + + wlr_cursor_attach_input_device(cursor, &touch->base); +} + void cursorframe(struct wl_listener *listener, void *data) { @@ -1335,6 +1383,9 @@ inputdevice(struct wl_listener *listener, void *data) case WLR_INPUT_DEVICE_POINTER: createpointer(wlr_pointer_from_input_device(device)); break; + case WLR_INPUT_DEVICE_TOUCH: + createtouch(wlr_touch_from_input_device(device)); + break; default: /* TODO handle other input device types */ break; @@ -2315,6 +2366,10 @@ setup(void) LISTEN_STATIC(&cursor->events.button, buttonpress); LISTEN_STATIC(&cursor->events.axis, axisnotify); LISTEN_STATIC(&cursor->events.frame, cursorframe); + LISTEN_STATIC(&cursor->events.touch_down, touchdown); + LISTEN_STATIC(&cursor->events.touch_frame, cursorframe); + LISTEN_STATIC(&cursor->events.touch_motion, motionabsolute); + LISTEN_STATIC(&cursor->events.touch_up, touchup); cursor_shape_mgr = wlr_cursor_shape_manager_v1_create(dpy, 1); LISTEN_STATIC(&cursor_shape_mgr->events.request_set_shape, setcursorshape); @@ -2528,6 +2583,38 @@ toggleview(const Arg *arg) printstatus(); } +void +touchdown(struct wl_listener *listener, void *data) +{ + struct wlr_pointer_button_event *button_event = data; + +#ifdef POINTERCONSTRAINTS + struct wlr_pointer_motion_absolute_event *event = data; + double lx, ly, dx, dy; + + wlr_cursor_absolute_to_layout_coords(cursor, &event->pointer->base, event->x, event->y, &lx, &ly); + wlr_cursor_warp_closest(cursor, &event->pointer->base, lx, ly); + dx = lx - cursor->x; + dy = ly - cursor->y; + motionnotify(event->time_msec, &event->pointer->base, dx, dy, dx, dy); +#else + motionabsolute(listener, data); +#endif + + button_event->button=BTN_LEFT; + button_event->state=WLR_BUTTON_PRESSED; + buttonpress(listener, button_event); +} + +void +touchup(struct wl_listener *listener, void *data) +{ + struct wlr_pointer_button_event *button_event = data; + button_event->button=BTN_LEFT; + button_event->state=WLR_BUTTON_RELEASED; + buttonpress(listener, button_event); +} + void unlocksession(struct wl_listener *listener, void *data) {