mirror of
https://github.com/swaywm/sway.git
synced 2024-11-14 06:24:20 +01:00
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.
This commit is contained in:
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,
|
wlr_tablet_v2_tablet_tool_notify_button(sway_tool->tablet_v2_tool,
|
||||||
event->button, (enum zwp_tablet_pad_v2_button_state)event->state);
|
event->button, (enum zwp_tablet_pad_v2_button_state)event->state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update tool button count.
|
||||||
|
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…
Reference in New Issue
Block a user