aboutsummaryrefslogtreecommitdiffstats
path: root/sway/input/cursor.c
diff options
context:
space:
mode:
authorLibravatar John Chadwick <john@jchw.io>2022-05-30 12:48:07 -0400
committerLibravatar Tudor Brindus <vulcainus@gmail.com>2023-01-07 23:52:27 -0500
commit3061999ec5ab25524e5a4ba5f5518c19bf57ce95 (patch)
tree21fafffd1a8571a4ab2beef887dee046944b5036 /sway/input/cursor.c
parentwarp_to_constraint_cursor_hint: Handle NULL view (diff)
downloadsway-3061999ec5ab25524e5a4ba5f5518c19bf57ce95.tar.gz
sway-3061999ec5ab25524e5a4ba5f5518c19bf57ce95.tar.zst
sway-3061999ec5ab25524e5a4ba5f5518c19bf57ce95.zip
Improve tablet tool button handling.
This change allows the tablet tool button to be used for floating mod resize. In addition, it attempts to ensure that tablet tool events are consistent such that tablet v2 events and pointer events will never be interleaved, and such that the tool buttons count will never fall out of sync and cause tool button emulation to break. Some of this logic is similar to what is done for tablet tool tip, but not quite identical, because of the complication that we have to deal with multiple inputs that can overlap eachother. Fixes #7036.
Diffstat (limited to 'sway/input/cursor.c')
-rw-r--r--sway/input/cursor.c54
1 files changed, 47 insertions, 7 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 9d83008f..243eb42c 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -818,7 +818,34 @@ static void handle_tool_button(struct wl_listener *listener, void *data) {
818 node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y, 818 node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y,
819 &surface, &sx, &sy); 819 &surface, &sx, &sy);
820 820
821 if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { 821 // TODO: floating resize should support graphics tablet events
822 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(cursor->seat->wlr_seat);
823 uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
824 bool mod_pressed = modifiers & config->floating_mod;
825
826 bool surface_supports_tablet_events =
827 surface && wlr_surface_accepts_tablet_v2(tablet_v2, surface);
828
829 // Simulate pointer when:
830 // 1. The modifier key is pressed, OR
831 // 2. The surface under the cursor does not support tablet events.
832 bool should_simulate_pointer = mod_pressed || !surface_supports_tablet_events;
833
834 // Similar to tool tip, we need to selectively simulate mouse events, but we
835 // want to make sure that it is always consistent. Because all tool buttons
836 // currently map to BTN_RIGHT, we need to keep count of how many tool
837 // buttons are currently pressed down so we can send consistent events.
838 //
839 // The logic follows:
840 // - If we are already simulating the pointer, we should continue to do so
841 // until at least no tool button is held down.
842 // - If we should simulate the pointer and no tool button is currently held
843 // down, begin simulating the pointer.
844 // - If neither of the above are true, send the tablet events.
845 if ((cursor->tool_buttons > 0 && cursor->simulating_pointer_from_tool_button)
846 || (cursor->tool_buttons == 0 && should_simulate_pointer)) {
847 cursor->simulating_pointer_from_tool_button = true;
848
822 // TODO: the user may want to configure which tool buttons are mapped to 849 // TODO: the user may want to configure which tool buttons are mapped to
823 // which simulated pointer buttons 850 // which simulated pointer buttons
824 switch (event->state) { 851 switch (event->state) {
@@ -827,22 +854,35 @@ static void handle_tool_button(struct wl_listener *listener, void *data) {
827 dispatch_cursor_button(cursor, &event->tablet->base, 854 dispatch_cursor_button(cursor, &event->tablet->base,
828 event->time_msec, BTN_RIGHT, event->state); 855 event->time_msec, BTN_RIGHT, event->state);
829 } 856 }
830 cursor->tool_buttons++;
831 break; 857 break;
832 case WLR_BUTTON_RELEASED: 858 case WLR_BUTTON_RELEASED:
833 if (cursor->tool_buttons == 1) { 859 if (cursor->tool_buttons <= 1) {
834 dispatch_cursor_button(cursor, &event->tablet->base, 860 dispatch_cursor_button(cursor, &event->tablet->base,
835 event->time_msec, BTN_RIGHT, event->state); 861 event->time_msec, BTN_RIGHT, event->state);
836 } 862 }
837 cursor->tool_buttons--;
838 break; 863 break;
839 } 864 }
840 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); 865 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
841 return; 866 } else {
867 cursor->simulating_pointer_from_tool_button = false;
868
869 wlr_tablet_v2_tablet_tool_notify_button(sway_tool->tablet_v2_tool,
870 event->button, (enum zwp_tablet_pad_v2_button_state)event->state);
842 } 871 }
843 872
844 wlr_tablet_v2_tablet_tool_notify_button(sway_tool->tablet_v2_tool, 873 // Update tool button count.
845 event->button, (enum zwp_tablet_pad_v2_button_state)event->state); 874 switch (event->state) {
875 case WLR_BUTTON_PRESSED:
876 cursor->tool_buttons++;
877 break;
878 case WLR_BUTTON_RELEASED:
879 if (cursor->tool_buttons == 0) {
880 sway_log(SWAY_ERROR, "inconsistent tablet tool button events");
881 } else {
882 cursor->tool_buttons--;
883 }
884 break;
885 }
846} 886}
847 887
848static void check_constraint_region(struct sway_cursor *cursor) { 888static void check_constraint_region(struct sway_cursor *cursor) {