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.
master
John Chadwick 3 years ago committed by Tudor Brindus
parent 88c17ece3b
commit 3061999ec5

@ -64,6 +64,7 @@ struct sway_cursor {
struct wl_listener tool_proximity; struct wl_listener tool_proximity;
struct wl_listener tool_button; struct wl_listener tool_button;
bool simulating_pointer_from_tool_tip; bool simulating_pointer_from_tool_tip;
bool simulating_pointer_from_tool_button;
uint32_t tool_buttons; uint32_t tool_buttons;
struct wl_listener request_set_cursor; struct wl_listener request_set_cursor;

@ -818,7 +818,34 @@ static void handle_tool_button(struct wl_listener *listener, void *data) {
node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y, node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y,
&surface, &sx, &sy); &surface, &sx, &sy);
if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { // TODO: floating resize should support graphics tablet events
struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(cursor->seat->wlr_seat);
uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
bool mod_pressed = modifiers & config->floating_mod;
bool surface_supports_tablet_events =
surface && wlr_surface_accepts_tablet_v2(tablet_v2, surface);
// Simulate pointer when:
// 1. The modifier key is pressed, OR
// 2. The surface under the cursor does not support tablet events.
bool should_simulate_pointer = mod_pressed || !surface_supports_tablet_events;
// Similar to tool tip, we need to selectively simulate mouse events, but we
// want to make sure that it is always consistent. Because all tool buttons
// currently map to BTN_RIGHT, we need to keep count of how many tool
// buttons are currently pressed down so we can send consistent events.
//
// The logic follows:
// - If we are already simulating the pointer, we should continue to do so
// until at least no tool button is held down.
// - If we should simulate the pointer and no tool button is currently held
// down, begin simulating the pointer.
// - If neither of the above are true, send the tablet events.
if ((cursor->tool_buttons > 0 && cursor->simulating_pointer_from_tool_button)
|| (cursor->tool_buttons == 0 && should_simulate_pointer)) {
cursor->simulating_pointer_from_tool_button = true;
// TODO: the user may want to configure which tool buttons are mapped to // TODO: the user may want to configure which tool buttons are mapped to
// which simulated pointer buttons // which simulated pointer buttons
switch (event->state) { switch (event->state) {
@ -827,22 +854,35 @@ static void handle_tool_button(struct wl_listener *listener, void *data) {
dispatch_cursor_button(cursor, &event->tablet->base, dispatch_cursor_button(cursor, &event->tablet->base,
event->time_msec, BTN_RIGHT, event->state); event->time_msec, BTN_RIGHT, event->state);
} }
cursor->tool_buttons++;
break; break;
case WLR_BUTTON_RELEASED: case WLR_BUTTON_RELEASED:
if (cursor->tool_buttons == 1) { if (cursor->tool_buttons <= 1) {
dispatch_cursor_button(cursor, &event->tablet->base, dispatch_cursor_button(cursor, &event->tablet->base,
event->time_msec, BTN_RIGHT, event->state); event->time_msec, BTN_RIGHT, event->state);
} }
cursor->tool_buttons--;
break; break;
} }
wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
return; } else {
cursor->simulating_pointer_from_tool_button = false;
wlr_tablet_v2_tablet_tool_notify_button(sway_tool->tablet_v2_tool,
event->button, (enum zwp_tablet_pad_v2_button_state)event->state);
} }
wlr_tablet_v2_tablet_tool_notify_button(sway_tool->tablet_v2_tool, // Update tool button count.
event->button, (enum zwp_tablet_pad_v2_button_state)event->state); switch (event->state) {
case WLR_BUTTON_PRESSED:
cursor->tool_buttons++;
break;
case WLR_BUTTON_RELEASED:
if (cursor->tool_buttons == 0) {
sway_log(SWAY_ERROR, "inconsistent tablet tool button events");
} else {
cursor->tool_buttons--;
}
break;
}
} }
static void check_constraint_region(struct sway_cursor *cursor) { static void check_constraint_region(struct sway_cursor *cursor) {

Loading…
Cancel
Save