aboutsummaryrefslogtreecommitdiffstats
path: root/sway/input
diff options
context:
space:
mode:
Diffstat (limited to 'sway/input')
-rw-r--r--sway/input/cursor.c587
-rw-r--r--sway/input/input-manager.c149
-rw-r--r--sway/input/keyboard.c190
-rw-r--r--sway/input/libinput.c105
-rw-r--r--sway/input/seat.c449
-rw-r--r--sway/input/seatop_default.c543
-rw-r--r--sway/input/seatop_down.c181
-rw-r--r--sway/input/seatop_move_floating.c6
-rw-r--r--sway/input/seatop_move_tiling.c75
-rw-r--r--sway/input/seatop_resize_floating.c21
-rw-r--r--sway/input/seatop_resize_tiling.c3
-rw-r--r--sway/input/switch.c34
-rw-r--r--sway/input/tablet.c50
-rw-r--r--sway/input/text_input.c229
14 files changed, 1785 insertions, 837 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c
index 2fe5b202..0b4a36d9 100644
--- a/sway/input/cursor.c
+++ b/sway/input/cursor.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 1#include <assert.h>
3#include <math.h> 2#include <math.h>
4#include <libevdev/libevdev.h> 3#include <libevdev/libevdev.h>
@@ -7,8 +6,9 @@
7#include <time.h> 6#include <time.h>
8#include <strings.h> 7#include <strings.h>
9#include <wlr/types/wlr_cursor.h> 8#include <wlr/types/wlr_cursor.h>
10#include <wlr/types/wlr_idle.h> 9#include <wlr/types/wlr_cursor_shape_v1.h>
11#include <wlr/types/wlr_pointer.h> 10#include <wlr/types/wlr_pointer.h>
11#include <wlr/types/wlr_relative_pointer_v1.h>
12#include <wlr/types/wlr_touch.h> 12#include <wlr/types/wlr_touch.h>
13#include <wlr/types/wlr_tablet_v2.h> 13#include <wlr/types/wlr_tablet_v2.h>
14#include <wlr/types/wlr_tablet_pad.h> 14#include <wlr/types/wlr_tablet_pad.h>
@@ -19,12 +19,12 @@
19#include "log.h" 19#include "log.h"
20#include "util.h" 20#include "util.h"
21#include "sway/commands.h" 21#include "sway/commands.h"
22#include "sway/desktop.h"
23#include "sway/input/cursor.h" 22#include "sway/input/cursor.h"
24#include "sway/input/keyboard.h" 23#include "sway/input/keyboard.h"
25#include "sway/input/tablet.h" 24#include "sway/input/tablet.h"
26#include "sway/layers.h" 25#include "sway/layers.h"
27#include "sway/output.h" 26#include "sway/output.h"
27#include "sway/scene_descriptor.h"
28#include "sway/tree/container.h" 28#include "sway/tree/container.h"
29#include "sway/tree/root.h" 29#include "sway/tree/root.h"
30#include "sway/tree/view.h" 30#include "sway/tree/view.h"
@@ -37,45 +37,6 @@ static uint32_t get_current_time_msec(void) {
37 return now.tv_sec * 1000 + now.tv_nsec / 1000000; 37 return now.tv_sec * 1000 + now.tv_nsec / 1000000;
38} 38}
39 39
40static struct wlr_surface *layer_surface_at(struct sway_output *output,
41 struct wl_list *layer, double ox, double oy, double *sx, double *sy) {
42 struct sway_layer_surface *sway_layer;
43 wl_list_for_each_reverse(sway_layer, layer, link) {
44 double _sx = ox - sway_layer->geo.x;
45 double _sy = oy - sway_layer->geo.y;
46 struct wlr_surface *sub = wlr_layer_surface_v1_surface_at(
47 sway_layer->layer_surface, _sx, _sy, sx, sy);
48 if (sub) {
49 return sub;
50 }
51 }
52 return NULL;
53}
54
55static bool surface_is_xdg_popup(struct wlr_surface *surface) {
56 if (wlr_surface_is_xdg_surface(surface)) {
57 struct wlr_xdg_surface *xdg_surface =
58 wlr_xdg_surface_from_wlr_surface(surface);
59 return xdg_surface->role == WLR_XDG_SURFACE_ROLE_POPUP;
60 }
61 return false;
62}
63
64static struct wlr_surface *layer_surface_popup_at(struct sway_output *output,
65 struct wl_list *layer, double ox, double oy, double *sx, double *sy) {
66 struct sway_layer_surface *sway_layer;
67 wl_list_for_each_reverse(sway_layer, layer, link) {
68 double _sx = ox - sway_layer->geo.x;
69 double _sy = oy - sway_layer->geo.y;
70 struct wlr_surface *sub = wlr_layer_surface_v1_surface_at(
71 sway_layer->layer_surface, _sx, _sy, sx, sy);
72 if (sub && surface_is_xdg_popup(sub)) {
73 return sub;
74 }
75 }
76 return NULL;
77}
78
79/** 40/**
80 * Returns the node at the cursor's position. If there is a surface at that 41 * Returns the node at the cursor's position. If there is a surface at that
81 * location, it is stored in **surface (it may not be a view). 42 * location, it is stored in **surface (it may not be a view).
@@ -83,116 +44,101 @@ static struct wlr_surface *layer_surface_popup_at(struct sway_output *output,
83struct sway_node *node_at_coords( 44struct sway_node *node_at_coords(
84 struct sway_seat *seat, double lx, double ly, 45 struct sway_seat *seat, double lx, double ly,
85 struct wlr_surface **surface, double *sx, double *sy) { 46 struct wlr_surface **surface, double *sx, double *sy) {
86 // check for unmanaged views first 47 struct wlr_scene_node *scene_node = NULL;
87#if HAVE_XWAYLAND 48
88 struct wl_list *unmanaged = &root->xwayland_unmanaged; 49 struct wlr_scene_node *node;
89 struct sway_xwayland_unmanaged *unmanaged_surface; 50 wl_list_for_each_reverse(node, &root->layer_tree->children, link) {
90 wl_list_for_each_reverse(unmanaged_surface, unmanaged, link) { 51 struct wlr_scene_tree *layer = wlr_scene_tree_from_node(node);
91 struct wlr_xwayland_surface *xsurface = 52
92 unmanaged_surface->wlr_xwayland_surface; 53 bool non_interactive = scene_descriptor_try_get(&layer->node,
93 54 SWAY_SCENE_DESC_NON_INTERACTIVE);
94 double _sx = lx - unmanaged_surface->lx; 55 if (non_interactive) {
95 double _sy = ly - unmanaged_surface->ly; 56 continue;
96 if (wlr_surface_point_accepts_input(xsurface->surface, _sx, _sy)) { 57 }
97 *surface = xsurface->surface; 58
98 *sx = _sx; 59 scene_node = wlr_scene_node_at(&layer->node, lx, ly, sx, sy);
99 *sy = _sy; 60 if (scene_node) {
100 return NULL; 61 break;
101 } 62 }
102 } 63 }
64
65 if (scene_node) {
66 // determine what wlr_surface we clicked on
67 if (scene_node->type == WLR_SCENE_NODE_BUFFER) {
68 struct wlr_scene_buffer *scene_buffer =
69 wlr_scene_buffer_from_node(scene_node);
70 struct wlr_scene_surface *scene_surface =
71 wlr_scene_surface_try_from_buffer(scene_buffer);
72
73 if (scene_surface) {
74 *surface = scene_surface->surface;
75 }
76 }
77
78 // determine what container we clicked on
79 struct wlr_scene_node *current = scene_node;
80 while (true) {
81 struct sway_container *con = scene_descriptor_try_get(current,
82 SWAY_SCENE_DESC_CONTAINER);
83
84 if (!con) {
85 struct sway_view *view = scene_descriptor_try_get(current,
86 SWAY_SCENE_DESC_VIEW);
87 if (view) {
88 con = view->container;
89 }
90 }
91
92 if (!con) {
93 struct sway_popup_desc *popup =
94 scene_descriptor_try_get(current, SWAY_SCENE_DESC_POPUP);
95 if (popup && popup->view) {
96 con = popup->view->container;
97 }
98 }
99
100 if (con && (!con->view || con->view->surface)) {
101 return &con->node;
102 }
103
104 if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_LAYER_SHELL)) {
105 // We don't want to feed through the current workspace on
106 // layer shells
107 return NULL;
108 }
109
110#if WLR_HAS_XWAYLAND
111 if (scene_descriptor_try_get(current, SWAY_SCENE_DESC_XWAYLAND_UNMANAGED)) {
112 return NULL;
113 }
103#endif 114#endif
104 // find the output the cursor is on 115
116 if (!current->parent) {
117 break;
118 }
119
120 current = &current->parent->node;
121 }
122 }
123
124 // if we aren't on a container, determine what workspace we are on
105 struct wlr_output *wlr_output = wlr_output_layout_output_at( 125 struct wlr_output *wlr_output = wlr_output_layout_output_at(
106 root->output_layout, lx, ly); 126 root->output_layout, lx, ly);
107 if (wlr_output == NULL) { 127 if (wlr_output == NULL) {
108 return NULL; 128 return NULL;
109 } 129 }
130
110 struct sway_output *output = wlr_output->data; 131 struct sway_output *output = wlr_output->data;
111 if (!output || !output->enabled) { 132 if (!output || !output->enabled) {
112 // output is being destroyed or is being enabled 133 // output is being destroyed or is being enabled
113 return NULL; 134 return NULL;
114 } 135 }
115 double ox = lx, oy = ly;
116 wlr_output_layout_output_coords(root->output_layout, wlr_output, &ox, &oy);
117 136
118 if (root->fullscreen_global) {
119 // Try fullscreen container
120 struct sway_container *con = tiling_container_at(
121 &root->fullscreen_global->node, lx, ly, surface, sx, sy);
122 if (con) {
123 return &con->node;
124 }
125 return NULL;
126 }
127
128 // find the focused workspace on the output for this seat
129 struct sway_workspace *ws = output_get_active_workspace(output); 137 struct sway_workspace *ws = output_get_active_workspace(output);
130 if (!ws) { 138 if (!ws) {
131 return NULL; 139 return NULL;
132 } 140 }
133 141
134 if ((*surface = layer_surface_at(output,
135 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
136 ox, oy, sx, sy))) {
137 return NULL;
138 }
139 if (ws->fullscreen) {
140 // Try transient containers
141 for (int i = 0; i < ws->floating->length; ++i) {
142 struct sway_container *floater = ws->floating->items[i];
143 if (container_is_transient_for(floater, ws->fullscreen)) {
144 struct sway_container *con = tiling_container_at(
145 &floater->node, lx, ly, surface, sx, sy);
146 if (con) {
147 return &con->node;
148 }
149 }
150 }
151 // Try fullscreen container
152 struct sway_container *con =
153 tiling_container_at(&ws->fullscreen->node, lx, ly, surface, sx, sy);
154 if (con) {
155 return &con->node;
156 }
157 return NULL;
158 }
159 if ((*surface = layer_surface_popup_at(output,
160 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
161 ox, oy, sx, sy))) {
162 return NULL;
163 }
164 if ((*surface = layer_surface_popup_at(output,
165 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
166 ox, oy, sx, sy))) {
167 return NULL;
168 }
169 if ((*surface = layer_surface_popup_at(output,
170 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
171 ox, oy, sx, sy))) {
172 return NULL;
173 }
174 if ((*surface = layer_surface_at(output,
175 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
176 ox, oy, sx, sy))) {
177 return NULL;
178 }
179
180 struct sway_container *c;
181 if ((c = container_at(ws, lx, ly, surface, sx, sy))) {
182 return &c->node;
183 }
184
185 if ((*surface = layer_surface_at(output,
186 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
187 ox, oy, sx, sy))) {
188 return NULL;
189 }
190 if ((*surface = layer_surface_at(output,
191 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
192 ox, oy, sx, sy))) {
193 return NULL;
194 }
195
196 return &ws->node; 142 return &ws->node;
197} 143}
198 144
@@ -218,7 +164,7 @@ void cursor_update_image(struct sway_cursor *cursor,
218 // Try a node's resize edge 164 // Try a node's resize edge
219 enum wlr_edges edge = find_resize_edge(node->sway_container, NULL, cursor); 165 enum wlr_edges edge = find_resize_edge(node->sway_container, NULL, cursor);
220 if (edge == WLR_EDGE_NONE) { 166 if (edge == WLR_EDGE_NONE) {
221 cursor_set_image(cursor, "left_ptr", NULL); 167 cursor_set_image(cursor, "default", NULL);
222 } else if (container_is_floating(node->sway_container)) { 168 } else if (container_is_floating(node->sway_container)) {
223 cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL); 169 cursor_set_image(cursor, wlr_xcursor_get_resize_name(edge), NULL);
224 } else { 170 } else {
@@ -229,12 +175,12 @@ void cursor_update_image(struct sway_cursor *cursor,
229 } 175 }
230 } 176 }
231 } else { 177 } else {
232 cursor_set_image(cursor, "left_ptr", NULL); 178 cursor_set_image(cursor, "default", NULL);
233 } 179 }
234} 180}
235 181
236static void cursor_hide(struct sway_cursor *cursor) { 182static void cursor_hide(struct sway_cursor *cursor) {
237 wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0); 183 wlr_cursor_unset_image(cursor->cursor);
238 cursor->hidden = true; 184 cursor->hidden = true;
239 wlr_seat_pointer_notify_clear_focus(cursor->seat->wlr_seat); 185 wlr_seat_pointer_notify_clear_focus(cursor->seat->wlr_seat);
240} 186}
@@ -297,7 +243,7 @@ static enum sway_input_idle_source idle_source_from_device(
297 return IDLE_SOURCE_POINTER; 243 return IDLE_SOURCE_POINTER;
298 case WLR_INPUT_DEVICE_TOUCH: 244 case WLR_INPUT_DEVICE_TOUCH:
299 return IDLE_SOURCE_TOUCH; 245 return IDLE_SOURCE_TOUCH;
300 case WLR_INPUT_DEVICE_TABLET_TOOL: 246 case WLR_INPUT_DEVICE_TABLET:
301 return IDLE_SOURCE_TABLET_TOOL; 247 return IDLE_SOURCE_TABLET_TOOL;
302 case WLR_INPUT_DEVICE_TABLET_PAD: 248 case WLR_INPUT_DEVICE_TABLET_PAD:
303 return IDLE_SOURCE_TABLET_PAD; 249 return IDLE_SOURCE_TABLET_PAD;
@@ -346,7 +292,7 @@ void cursor_unhide(struct sway_cursor *cursor) {
346 wl_event_source_timer_update(cursor->hide_source, cursor_get_timeout(cursor)); 292 wl_event_source_timer_update(cursor->hide_source, cursor_get_timeout(cursor));
347} 293}
348 294
349static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, 295void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
350 struct wlr_input_device *device, double dx, double dy, 296 struct wlr_input_device *device, double dx, double dy,
351 double dx_unaccel, double dy_unaccel) { 297 double dx_unaccel, double dy_unaccel) {
352 wlr_relative_pointer_manager_v1_send_relative_motion( 298 wlr_relative_pointer_manager_v1_send_relative_motion(
@@ -383,33 +329,34 @@ static void pointer_motion(struct sway_cursor *cursor, uint32_t time_msec,
383static void handle_pointer_motion_relative( 329static void handle_pointer_motion_relative(
384 struct wl_listener *listener, void *data) { 330 struct wl_listener *listener, void *data) {
385 struct sway_cursor *cursor = wl_container_of(listener, cursor, motion); 331 struct sway_cursor *cursor = wl_container_of(listener, cursor, motion);
386 struct wlr_event_pointer_motion *e = data; 332 struct wlr_pointer_motion_event *e = data;
387 cursor_handle_activity_from_device(cursor, e->device); 333 cursor_handle_activity_from_device(cursor, &e->pointer->base);
388 334
389 pointer_motion(cursor, e->time_msec, e->device, e->delta_x, e->delta_y, 335 pointer_motion(cursor, e->time_msec, &e->pointer->base, e->delta_x,
390 e->unaccel_dx, e->unaccel_dy); 336 e->delta_y, e->unaccel_dx, e->unaccel_dy);
391} 337}
392 338
393static void handle_pointer_motion_absolute( 339static void handle_pointer_motion_absolute(
394 struct wl_listener *listener, void *data) { 340 struct wl_listener *listener, void *data) {
395 struct sway_cursor *cursor = 341 struct sway_cursor *cursor =
396 wl_container_of(listener, cursor, motion_absolute); 342 wl_container_of(listener, cursor, motion_absolute);
397 struct wlr_event_pointer_motion_absolute *event = data; 343 struct wlr_pointer_motion_absolute_event *event = data;
398 cursor_handle_activity_from_device(cursor, event->device); 344 cursor_handle_activity_from_device(cursor, &event->pointer->base);
399 345
400 double lx, ly; 346 double lx, ly;
401 wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, 347 wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->pointer->base,
402 event->x, event->y, &lx, &ly); 348 event->x, event->y, &lx, &ly);
403 349
404 double dx = lx - cursor->cursor->x; 350 double dx = lx - cursor->cursor->x;
405 double dy = ly - cursor->cursor->y; 351 double dy = ly - cursor->cursor->y;
406 352
407 pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); 353 pointer_motion(cursor, event->time_msec, &event->pointer->base, dx, dy,
354 dx, dy);
408} 355}
409 356
410void dispatch_cursor_button(struct sway_cursor *cursor, 357void dispatch_cursor_button(struct sway_cursor *cursor,
411 struct wlr_input_device *device, uint32_t time_msec, uint32_t button, 358 struct wlr_input_device *device, uint32_t time_msec, uint32_t button,
412 enum wlr_button_state state) { 359 enum wl_pointer_button_state state) {
413 if (time_msec == 0) { 360 if (time_msec == 0) {
414 time_msec = get_current_time_msec(); 361 time_msec = get_current_time_msec();
415 } 362 }
@@ -419,9 +366,9 @@ void dispatch_cursor_button(struct sway_cursor *cursor,
419 366
420static void handle_pointer_button(struct wl_listener *listener, void *data) { 367static void handle_pointer_button(struct wl_listener *listener, void *data) {
421 struct sway_cursor *cursor = wl_container_of(listener, cursor, button); 368 struct sway_cursor *cursor = wl_container_of(listener, cursor, button);
422 struct wlr_event_pointer_button *event = data; 369 struct wlr_pointer_button_event *event = data;
423 370
424 if (event->state == WLR_BUTTON_PRESSED) { 371 if (event->state == WL_POINTER_BUTTON_STATE_PRESSED) {
425 cursor->pressed_button_count++; 372 cursor->pressed_button_count++;
426 } else { 373 } else {
427 if (cursor->pressed_button_count > 0) { 374 if (cursor->pressed_button_count > 0) {
@@ -431,20 +378,20 @@ static void handle_pointer_button(struct wl_listener *listener, void *data) {
431 } 378 }
432 } 379 }
433 380
434 cursor_handle_activity_from_device(cursor, event->device); 381 cursor_handle_activity_from_device(cursor, &event->pointer->base);
435 dispatch_cursor_button(cursor, event->device, 382 dispatch_cursor_button(cursor, &event->pointer->base,
436 event->time_msec, event->button, event->state); 383 event->time_msec, event->button, event->state);
437} 384}
438 385
439void dispatch_cursor_axis(struct sway_cursor *cursor, 386void dispatch_cursor_axis(struct sway_cursor *cursor,
440 struct wlr_event_pointer_axis *event) { 387 struct wlr_pointer_axis_event *event) {
441 seatop_pointer_axis(cursor->seat, event); 388 seatop_pointer_axis(cursor->seat, event);
442} 389}
443 390
444static void handle_pointer_axis(struct wl_listener *listener, void *data) { 391static void handle_pointer_axis(struct wl_listener *listener, void *data) {
445 struct sway_cursor *cursor = wl_container_of(listener, cursor, axis); 392 struct sway_cursor *cursor = wl_container_of(listener, cursor, axis);
446 struct wlr_event_pointer_axis *event = data; 393 struct wlr_pointer_axis_event *event = data;
447 cursor_handle_activity_from_device(cursor, event->device); 394 cursor_handle_activity_from_device(cursor, &event->pointer->base);
448 dispatch_cursor_axis(cursor, event); 395 dispatch_cursor_axis(cursor, event);
449} 396}
450 397
@@ -455,93 +402,76 @@ static void handle_pointer_frame(struct wl_listener *listener, void *data) {
455 402
456static void handle_touch_down(struct wl_listener *listener, void *data) { 403static void handle_touch_down(struct wl_listener *listener, void *data) {
457 struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down); 404 struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_down);
458 struct wlr_event_touch_down *event = data; 405 struct wlr_touch_down_event *event = data;
459 cursor_handle_activity_from_device(cursor, event->device); 406 cursor_handle_activity_from_device(cursor, &event->touch->base);
460 cursor_hide(cursor); 407 cursor_hide(cursor);
461 408
462 struct sway_seat *seat = cursor->seat; 409 struct sway_seat *seat = cursor->seat;
463 struct wlr_seat *wlr_seat = seat->wlr_seat;
464 struct wlr_surface *surface = NULL;
465 410
466 double lx, ly; 411 double lx, ly;
467 wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, 412 wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base,
468 event->x, event->y, &lx, &ly); 413 event->x, event->y, &lx, &ly);
469 double sx, sy;
470 struct sway_node *focused_node = node_at_coords(seat, lx, ly, &surface, &sx, &sy);
471 414
472 seat->touch_id = event->touch_id; 415 seat->touch_id = event->touch_id;
473 seat->touch_x = lx; 416 seat->touch_x = lx;
474 seat->touch_y = ly; 417 seat->touch_y = ly;
475 418
476 if (surface && wlr_surface_accepts_touch(wlr_seat, surface)) { 419 seatop_touch_down(seat, event, lx, ly);
477 if (seat_is_input_allowed(seat, surface)) { 420}
478 wlr_seat_touch_notify_down(wlr_seat, surface, event->time_msec,
479 event->touch_id, sx, sy);
480 421
481 if (focused_node) { 422static void handle_touch_up(struct wl_listener *listener, void *data) {
482 seat_set_focus(seat, focused_node); 423 struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up);
483 } 424 struct wlr_touch_up_event *event = data;
425 cursor_handle_activity_from_device(cursor, &event->touch->base);
426
427 struct sway_seat *seat = cursor->seat;
428
429 if (cursor->simulating_pointer_from_touch) {
430 if (cursor->pointer_touch_id == cursor->seat->touch_id) {
431 cursor->pointer_touch_up = true;
432 dispatch_cursor_button(cursor, &event->touch->base,
433 event->time_msec, BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
484 } 434 }
485 } else if (!cursor->simulating_pointer_from_touch && 435 } else {
486 (!surface || seat_is_input_allowed(seat, surface))) { 436 seatop_touch_up(seat, event);
487 // Fallback to cursor simulation.
488 // The pointer_touch_id state is needed, so drags are not aborted when over
489 // a surface supporting touch and multi touch events don't interfere.
490 cursor->simulating_pointer_from_touch = true;
491 cursor->pointer_touch_id = seat->touch_id;
492 double dx, dy;
493 dx = lx - cursor->cursor->x;
494 dy = ly - cursor->cursor->y;
495 pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy);
496 dispatch_cursor_button(cursor, event->device, event->time_msec,
497 BTN_LEFT, WLR_BUTTON_PRESSED);
498 } 437 }
499} 438}
500 439
501static void handle_touch_up(struct wl_listener *listener, void *data) { 440static void handle_touch_cancel(struct wl_listener *listener, void *data) {
502 struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_up); 441 struct sway_cursor *cursor = wl_container_of(listener, cursor, touch_cancel);
503 struct wlr_event_touch_up *event = data; 442 struct wlr_touch_cancel_event *event = data;
504 cursor_handle_activity_from_device(cursor, event->device); 443 cursor_handle_activity_from_device(cursor, &event->touch->base);
505 444
506 struct wlr_seat *wlr_seat = cursor->seat->wlr_seat; 445 struct sway_seat *seat = cursor->seat;
507 446
508 if (cursor->simulating_pointer_from_touch) { 447 if (cursor->simulating_pointer_from_touch) {
509 if (cursor->pointer_touch_id == cursor->seat->touch_id) { 448 if (cursor->pointer_touch_id == cursor->seat->touch_id) {
510 cursor->pointer_touch_up = true; 449 cursor->pointer_touch_up = true;
511 dispatch_cursor_button(cursor, event->device, event->time_msec, 450 dispatch_cursor_button(cursor, &event->touch->base,
512 BTN_LEFT, WLR_BUTTON_RELEASED); 451 event->time_msec, BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
513 } 452 }
514 } else { 453 } else {
515 wlr_seat_touch_notify_up(wlr_seat, event->time_msec, event->touch_id); 454 seatop_touch_cancel(seat, event);
516 } 455 }
517} 456}
518 457
519static void handle_touch_motion(struct wl_listener *listener, void *data) { 458static void handle_touch_motion(struct wl_listener *listener, void *data) {
520 struct sway_cursor *cursor = 459 struct sway_cursor *cursor =
521 wl_container_of(listener, cursor, touch_motion); 460 wl_container_of(listener, cursor, touch_motion);
522 struct wlr_event_touch_motion *event = data; 461 struct wlr_touch_motion_event *event = data;
523 cursor_handle_activity_from_device(cursor, event->device); 462 cursor_handle_activity_from_device(cursor, &event->touch->base);
524 463
525 struct sway_seat *seat = cursor->seat; 464 struct sway_seat *seat = cursor->seat;
526 struct wlr_seat *wlr_seat = seat->wlr_seat;
527 struct wlr_surface *surface = NULL;
528 465
529 double lx, ly; 466 double lx, ly;
530 wlr_cursor_absolute_to_layout_coords(cursor->cursor, event->device, 467 wlr_cursor_absolute_to_layout_coords(cursor->cursor, &event->touch->base,
531 event->x, event->y, &lx, &ly); 468 event->x, event->y, &lx, &ly);
532 double sx, sy;
533 node_at_coords(cursor->seat, lx, ly, &surface, &sx, &sy);
534 469
535 if (seat->touch_id == event->touch_id) { 470 if (seat->touch_id == event->touch_id) {
536 seat->touch_x = lx; 471 seat->touch_x = lx;
537 seat->touch_y = ly; 472 seat->touch_y = ly;
538 473
539 struct sway_drag_icon *drag_icon; 474 drag_icons_update_position(seat);
540 wl_list_for_each(drag_icon, &root->drag_icons, link) {
541 if (drag_icon->seat == seat) {
542 drag_icon_update_position(drag_icon);
543 }
544 }
545 } 475 }
546 476
547 if (cursor->simulating_pointer_from_touch) { 477 if (cursor->simulating_pointer_from_touch) {
@@ -549,11 +479,11 @@ static void handle_touch_motion(struct wl_listener *listener, void *data) {
549 double dx, dy; 479 double dx, dy;
550 dx = lx - cursor->cursor->x; 480 dx = lx - cursor->cursor->x;
551 dy = ly - cursor->cursor->y; 481 dy = ly - cursor->cursor->y;
552 pointer_motion(cursor, event->time_msec, event->device, dx, dy, dx, dy); 482 pointer_motion(cursor, event->time_msec, &event->touch->base,
483 dx, dy, dx, dy);
553 } 484 }
554 } else if (surface) { 485 } else {
555 wlr_seat_touch_notify_motion(wlr_seat, event->time_msec, 486 seatop_touch_motion(seat, event, lx, ly);
556 event->touch_id, sx, sy);
557 } 487 }
558} 488}
559 489
@@ -588,14 +518,15 @@ static void apply_mapping_from_region(struct wlr_input_device *device,
588 double x1 = region->x1, x2 = region->x2; 518 double x1 = region->x1, x2 = region->x2;
589 double y1 = region->y1, y2 = region->y2; 519 double y1 = region->y1, y2 = region->y2;
590 520
591 if (region->mm) { 521 if (region->mm && device->type == WLR_INPUT_DEVICE_TABLET) {
592 if (device->width_mm == 0 || device->height_mm == 0) { 522 struct wlr_tablet *tablet = wlr_tablet_from_input_device(device);
523 if (tablet->width_mm == 0 || tablet->height_mm == 0) {
593 return; 524 return;
594 } 525 }
595 x1 /= device->width_mm; 526 x1 /= tablet->width_mm;
596 x2 /= device->width_mm; 527 x2 /= tablet->width_mm;
597 y1 /= device->height_mm; 528 y1 /= tablet->height_mm;
598 y2 /= device->height_mm; 529 y2 /= tablet->height_mm;
599 } 530 }
600 531
601 *x = apply_mapping_from_coord(x1, x2, *x); 532 *x = apply_mapping_from_coord(x1, x2, *x);
@@ -657,8 +588,8 @@ static void handle_tablet_tool_position(struct sway_cursor *cursor,
657 588
658static void handle_tool_axis(struct wl_listener *listener, void *data) { 589static void handle_tool_axis(struct wl_listener *listener, void *data) {
659 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis); 590 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_axis);
660 struct wlr_event_tablet_tool_axis *event = data; 591 struct wlr_tablet_tool_axis_event *event = data;
661 cursor_handle_activity_from_device(cursor, event->device); 592 cursor_handle_activity_from_device(cursor, &event->tablet->base);
662 593
663 struct sway_tablet_tool *sway_tool = event->tool->data; 594 struct sway_tablet_tool *sway_tool = event->tool->data;
664 if (!sway_tool) { 595 if (!sway_tool) {
@@ -713,8 +644,8 @@ static void handle_tool_axis(struct wl_listener *listener, void *data) {
713 644
714static void handle_tool_tip(struct wl_listener *listener, void *data) { 645static void handle_tool_tip(struct wl_listener *listener, void *data) {
715 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip); 646 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_tip);
716 struct wlr_event_tablet_tool_tip *event = data; 647 struct wlr_tablet_tool_tip_event *event = data;
717 cursor_handle_activity_from_device(cursor, event->device); 648 cursor_handle_activity_from_device(cursor, &event->tablet->base);
718 649
719 struct sway_tablet_tool *sway_tool = event->tool->data; 650 struct sway_tablet_tool *sway_tool = event->tool->data;
720 struct wlr_tablet_v2_tablet *tablet_v2 = sway_tool->tablet->tablet_v2; 651 struct wlr_tablet_v2_tablet *tablet_v2 = sway_tool->tablet->tablet_v2;
@@ -729,8 +660,8 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
729 if (cursor->simulating_pointer_from_tool_tip && 660 if (cursor->simulating_pointer_from_tool_tip &&
730 event->state == WLR_TABLET_TOOL_TIP_UP) { 661 event->state == WLR_TABLET_TOOL_TIP_UP) {
731 cursor->simulating_pointer_from_tool_tip = false; 662 cursor->simulating_pointer_from_tool_tip = false;
732 dispatch_cursor_button(cursor, event->device, event->time_msec, 663 dispatch_cursor_button(cursor, &event->tablet->base, event->time_msec,
733 BTN_LEFT, WLR_BUTTON_RELEASED); 664 BTN_LEFT, WL_POINTER_BUTTON_STATE_RELEASED);
734 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); 665 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
735 } else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { 666 } else if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) {
736 // If we started holding the tool tip down on a surface that accepts 667 // If we started holding the tool tip down on a surface that accepts
@@ -741,8 +672,8 @@ static void handle_tool_tip(struct wl_listener *listener, void *data) {
741 WLR_TABLET_TOOL_TIP_UP); 672 WLR_TABLET_TOOL_TIP_UP);
742 } else { 673 } else {
743 cursor->simulating_pointer_from_tool_tip = true; 674 cursor->simulating_pointer_from_tool_tip = true;
744 dispatch_cursor_button(cursor, event->device, event->time_msec, 675 dispatch_cursor_button(cursor, &event->tablet->base,
745 BTN_LEFT, WLR_BUTTON_PRESSED); 676 event->time_msec, BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
746 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); 677 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
747 } 678 }
748 } else { 679 } else {
@@ -764,12 +695,13 @@ static struct sway_tablet *get_tablet_for_device(struct sway_cursor *cursor,
764static void handle_tool_proximity(struct wl_listener *listener, void *data) { 695static void handle_tool_proximity(struct wl_listener *listener, void *data) {
765 struct sway_cursor *cursor = 696 struct sway_cursor *cursor =
766 wl_container_of(listener, cursor, tool_proximity); 697 wl_container_of(listener, cursor, tool_proximity);
767 struct wlr_event_tablet_tool_proximity *event = data; 698 struct wlr_tablet_tool_proximity_event *event = data;
768 cursor_handle_activity_from_device(cursor, event->device); 699 cursor_handle_activity_from_device(cursor, &event->tablet->base);
769 700
770 struct wlr_tablet_tool *tool = event->tool; 701 struct wlr_tablet_tool *tool = event->tool;
771 if (!tool->data) { 702 if (!tool->data) {
772 struct sway_tablet *tablet = get_tablet_for_device(cursor, event->device); 703 struct sway_tablet *tablet = get_tablet_for_device(cursor,
704 &event->tablet->base);
773 if (!tablet) { 705 if (!tablet) {
774 sway_log(SWAY_ERROR, "no tablet for tablet tool"); 706 sway_log(SWAY_ERROR, "no tablet for tablet tool");
775 return; 707 return;
@@ -794,8 +726,8 @@ static void handle_tool_proximity(struct wl_listener *listener, void *data) {
794 726
795static void handle_tool_button(struct wl_listener *listener, void *data) { 727static void handle_tool_button(struct wl_listener *listener, void *data) {
796 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button); 728 struct sway_cursor *cursor = wl_container_of(listener, cursor, tool_button);
797 struct wlr_event_tablet_tool_button *event = data; 729 struct wlr_tablet_tool_button_event *event = data;
798 cursor_handle_activity_from_device(cursor, event->device); 730 cursor_handle_activity_from_device(cursor, &event->tablet->base);
799 731
800 struct sway_tablet_tool *sway_tool = event->tool->data; 732 struct sway_tablet_tool *sway_tool = event->tool->data;
801 if (!sway_tool) { 733 if (!sway_tool) {
@@ -810,31 +742,71 @@ static void handle_tool_button(struct wl_listener *listener, void *data) {
810 node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y, 742 node_at_coords(cursor->seat, cursor->cursor->x, cursor->cursor->y,
811 &surface, &sx, &sy); 743 &surface, &sx, &sy);
812 744
813 if (!surface || !wlr_surface_accepts_tablet_v2(tablet_v2, surface)) { 745 // TODO: floating resize should support graphics tablet events
746 struct wlr_keyboard *keyboard = wlr_seat_get_keyboard(cursor->seat->wlr_seat);
747 uint32_t modifiers = keyboard ? wlr_keyboard_get_modifiers(keyboard) : 0;
748 bool mod_pressed = modifiers & config->floating_mod;
749
750 bool surface_supports_tablet_events =
751 surface && wlr_surface_accepts_tablet_v2(tablet_v2, surface);
752
753 // Simulate pointer when:
754 // 1. The modifier key is pressed, OR
755 // 2. The surface under the cursor does not support tablet events.
756 bool should_simulate_pointer = mod_pressed || !surface_supports_tablet_events;
757
758 // Similar to tool tip, we need to selectively simulate mouse events, but we
759 // want to make sure that it is always consistent. Because all tool buttons
760 // currently map to BTN_RIGHT, we need to keep count of how many tool
761 // buttons are currently pressed down so we can send consistent events.
762 //
763 // The logic follows:
764 // - If we are already simulating the pointer, we should continue to do so
765 // until at least no tool button is held down.
766 // - If we should simulate the pointer and no tool button is currently held
767 // down, begin simulating the pointer.
768 // - If neither of the above are true, send the tablet events.
769 if ((cursor->tool_buttons > 0 && cursor->simulating_pointer_from_tool_button)
770 || (cursor->tool_buttons == 0 && should_simulate_pointer)) {
771 cursor->simulating_pointer_from_tool_button = true;
772
814 // TODO: the user may want to configure which tool buttons are mapped to 773 // TODO: the user may want to configure which tool buttons are mapped to
815 // which simulated pointer buttons 774 // which simulated pointer buttons
816 switch (event->state) { 775 switch (event->state) {
817 case WLR_BUTTON_PRESSED: 776 case WLR_BUTTON_PRESSED:
818 if (cursor->tool_buttons == 0) { 777 if (cursor->tool_buttons == 0) {
819 dispatch_cursor_button(cursor, event->device, 778 dispatch_cursor_button(cursor, &event->tablet->base,
820 event->time_msec, BTN_RIGHT, event->state); 779 event->time_msec, BTN_RIGHT, WL_POINTER_BUTTON_STATE_PRESSED);
821 } 780 }
822 cursor->tool_buttons++;
823 break; 781 break;
824 case WLR_BUTTON_RELEASED: 782 case WLR_BUTTON_RELEASED:
825 if (cursor->tool_buttons == 1) { 783 if (cursor->tool_buttons <= 1) {
826 dispatch_cursor_button(cursor, event->device, 784 dispatch_cursor_button(cursor, &event->tablet->base,
827 event->time_msec, BTN_RIGHT, event->state); 785 event->time_msec, BTN_RIGHT, WL_POINTER_BUTTON_STATE_RELEASED);
828 } 786 }
829 cursor->tool_buttons--;
830 break; 787 break;
831 } 788 }
832 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat); 789 wlr_seat_pointer_notify_frame(cursor->seat->wlr_seat);
833 return; 790 } else {
791 cursor->simulating_pointer_from_tool_button = false;
792
793 wlr_tablet_v2_tablet_tool_notify_button(sway_tool->tablet_v2_tool,
794 event->button, (enum zwp_tablet_pad_v2_button_state)event->state);
834 } 795 }
835 796
836 wlr_tablet_v2_tablet_tool_notify_button(sway_tool->tablet_v2_tool, 797 // Update tool button count.
837 event->button, (enum zwp_tablet_pad_v2_button_state)event->state); 798 switch (event->state) {
799 case WLR_BUTTON_PRESSED:
800 cursor->tool_buttons++;
801 break;
802 case WLR_BUTTON_RELEASED:
803 if (cursor->tool_buttons == 0) {
804 sway_log(SWAY_ERROR, "inconsistent tablet tool button events");
805 } else {
806 cursor->tool_buttons--;
807 }
808 break;
809 }
838} 810}
839 811
840static void check_constraint_region(struct sway_cursor *cursor) { 812static void check_constraint_region(struct sway_cursor *cursor) {
@@ -920,59 +892,68 @@ static void handle_request_pointer_set_cursor(struct wl_listener *listener,
920 event->hotspot_y, focused_client); 892 event->hotspot_y, focused_client);
921} 893}
922 894
895static void handle_pointer_hold_begin(struct wl_listener *listener, void *data) {
896 struct sway_cursor *cursor = wl_container_of(
897 listener, cursor, hold_begin);
898 struct wlr_pointer_hold_begin_event *event = data;
899 cursor_handle_activity_from_device(cursor, &event->pointer->base);
900 seatop_hold_begin(cursor->seat, event);
901}
902
903static void handle_pointer_hold_end(struct wl_listener *listener, void *data) {
904 struct sway_cursor *cursor = wl_container_of(
905 listener, cursor, hold_end);
906 struct wlr_pointer_hold_end_event *event = data;
907 cursor_handle_activity_from_device(cursor, &event->pointer->base);
908 seatop_hold_end(cursor->seat, event);
909}
910
923static void handle_pointer_pinch_begin(struct wl_listener *listener, void *data) { 911static void handle_pointer_pinch_begin(struct wl_listener *listener, void *data) {
924 struct sway_cursor *cursor = wl_container_of( 912 struct sway_cursor *cursor = wl_container_of(
925 listener, cursor, pinch_begin); 913 listener, cursor, pinch_begin);
926 struct wlr_event_pointer_pinch_begin *event = data; 914 struct wlr_pointer_pinch_begin_event *event = data;
927 wlr_pointer_gestures_v1_send_pinch_begin( 915 cursor_handle_activity_from_device(cursor, &event->pointer->base);
928 cursor->pointer_gestures, cursor->seat->wlr_seat, 916 seatop_pinch_begin(cursor->seat, event);
929 event->time_msec, event->fingers);
930} 917}
931 918
932static void handle_pointer_pinch_update(struct wl_listener *listener, void *data) { 919static void handle_pointer_pinch_update(struct wl_listener *listener, void *data) {
933 struct sway_cursor *cursor = wl_container_of( 920 struct sway_cursor *cursor = wl_container_of(
934 listener, cursor, pinch_update); 921 listener, cursor, pinch_update);
935 struct wlr_event_pointer_pinch_update *event = data; 922 struct wlr_pointer_pinch_update_event *event = data;
936 wlr_pointer_gestures_v1_send_pinch_update( 923 cursor_handle_activity_from_device(cursor, &event->pointer->base);
937 cursor->pointer_gestures, cursor->seat->wlr_seat, 924 seatop_pinch_update(cursor->seat, event);
938 event->time_msec, event->dx, event->dy,
939 event->scale, event->rotation);
940} 925}
941 926
942static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) { 927static void handle_pointer_pinch_end(struct wl_listener *listener, void *data) {
943 struct sway_cursor *cursor = wl_container_of( 928 struct sway_cursor *cursor = wl_container_of(
944 listener, cursor, pinch_end); 929 listener, cursor, pinch_end);
945 struct wlr_event_pointer_pinch_end *event = data; 930 struct wlr_pointer_pinch_end_event *event = data;
946 wlr_pointer_gestures_v1_send_pinch_end( 931 cursor_handle_activity_from_device(cursor, &event->pointer->base);
947 cursor->pointer_gestures, cursor->seat->wlr_seat, 932 seatop_pinch_end(cursor->seat, event);
948 event->time_msec, event->cancelled);
949} 933}
950 934
951static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data) { 935static void handle_pointer_swipe_begin(struct wl_listener *listener, void *data) {
952 struct sway_cursor *cursor = wl_container_of( 936 struct sway_cursor *cursor = wl_container_of(
953 listener, cursor, swipe_begin); 937 listener, cursor, swipe_begin);
954 struct wlr_event_pointer_swipe_begin *event = data; 938 struct wlr_pointer_swipe_begin_event *event = data;
955 wlr_pointer_gestures_v1_send_swipe_begin( 939 cursor_handle_activity_from_device(cursor, &event->pointer->base);
956 cursor->pointer_gestures, cursor->seat->wlr_seat, 940 seatop_swipe_begin(cursor->seat, event);
957 event->time_msec, event->fingers);
958} 941}
959 942
960static void handle_pointer_swipe_update(struct wl_listener *listener, void *data) { 943static void handle_pointer_swipe_update(struct wl_listener *listener, void *data) {
961 struct sway_cursor *cursor = wl_container_of( 944 struct sway_cursor *cursor = wl_container_of(
962 listener, cursor, swipe_update); 945 listener, cursor, swipe_update);
963 struct wlr_event_pointer_swipe_update *event = data; 946 struct wlr_pointer_swipe_update_event *event = data;
964 wlr_pointer_gestures_v1_send_swipe_update( 947 cursor_handle_activity_from_device(cursor, &event->pointer->base);
965 cursor->pointer_gestures, cursor->seat->wlr_seat, 948 seatop_swipe_update(cursor->seat, event);
966 event->time_msec, event->dx, event->dy);
967} 949}
968 950
969static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) { 951static void handle_pointer_swipe_end(struct wl_listener *listener, void *data) {
970 struct sway_cursor *cursor = wl_container_of( 952 struct sway_cursor *cursor = wl_container_of(
971 listener, cursor, swipe_end); 953 listener, cursor, swipe_end);
972 struct wlr_event_pointer_swipe_end *event = data; 954 struct wlr_pointer_swipe_end_event *event = data;
973 wlr_pointer_gestures_v1_send_swipe_end( 955 cursor_handle_activity_from_device(cursor, &event->pointer->base);
974 cursor->pointer_gestures, cursor->seat->wlr_seat, 956 seatop_swipe_end(cursor->seat, event);
975 event->time_msec, event->cancelled);
976} 957}
977 958
978static void handle_image_surface_destroy(struct wl_listener *listener, 959static void handle_image_surface_destroy(struct wl_listener *listener,
@@ -1011,10 +992,9 @@ void cursor_set_image(struct sway_cursor *cursor, const char *image,
1011 } 992 }
1012 993
1013 if (!image) { 994 if (!image) {
1014 wlr_cursor_set_image(cursor->cursor, NULL, 0, 0, 0, 0, 0, 0); 995 wlr_cursor_unset_image(cursor->cursor);
1015 } else if (!current_image || strcmp(current_image, image) != 0) { 996 } else if (!current_image || strcmp(current_image, image) != 0) {
1016 wlr_xcursor_manager_set_cursor_image(cursor->xcursor_manager, image, 997 wlr_cursor_set_xcursor(cursor->cursor, cursor->xcursor_manager, image);
1017 cursor->cursor);
1018 } 998 }
1019} 999}
1020 1000
@@ -1046,6 +1026,8 @@ void sway_cursor_destroy(struct sway_cursor *cursor) {
1046 wl_event_source_remove(cursor->hide_source); 1026 wl_event_source_remove(cursor->hide_source);
1047 1027
1048 wl_list_remove(&cursor->image_surface_destroy.link); 1028 wl_list_remove(&cursor->image_surface_destroy.link);
1029 wl_list_remove(&cursor->hold_begin.link);
1030 wl_list_remove(&cursor->hold_end.link);
1049 wl_list_remove(&cursor->pinch_begin.link); 1031 wl_list_remove(&cursor->pinch_begin.link);
1050 wl_list_remove(&cursor->pinch_update.link); 1032 wl_list_remove(&cursor->pinch_update.link);
1051 wl_list_remove(&cursor->pinch_end.link); 1033 wl_list_remove(&cursor->pinch_end.link);
@@ -1059,6 +1041,7 @@ void sway_cursor_destroy(struct sway_cursor *cursor) {
1059 wl_list_remove(&cursor->frame.link); 1041 wl_list_remove(&cursor->frame.link);
1060 wl_list_remove(&cursor->touch_down.link); 1042 wl_list_remove(&cursor->touch_down.link);
1061 wl_list_remove(&cursor->touch_up.link); 1043 wl_list_remove(&cursor->touch_up.link);
1044 wl_list_remove(&cursor->touch_cancel.link);
1062 wl_list_remove(&cursor->touch_motion.link); 1045 wl_list_remove(&cursor->touch_motion.link);
1063 wl_list_remove(&cursor->touch_frame.link); 1046 wl_list_remove(&cursor->touch_frame.link);
1064 wl_list_remove(&cursor->tool_axis.link); 1047 wl_list_remove(&cursor->tool_axis.link);
@@ -1095,19 +1078,24 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
1095 wl_list_init(&cursor->image_surface_destroy.link); 1078 wl_list_init(&cursor->image_surface_destroy.link);
1096 cursor->image_surface_destroy.notify = handle_image_surface_destroy; 1079 cursor->image_surface_destroy.notify = handle_image_surface_destroy;
1097 1080
1098 cursor->pointer_gestures = wlr_pointer_gestures_v1_create(server.wl_display); 1081 wl_signal_add(&wlr_cursor->events.hold_begin, &cursor->hold_begin);
1099 cursor->pinch_begin.notify = handle_pointer_pinch_begin; 1082 cursor->hold_begin.notify = handle_pointer_hold_begin;
1083 wl_signal_add(&wlr_cursor->events.hold_end, &cursor->hold_end);
1084 cursor->hold_end.notify = handle_pointer_hold_end;
1085
1100 wl_signal_add(&wlr_cursor->events.pinch_begin, &cursor->pinch_begin); 1086 wl_signal_add(&wlr_cursor->events.pinch_begin, &cursor->pinch_begin);
1101 cursor->pinch_update.notify = handle_pointer_pinch_update; 1087 cursor->pinch_begin.notify = handle_pointer_pinch_begin;
1102 wl_signal_add(&wlr_cursor->events.pinch_update, &cursor->pinch_update); 1088 wl_signal_add(&wlr_cursor->events.pinch_update, &cursor->pinch_update);
1103 cursor->pinch_end.notify = handle_pointer_pinch_end; 1089 cursor->pinch_update.notify = handle_pointer_pinch_update;
1104 wl_signal_add(&wlr_cursor->events.pinch_end, &cursor->pinch_end); 1090 wl_signal_add(&wlr_cursor->events.pinch_end, &cursor->pinch_end);
1105 cursor->swipe_begin.notify = handle_pointer_swipe_begin; 1091 cursor->pinch_end.notify = handle_pointer_pinch_end;
1092
1106 wl_signal_add(&wlr_cursor->events.swipe_begin, &cursor->swipe_begin); 1093 wl_signal_add(&wlr_cursor->events.swipe_begin, &cursor->swipe_begin);
1107 cursor->swipe_update.notify = handle_pointer_swipe_update; 1094 cursor->swipe_begin.notify = handle_pointer_swipe_begin;
1108 wl_signal_add(&wlr_cursor->events.swipe_update, &cursor->swipe_update); 1095 wl_signal_add(&wlr_cursor->events.swipe_update, &cursor->swipe_update);
1109 cursor->swipe_end.notify = handle_pointer_swipe_end; 1096 cursor->swipe_update.notify = handle_pointer_swipe_update;
1110 wl_signal_add(&wlr_cursor->events.swipe_end, &cursor->swipe_end); 1097 wl_signal_add(&wlr_cursor->events.swipe_end, &cursor->swipe_end);
1098 cursor->swipe_end.notify = handle_pointer_swipe_end;
1111 1099
1112 // input events 1100 // input events
1113 wl_signal_add(&wlr_cursor->events.motion, &cursor->motion); 1101 wl_signal_add(&wlr_cursor->events.motion, &cursor->motion);
@@ -1132,6 +1120,9 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) {
1132 wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up); 1120 wl_signal_add(&wlr_cursor->events.touch_up, &cursor->touch_up);
1133 cursor->touch_up.notify = handle_touch_up; 1121 cursor->touch_up.notify = handle_touch_up;
1134 1122
1123 wl_signal_add(&wlr_cursor->events.touch_cancel, &cursor->touch_cancel);
1124 cursor->touch_cancel.notify = handle_touch_cancel;
1125
1135 wl_signal_add(&wlr_cursor->events.touch_motion, 1126 wl_signal_add(&wlr_cursor->events.touch_motion,
1136 &cursor->touch_motion); 1127 &cursor->touch_motion);
1137 cursor->touch_motion.notify = handle_touch_motion; 1128 cursor->touch_motion.notify = handle_touch_motion;
@@ -1224,11 +1215,7 @@ uint32_t get_mouse_bindsym(const char *name, char **error) {
1224 // Get event code from name 1215 // Get event code from name
1225 int code = libevdev_event_code_from_name(EV_KEY, name); 1216 int code = libevdev_event_code_from_name(EV_KEY, name);
1226 if (code == -1) { 1217 if (code == -1) {
1227 size_t len = snprintf(NULL, 0, "Unknown event %s", name) + 1; 1218 *error = format_str("Unknown event %s", name);
1228 *error = malloc(len);
1229 if (*error) {
1230 snprintf(*error, len, "Unknown event %s", name);
1231 }
1232 return 0; 1219 return 0;
1233 } 1220 }
1234 return code; 1221 return code;
@@ -1250,13 +1237,8 @@ uint32_t get_mouse_bindcode(const char *name, char **error) {
1250 } 1237 }
1251 const char *event = libevdev_event_code_get_name(EV_KEY, code); 1238 const char *event = libevdev_event_code_get_name(EV_KEY, code);
1252 if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) { 1239 if (!event || strncmp(event, "BTN_", strlen("BTN_")) != 0) {
1253 size_t len = snprintf(NULL, 0, "Event code %d (%s) is not a button", 1240 *error = format_str("Event code %d (%s) is not a button",
1254 code, event ? event : "(null)") + 1; 1241 code, event ? event : "(null)");
1255 *error = malloc(len);
1256 if (*error) {
1257 snprintf(*error, len, "Event code %d (%s) is not a button",
1258 code, event ? event : "(null)");
1259 }
1260 return 0; 1242 return 0;
1261 } 1243 }
1262 return code; 1244 return code;
@@ -1289,12 +1271,15 @@ const char *get_mouse_button_name(uint32_t button) {
1289static void warp_to_constraint_cursor_hint(struct sway_cursor *cursor) { 1271static void warp_to_constraint_cursor_hint(struct sway_cursor *cursor) {
1290 struct wlr_pointer_constraint_v1 *constraint = cursor->active_constraint; 1272 struct wlr_pointer_constraint_v1 *constraint = cursor->active_constraint;
1291 1273
1292 if (constraint->current.committed & 1274 if (constraint->current.cursor_hint.enabled) {
1293 WLR_POINTER_CONSTRAINT_V1_STATE_CURSOR_HINT) {
1294 double sx = constraint->current.cursor_hint.x; 1275 double sx = constraint->current.cursor_hint.x;
1295 double sy = constraint->current.cursor_hint.y; 1276 double sy = constraint->current.cursor_hint.y;
1296 1277
1297 struct sway_view *view = view_from_wlr_surface(constraint->surface); 1278 struct sway_view *view = view_from_wlr_surface(constraint->surface);
1279 if (!view) {
1280 return;
1281 }
1282
1298 struct sway_container *con = view->container; 1283 struct sway_container *con = view->container;
1299 1284
1300 double lx = sx + con->pending.content_x - view->geometry.x; 1285 double lx = sx + con->pending.content_x - view->geometry.x;
@@ -1345,12 +1330,9 @@ void handle_pointer_constraint(struct wl_listener *listener, void *data) {
1345 sway_constraint->destroy.notify = handle_constraint_destroy; 1330 sway_constraint->destroy.notify = handle_constraint_destroy;
1346 wl_signal_add(&constraint->events.destroy, &sway_constraint->destroy); 1331 wl_signal_add(&constraint->events.destroy, &sway_constraint->destroy);
1347 1332
1348 struct sway_node *focus = seat_get_focus(seat); 1333 struct wlr_surface *surface = seat->wlr_seat->keyboard_state.focused_surface;
1349 if (focus && focus->type == N_CONTAINER && focus->sway_container->view) { 1334 if (surface && surface == constraint->surface) {
1350 struct wlr_surface *surface = focus->sway_container->view->surface; 1335 sway_cursor_constrain(seat->cursor, constraint);
1351 if (surface == constraint->surface) {
1352 sway_cursor_constrain(seat->cursor, constraint);
1353 }
1354 } 1336 }
1355} 1337}
1356 1338
@@ -1408,3 +1390,26 @@ void sway_cursor_constrain(struct sway_cursor *cursor,
1408 wl_signal_add(&constraint->surface->events.commit, 1390 wl_signal_add(&constraint->surface->events.commit,
1409 &cursor->constraint_commit); 1391 &cursor->constraint_commit);
1410} 1392}
1393
1394void handle_request_set_cursor_shape(struct wl_listener *listener, void *data) {
1395 const struct wlr_cursor_shape_manager_v1_request_set_shape_event *event = data;
1396 struct sway_seat *seat = event->seat_client->seat->data;
1397
1398 if (!seatop_allows_set_cursor(seat)) {
1399 return;
1400 }
1401
1402 struct wl_client *focused_client = NULL;
1403 struct wlr_surface *focused_surface = seat->wlr_seat->pointer_state.focused_surface;
1404 if (focused_surface != NULL) {
1405 focused_client = wl_resource_get_client(focused_surface->resource);
1406 }
1407
1408 // TODO: check cursor mode
1409 if (focused_client == NULL || event->seat_client->client != focused_client) {
1410 sway_log(SWAY_DEBUG, "denying request to set cursor from unfocused client");
1411 return;
1412 }
1413
1414 cursor_set_image(seat->cursor, wlr_cursor_shape_v1_name(event->shape), focused_client);
1415}
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c
index f04a8ce0..248ca34e 100644
--- a/sway/input/input-manager.c
+++ b/sway/input/input-manager.c
@@ -1,12 +1,12 @@
1#define _POSIX_C_SOURCE 200809L
2#include <ctype.h> 1#include <ctype.h>
3#include <stdio.h> 2#include <stdio.h>
4#include <string.h> 3#include <string.h>
5#include <math.h> 4#include <math.h>
5#include <assert.h>
6#include <wlr/config.h>
6#include <wlr/backend/libinput.h> 7#include <wlr/backend/libinput.h>
7#include <wlr/types/wlr_cursor.h> 8#include <wlr/types/wlr_cursor.h>
8#include <wlr/types/wlr_keyboard_group.h> 9#include <wlr/types/wlr_keyboard_group.h>
9#include <wlr/types/wlr_input_inhibitor.h>
10#include <wlr/types/wlr_virtual_keyboard_v1.h> 10#include <wlr/types/wlr_virtual_keyboard_v1.h>
11#include <wlr/types/wlr_virtual_pointer_v1.h> 11#include <wlr/types/wlr_virtual_pointer_v1.h>
12#include "sway/config.h" 12#include "sway/config.h"
@@ -22,6 +22,10 @@
22#include "list.h" 22#include "list.h"
23#include "log.h" 23#include "log.h"
24 24
25#if WLR_HAS_LIBINPUT_BACKEND
26#include <wlr/backend/libinput.h>
27#endif
28
25#define DEFAULT_SEAT "seat0" 29#define DEFAULT_SEAT "seat0"
26 30
27struct input_config *current_input_config = NULL; 31struct input_config *current_input_config = NULL;
@@ -63,8 +67,15 @@ struct sway_seat *input_manager_sway_seat_from_wlr_seat(struct wlr_seat *wlr_sea
63} 67}
64 68
65char *input_device_get_identifier(struct wlr_input_device *device) { 69char *input_device_get_identifier(struct wlr_input_device *device) {
66 int vendor = device->vendor; 70 int vendor = 0, product = 0;
67 int product = device->product; 71#if WLR_HAS_LIBINPUT_BACKEND
72 if (wlr_input_device_is_libinput(device)) {
73 struct libinput_device *libinput_dev = wlr_libinput_get_device_handle(device);
74 vendor = libinput_device_get_id_vendor(libinput_dev);
75 product = libinput_device_get_id_product(libinput_dev);
76 }
77#endif
78
68 char *name = strdup(device->name ? device->name : ""); 79 char *name = strdup(device->name ? device->name : "");
69 strip_whitespace(name); 80 strip_whitespace(name);
70 81
@@ -76,20 +87,13 @@ char *input_device_get_identifier(struct wlr_input_device *device) {
76 } 87 }
77 } 88 }
78 89
79 const char *fmt = "%d:%d:%s"; 90 char *identifier = format_str("%d:%d:%s", vendor, product, name);
80 int len = snprintf(NULL, 0, fmt, vendor, product, name) + 1;
81 char *identifier = malloc(len);
82 if (!identifier) {
83 sway_log(SWAY_ERROR, "Unable to allocate unique input device name");
84 return NULL;
85 }
86
87 snprintf(identifier, len, fmt, vendor, product, name);
88 free(name); 91 free(name);
89 return identifier; 92 return identifier;
90} 93}
91 94
92static bool device_is_touchpad(struct sway_input_device *device) { 95static bool device_is_touchpad(struct sway_input_device *device) {
96#if WLR_HAS_LIBINPUT_BACKEND
93 if (device->wlr_device->type != WLR_INPUT_DEVICE_POINTER || 97 if (device->wlr_device->type != WLR_INPUT_DEVICE_POINTER ||
94 !wlr_input_device_is_libinput(device->wlr_device)) { 98 !wlr_input_device_is_libinput(device->wlr_device)) {
95 return false; 99 return false;
@@ -99,6 +103,9 @@ static bool device_is_touchpad(struct sway_input_device *device) {
99 wlr_libinput_get_device_handle(device->wlr_device); 103 wlr_libinput_get_device_handle(device->wlr_device);
100 104
101 return libinput_device_config_tap_get_finger_count(libinput_device) > 0; 105 return libinput_device_config_tap_get_finger_count(libinput_device) > 0;
106#else
107 return false;
108#endif
102} 109}
103 110
104const char *input_device_get_type(struct sway_input_device *device) { 111const char *input_device_get_type(struct sway_input_device *device) {
@@ -113,7 +120,7 @@ const char *input_device_get_type(struct sway_input_device *device) {
113 return "keyboard"; 120 return "keyboard";
114 case WLR_INPUT_DEVICE_TOUCH: 121 case WLR_INPUT_DEVICE_TOUCH:
115 return "touch"; 122 return "touch";
116 case WLR_INPUT_DEVICE_TABLET_TOOL: 123 case WLR_INPUT_DEVICE_TABLET:
117 return "tablet_tool"; 124 return "tablet_tool";
118 case WLR_INPUT_DEVICE_TABLET_PAD: 125 case WLR_INPUT_DEVICE_TABLET_PAD:
119 return "tablet_pad"; 126 return "tablet_pad";
@@ -236,7 +243,11 @@ static void handle_new_input(struct wl_listener *listener, void *data) {
236 243
237 apply_input_type_config(input_device); 244 apply_input_type_config(input_device);
238 245
239 sway_input_configure_libinput_device(input_device); 246#if WLR_HAS_LIBINPUT_BACKEND
247 bool config_changed = sway_input_configure_libinput_device(input_device);
248#else
249 bool config_changed = false;
250#endif
240 251
241 wl_signal_add(&device->events.destroy, &input_device->device_destroy); 252 wl_signal_add(&device->events.destroy, &input_device->device_destroy);
242 input_device->device_destroy.notify = handle_device_destroy; 253 input_device->device_destroy.notify = handle_device_destroy;
@@ -274,29 +285,9 @@ static void handle_new_input(struct wl_listener *listener, void *data) {
274 } 285 }
275 286
276 ipc_event_input("added", input_device); 287 ipc_event_input("added", input_device);
277}
278 288
279static void handle_inhibit_activate(struct wl_listener *listener, void *data) { 289 if (config_changed) {
280 struct sway_input_manager *input_manager = wl_container_of( 290 ipc_event_input("libinput_config", input_device);
281 listener, input_manager, inhibit_activate);
282 struct sway_seat *seat;
283 wl_list_for_each(seat, &input_manager->seats, link) {
284 seat_set_exclusive_client(seat, input_manager->inhibit->active_client);
285 }
286}
287
288static void handle_inhibit_deactivate(struct wl_listener *listener, void *data) {
289 struct sway_input_manager *input_manager = wl_container_of(
290 listener, input_manager, inhibit_deactivate);
291 struct sway_seat *seat;
292 wl_list_for_each(seat, &input_manager->seats, link) {
293 seat_set_exclusive_client(seat, NULL);
294 struct sway_node *previous = seat_get_focus(seat);
295 if (previous) {
296 // Hack to get seat to re-focus the return value of get_focus
297 seat_set_focus(seat, NULL);
298 seat_set_focus(seat, previous);
299 }
300 } 291 }
301} 292}
302 293
@@ -377,7 +368,7 @@ void handle_virtual_keyboard(struct wl_listener *listener, void *data) {
377 struct sway_input_manager *input_manager = 368 struct sway_input_manager *input_manager =
378 wl_container_of(listener, input_manager, virtual_keyboard_new); 369 wl_container_of(listener, input_manager, virtual_keyboard_new);
379 struct wlr_virtual_keyboard_v1 *keyboard = data; 370 struct wlr_virtual_keyboard_v1 *keyboard = data;
380 struct wlr_input_device *device = &keyboard->input_device; 371 struct wlr_input_device *device = &keyboard->keyboard.base;
381 372
382 // TODO: Amend protocol to allow NULL seat 373 // TODO: Amend protocol to allow NULL seat
383 struct sway_seat *seat = keyboard->seat ? 374 struct sway_seat *seat = keyboard->seat ?
@@ -410,7 +401,7 @@ void handle_virtual_pointer(struct wl_listener *listener, void *data) {
410 wl_container_of(listener, input_manager, virtual_pointer_new); 401 wl_container_of(listener, input_manager, virtual_pointer_new);
411 struct wlr_virtual_pointer_v1_new_pointer_event *event = data; 402 struct wlr_virtual_pointer_v1_new_pointer_event *event = data;
412 struct wlr_virtual_pointer_v1 *pointer = event->new_pointer; 403 struct wlr_virtual_pointer_v1 *pointer = event->new_pointer;
413 struct wlr_input_device *device = &pointer->input_device; 404 struct wlr_input_device *device = &pointer->pointer.base;
414 405
415 struct sway_seat *seat = event->suggested_seat ? 406 struct sway_seat *seat = event->suggested_seat ?
416 input_manager_sway_seat_from_wlr_seat(event->suggested_seat) : 407 input_manager_sway_seat_from_wlr_seat(event->suggested_seat) :
@@ -442,6 +433,20 @@ void handle_virtual_pointer(struct wl_listener *listener, void *data) {
442 } 433 }
443} 434}
444 435
436static void handle_transient_seat_manager_create_seat(
437 struct wl_listener *listener, void *data) {
438 struct wlr_transient_seat_v1 *transient_seat = data;
439 static uint64_t i;
440 char name[256];
441 snprintf(name, sizeof(name), "transient-%"PRIx64, i++);
442 struct sway_seat *seat = seat_create(name);
443 if (seat && seat->wlr_seat) {
444 wlr_transient_seat_v1_ready(transient_seat, seat->wlr_seat);
445 } else {
446 wlr_transient_seat_v1_deny(transient_seat);
447 }
448}
449
445struct sway_input_manager *input_manager_create(struct sway_server *server) { 450struct sway_input_manager *input_manager_create(struct sway_server *server) {
446 struct sway_input_manager *input = 451 struct sway_input_manager *input =
447 calloc(1, sizeof(struct sway_input_manager)); 452 calloc(1, sizeof(struct sway_input_manager));
@@ -468,14 +473,6 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) {
468 &input->virtual_pointer_new); 473 &input->virtual_pointer_new);
469 input->virtual_pointer_new.notify = handle_virtual_pointer; 474 input->virtual_pointer_new.notify = handle_virtual_pointer;
470 475
471 input->inhibit = wlr_input_inhibit_manager_create(server->wl_display);
472 input->inhibit_activate.notify = handle_inhibit_activate;
473 wl_signal_add(&input->inhibit->events.activate,
474 &input->inhibit_activate);
475 input->inhibit_deactivate.notify = handle_inhibit_deactivate;
476 wl_signal_add(&input->inhibit->events.deactivate,
477 &input->inhibit_deactivate);
478
479 input->keyboard_shortcuts_inhibit = 476 input->keyboard_shortcuts_inhibit =
480 wlr_keyboard_shortcuts_inhibit_v1_create(server->wl_display); 477 wlr_keyboard_shortcuts_inhibit_v1_create(server->wl_display);
481 input->keyboard_shortcuts_inhibit_new_inhibitor.notify = 478 input->keyboard_shortcuts_inhibit_new_inhibitor.notify =
@@ -483,6 +480,17 @@ struct sway_input_manager *input_manager_create(struct sway_server *server) {
483 wl_signal_add(&input->keyboard_shortcuts_inhibit->events.new_inhibitor, 480 wl_signal_add(&input->keyboard_shortcuts_inhibit->events.new_inhibitor,
484 &input->keyboard_shortcuts_inhibit_new_inhibitor); 481 &input->keyboard_shortcuts_inhibit_new_inhibitor);
485 482
483 input->pointer_gestures = wlr_pointer_gestures_v1_create(server->wl_display);
484
485 input->transient_seat_manager =
486 wlr_transient_seat_manager_v1_create(server->wl_display);
487 assert(input->transient_seat_manager);
488
489 input->transient_seat_create.notify =
490 handle_transient_seat_manager_create_seat;
491 wl_signal_add(&input->transient_seat_manager->events.create_seat,
492 &input->transient_seat_create);
493
486 return input; 494 return input;
487} 495}
488 496
@@ -520,21 +528,50 @@ static void retranslate_keysyms(struct input_config *input_config) {
520 return; 528 return;
521 } 529 }
522 } 530 }
531
532 for (int i = 0; i < config->input_type_configs->length; ++i) {
533 struct input_config *ic = config->input_type_configs->items[i];
534 if (ic->xkb_layout || ic->xkb_file) {
535 // this is the first config with xkb_layout or xkb_file
536 if (ic->identifier == input_config->identifier) {
537 translate_keysyms(ic);
538 }
539
540 return;
541 }
542 }
523} 543}
524 544
525static void input_manager_configure_input( 545static void input_manager_configure_input(
526 struct sway_input_device *input_device) { 546 struct sway_input_device *input_device) {
527 sway_input_configure_libinput_device(input_device); 547#if WLR_HAS_LIBINPUT_BACKEND
548 bool config_changed = sway_input_configure_libinput_device(input_device);
549#else
550 bool config_changed = false;
551#endif
528 struct sway_seat *seat = NULL; 552 struct sway_seat *seat = NULL;
529 wl_list_for_each(seat, &server.input->seats, link) { 553 wl_list_for_each(seat, &server.input->seats, link) {
530 seat_configure_device(seat, input_device); 554 seat_configure_device(seat, input_device);
531 } 555 }
556 if (config_changed) {
557 ipc_event_input("libinput_config", input_device);
558 }
532} 559}
533 560
534void input_manager_configure_all_inputs(void) { 561void input_manager_configure_all_input_mappings(void) {
535 struct sway_input_device *input_device = NULL; 562 struct sway_input_device *input_device;
536 wl_list_for_each(input_device, &server.input->devices, link) { 563 wl_list_for_each(input_device, &server.input->devices, link) {
537 input_manager_configure_input(input_device); 564 struct sway_seat *seat;
565 wl_list_for_each(seat, &server.input->seats, link) {
566 seat_configure_device_mapping(seat, input_device);
567 }
568
569#if WLR_HAS_LIBINPUT_BACKEND
570 // Input devices mapped to unavailable outputs get their libinput
571 // send_events setting switched to false. We need to re-enable this
572 // when the output appears.
573 sway_input_configure_libinput_device_send_events(input_device);
574#endif
538 } 575 }
539} 576}
540 577
@@ -556,7 +593,9 @@ void input_manager_apply_input_config(struct input_config *input_config) {
556} 593}
557 594
558void input_manager_reset_input(struct sway_input_device *input_device) { 595void input_manager_reset_input(struct sway_input_device *input_device) {
596#if WLR_HAS_LIBINPUT_BACKEND
559 sway_input_reset_libinput_device(input_device); 597 sway_input_reset_libinput_device(input_device);
598#endif
560 struct sway_seat *seat = NULL; 599 struct sway_seat *seat = NULL;
561 wl_list_for_each(seat, &server.input->seats, link) { 600 wl_list_for_each(seat, &server.input->seats, link) {
562 seat_reset_device(seat, input_device); 601 seat_reset_device(seat, input_device);
@@ -564,6 +603,13 @@ void input_manager_reset_input(struct sway_input_device *input_device) {
564} 603}
565 604
566void input_manager_reset_all_inputs(void) { 605void input_manager_reset_all_inputs(void) {
606 // Set the active keyboard to NULL to avoid spamming configuration updates
607 // for all keyboard devices.
608 struct sway_seat *seat;
609 wl_list_for_each(seat, &server.input->seats, link) {
610 wlr_seat_set_keyboard(seat->wlr_seat, NULL);
611 }
612
567 struct sway_input_device *input_device = NULL; 613 struct sway_input_device *input_device = NULL;
568 wl_list_for_each(input_device, &server.input->devices, link) { 614 wl_list_for_each(input_device, &server.input->devices, link) {
569 input_manager_reset_input(input_device); 615 input_manager_reset_input(input_device);
@@ -572,7 +618,6 @@ void input_manager_reset_all_inputs(void) {
572 // If there is at least one keyboard using the default keymap, repeat delay, 618 // If there is at least one keyboard using the default keymap, repeat delay,
573 // and repeat rate, then it is possible that there is a keyboard group that 619 // and repeat rate, then it is possible that there is a keyboard group that
574 // need their keyboard disarmed. 620 // need their keyboard disarmed.
575 struct sway_seat *seat;
576 wl_list_for_each(seat, &server.input->seats, link) { 621 wl_list_for_each(seat, &server.input->seats, link) {
577 struct sway_keyboard_group *group; 622 struct sway_keyboard_group *group;
578 wl_list_for_each(group, &seat->keyboard_groups, link) { 623 wl_list_for_each(group, &seat->keyboard_groups, link) {
diff --git a/sway/input/keyboard.c b/sway/input/keyboard.c
index f258ac7d..f74d0658 100644
--- a/sway/input/keyboard.c
+++ b/sway/input/keyboard.c
@@ -1,10 +1,9 @@
1#include <assert.h> 1#include <assert.h>
2#include <limits.h> 2#include <limits.h>
3#include <strings.h> 3#include <strings.h>
4#include <wlr/config.h>
4#include <wlr/backend/multi.h> 5#include <wlr/backend/multi.h>
5#include <wlr/backend/session.h>
6#include <wlr/interfaces/wlr_keyboard.h> 6#include <wlr/interfaces/wlr_keyboard.h>
7#include <wlr/types/wlr_idle.h>
8#include <wlr/types/wlr_keyboard.h> 7#include <wlr/types/wlr_keyboard.h>
9#include <wlr/types/wlr_keyboard_group.h> 8#include <wlr/types/wlr_keyboard_group.h>
10#include <xkbcommon/xkbcommon-names.h> 9#include <xkbcommon/xkbcommon-names.h>
@@ -16,6 +15,10 @@
16#include "sway/ipc-server.h" 15#include "sway/ipc-server.h"
17#include "log.h" 16#include "log.h"
18 17
18#if WLR_HAS_SESSION
19#include <wlr/backend/session.h>
20#endif
21
19static struct modifier_key { 22static struct modifier_key {
20 char *name; 23 char *name;
21 uint32_t mod; 24 uint32_t mod;
@@ -29,6 +32,7 @@ static struct modifier_key {
29 { XKB_MOD_NAME_NUM, WLR_MODIFIER_MOD2 }, 32 { XKB_MOD_NAME_NUM, WLR_MODIFIER_MOD2 },
30 { "Mod3", WLR_MODIFIER_MOD3 }, 33 { "Mod3", WLR_MODIFIER_MOD3 },
31 { XKB_MOD_NAME_LOGO, WLR_MODIFIER_LOGO }, 34 { XKB_MOD_NAME_LOGO, WLR_MODIFIER_LOGO },
35 { "Super", WLR_MODIFIER_LOGO },
32 { "Mod5", WLR_MODIFIER_MOD5 }, 36 { "Mod5", WLR_MODIFIER_MOD5 },
33}; 37};
34 38
@@ -264,14 +268,12 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard,
264 xkb_keysym_t keysym = pressed_keysyms[i]; 268 xkb_keysym_t keysym = pressed_keysyms[i];
265 if (keysym >= XKB_KEY_XF86Switch_VT_1 && 269 if (keysym >= XKB_KEY_XF86Switch_VT_1 &&
266 keysym <= XKB_KEY_XF86Switch_VT_12) { 270 keysym <= XKB_KEY_XF86Switch_VT_12) {
267 if (wlr_backend_is_multi(server.backend)) { 271#if WLR_HAS_SESSION
268 struct wlr_session *session = 272 if (server.session) {
269 wlr_backend_get_session(server.backend); 273 unsigned vt = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
270 if (session) { 274 wlr_session_change_vt(server.session, vt);
271 unsigned vt = keysym - XKB_KEY_XF86Switch_VT_1 + 1;
272 wlr_session_change_vt(session, vt);
273 }
274 } 275 }
276#endif
275 return true; 277 return true;
276 } 278 }
277 } 279 }
@@ -291,14 +293,12 @@ static bool keyboard_execute_compositor_binding(struct sway_keyboard *keyboard,
291static size_t keyboard_keysyms_translated(struct sway_keyboard *keyboard, 293static size_t keyboard_keysyms_translated(struct sway_keyboard *keyboard,
292 xkb_keycode_t keycode, const xkb_keysym_t **keysyms, 294 xkb_keycode_t keycode, const xkb_keysym_t **keysyms,
293 uint32_t *modifiers) { 295 uint32_t *modifiers) {
294 struct wlr_input_device *device = 296 *modifiers = wlr_keyboard_get_modifiers(keyboard->wlr);
295 keyboard->seat_device->input_device->wlr_device;
296 *modifiers = wlr_keyboard_get_modifiers(device->keyboard);
297 xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods2( 297 xkb_mod_mask_t consumed = xkb_state_key_get_consumed_mods2(
298 device->keyboard->xkb_state, keycode, XKB_CONSUMED_MODE_XKB); 298 keyboard->wlr->xkb_state, keycode, XKB_CONSUMED_MODE_XKB);
299 *modifiers = *modifiers & ~consumed; 299 *modifiers = *modifiers & ~consumed;
300 300
301 return xkb_state_key_get_syms(device->keyboard->xkb_state, 301 return xkb_state_key_get_syms(keyboard->wlr->xkb_state,
302 keycode, keysyms); 302 keycode, keysyms);
303} 303}
304 304
@@ -314,13 +314,11 @@ static size_t keyboard_keysyms_translated(struct sway_keyboard *keyboard,
314static size_t keyboard_keysyms_raw(struct sway_keyboard *keyboard, 314static size_t keyboard_keysyms_raw(struct sway_keyboard *keyboard,
315 xkb_keycode_t keycode, const xkb_keysym_t **keysyms, 315 xkb_keycode_t keycode, const xkb_keysym_t **keysyms,
316 uint32_t *modifiers) { 316 uint32_t *modifiers) {
317 struct wlr_input_device *device = 317 *modifiers = wlr_keyboard_get_modifiers(keyboard->wlr);
318 keyboard->seat_device->input_device->wlr_device;
319 *modifiers = wlr_keyboard_get_modifiers(device->keyboard);
320 318
321 xkb_layout_index_t layout_index = xkb_state_key_get_layout( 319 xkb_layout_index_t layout_index = xkb_state_key_get_layout(
322 device->keyboard->xkb_state, keycode); 320 keyboard->wlr->xkb_state, keycode);
323 return xkb_keymap_key_get_syms_by_level(device->keyboard->keymap, 321 return xkb_keymap_key_get_syms_by_level(keyboard->wlr->keymap,
324 keycode, layout_index, 0, keysyms); 322 keycode, layout_index, 0, keysyms);
325} 323}
326 324
@@ -360,8 +358,7 @@ static void update_keyboard_state(struct sway_keyboard *keyboard,
360 keyinfo->keycode, &keyinfo->translated_keysyms, 358 keyinfo->keycode, &keyinfo->translated_keysyms,
361 &keyinfo->translated_modifiers); 359 &keyinfo->translated_modifiers);
362 360
363 keyinfo->code_modifiers = wlr_keyboard_get_modifiers( 361 keyinfo->code_modifiers = wlr_keyboard_get_modifiers(keyboard->wlr);
364 keyboard->seat_device->input_device->wlr_device->keyboard);
365 362
366 // Update shortcut model keyinfo 363 // Update shortcut model keyinfo
367 update_shortcut_state(&keyboard->state_keycodes, raw_keycode, keystate, 364 update_shortcut_state(&keyboard->state_keycodes, raw_keycode, keystate,
@@ -401,15 +398,15 @@ static struct wlr_input_method_keyboard_grab_v2 *keyboard_get_im_grab(
401} 398}
402 399
403static void handle_key_event(struct sway_keyboard *keyboard, 400static void handle_key_event(struct sway_keyboard *keyboard,
404 struct wlr_event_keyboard_key *event) { 401 struct wlr_keyboard_key_event *event) {
405 struct sway_seat *seat = keyboard->seat_device->sway_seat; 402 struct sway_seat *seat = keyboard->seat_device->sway_seat;
406 struct wlr_seat *wlr_seat = seat->wlr_seat; 403 struct wlr_seat *wlr_seat = seat->wlr_seat;
407 struct wlr_input_device *wlr_device = 404 struct wlr_input_device *wlr_device =
408 keyboard->seat_device->input_device->wlr_device; 405 keyboard->seat_device->input_device->wlr_device;
409 char *device_identifier = input_device_get_identifier(wlr_device); 406 char *device_identifier = input_device_get_identifier(wlr_device);
410 bool exact_identifier = wlr_device->keyboard->group != NULL; 407 bool exact_identifier = keyboard->wlr->group != NULL;
411 seat_idle_notify_activity(seat, IDLE_SOURCE_KEYBOARD); 408 seat_idle_notify_activity(seat, IDLE_SOURCE_KEYBOARD);
412 bool input_inhibited = seat->exclusive_client != NULL; 409 bool locked = server.session_lock.lock;
413 struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor = 410 struct sway_keyboard_shortcuts_inhibitor *sway_inhibitor =
414 keyboard_shortcuts_inhibitor_get_for_focused_surface(seat); 411 keyboard_shortcuts_inhibitor_get_for_focused_surface(seat);
415 bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active; 412 bool shortcuts_inhibited = sway_inhibitor && sway_inhibitor->inhibitor->active;
@@ -427,17 +424,17 @@ static void handle_key_event(struct sway_keyboard *keyboard,
427 struct sway_binding *binding_released = NULL; 424 struct sway_binding *binding_released = NULL;
428 get_active_binding(&keyboard->state_keycodes, 425 get_active_binding(&keyboard->state_keycodes,
429 config->current_mode->keycode_bindings, &binding_released, 426 config->current_mode->keycode_bindings, &binding_released,
430 keyinfo.code_modifiers, true, input_inhibited, 427 keyinfo.code_modifiers, true, locked,
431 shortcuts_inhibited, device_identifier, 428 shortcuts_inhibited, device_identifier,
432 exact_identifier, keyboard->effective_layout); 429 exact_identifier, keyboard->effective_layout);
433 get_active_binding(&keyboard->state_keysyms_raw, 430 get_active_binding(&keyboard->state_keysyms_raw,
434 config->current_mode->keysym_bindings, &binding_released, 431 config->current_mode->keysym_bindings, &binding_released,
435 keyinfo.raw_modifiers, true, input_inhibited, 432 keyinfo.raw_modifiers, true, locked,
436 shortcuts_inhibited, device_identifier, 433 shortcuts_inhibited, device_identifier,
437 exact_identifier, keyboard->effective_layout); 434 exact_identifier, keyboard->effective_layout);
438 get_active_binding(&keyboard->state_keysyms_translated, 435 get_active_binding(&keyboard->state_keysyms_translated,
439 config->current_mode->keysym_bindings, &binding_released, 436 config->current_mode->keysym_bindings, &binding_released,
440 keyinfo.translated_modifiers, true, input_inhibited, 437 keyinfo.translated_modifiers, true, locked,
441 shortcuts_inhibited, device_identifier, 438 shortcuts_inhibited, device_identifier,
442 exact_identifier, keyboard->effective_layout); 439 exact_identifier, keyboard->effective_layout);
443 440
@@ -459,17 +456,17 @@ static void handle_key_event(struct sway_keyboard *keyboard,
459 if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) { 456 if (event->state == WL_KEYBOARD_KEY_STATE_PRESSED) {
460 get_active_binding(&keyboard->state_keycodes, 457 get_active_binding(&keyboard->state_keycodes,
461 config->current_mode->keycode_bindings, &binding, 458 config->current_mode->keycode_bindings, &binding,
462 keyinfo.code_modifiers, false, input_inhibited, 459 keyinfo.code_modifiers, false, locked,
463 shortcuts_inhibited, device_identifier, 460 shortcuts_inhibited, device_identifier,
464 exact_identifier, keyboard->effective_layout); 461 exact_identifier, keyboard->effective_layout);
465 get_active_binding(&keyboard->state_keysyms_raw, 462 get_active_binding(&keyboard->state_keysyms_raw,
466 config->current_mode->keysym_bindings, &binding, 463 config->current_mode->keysym_bindings, &binding,
467 keyinfo.raw_modifiers, false, input_inhibited, 464 keyinfo.raw_modifiers, false, locked,
468 shortcuts_inhibited, device_identifier, 465 shortcuts_inhibited, device_identifier,
469 exact_identifier, keyboard->effective_layout); 466 exact_identifier, keyboard->effective_layout);
470 get_active_binding(&keyboard->state_keysyms_translated, 467 get_active_binding(&keyboard->state_keysyms_translated,
471 config->current_mode->keysym_bindings, &binding, 468 config->current_mode->keysym_bindings, &binding,
472 keyinfo.translated_modifiers, false, input_inhibited, 469 keyinfo.translated_modifiers, false, locked,
473 shortcuts_inhibited, device_identifier, 470 shortcuts_inhibited, device_identifier,
474 exact_identifier, keyboard->effective_layout); 471 exact_identifier, keyboard->effective_layout);
475 } 472 }
@@ -477,10 +474,10 @@ static void handle_key_event(struct sway_keyboard *keyboard,
477 // Set up (or clear) keyboard repeat for a pressed binding. Since the 474 // Set up (or clear) keyboard repeat for a pressed binding. Since the
478 // binding may remove the keyboard, the timer needs to be updated first 475 // binding may remove the keyboard, the timer needs to be updated first
479 if (binding && !(binding->flags & BINDING_NOREPEAT) && 476 if (binding && !(binding->flags & BINDING_NOREPEAT) &&
480 wlr_device->keyboard->repeat_info.delay > 0) { 477 keyboard->wlr->repeat_info.delay > 0) {
481 keyboard->repeat_binding = binding; 478 keyboard->repeat_binding = binding;
482 if (wl_event_source_timer_update(keyboard->key_repeat_source, 479 if (wl_event_source_timer_update(keyboard->key_repeat_source,
483 wlr_device->keyboard->repeat_info.delay) < 0) { 480 keyboard->wlr->repeat_info.delay) < 0) {
484 sway_log(SWAY_DEBUG, "failed to set key repeat timer"); 481 sway_log(SWAY_DEBUG, "failed to set key repeat timer");
485 } 482 }
486 } else if (keyboard->repeat_binding) { 483 } else if (keyboard->repeat_binding) {
@@ -492,7 +489,7 @@ static void handle_key_event(struct sway_keyboard *keyboard,
492 handled = true; 489 handled = true;
493 } 490 }
494 491
495 if (!handled && wlr_device->keyboard->group) { 492 if (!handled && keyboard->wlr->group) {
496 // Only handle device specific bindings for keyboards in a group 493 // Only handle device specific bindings for keyboards in a group
497 free(device_identifier); 494 free(device_identifier);
498 return; 495 return;
@@ -517,7 +514,7 @@ static void handle_key_event(struct sway_keyboard *keyboard,
517 &keyboard->state_pressed_sent, event->keycode, 514 &keyboard->state_pressed_sent, event->keycode,
518 event->state, keyinfo.keycode, 0); 515 event->state, keyinfo.keycode, 0);
519 if (pressed_sent) { 516 if (pressed_sent) {
520 wlr_seat_set_keyboard(wlr_seat, wlr_device); 517 wlr_seat_set_keyboard(wlr_seat, keyboard->wlr);
521 wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, 518 wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,
522 event->keycode, event->state); 519 event->keycode, event->state);
523 handled = true; 520 handled = true;
@@ -528,8 +525,7 @@ static void handle_key_event(struct sway_keyboard *keyboard,
528 struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard); 525 struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard);
529 526
530 if (kb_grab) { 527 if (kb_grab) {
531 wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab, 528 wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab, keyboard->wlr);
532 wlr_device->keyboard);
533 wlr_input_method_keyboard_grab_v2_send_key(kb_grab, 529 wlr_input_method_keyboard_grab_v2_send_key(kb_grab,
534 event->time_msec, event->keycode, event->state); 530 event->time_msec, event->keycode, event->state);
535 handled = true; 531 handled = true;
@@ -542,7 +538,7 @@ static void handle_key_event(struct sway_keyboard *keyboard,
542 update_shortcut_state( 538 update_shortcut_state(
543 &keyboard->state_pressed_sent, event->keycode, event->state, 539 &keyboard->state_pressed_sent, event->keycode, event->state,
544 keyinfo.keycode, 0); 540 keyinfo.keycode, 0);
545 wlr_seat_set_keyboard(wlr_seat, wlr_device); 541 wlr_seat_set_keyboard(wlr_seat, keyboard->wlr);
546 wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec, 542 wlr_seat_keyboard_notify_key(wlr_seat, event->time_msec,
547 event->keycode, event->state); 543 event->keycode, event->state);
548 } 544 }
@@ -618,14 +614,12 @@ static void handle_keyboard_group_leave(struct wl_listener *listener,
618} 614}
619 615
620static int handle_keyboard_repeat(void *data) { 616static int handle_keyboard_repeat(void *data) {
621 struct sway_keyboard *keyboard = (struct sway_keyboard *)data; 617 struct sway_keyboard *keyboard = data;
622 struct wlr_keyboard *wlr_device =
623 keyboard->seat_device->input_device->wlr_device->keyboard;
624 if (keyboard->repeat_binding) { 618 if (keyboard->repeat_binding) {
625 if (wlr_device->repeat_info.rate > 0) { 619 if (keyboard->wlr->repeat_info.rate > 0) {
626 // We queue the next event first, as the command might cancel it 620 // We queue the next event first, as the command might cancel it
627 if (wl_event_source_timer_update(keyboard->key_repeat_source, 621 if (wl_event_source_timer_update(keyboard->key_repeat_source,
628 1000 / wlr_device->repeat_info.rate) < 0) { 622 1000 / keyboard->wlr->repeat_info.rate) < 0) {
629 sway_log(SWAY_DEBUG, "failed to update key repeat timer"); 623 sway_log(SWAY_DEBUG, "failed to update key repeat timer");
630 } 624 }
631 } 625 }
@@ -658,31 +652,28 @@ static void determine_bar_visibility(uint32_t modifiers) {
658} 652}
659 653
660static void handle_modifier_event(struct sway_keyboard *keyboard) { 654static void handle_modifier_event(struct sway_keyboard *keyboard) {
661 struct wlr_input_device *wlr_device = 655 if (!keyboard->wlr->group) {
662 keyboard->seat_device->input_device->wlr_device;
663 if (!wlr_device->keyboard->group) {
664 struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard); 656 struct wlr_input_method_keyboard_grab_v2 *kb_grab = keyboard_get_im_grab(keyboard);
665 657
666 if (kb_grab) { 658 if (kb_grab) {
667 wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab, 659 wlr_input_method_keyboard_grab_v2_set_keyboard(kb_grab, keyboard->wlr);
668 wlr_device->keyboard);
669 wlr_input_method_keyboard_grab_v2_send_modifiers(kb_grab, 660 wlr_input_method_keyboard_grab_v2_send_modifiers(kb_grab,
670 &wlr_device->keyboard->modifiers); 661 &keyboard->wlr->modifiers);
671 } else { 662 } else {
672 struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; 663 struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat;
673 wlr_seat_set_keyboard(wlr_seat, wlr_device); 664 wlr_seat_set_keyboard(wlr_seat, keyboard->wlr);
674 wlr_seat_keyboard_notify_modifiers(wlr_seat, 665 wlr_seat_keyboard_notify_modifiers(wlr_seat,
675 &wlr_device->keyboard->modifiers); 666 &keyboard->wlr->modifiers);
676 } 667 }
677 668
678 uint32_t modifiers = wlr_keyboard_get_modifiers(wlr_device->keyboard); 669 uint32_t modifiers = wlr_keyboard_get_modifiers(keyboard->wlr);
679 determine_bar_visibility(modifiers); 670 determine_bar_visibility(modifiers);
680 } 671 }
681 672
682 if (wlr_device->keyboard->modifiers.group != keyboard->effective_layout) { 673 if (keyboard->wlr->modifiers.group != keyboard->effective_layout) {
683 keyboard->effective_layout = wlr_device->keyboard->modifiers.group; 674 keyboard->effective_layout = keyboard->wlr->modifiers.group;
684 675
685 if (!wlr_keyboard_group_from_wlr_keyboard(wlr_device->keyboard)) { 676 if (!wlr_keyboard_group_from_wlr_keyboard(keyboard->wlr)) {
686 ipc_event_input("xkb_layout", keyboard->seat_device->input_device); 677 ipc_event_input("xkb_layout", keyboard->seat_device->input_device);
687 } 678 }
688 } 679 }
@@ -711,6 +702,7 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat,
711 } 702 }
712 703
713 keyboard->seat_device = device; 704 keyboard->seat_device = device;
705 keyboard->wlr = wlr_keyboard_from_input_device(device->input_device->wlr_device);
714 device->keyboard = keyboard; 706 device->keyboard = keyboard;
715 707
716 wl_list_init(&keyboard->keyboard_key.link); 708 wl_list_init(&keyboard->keyboard_key.link);
@@ -724,23 +716,11 @@ struct sway_keyboard *sway_keyboard_create(struct sway_seat *seat,
724 716
725static void handle_xkb_context_log(struct xkb_context *context, 717static void handle_xkb_context_log(struct xkb_context *context,
726 enum xkb_log_level level, const char *format, va_list args) { 718 enum xkb_log_level level, const char *format, va_list args) {
727 va_list args_copy; 719 char *error = vformat_str(format, args);
728 va_copy(args_copy, args);
729 size_t length = vsnprintf(NULL, 0, format, args_copy) + 1;
730 va_end(args_copy);
731
732 char *error = malloc(length);
733 if (!error) {
734 sway_log(SWAY_ERROR, "Failed to allocate libxkbcommon log message");
735 return;
736 }
737
738 va_copy(args_copy, args);
739 vsnprintf(error, length, format, args_copy);
740 va_end(args_copy);
741 720
742 if (error[length - 2] == '\n') { 721 size_t len = strlen(error);
743 error[length - 2] = '\0'; 722 if (error[len - 1] == '\n') {
723 error[len - 1] = '\0';
744 } 724 }
745 725
746 sway_log_importance_t importance = SWAY_DEBUG; 726 sway_log_importance_t importance = SWAY_DEBUG;
@@ -761,7 +741,7 @@ static void handle_xkb_context_log(struct xkb_context *context,
761 741
762struct xkb_keymap *sway_keyboard_compile_keymap(struct input_config *ic, 742struct xkb_keymap *sway_keyboard_compile_keymap(struct input_config *ic,
763 char **error) { 743 char **error) {
764 struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); 744 struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_SECURE_GETENV);
765 if (!sway_assert(context, "cannot create XKB context")) { 745 if (!sway_assert(context, "cannot create XKB context")) {
766 return NULL; 746 return NULL;
767 } 747 }
@@ -775,13 +755,8 @@ struct xkb_keymap *sway_keyboard_compile_keymap(struct input_config *ic,
775 if (!keymap_file) { 755 if (!keymap_file) {
776 sway_log_errno(SWAY_ERROR, "cannot read xkb file %s", ic->xkb_file); 756 sway_log_errno(SWAY_ERROR, "cannot read xkb file %s", ic->xkb_file);
777 if (error) { 757 if (error) {
778 size_t len = snprintf(NULL, 0, "cannot read xkb file %s: %s", 758 *error = format_str("cannot read xkb file %s: %s",
779 ic->xkb_file, strerror(errno)) + 1; 759 ic->xkb_file, strerror(errno));
780 *error = malloc(len);
781 if (*error) {
782 snprintf(*error, len, "cannot read xkb_file %s: %s",
783 ic->xkb_file, strerror(errno));
784 }
785 } 760 }
786 goto cleanup; 761 goto cleanup;
787 } 762 }
@@ -819,13 +794,12 @@ static void destroy_empty_wlr_keyboard_group(void *data) {
819 794
820static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) { 795static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) {
821 struct sway_input_device *device = keyboard->seat_device->input_device; 796 struct sway_input_device *device = keyboard->seat_device->input_device;
822 struct wlr_keyboard *wlr_keyboard = device->wlr_device->keyboard; 797 struct wlr_keyboard_group *wlr_group = keyboard->wlr->group;
823 struct wlr_keyboard_group *wlr_group = wlr_keyboard->group;
824 798
825 sway_log(SWAY_DEBUG, "Removing keyboard %s from group %p", 799 sway_log(SWAY_DEBUG, "Removing keyboard %s from group %p",
826 device->identifier, wlr_group); 800 device->identifier, wlr_group);
827 801
828 wlr_keyboard_group_remove_keyboard(wlr_keyboard->group, wlr_keyboard); 802 wlr_keyboard_group_remove_keyboard(keyboard->wlr->group, keyboard->wlr);
829 803
830 if (wl_list_empty(&wlr_group->devices)) { 804 if (wl_list_empty(&wlr_group->devices)) {
831 sway_log(SWAY_DEBUG, "Destroying empty keyboard group %p", 805 sway_log(SWAY_DEBUG, "Destroying empty keyboard group %p",
@@ -850,9 +824,7 @@ static void sway_keyboard_group_remove(struct sway_keyboard *keyboard) {
850} 824}
851 825
852static void sway_keyboard_group_remove_invalid(struct sway_keyboard *keyboard) { 826static void sway_keyboard_group_remove_invalid(struct sway_keyboard *keyboard) {
853 struct sway_input_device *device = keyboard->seat_device->input_device; 827 if (!keyboard->wlr->group) {
854 struct wlr_keyboard *wlr_keyboard = device->wlr_device->keyboard;
855 if (!wlr_keyboard->group) {
856 return; 828 return;
857 } 829 }
858 830
@@ -868,7 +840,7 @@ static void sway_keyboard_group_remove_invalid(struct sway_keyboard *keyboard) {
868 break; 840 break;
869 case KEYBOARD_GROUP_DEFAULT: /* fallthrough */ 841 case KEYBOARD_GROUP_DEFAULT: /* fallthrough */
870 case KEYBOARD_GROUP_SMART:; 842 case KEYBOARD_GROUP_SMART:;
871 struct wlr_keyboard_group *group = wlr_keyboard->group; 843 struct wlr_keyboard_group *group = keyboard->wlr->group;
872 if (!wlr_keyboard_keymaps_match(keyboard->keymap, group->keyboard.keymap) || 844 if (!wlr_keyboard_keymaps_match(keyboard->keymap, group->keyboard.keymap) ||
873 !repeat_info_match(keyboard, &group->keyboard)) { 845 !repeat_info_match(keyboard, &group->keyboard)) {
874 sway_keyboard_group_remove(keyboard); 846 sway_keyboard_group_remove(keyboard);
@@ -879,7 +851,6 @@ static void sway_keyboard_group_remove_invalid(struct sway_keyboard *keyboard) {
879 851
880static void sway_keyboard_group_add(struct sway_keyboard *keyboard) { 852static void sway_keyboard_group_add(struct sway_keyboard *keyboard) {
881 struct sway_input_device *device = keyboard->seat_device->input_device; 853 struct sway_input_device *device = keyboard->seat_device->input_device;
882 struct wlr_keyboard *wlr_keyboard = device->wlr_device->keyboard;
883 struct sway_seat *seat = keyboard->seat_device->sway_seat; 854 struct sway_seat *seat = keyboard->seat_device->sway_seat;
884 struct seat_config *sc = seat_get_config(seat); 855 struct seat_config *sc = seat_get_config(seat);
885 856
@@ -911,7 +882,7 @@ static void sway_keyboard_group_add(struct sway_keyboard *keyboard) {
911 repeat_info_match(keyboard, &wlr_group->keyboard)) { 882 repeat_info_match(keyboard, &wlr_group->keyboard)) {
912 sway_log(SWAY_DEBUG, "Adding keyboard %s to group %p", 883 sway_log(SWAY_DEBUG, "Adding keyboard %s to group %p",
913 device->identifier, wlr_group); 884 device->identifier, wlr_group);
914 wlr_keyboard_group_add_keyboard(wlr_group, wlr_keyboard); 885 wlr_keyboard_group_add_keyboard(wlr_group, keyboard->wlr);
915 return; 886 return;
916 } 887 }
917 break; 888 break;
@@ -950,7 +921,7 @@ static void sway_keyboard_group_add(struct sway_keyboard *keyboard) {
950 goto cleanup; 921 goto cleanup;
951 } 922 }
952 sway_group->seat_device->input_device->wlr_device = 923 sway_group->seat_device->input_device->wlr_device =
953 sway_group->wlr_group->input_device; 924 &sway_group->wlr_group->keyboard.base;
954 925
955 if (!sway_keyboard_create(seat, sway_group->seat_device)) { 926 if (!sway_keyboard_create(seat, sway_group->seat_device)) {
956 sway_log(SWAY_ERROR, "Failed to allocate sway_keyboard for group"); 927 sway_log(SWAY_ERROR, "Failed to allocate sway_keyboard for group");
@@ -959,7 +930,7 @@ static void sway_keyboard_group_add(struct sway_keyboard *keyboard) {
959 930
960 sway_log(SWAY_DEBUG, "Adding keyboard %s to group %p", 931 sway_log(SWAY_DEBUG, "Adding keyboard %s to group %p",
961 device->identifier, sway_group->wlr_group); 932 device->identifier, sway_group->wlr_group);
962 wlr_keyboard_group_add_keyboard(sway_group->wlr_group, wlr_keyboard); 933 wlr_keyboard_group_add_keyboard(sway_group->wlr_group, keyboard->wlr);
963 934
964 wl_list_insert(&seat->keyboard_groups, &sway_group->link); 935 wl_list_insert(&seat->keyboard_groups, &sway_group->link);
965 936
@@ -991,10 +962,8 @@ cleanup:
991void sway_keyboard_configure(struct sway_keyboard *keyboard) { 962void sway_keyboard_configure(struct sway_keyboard *keyboard) {
992 struct input_config *input_config = 963 struct input_config *input_config =
993 input_device_get_config(keyboard->seat_device->input_device); 964 input_device_get_config(keyboard->seat_device->input_device);
994 struct wlr_input_device *wlr_device =
995 keyboard->seat_device->input_device->wlr_device;
996 965
997 if (!sway_assert(!wlr_keyboard_group_from_wlr_keyboard(wlr_device->keyboard), 966 if (!sway_assert(!wlr_keyboard_group_from_wlr_keyboard(keyboard->wlr),
998 "sway_keyboard_configure should not be called with a " 967 "sway_keyboard_configure should not be called with a "
999 "keyboard group's keyboard")) { 968 "keyboard group's keyboard")) {
1000 return; 969 return;
@@ -1036,11 +1005,11 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) {
1036 1005
1037 sway_keyboard_group_remove_invalid(keyboard); 1006 sway_keyboard_group_remove_invalid(keyboard);
1038 1007
1039 wlr_keyboard_set_keymap(wlr_device->keyboard, keyboard->keymap); 1008 wlr_keyboard_set_keymap(keyboard->wlr, keyboard->keymap);
1040 wlr_keyboard_set_repeat_info(wlr_device->keyboard, 1009 wlr_keyboard_set_repeat_info(keyboard->wlr,
1041 keyboard->repeat_rate, keyboard->repeat_delay); 1010 keyboard->repeat_rate, keyboard->repeat_delay);
1042 1011
1043 if (!wlr_device->keyboard->group) { 1012 if (!keyboard->wlr->group) {
1044 sway_keyboard_group_add(keyboard); 1013 sway_keyboard_group_add(keyboard);
1045 } 1014 }
1046 1015
@@ -1060,40 +1029,42 @@ void sway_keyboard_configure(struct sway_keyboard *keyboard) {
1060 } 1029 }
1061 } 1030 }
1062 if (locked_mods) { 1031 if (locked_mods) {
1063 wlr_keyboard_notify_modifiers(wlr_device->keyboard, 0, 0, 1032 wlr_keyboard_notify_modifiers(keyboard->wlr, 0, 0,
1064 locked_mods, 0); 1033 locked_mods, 0);
1065 uint32_t leds = 0; 1034 uint32_t leds = 0;
1066 for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) { 1035 for (uint32_t i = 0; i < WLR_LED_COUNT; ++i) {
1067 if (xkb_state_led_index_is_active( 1036 if (xkb_state_led_index_is_active(keyboard->wlr->xkb_state,
1068 wlr_device->keyboard->xkb_state, 1037 keyboard->wlr->led_indexes[i])) {
1069 wlr_device->keyboard->led_indexes[i])) {
1070 leds |= (1 << i); 1038 leds |= (1 << i);
1071 } 1039 }
1072 } 1040 }
1073 if (wlr_device->keyboard->group) { 1041 if (keyboard->wlr->group) {
1074 wlr_keyboard_led_update( 1042 wlr_keyboard_led_update(&keyboard->wlr->group->keyboard, leds);
1075 &wlr_device->keyboard->group->keyboard, leds);
1076 } else { 1043 } else {
1077 wlr_keyboard_led_update(wlr_device->keyboard, leds); 1044 wlr_keyboard_led_update(keyboard->wlr, leds);
1078 } 1045 }
1079 } 1046 }
1080 } else { 1047 } else {
1081 xkb_keymap_unref(keymap); 1048 xkb_keymap_unref(keymap);
1082 sway_keyboard_group_remove_invalid(keyboard); 1049 sway_keyboard_group_remove_invalid(keyboard);
1083 if (!wlr_device->keyboard->group) { 1050 if (!keyboard->wlr->group) {
1084 sway_keyboard_group_add(keyboard); 1051 sway_keyboard_group_add(keyboard);
1085 } 1052 }
1086 } 1053 }
1087 1054
1055 // If the seat has no active keyboard, set this one
1088 struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat; 1056 struct wlr_seat *seat = keyboard->seat_device->sway_seat->wlr_seat;
1089 wlr_seat_set_keyboard(seat, wlr_device); 1057 struct wlr_keyboard *current_keyboard = seat->keyboard_state.keyboard;
1058 if (current_keyboard == NULL) {
1059 wlr_seat_set_keyboard(seat, keyboard->wlr);
1060 }
1090 1061
1091 wl_list_remove(&keyboard->keyboard_key.link); 1062 wl_list_remove(&keyboard->keyboard_key.link);
1092 wl_signal_add(&wlr_device->keyboard->events.key, &keyboard->keyboard_key); 1063 wl_signal_add(&keyboard->wlr->events.key, &keyboard->keyboard_key);
1093 keyboard->keyboard_key.notify = handle_keyboard_key; 1064 keyboard->keyboard_key.notify = handle_keyboard_key;
1094 1065
1095 wl_list_remove(&keyboard->keyboard_modifiers.link); 1066 wl_list_remove(&keyboard->keyboard_modifiers.link);
1096 wl_signal_add(&wlr_device->keyboard->events.modifiers, 1067 wl_signal_add(&keyboard->wlr->events.modifiers,
1097 &keyboard->keyboard_modifiers); 1068 &keyboard->keyboard_modifiers);
1098 keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers; 1069 keyboard->keyboard_modifiers.notify = handle_keyboard_modifiers;
1099 1070
@@ -1110,12 +1081,11 @@ void sway_keyboard_destroy(struct sway_keyboard *keyboard) {
1110 if (!keyboard) { 1081 if (!keyboard) {
1111 return; 1082 return;
1112 } 1083 }
1113 if (keyboard->seat_device->input_device->wlr_device->keyboard->group) { 1084 if (keyboard->wlr->group) {
1114 sway_keyboard_group_remove(keyboard); 1085 sway_keyboard_group_remove(keyboard);
1115 } 1086 }
1116 struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat; 1087 struct wlr_seat *wlr_seat = keyboard->seat_device->sway_seat->wlr_seat;
1117 struct sway_input_device *device = keyboard->seat_device->input_device; 1088 if (wlr_seat_get_keyboard(wlr_seat) == keyboard->wlr) {
1118 if (wlr_seat_get_keyboard(wlr_seat) == device->wlr_device->keyboard) {
1119 wlr_seat_set_keyboard(wlr_seat, NULL); 1089 wlr_seat_set_keyboard(wlr_seat, NULL);
1120 } 1090 }
1121 if (keyboard->keymap) { 1091 if (keyboard->keymap) {
diff --git a/sway/input/libinput.c b/sway/input/libinput.c
index 060a584a..0266c7a9 100644
--- a/sway/input/libinput.c
+++ b/sway/input/libinput.c
@@ -79,6 +79,16 @@ static bool set_accel_speed(struct libinput_device *device, double speed) {
79 return true; 79 return true;
80} 80}
81 81
82static bool set_rotation_angle(struct libinput_device *device, double angle) {
83 if (!libinput_device_config_rotation_is_available(device) ||
84 libinput_device_config_rotation_get_angle(device) == angle) {
85 return false;
86 }
87 sway_log(SWAY_DEBUG, "rotation_set_angle(%f)", angle);
88 log_status(libinput_device_config_rotation_set_angle(device, angle));
89 return true;
90}
91
82static bool set_accel_profile(struct libinput_device *device, 92static bool set_accel_profile(struct libinput_device *device,
83 enum libinput_config_accel_profile profile) { 93 enum libinput_config_accel_profile profile) {
84 if (!libinput_device_config_accel_is_available(device) || 94 if (!libinput_device_config_accel_is_available(device) ||
@@ -156,6 +166,18 @@ static bool set_scroll_button(struct libinput_device *dev, uint32_t button) {
156 return true; 166 return true;
157} 167}
158 168
169static bool set_scroll_button_lock(struct libinput_device *dev,
170 enum libinput_config_scroll_button_lock_state lock) {
171 uint32_t scroll = libinput_device_config_scroll_get_methods(dev);
172 if ((scroll & ~LIBINPUT_CONFIG_SCROLL_NO_SCROLL) == 0 ||
173 libinput_device_config_scroll_get_button_lock(dev) == lock) {
174 return false;
175 }
176 sway_log(SWAY_DEBUG, "scroll_set_button_lock(%" PRIu32 ")", lock);
177 log_status(libinput_device_config_scroll_set_button_lock(dev, lock));
178 return true;
179}
180
159static bool set_dwt(struct libinput_device *device, bool dwt) { 181static bool set_dwt(struct libinput_device *device, bool dwt) {
160 if (!libinput_device_config_dwt_is_available(device) || 182 if (!libinput_device_config_dwt_is_available(device) ||
161 libinput_device_config_dwt_get_enabled(device) == dwt) { 183 libinput_device_config_dwt_get_enabled(device) == dwt) {
@@ -166,6 +188,16 @@ static bool set_dwt(struct libinput_device *device, bool dwt) {
166 return true; 188 return true;
167} 189}
168 190
191static bool set_dwtp(struct libinput_device *device, bool dwtp) {
192 if (!libinput_device_config_dwtp_is_available(device) ||
193 libinput_device_config_dwtp_get_enabled(device) == dwtp) {
194 return false;
195 }
196 sway_log(SWAY_DEBUG, "dwtp_set_enabled(%d)", dwtp);
197 log_status(libinput_device_config_dwtp_set_enabled(device, dwtp));
198 return true;
199}
200
169static bool set_calibration_matrix(struct libinput_device *dev, float mat[6]) { 201static bool set_calibration_matrix(struct libinput_device *dev, float mat[6]) {
170 if (!libinput_device_config_calibration_has_matrix(dev)) { 202 if (!libinput_device_config_calibration_has_matrix(dev)) {
171 return false; 203 return false;
@@ -187,35 +219,38 @@ static bool set_calibration_matrix(struct libinput_device *dev, float mat[6]) {
187 return changed; 219 return changed;
188} 220}
189 221
190void sway_input_configure_libinput_device(struct sway_input_device *input_device) { 222static bool configure_send_events(struct libinput_device *device,
191 struct input_config *ic = input_device_get_config(input_device); 223 struct input_config *ic) {
192 if (!ic || !wlr_input_device_is_libinput(input_device->wlr_device)) {
193 return;
194 }
195
196 struct libinput_device *device =
197 wlr_libinput_get_device_handle(input_device->wlr_device);
198 sway_log(SWAY_DEBUG, "sway_input_configure_libinput_device('%s' on '%s')",
199 ic->identifier, input_device->identifier);
200
201 bool changed = false;
202 if (ic->mapped_to_output && 224 if (ic->mapped_to_output &&
225 strcmp("*", ic->mapped_to_output) != 0 &&
203 !output_by_name_or_id(ic->mapped_to_output)) { 226 !output_by_name_or_id(ic->mapped_to_output)) {
204 sway_log(SWAY_DEBUG, 227 sway_log(SWAY_DEBUG,
205 "%s '%s' is mapped to offline output '%s'; disabling input", 228 "%s '%s' is mapped to offline output '%s'; disabling input",
206 ic->input_type, ic->identifier, ic->mapped_to_output); 229 ic->input_type, ic->identifier, ic->mapped_to_output);
207 changed |= set_send_events(device, 230 return set_send_events(device, LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
208 LIBINPUT_CONFIG_SEND_EVENTS_DISABLED);
209 } else if (ic->send_events != INT_MIN) { 231 } else if (ic->send_events != INT_MIN) {
210 changed |= set_send_events(device, ic->send_events); 232 return set_send_events(device, ic->send_events);
211 } else { 233 } else {
212 // Have to reset to the default mode here, otherwise if ic->send_events 234 // Have to reset to the default mode here, otherwise if ic->send_events
213 // is unset and a mapped output just came online after being disabled, 235 // is unset and a mapped output just came online after being disabled,
214 // we'd remain stuck sending no events. 236 // we'd remain stuck sending no events.
215 changed |= set_send_events(device, 237 return set_send_events(device,
216 libinput_device_config_send_events_get_default_mode(device)); 238 libinput_device_config_send_events_get_default_mode(device));
217 } 239 }
240}
241
242bool sway_input_configure_libinput_device(struct sway_input_device *input_device) {
243 struct input_config *ic = input_device_get_config(input_device);
244 if (!ic || !wlr_input_device_is_libinput(input_device->wlr_device)) {
245 return false;
246 }
247
248 struct libinput_device *device =
249 wlr_libinput_get_device_handle(input_device->wlr_device);
250 sway_log(SWAY_DEBUG, "sway_input_configure_libinput_device('%s' on '%s')",
251 ic->identifier, input_device->identifier);
218 252
253 bool changed = configure_send_events(device, ic);
219 if (ic->tap != INT_MIN) { 254 if (ic->tap != INT_MIN) {
220 changed |= set_tap(device, ic->tap); 255 changed |= set_tap(device, ic->tap);
221 } 256 }
@@ -231,6 +266,9 @@ void sway_input_configure_libinput_device(struct sway_input_device *input_device
231 if (ic->pointer_accel != FLT_MIN) { 266 if (ic->pointer_accel != FLT_MIN) {
232 changed |= set_accel_speed(device, ic->pointer_accel); 267 changed |= set_accel_speed(device, ic->pointer_accel);
233 } 268 }
269 if (ic->rotation_angle != FLT_MIN) {
270 changed |= set_rotation_angle(device, ic->rotation_angle);
271 }
234 if (ic->accel_profile != INT_MIN) { 272 if (ic->accel_profile != INT_MIN) {
235 changed |= set_accel_profile(device, ic->accel_profile); 273 changed |= set_accel_profile(device, ic->accel_profile);
236 } 274 }
@@ -252,13 +290,33 @@ void sway_input_configure_libinput_device(struct sway_input_device *input_device
252 if (ic->scroll_button != INT_MIN) { 290 if (ic->scroll_button != INT_MIN) {
253 changed |= set_scroll_button(device, ic->scroll_button); 291 changed |= set_scroll_button(device, ic->scroll_button);
254 } 292 }
293 if (ic->scroll_button_lock != INT_MIN) {
294 changed |= set_scroll_button_lock(device, ic->scroll_button_lock);
295 }
255 if (ic->dwt != INT_MIN) { 296 if (ic->dwt != INT_MIN) {
256 changed |= set_dwt(device, ic->dwt); 297 changed |= set_dwt(device, ic->dwt);
257 } 298 }
299 if (ic->dwtp != INT_MIN) {
300 changed |= set_dwtp(device, ic->dwtp);
301 }
258 if (ic->calibration_matrix.configured) { 302 if (ic->calibration_matrix.configured) {
259 changed |= set_calibration_matrix(device, ic->calibration_matrix.matrix); 303 changed |= set_calibration_matrix(device, ic->calibration_matrix.matrix);
260 } 304 }
261 305
306 return changed;
307}
308
309void sway_input_configure_libinput_device_send_events(
310 struct sway_input_device *input_device) {
311 struct input_config *ic = input_device_get_config(input_device);
312 if (!ic || !wlr_input_device_is_libinput(input_device->wlr_device)) {
313 return;
314 }
315
316 struct libinput_device *device =
317 wlr_libinput_get_device_handle(input_device->wlr_device);
318 bool changed = configure_send_events(device, ic);
319
262 if (changed) { 320 if (changed) {
263 ipc_event_input("libinput_config", input_device); 321 ipc_event_input("libinput_config", input_device);
264 } 322 }
@@ -287,6 +345,8 @@ void sway_input_reset_libinput_device(struct sway_input_device *input_device) {
287 libinput_device_config_tap_get_default_drag_lock_enabled(device)); 345 libinput_device_config_tap_get_default_drag_lock_enabled(device));
288 changed |= set_accel_speed(device, 346 changed |= set_accel_speed(device,
289 libinput_device_config_accel_get_default_speed(device)); 347 libinput_device_config_accel_get_default_speed(device));
348 changed |= set_rotation_angle(device,
349 libinput_device_config_rotation_get_default_angle(device));
290 changed |= set_accel_profile(device, 350 changed |= set_accel_profile(device,
291 libinput_device_config_accel_get_default_profile(device)); 351 libinput_device_config_accel_get_default_profile(device));
292 changed |= set_natural_scroll(device, 352 changed |= set_natural_scroll(device,
@@ -304,6 +364,8 @@ void sway_input_reset_libinput_device(struct sway_input_device *input_device) {
304 libinput_device_config_scroll_get_default_button(device)); 364 libinput_device_config_scroll_get_default_button(device));
305 changed |= set_dwt(device, 365 changed |= set_dwt(device,
306 libinput_device_config_dwt_get_default_enabled(device)); 366 libinput_device_config_dwt_get_default_enabled(device));
367 changed |= set_dwtp(device,
368 libinput_device_config_dwtp_get_default_enabled(device));
307 369
308 float matrix[6]; 370 float matrix[6];
309 libinput_device_config_calibration_get_default_matrix(device, matrix); 371 libinput_device_config_calibration_get_default_matrix(device, matrix);
@@ -332,6 +394,13 @@ bool sway_libinput_device_is_builtin(struct sway_input_device *sway_device) {
332 return false; 394 return false;
333 } 395 }
334 396
335 const char prefix[] = "platform-"; 397 const char prefix_platform[] = "platform-";
336 return strncmp(id_path, prefix, strlen(prefix)) == 0; 398 if (strncmp(id_path, prefix_platform, strlen(prefix_platform)) != 0) {
399 return false;
400 }
401
402 const char prefix_pci[] = "pci-";
403 const char infix_platform[] = "-platform-";
404 return (strncmp(id_path, prefix_pci, strlen(prefix_pci)) == 0) &&
405 strstr(id_path, infix_platform);
337} 406}
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 2d714acd..da4bb12a 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -1,22 +1,23 @@
1#define _POSIX_C_SOURCE 200809L
2#include <assert.h> 1#include <assert.h>
3#include <linux/input-event-codes.h> 2#include <linux/input-event-codes.h>
4#include <string.h> 3#include <string.h>
5#include <strings.h> 4#include <strings.h>
6#include <time.h> 5#include <time.h>
6#include <wlr/config.h>
7#include <wlr/types/wlr_cursor.h> 7#include <wlr/types/wlr_cursor.h>
8#include <wlr/types/wlr_data_device.h> 8#include <wlr/types/wlr_data_device.h>
9#include <wlr/types/wlr_idle.h> 9#include <wlr/types/wlr_idle_notify_v1.h>
10#include <wlr/types/wlr_keyboard_group.h> 10#include <wlr/types/wlr_keyboard_group.h>
11#include <wlr/types/wlr_output_layout.h> 11#include <wlr/types/wlr_output_layout.h>
12#include <wlr/types/wlr_primary_selection.h> 12#include <wlr/types/wlr_primary_selection.h>
13#include <wlr/types/wlr_tablet_v2.h> 13#include <wlr/types/wlr_tablet_v2.h>
14#include <wlr/types/wlr_touch.h>
14#include <wlr/types/wlr_xcursor_manager.h> 15#include <wlr/types/wlr_xcursor_manager.h>
15#include "config.h" 16#include "config.h"
16#include "list.h" 17#include "list.h"
17#include "log.h" 18#include "log.h"
18#include "sway/config.h" 19#include "sway/config.h"
19#include "sway/desktop.h" 20#include "sway/scene_descriptor.h"
20#include "sway/input/cursor.h" 21#include "sway/input/cursor.h"
21#include "sway/input/input-manager.h" 22#include "sway/input/input-manager.h"
22#include "sway/input/keyboard.h" 23#include "sway/input/keyboard.h"
@@ -42,6 +43,7 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) {
42 sway_keyboard_destroy(seat_device->keyboard); 43 sway_keyboard_destroy(seat_device->keyboard);
43 sway_tablet_destroy(seat_device->tablet); 44 sway_tablet_destroy(seat_device->tablet);
44 sway_tablet_pad_destroy(seat_device->tablet_pad); 45 sway_tablet_pad_destroy(seat_device->tablet_pad);
46 sway_switch_destroy(seat_device->switch_device);
45 wlr_cursor_detach_input_device(seat_device->sway_seat->cursor->cursor, 47 wlr_cursor_detach_input_device(seat_device->sway_seat->cursor->cursor,
46 seat_device->input_device->wlr_device); 48 seat_device->input_device->wlr_device);
47 wl_list_remove(&seat_device->link); 49 wl_list_remove(&seat_device->link);
@@ -51,10 +53,26 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) {
51static void seat_node_destroy(struct sway_seat_node *seat_node) { 53static void seat_node_destroy(struct sway_seat_node *seat_node) {
52 wl_list_remove(&seat_node->destroy.link); 54 wl_list_remove(&seat_node->destroy.link);
53 wl_list_remove(&seat_node->link); 55 wl_list_remove(&seat_node->link);
56
57 /*
58 * This is the only time we remove items from the focus stack without
59 * immediately re-adding them. If we just removed the last thing,
60 * mark that nothing has focus anymore.
61 */
62 if (wl_list_empty(&seat_node->seat->focus_stack)) {
63 seat_node->seat->has_focus = false;
64 }
65
54 free(seat_node); 66 free(seat_node);
55} 67}
56 68
57void seat_destroy(struct sway_seat *seat) { 69void seat_destroy(struct sway_seat *seat) {
70 wlr_seat_destroy(seat->wlr_seat);
71}
72
73static void handle_seat_destroy(struct wl_listener *listener, void *data) {
74 struct sway_seat *seat = wl_container_of(listener, seat, destroy);
75
58 if (seat == config->handler_context.seat) { 76 if (seat == config->handler_context.seat) {
59 config->handler_context.seat = input_manager_get_default_seat(); 77 config->handler_context.seat = input_manager_get_default_seat();
60 } 78 }
@@ -75,10 +93,11 @@ void seat_destroy(struct sway_seat *seat) {
75 wl_list_remove(&seat->request_set_selection.link); 93 wl_list_remove(&seat->request_set_selection.link);
76 wl_list_remove(&seat->request_set_primary_selection.link); 94 wl_list_remove(&seat->request_set_primary_selection.link);
77 wl_list_remove(&seat->link); 95 wl_list_remove(&seat->link);
78 wlr_seat_destroy(seat->wlr_seat); 96 wl_list_remove(&seat->destroy.link);
79 for (int i = 0; i < seat->deferred_bindings->length; i++) { 97 for (int i = 0; i < seat->deferred_bindings->length; i++) {
80 free_sway_binding(seat->deferred_bindings->items[i]); 98 free_sway_binding(seat->deferred_bindings->items[i]);
81 } 99 }
100 wlr_scene_node_destroy(&seat->scene_tree->node);
82 list_free(seat->deferred_bindings); 101 list_free(seat->deferred_bindings);
83 free(seat->prev_workspace_name); 102 free(seat->prev_workspace_name);
84 free(seat); 103 free(seat);
@@ -86,21 +105,10 @@ void seat_destroy(struct sway_seat *seat) {
86 105
87void seat_idle_notify_activity(struct sway_seat *seat, 106void seat_idle_notify_activity(struct sway_seat *seat,
88 enum sway_input_idle_source source) { 107 enum sway_input_idle_source source) {
89 uint32_t mask = seat->idle_inhibit_sources; 108 if ((source & seat->idle_inhibit_sources) == 0) {
90 struct wlr_idle_timeout *timeout; 109 return;
91 int ntimers = 0, nidle = 0;
92 wl_list_for_each(timeout, &server.idle->idle_timers, link) {
93 ++ntimers;
94 if (timeout->idle_state) {
95 ++nidle;
96 }
97 }
98 if (nidle == ntimers) {
99 mask = seat->idle_wake_sources;
100 }
101 if ((source & mask) > 0) {
102 wlr_idle_notify_activity(server.idle, seat->wlr_seat);
103 } 110 }
111 wlr_idle_notifier_v1_notify_activity(server.idle_notifier_v1, seat->wlr_seat);
104} 112}
105 113
106/** 114/**
@@ -130,7 +138,7 @@ static struct sway_keyboard *sway_keyboard_for_wlr_keyboard(
130 if (input_device->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) { 138 if (input_device->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) {
131 continue; 139 continue;
132 } 140 }
133 if (input_device->wlr_device->keyboard == wlr_keyboard) { 141 if (input_device->wlr_device == &wlr_keyboard->base) {
134 return seat_device->keyboard; 142 return seat_device->keyboard;
135 } 143 }
136 } 144 }
@@ -138,7 +146,7 @@ static struct sway_keyboard *sway_keyboard_for_wlr_keyboard(
138 wl_list_for_each(group, &seat->keyboard_groups, link) { 146 wl_list_for_each(group, &seat->keyboard_groups, link) {
139 struct sway_input_device *input_device = 147 struct sway_input_device *input_device =
140 group->seat_device->input_device; 148 group->seat_device->input_device;
141 if (input_device->wlr_device->keyboard == wlr_keyboard) { 149 if (input_device->wlr_device == &wlr_keyboard->base) {
142 return group->seat_device->keyboard; 150 return group->seat_device->keyboard;
143 } 151 }
144 } 152 }
@@ -162,11 +170,11 @@ static void seat_keyboard_notify_enter(struct sway_seat *seat,
162 state->pressed_keycodes, state->npressed, &keyboard->modifiers); 170 state->pressed_keycodes, state->npressed, &keyboard->modifiers);
163} 171}
164 172
165static void seat_tablet_pads_notify_enter(struct sway_seat *seat, 173static void seat_tablet_pads_set_focus(struct sway_seat *seat,
166 struct wlr_surface *surface) { 174 struct wlr_surface *surface) {
167 struct sway_seat_device *seat_device; 175 struct sway_seat_device *seat_device;
168 wl_list_for_each(seat_device, &seat->devices, link) { 176 wl_list_for_each(seat_device, &seat->devices, link) {
169 sway_tablet_pad_notify_enter(seat_device->tablet_pad, surface); 177 sway_tablet_pad_set_focus(seat_device->tablet_pad, surface);
170 } 178 }
171} 179}
172 180
@@ -182,7 +190,7 @@ static void seat_send_focus(struct sway_node *node, struct sway_seat *seat) {
182 node->sway_container->view : NULL; 190 node->sway_container->view : NULL;
183 191
184 if (view && seat_is_input_allowed(seat, view->surface)) { 192 if (view && seat_is_input_allowed(seat, view->surface)) {
185#if HAVE_XWAYLAND 193#if WLR_HAS_XWAYLAND
186 if (view->type == SWAY_VIEW_XWAYLAND) { 194 if (view->type == SWAY_VIEW_XWAYLAND) {
187 struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; 195 struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland;
188 wlr_xwayland_set_seat(xwayland, seat->wlr_seat); 196 wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
@@ -190,7 +198,7 @@ static void seat_send_focus(struct sway_node *node, struct sway_seat *seat) {
190#endif 198#endif
191 199
192 seat_keyboard_notify_enter(seat, view->surface); 200 seat_keyboard_notify_enter(seat, view->surface);
193 seat_tablet_pads_notify_enter(seat, view->surface); 201 seat_tablet_pads_set_focus(seat, view->surface);
194 sway_input_method_relay_set_focus(&seat->im_relay, view->surface); 202 sway_input_method_relay_set_focus(&seat->im_relay, view->surface);
195 203
196 struct wlr_pointer_constraint_v1 *constraint = 204 struct wlr_pointer_constraint_v1 *constraint =
@@ -210,14 +218,13 @@ void seat_for_each_node(struct sway_seat *seat,
210 218
211struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat, 219struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat,
212 struct sway_node *ancestor) { 220 struct sway_node *ancestor) {
213 if (ancestor->type == N_CONTAINER && ancestor->sway_container->view) { 221 if (node_is_view(ancestor)) {
214 return ancestor->sway_container; 222 return ancestor->sway_container;
215 } 223 }
216 struct sway_seat_node *current; 224 struct sway_seat_node *current;
217 wl_list_for_each(current, &seat->focus_stack, link) { 225 wl_list_for_each(current, &seat->focus_stack, link) {
218 struct sway_node *node = current->node; 226 struct sway_node *node = current->node;
219 if (node->type == N_CONTAINER && node->sway_container->view && 227 if (node_is_view(node) && node_has_ancestor(node, ancestor)) {
220 node_has_ancestor(node, ancestor)) {
221 return node->sway_container; 228 return node->sway_container;
222 } 229 }
223 } 230 }
@@ -236,7 +243,7 @@ static void handle_seat_node_destroy(struct wl_listener *listener, void *data) {
236 seat_node_destroy(seat_node); 243 seat_node_destroy(seat_node);
237 // If an unmanaged or layer surface is focused when an output gets 244 // If an unmanaged or layer surface is focused when an output gets
238 // disabled and an empty workspace on the output was focused by the 245 // disabled and an empty workspace on the output was focused by the
239 // seat, the seat needs to refocus it's focus inactive to update the 246 // seat, the seat needs to refocus its focus inactive to update the
240 // value of seat->workspace. 247 // value of seat->workspace.
241 if (seat->workspace == node->sway_workspace) { 248 if (seat->workspace == node->sway_workspace) {
242 struct sway_node *node = seat_get_focus_inactive(seat, &root->node); 249 struct sway_node *node = seat_get_focus_inactive(seat, &root->node);
@@ -352,25 +359,15 @@ static void handle_new_node(struct wl_listener *listener, void *data) {
352 seat_node_from_node(seat, node); 359 seat_node_from_node(seat, node);
353} 360}
354 361
355static void drag_icon_damage_whole(struct sway_drag_icon *icon) { 362static void drag_icon_update_position(struct sway_seat *seat, struct wlr_scene_node *node) {
356 if (!icon->wlr_drag_icon->mapped) { 363 struct wlr_drag_icon *wlr_icon = scene_descriptor_try_get(node, SWAY_SCENE_DESC_DRAG_ICON);
357 return;
358 }
359 desktop_damage_surface(icon->wlr_drag_icon->surface, icon->x, icon->y, true);
360}
361
362void drag_icon_update_position(struct sway_drag_icon *icon) {
363 drag_icon_damage_whole(icon);
364
365 struct wlr_drag_icon *wlr_icon = icon->wlr_drag_icon;
366 struct sway_seat *seat = icon->seat;
367 struct wlr_cursor *cursor = seat->cursor->cursor; 364 struct wlr_cursor *cursor = seat->cursor->cursor;
365
368 switch (wlr_icon->drag->grab_type) { 366 switch (wlr_icon->drag->grab_type) {
369 case WLR_DRAG_GRAB_KEYBOARD: 367 case WLR_DRAG_GRAB_KEYBOARD:
370 return; 368 return;
371 case WLR_DRAG_GRAB_KEYBOARD_POINTER: 369 case WLR_DRAG_GRAB_KEYBOARD_POINTER:
372 icon->x = cursor->x; 370 wlr_scene_node_set_position(node, cursor->x, cursor->y);
373 icon->y = cursor->y;
374 break; 371 break;
375 case WLR_DRAG_GRAB_KEYBOARD_TOUCH:; 372 case WLR_DRAG_GRAB_KEYBOARD_TOUCH:;
376 struct wlr_touch_point *point = 373 struct wlr_touch_point *point =
@@ -378,39 +375,15 @@ void drag_icon_update_position(struct sway_drag_icon *icon) {
378 if (point == NULL) { 375 if (point == NULL) {
379 return; 376 return;
380 } 377 }
381 icon->x = seat->touch_x; 378 wlr_scene_node_set_position(node, seat->touch_x, seat->touch_y);
382 icon->y = seat->touch_y;
383 } 379 }
384
385 drag_icon_damage_whole(icon);
386} 380}
387 381
388static void drag_icon_handle_surface_commit(struct wl_listener *listener, 382void drag_icons_update_position(struct sway_seat *seat) {
389 void *data) { 383 struct wlr_scene_node *node;
390 struct sway_drag_icon *icon = 384 wl_list_for_each(node, &seat->drag_icons->children, link) {
391 wl_container_of(listener, icon, surface_commit); 385 drag_icon_update_position(seat, node);
392 drag_icon_update_position(icon); 386 }
393}
394
395static void drag_icon_handle_map(struct wl_listener *listener, void *data) {
396 struct sway_drag_icon *icon = wl_container_of(listener, icon, map);
397 drag_icon_damage_whole(icon);
398}
399
400static void drag_icon_handle_unmap(struct wl_listener *listener, void *data) {
401 struct sway_drag_icon *icon = wl_container_of(listener, icon, unmap);
402 drag_icon_damage_whole(icon);
403}
404
405static void drag_icon_handle_destroy(struct wl_listener *listener, void *data) {
406 struct sway_drag_icon *icon = wl_container_of(listener, icon, destroy);
407 icon->wlr_drag_icon->data = NULL;
408 wl_list_remove(&icon->link);
409 wl_list_remove(&icon->surface_commit.link);
410 wl_list_remove(&icon->unmap.link);
411 wl_list_remove(&icon->map.link);
412 wl_list_remove(&icon->destroy.link);
413 free(icon);
414} 387}
415 388
416static void drag_handle_destroy(struct wl_listener *listener, void *data) { 389static void drag_handle_destroy(struct wl_listener *listener, void *data) {
@@ -482,27 +455,20 @@ static void handle_start_drag(struct wl_listener *listener, void *data) {
482 455
483 struct wlr_drag_icon *wlr_drag_icon = wlr_drag->icon; 456 struct wlr_drag_icon *wlr_drag_icon = wlr_drag->icon;
484 if (wlr_drag_icon != NULL) { 457 if (wlr_drag_icon != NULL) {
485 struct sway_drag_icon *icon = calloc(1, sizeof(struct sway_drag_icon)); 458 struct wlr_scene_tree *tree = wlr_scene_drag_icon_create(seat->drag_icons, wlr_drag_icon);
486 if (icon == NULL) { 459 if (!tree) {
487 sway_log(SWAY_ERROR, "Allocation failed"); 460 sway_log(SWAY_ERROR, "Failed to allocate a drag icon scene tree");
488 return; 461 return;
489 } 462 }
490 icon->seat = seat;
491 icon->wlr_drag_icon = wlr_drag_icon;
492 wlr_drag_icon->data = icon;
493 463
494 icon->surface_commit.notify = drag_icon_handle_surface_commit; 464 if (!scene_descriptor_assign(&tree->node, SWAY_SCENE_DESC_DRAG_ICON,
495 wl_signal_add(&wlr_drag_icon->surface->events.commit, &icon->surface_commit); 465 wlr_drag_icon)) {
496 icon->unmap.notify = drag_icon_handle_unmap; 466 sway_log(SWAY_ERROR, "Failed to allocate a drag icon scene descriptor");
497 wl_signal_add(&wlr_drag_icon->events.unmap, &icon->unmap); 467 wlr_scene_node_destroy(&tree->node);
498 icon->map.notify = drag_icon_handle_map; 468 return;
499 wl_signal_add(&wlr_drag_icon->events.map, &icon->map); 469 }
500 icon->destroy.notify = drag_icon_handle_destroy;
501 wl_signal_add(&wlr_drag_icon->events.destroy, &icon->destroy);
502
503 wl_list_insert(&root->drag_icons, &icon->link);
504 470
505 drag_icon_update_position(icon); 471 drag_icon_update_position(seat, &tree->node);
506 } 472 }
507 seatop_begin_default(seat); 473 seatop_begin_default(seat);
508} 474}
@@ -549,8 +515,18 @@ struct sway_seat *seat_create(const char *seat_name) {
549 return NULL; 515 return NULL;
550 } 516 }
551 517
518 bool failed = false;
519 seat->scene_tree = alloc_scene_tree(root->layers.seat, &failed);
520 seat->drag_icons = alloc_scene_tree(seat->scene_tree, &failed);
521 if (failed) {
522 wlr_scene_node_destroy(&seat->scene_tree->node);
523 free(seat);
524 return NULL;
525 }
526
552 seat->wlr_seat = wlr_seat_create(server.wl_display, seat_name); 527 seat->wlr_seat = wlr_seat_create(server.wl_display, seat_name);
553 if (!sway_assert(seat->wlr_seat, "could not allocate seat")) { 528 if (!sway_assert(seat->wlr_seat, "could not allocate seat")) {
529 wlr_scene_node_destroy(&seat->scene_tree->node);
554 free(seat); 530 free(seat);
555 return NULL; 531 return NULL;
556 } 532 }
@@ -558,11 +534,15 @@ struct sway_seat *seat_create(const char *seat_name) {
558 534
559 seat->cursor = sway_cursor_create(seat); 535 seat->cursor = sway_cursor_create(seat);
560 if (!seat->cursor) { 536 if (!seat->cursor) {
537 wlr_scene_node_destroy(&seat->scene_tree->node);
561 wlr_seat_destroy(seat->wlr_seat); 538 wlr_seat_destroy(seat->wlr_seat);
562 free(seat); 539 free(seat);
563 return NULL; 540 return NULL;
564 } 541 }
565 542
543 seat->destroy.notify = handle_seat_destroy;
544 wl_signal_add(&seat->wlr_seat->events.destroy, &seat->destroy);
545
566 seat->idle_inhibit_sources = seat->idle_wake_sources = 546 seat->idle_inhibit_sources = seat->idle_wake_sources =
567 IDLE_SOURCE_KEYBOARD | 547 IDLE_SOURCE_KEYBOARD |
568 IDLE_SOURCE_POINTER | 548 IDLE_SOURCE_POINTER |
@@ -636,7 +616,7 @@ static void seat_update_capabilities(struct sway_seat *seat) {
636 case WLR_INPUT_DEVICE_TOUCH: 616 case WLR_INPUT_DEVICE_TOUCH:
637 caps |= WL_SEAT_CAPABILITY_TOUCH; 617 caps |= WL_SEAT_CAPABILITY_TOUCH;
638 break; 618 break;
639 case WLR_INPUT_DEVICE_TABLET_TOOL: 619 case WLR_INPUT_DEVICE_TABLET:
640 caps |= WL_SEAT_CAPABILITY_POINTER; 620 caps |= WL_SEAT_CAPABILITY_POINTER;
641 break; 621 break;
642 case WLR_INPUT_DEVICE_SWITCH: 622 case WLR_INPUT_DEVICE_SWITCH:
@@ -654,7 +634,7 @@ static void seat_update_capabilities(struct sway_seat *seat) {
654 } else { 634 } else {
655 wlr_seat_set_capabilities(seat->wlr_seat, caps); 635 wlr_seat_set_capabilities(seat->wlr_seat, caps);
656 if ((previous_caps & WL_SEAT_CAPABILITY_POINTER) == 0) { 636 if ((previous_caps & WL_SEAT_CAPABILITY_POINTER) == 0) {
657 cursor_set_image(seat->cursor, "left_ptr", NULL); 637 cursor_set_image(seat->cursor, "default", NULL);
658 } 638 }
659 } 639 }
660} 640}
@@ -694,19 +674,28 @@ static const char *get_builtin_output_name(void) {
694static bool is_touch_or_tablet_tool(struct sway_seat_device *seat_device) { 674static bool is_touch_or_tablet_tool(struct sway_seat_device *seat_device) {
695 switch (seat_device->input_device->wlr_device->type) { 675 switch (seat_device->input_device->wlr_device->type) {
696 case WLR_INPUT_DEVICE_TOUCH: 676 case WLR_INPUT_DEVICE_TOUCH:
697 case WLR_INPUT_DEVICE_TABLET_TOOL: 677 case WLR_INPUT_DEVICE_TABLET:
698 return true; 678 return true;
699 default: 679 default:
700 return false; 680 return false;
701 } 681 }
702} 682}
703 683
704static void seat_apply_input_config(struct sway_seat *seat, 684static void seat_apply_input_mapping(struct sway_seat *seat,
705 struct sway_seat_device *sway_device) { 685 struct sway_seat_device *sway_device) {
706 struct input_config *ic = 686 struct input_config *ic =
707 input_device_get_config(sway_device->input_device); 687 input_device_get_config(sway_device->input_device);
708 688
709 sway_log(SWAY_DEBUG, "Applying input config to %s", 689 switch (sway_device->input_device->wlr_device->type) {
690 case WLR_INPUT_DEVICE_POINTER:
691 case WLR_INPUT_DEVICE_TOUCH:
692 case WLR_INPUT_DEVICE_TABLET:
693 break;
694 default:
695 return; // these devices don't support mappings
696 }
697
698 sway_log(SWAY_DEBUG, "Applying input mapping to %s",
710 sway_device->input_device->identifier); 699 sway_device->input_device->identifier);
711 700
712 const char *mapped_to_output = ic == NULL ? NULL : ic->mapped_to_output; 701 const char *mapped_to_output = ic == NULL ? NULL : ic->mapped_to_output;
@@ -715,14 +704,26 @@ static void seat_apply_input_config(struct sway_seat *seat,
715 ic == NULL ? MAPPED_TO_DEFAULT : ic->mapped_to; 704 ic == NULL ? MAPPED_TO_DEFAULT : ic->mapped_to;
716 705
717 switch (mapped_to) { 706 switch (mapped_to) {
718 case MAPPED_TO_DEFAULT: 707 case MAPPED_TO_DEFAULT:;
719 /* 708 /*
720 * If the wlroots backend provides an output name, use that. 709 * If the wlroots backend provides an output name, use that.
721 * 710 *
722 * Otherwise, try to map built-in touch and tablet tool devices to the 711 * Otherwise, try to map built-in touch and pointer devices to the
723 * built-in output. 712 * built-in output.
724 */ 713 */
725 mapped_to_output = sway_device->input_device->wlr_device->output_name; 714 struct wlr_input_device *dev = sway_device->input_device->wlr_device;
715 switch (dev->type) {
716 case WLR_INPUT_DEVICE_POINTER:
717 mapped_to_output = wlr_pointer_from_input_device(dev)->output_name;
718 break;
719 case WLR_INPUT_DEVICE_TOUCH:
720 mapped_to_output = wlr_touch_from_input_device(dev)->output_name;
721 break;
722 default:
723 mapped_to_output = NULL;
724 break;
725 }
726#if WLR_HAS_LIBINPUT_BACKEND
726 if (mapped_to_output == NULL && is_touch_or_tablet_tool(sway_device) && 727 if (mapped_to_output == NULL && is_touch_or_tablet_tool(sway_device) &&
727 sway_libinput_device_is_builtin(sway_device->input_device)) { 728 sway_libinput_device_is_builtin(sway_device->input_device)) {
728 mapped_to_output = get_builtin_output_name(); 729 mapped_to_output = get_builtin_output_name();
@@ -731,6 +732,10 @@ static void seat_apply_input_config(struct sway_seat *seat,
731 mapped_to_output, sway_device->input_device->identifier); 732 mapped_to_output, sway_device->input_device->identifier);
732 } 733 }
733 } 734 }
735#else
736 (void)is_touch_or_tablet_tool;
737 (void)get_builtin_output_name;
738#endif
734 if (mapped_to_output == NULL) { 739 if (mapped_to_output == NULL) {
735 return; 740 return;
736 } 741 }
@@ -774,12 +779,9 @@ static void seat_apply_input_config(struct sway_seat *seat,
774 779
775static void seat_configure_pointer(struct sway_seat *seat, 780static void seat_configure_pointer(struct sway_seat *seat,
776 struct sway_seat_device *sway_device) { 781 struct sway_seat_device *sway_device) {
777 if ((seat->wlr_seat->capabilities & WL_SEAT_CAPABILITY_POINTER) == 0) { 782 seat_configure_xcursor(seat);
778 seat_configure_xcursor(seat);
779 }
780 wlr_cursor_attach_input_device(seat->cursor->cursor, 783 wlr_cursor_attach_input_device(seat->cursor->cursor,
781 sway_device->input_device->wlr_device); 784 sway_device->input_device->wlr_device);
782 seat_apply_input_config(seat, sway_device);
783 wl_event_source_timer_update( 785 wl_event_source_timer_update(
784 seat->cursor->hide_source, cursor_get_timeout(seat->cursor)); 786 seat->cursor->hide_source, cursor_get_timeout(seat->cursor));
785} 787}
@@ -790,13 +792,22 @@ static void seat_configure_keyboard(struct sway_seat *seat,
790 sway_keyboard_create(seat, seat_device); 792 sway_keyboard_create(seat, seat_device);
791 } 793 }
792 sway_keyboard_configure(seat_device->keyboard); 794 sway_keyboard_configure(seat_device->keyboard);
793 wlr_seat_set_keyboard(seat->wlr_seat, 795
794 seat_device->input_device->wlr_device); 796 // We only need to update the current keyboard, as the rest will be updated
795 struct sway_node *focus = seat_get_focus(seat); 797 // as they are activated.
796 if (focus && node_is_view(focus)) { 798 struct wlr_keyboard *wlr_keyboard =
797 // force notify reenter to pick up the new configuration 799 wlr_keyboard_from_input_device(seat_device->input_device->wlr_device);
800 struct wlr_keyboard *current_keyboard = seat->wlr_seat->keyboard_state.keyboard;
801 if (wlr_keyboard != current_keyboard) {
802 return;
803 }
804
805 // force notify reenter to pick up the new configuration. This reuses
806 // the current focused surface to avoid breaking input grabs.
807 struct wlr_surface *surface = seat->wlr_seat->keyboard_state.focused_surface;
808 if (surface) {
798 wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat); 809 wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat);
799 seat_keyboard_notify_enter(seat, focus->sway_container->view->surface); 810 seat_keyboard_notify_enter(seat, surface);
800 } 811 }
801} 812}
802 813
@@ -805,7 +816,6 @@ static void seat_configure_switch(struct sway_seat *seat,
805 if (!seat_device->switch_device) { 816 if (!seat_device->switch_device) {
806 sway_switch_create(seat, seat_device); 817 sway_switch_create(seat, seat_device);
807 } 818 }
808 seat_apply_input_config(seat, seat_device);
809 sway_switch_configure(seat_device->switch_device); 819 sway_switch_configure(seat_device->switch_device);
810} 820}
811 821
@@ -813,7 +823,6 @@ static void seat_configure_touch(struct sway_seat *seat,
813 struct sway_seat_device *sway_device) { 823 struct sway_seat_device *sway_device) {
814 wlr_cursor_attach_input_device(seat->cursor->cursor, 824 wlr_cursor_attach_input_device(seat->cursor->cursor,
815 sway_device->input_device->wlr_device); 825 sway_device->input_device->wlr_device);
816 seat_apply_input_config(seat, sway_device);
817} 826}
818 827
819static void seat_configure_tablet_tool(struct sway_seat *seat, 828static void seat_configure_tablet_tool(struct sway_seat *seat,
@@ -824,7 +833,6 @@ static void seat_configure_tablet_tool(struct sway_seat *seat,
824 sway_configure_tablet(sway_device->tablet); 833 sway_configure_tablet(sway_device->tablet);
825 wlr_cursor_attach_input_device(seat->cursor->cursor, 834 wlr_cursor_attach_input_device(seat->cursor->cursor,
826 sway_device->input_device->wlr_device); 835 sway_device->input_device->wlr_device);
827 seat_apply_input_config(seat, sway_device);
828} 836}
829 837
830static void seat_configure_tablet_pad(struct sway_seat *seat, 838static void seat_configure_tablet_pad(struct sway_seat *seat,
@@ -874,13 +882,25 @@ void seat_configure_device(struct sway_seat *seat,
874 case WLR_INPUT_DEVICE_TOUCH: 882 case WLR_INPUT_DEVICE_TOUCH:
875 seat_configure_touch(seat, seat_device); 883 seat_configure_touch(seat, seat_device);
876 break; 884 break;
877 case WLR_INPUT_DEVICE_TABLET_TOOL: 885 case WLR_INPUT_DEVICE_TABLET:
878 seat_configure_tablet_tool(seat, seat_device); 886 seat_configure_tablet_tool(seat, seat_device);
879 break; 887 break;
880 case WLR_INPUT_DEVICE_TABLET_PAD: 888 case WLR_INPUT_DEVICE_TABLET_PAD:
881 seat_configure_tablet_pad(seat, seat_device); 889 seat_configure_tablet_pad(seat, seat_device);
882 break; 890 break;
883 } 891 }
892
893 seat_apply_input_mapping(seat, seat_device);
894}
895
896void seat_configure_device_mapping(struct sway_seat *seat,
897 struct sway_input_device *input_device) {
898 struct sway_seat_device *seat_device = seat_get_device(seat, input_device);
899 if (!seat_device) {
900 return;
901 }
902
903 seat_apply_input_mapping(seat, seat_device);
884} 904}
885 905
886void seat_reset_device(struct sway_seat *seat, 906void seat_reset_device(struct sway_seat *seat,
@@ -901,7 +921,7 @@ void seat_reset_device(struct sway_seat *seat,
901 case WLR_INPUT_DEVICE_TOUCH: 921 case WLR_INPUT_DEVICE_TOUCH:
902 seat_reset_input_config(seat, seat_device); 922 seat_reset_input_config(seat, seat_device);
903 break; 923 break;
904 case WLR_INPUT_DEVICE_TABLET_TOOL: 924 case WLR_INPUT_DEVICE_TABLET:
905 seat_reset_input_config(seat, seat_device); 925 seat_reset_input_config(seat, seat_device);
906 break; 926 break;
907 case WLR_INPUT_DEVICE_TABLET_PAD: 927 case WLR_INPUT_DEVICE_TABLET_PAD:
@@ -982,7 +1002,7 @@ void seat_configure_xcursor(struct sway_seat *seat) {
982 setenv("XCURSOR_THEME", cursor_theme, 1); 1002 setenv("XCURSOR_THEME", cursor_theme, 1);
983 } 1003 }
984 1004
985#if HAVE_XWAYLAND 1005#if WLR_HAS_XWAYLAND
986 if (server.xwayland.wlr_xwayland && (!server.xwayland.xcursor_manager || 1006 if (server.xwayland.wlr_xwayland && (!server.xwayland.xcursor_manager ||
987 !xcursor_manager_is_named(server.xwayland.xcursor_manager, 1007 !xcursor_manager_is_named(server.xwayland.xcursor_manager,
988 cursor_theme) || 1008 cursor_theme) ||
@@ -997,7 +1017,7 @@ void seat_configure_xcursor(struct sway_seat *seat) {
997 1017
998 wlr_xcursor_manager_load(server.xwayland.xcursor_manager, 1); 1018 wlr_xcursor_manager_load(server.xwayland.xcursor_manager, 1);
999 struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( 1019 struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor(
1000 server.xwayland.xcursor_manager, "left_ptr", 1); 1020 server.xwayland.xcursor_manager, "default", 1);
1001 if (xcursor != NULL) { 1021 if (xcursor != NULL) {
1002 struct wlr_xcursor_image *image = xcursor->images[0]; 1022 struct wlr_xcursor_image *image = xcursor->images[0];
1003 wlr_xwayland_set_cursor( 1023 wlr_xwayland_set_cursor(
@@ -1023,32 +1043,35 @@ void seat_configure_xcursor(struct sway_seat *seat) {
1023 sway_log(SWAY_ERROR, 1043 sway_log(SWAY_ERROR,
1024 "Cannot create XCursor manager for theme '%s'", cursor_theme); 1044 "Cannot create XCursor manager for theme '%s'", cursor_theme);
1025 } 1045 }
1026 }
1027 1046
1028 for (int i = 0; i < root->outputs->length; ++i) { 1047
1029 struct sway_output *sway_output = root->outputs->items[i]; 1048 for (int i = 0; i < root->outputs->length; ++i) {
1030 struct wlr_output *output = sway_output->wlr_output; 1049 struct sway_output *sway_output = root->outputs->items[i];
1031 bool result = 1050 struct wlr_output *output = sway_output->wlr_output;
1032 wlr_xcursor_manager_load(seat->cursor->xcursor_manager, 1051 bool result =
1033 output->scale); 1052 wlr_xcursor_manager_load(seat->cursor->xcursor_manager,
1034 if (!result) { 1053 output->scale);
1035 sway_log(SWAY_ERROR, 1054 if (!result) {
1036 "Cannot load xcursor theme for output '%s' with scale %f", 1055 sway_log(SWAY_ERROR,
1037 output->name, output->scale); 1056 "Cannot load xcursor theme for output '%s' with scale %f",
1057 output->name, output->scale);
1058 }
1038 } 1059 }
1039 }
1040 1060
1041 // Reset the cursor so that we apply it to outputs that just appeared 1061 // Reset the cursor so that we apply it to outputs that just appeared
1042 cursor_set_image(seat->cursor, NULL, NULL); 1062 cursor_set_image(seat->cursor, NULL, NULL);
1043 cursor_set_image(seat->cursor, "left_ptr", NULL); 1063 cursor_set_image(seat->cursor, "default", NULL);
1044 wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, 1064 wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x,
1045 seat->cursor->cursor->y); 1065 seat->cursor->cursor->y);
1066 }
1046} 1067}
1047 1068
1048bool seat_is_input_allowed(struct sway_seat *seat, 1069bool seat_is_input_allowed(struct sway_seat *seat,
1049 struct wlr_surface *surface) { 1070 struct wlr_surface *surface) {
1050 struct wl_client *client = wl_resource_get_client(surface->resource); 1071 if (server.session_lock.lock) {
1051 return !seat->exclusive_client || seat->exclusive_client == client; 1072 return sway_session_lock_has_surface(server.session_lock.lock, surface);
1073 }
1074 return true;
1052} 1075}
1053 1076
1054static void send_unfocus(struct sway_container *con, void *data) { 1077static void send_unfocus(struct sway_container *con, void *data) {
@@ -1107,15 +1130,7 @@ void seat_set_raw_focus(struct sway_seat *seat, struct sway_node *node) {
1107 } 1130 }
1108} 1131}
1109 1132
1110void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { 1133static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *node) {
1111 if (seat->focused_layer) {
1112 struct wlr_layer_surface_v1 *layer = seat->focused_layer;
1113 seat_set_focus_layer(seat, NULL);
1114 seat_set_focus(seat, node);
1115 seat_set_focus_layer(seat, layer);
1116 return;
1117 }
1118
1119 struct sway_node *last_focus = seat_get_focus(seat); 1134 struct sway_node *last_focus = seat_get_focus(seat);
1120 if (last_focus == node) { 1135 if (last_focus == node) {
1121 return; 1136 return;
@@ -1248,6 +1263,24 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) {
1248 } 1263 }
1249} 1264}
1250 1265
1266void seat_set_focus(struct sway_seat *seat, struct sway_node *node) {
1267 // Prevents the layer from losing focus if it has keyboard exclusivity
1268 if (seat->has_exclusive_layer) {
1269 struct wlr_layer_surface_v1 *layer = seat->focused_layer;
1270 seat_set_focus_layer(seat, NULL);
1271 seat_set_workspace_focus(seat, node);
1272 seat_set_focus_layer(seat, layer);
1273 } else if (seat->focused_layer) {
1274 seat_set_focus_layer(seat, NULL);
1275 seat_set_workspace_focus(seat, node);
1276 } else {
1277 seat_set_workspace_focus(seat, node);
1278 }
1279 if (server.session_lock.lock) {
1280 seat_set_focus_surface(seat, server.session_lock.lock->focused, false);
1281 }
1282}
1283
1251void seat_set_focus_container(struct sway_seat *seat, 1284void seat_set_focus_container(struct sway_seat *seat,
1252 struct sway_container *con) { 1285 struct sway_container *con) {
1253 seat_set_focus(seat, con ? &con->node : NULL); 1286 seat_set_focus(seat, con ? &con->node : NULL);
@@ -1273,7 +1306,7 @@ void seat_set_focus_surface(struct sway_seat *seat,
1273 } 1306 }
1274 1307
1275 sway_input_method_relay_set_focus(&seat->im_relay, surface); 1308 sway_input_method_relay_set_focus(&seat->im_relay, surface);
1276 seat_tablet_pads_notify_enter(seat, surface); 1309 seat_tablet_pads_set_focus(seat, surface);
1277} 1310}
1278 1311
1279void seat_set_focus_layer(struct sway_seat *seat, 1312void seat_set_focus_layer(struct sway_seat *seat,
@@ -1287,28 +1320,23 @@ void seat_set_focus_layer(struct sway_seat *seat,
1287 seat_set_focus(seat, previous); 1320 seat_set_focus(seat, previous);
1288 } 1321 }
1289 return; 1322 return;
1290 } else if (!layer || seat->focused_layer == layer) { 1323 } else if (!layer) {
1291 return; 1324 return;
1292 } 1325 }
1293 assert(layer->mapped); 1326 assert(layer->surface->mapped);
1294 seat_set_focus_surface(seat, layer->surface, true); 1327 if (layer->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP &&
1295 if (layer->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { 1328 layer->current.keyboard_interactive
1296 seat->focused_layer = layer; 1329 == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) {
1330 seat->has_exclusive_layer = true;
1297 } 1331 }
1298} 1332 if (seat->focused_layer == layer) {
1299
1300void seat_set_exclusive_client(struct sway_seat *seat,
1301 struct wl_client *client) {
1302 if (!client) {
1303 seat->exclusive_client = client;
1304 // Triggers a refocus of the topmost surface layer if necessary
1305 // TODO: Make layer surface focus per-output based on cursor position
1306 for (int i = 0; i < root->outputs->length; ++i) {
1307 struct sway_output *output = root->outputs->items[i];
1308 arrange_layers(output);
1309 }
1310 return; 1333 return;
1311 } 1334 }
1335 seat_set_focus_surface(seat, layer->surface, true);
1336 seat->focused_layer = layer;
1337}
1338
1339void seat_unfocus_unless_client(struct sway_seat *seat, struct wl_client *client) {
1312 if (seat->focused_layer) { 1340 if (seat->focused_layer) {
1313 if (wl_resource_get_client(seat->focused_layer->resource) != client) { 1341 if (wl_resource_get_client(seat->focused_layer->resource) != client) {
1314 seat_set_focus_layer(seat, NULL); 1342 seat_set_focus_layer(seat, NULL);
@@ -1335,7 +1363,6 @@ void seat_set_exclusive_client(struct sway_seat *seat,
1335 now.tv_nsec / 1000, point->touch_id); 1363 now.tv_nsec / 1000, point->touch_id);
1336 } 1364 }
1337 } 1365 }
1338 seat->exclusive_client = client;
1339} 1366}
1340 1367
1341struct sway_node *seat_get_focus_inactive(struct sway_seat *seat, 1368struct sway_node *seat_get_focus_inactive(struct sway_seat *seat,
@@ -1416,9 +1443,8 @@ struct sway_node *seat_get_focus(struct sway_seat *seat) {
1416 if (!seat->has_focus) { 1443 if (!seat->has_focus) {
1417 return NULL; 1444 return NULL;
1418 } 1445 }
1419 if (wl_list_empty(&seat->focus_stack)) { 1446 sway_assert(!wl_list_empty(&seat->focus_stack),
1420 return NULL; 1447 "focus_stack is empty, but has_focus is true");
1421 }
1422 struct sway_seat_node *current = 1448 struct sway_seat_node *current =
1423 wl_container_of(seat->focus_stack.next, current, link); 1449 wl_container_of(seat->focus_stack.next, current, link);
1424 return current->node; 1450 return current->node;
@@ -1503,7 +1529,7 @@ struct seat_config *seat_get_config_by_name(const char *name) {
1503} 1529}
1504 1530
1505void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, 1531void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec,
1506 uint32_t button, enum wlr_button_state state) { 1532 uint32_t button, enum wl_pointer_button_state state) {
1507 seat->last_button_serial = wlr_seat_pointer_notify_button(seat->wlr_seat, 1533 seat->last_button_serial = wlr_seat_pointer_notify_button(seat->wlr_seat,
1508 time_msec, button, state); 1534 time_msec, button, state);
1509} 1535}
@@ -1540,7 +1566,7 @@ void seatop_unref(struct sway_seat *seat, struct sway_container *con) {
1540 1566
1541void seatop_button(struct sway_seat *seat, uint32_t time_msec, 1567void seatop_button(struct sway_seat *seat, uint32_t time_msec,
1542 struct wlr_input_device *device, uint32_t button, 1568 struct wlr_input_device *device, uint32_t button,
1543 enum wlr_button_state state) { 1569 enum wl_pointer_button_state state) {
1544 if (seat->seatop_impl->button) { 1570 if (seat->seatop_impl->button) {
1545 seat->seatop_impl->button(seat, time_msec, device, button, state); 1571 seat->seatop_impl->button(seat, time_msec, device, button, state);
1546 } 1572 }
@@ -1553,12 +1579,38 @@ void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec) {
1553} 1579}
1554 1580
1555void seatop_pointer_axis(struct sway_seat *seat, 1581void seatop_pointer_axis(struct sway_seat *seat,
1556 struct wlr_event_pointer_axis *event) { 1582 struct wlr_pointer_axis_event *event) {
1557 if (seat->seatop_impl->pointer_axis) { 1583 if (seat->seatop_impl->pointer_axis) {
1558 seat->seatop_impl->pointer_axis(seat, event); 1584 seat->seatop_impl->pointer_axis(seat, event);
1559 } 1585 }
1560} 1586}
1561 1587
1588void seatop_touch_motion(struct sway_seat *seat, struct wlr_touch_motion_event *event,
1589 double lx, double ly) {
1590 if (seat->seatop_impl->touch_motion) {
1591 seat->seatop_impl->touch_motion(seat, event, lx, ly);
1592 }
1593}
1594
1595void seatop_touch_up(struct sway_seat *seat, struct wlr_touch_up_event *event) {
1596 if (seat->seatop_impl->touch_up) {
1597 seat->seatop_impl->touch_up(seat, event);
1598 }
1599}
1600
1601void seatop_touch_down(struct sway_seat *seat, struct wlr_touch_down_event *event,
1602 double lx, double ly) {
1603 if (seat->seatop_impl->touch_down) {
1604 seat->seatop_impl->touch_down(seat, event, lx, ly);
1605 }
1606}
1607
1608void seatop_touch_cancel(struct sway_seat *seat, struct wlr_touch_cancel_event *event) {
1609 if (seat->seatop_impl->touch_cancel) {
1610 seat->seatop_impl->touch_cancel(seat, event);
1611 }
1612}
1613
1562void seatop_tablet_tool_tip(struct sway_seat *seat, 1614void seatop_tablet_tool_tip(struct sway_seat *seat,
1563 struct sway_tablet_tool *tool, uint32_t time_msec, 1615 struct sway_tablet_tool *tool, uint32_t time_msec,
1564 enum wlr_tablet_tool_tip_state state) { 1616 enum wlr_tablet_tool_tip_state state) {
@@ -1576,6 +1628,62 @@ void seatop_tablet_tool_motion(struct sway_seat *seat,
1576 } 1628 }
1577} 1629}
1578 1630
1631void seatop_hold_begin(struct sway_seat *seat,
1632 struct wlr_pointer_hold_begin_event *event) {
1633 if (seat->seatop_impl->hold_begin) {
1634 seat->seatop_impl->hold_begin(seat, event);
1635 }
1636}
1637
1638void seatop_hold_end(struct sway_seat *seat,
1639 struct wlr_pointer_hold_end_event *event) {
1640 if (seat->seatop_impl->hold_end) {
1641 seat->seatop_impl->hold_end(seat, event);
1642 }
1643}
1644
1645void seatop_pinch_begin(struct sway_seat *seat,
1646 struct wlr_pointer_pinch_begin_event *event) {
1647 if (seat->seatop_impl->pinch_begin) {
1648 seat->seatop_impl->pinch_begin(seat, event);
1649 }
1650}
1651
1652void seatop_pinch_update(struct sway_seat *seat,
1653 struct wlr_pointer_pinch_update_event *event) {
1654 if (seat->seatop_impl->pinch_update) {
1655 seat->seatop_impl->pinch_update(seat, event);
1656 }
1657}
1658
1659void seatop_pinch_end(struct sway_seat *seat,
1660 struct wlr_pointer_pinch_end_event *event) {
1661 if (seat->seatop_impl->pinch_end) {
1662 seat->seatop_impl->pinch_end(seat, event);
1663 }
1664}
1665
1666void seatop_swipe_begin(struct sway_seat *seat,
1667 struct wlr_pointer_swipe_begin_event *event) {
1668 if (seat->seatop_impl->swipe_begin) {
1669 seat->seatop_impl->swipe_begin(seat, event);
1670 }
1671}
1672
1673void seatop_swipe_update(struct sway_seat *seat,
1674 struct wlr_pointer_swipe_update_event *event) {
1675 if (seat->seatop_impl->swipe_update) {
1676 seat->seatop_impl->swipe_update(seat, event);
1677 }
1678}
1679
1680void seatop_swipe_end(struct sway_seat *seat,
1681 struct wlr_pointer_swipe_end_event *event) {
1682 if (seat->seatop_impl->swipe_end) {
1683 seat->seatop_impl->swipe_end(seat, event);
1684 }
1685}
1686
1579void seatop_rebase(struct sway_seat *seat, uint32_t time_msec) { 1687void seatop_rebase(struct sway_seat *seat, uint32_t time_msec) {
1580 if (seat->seatop_impl->rebase) { 1688 if (seat->seatop_impl->rebase) {
1581 seat->seatop_impl->rebase(seat, time_msec); 1689 seat->seatop_impl->rebase(seat, time_msec);
@@ -1591,13 +1699,6 @@ void seatop_end(struct sway_seat *seat) {
1591 seat->seatop_impl = NULL; 1699 seat->seatop_impl = NULL;
1592} 1700}
1593 1701
1594void seatop_render(struct sway_seat *seat, struct sway_output *output,
1595 pixman_region32_t *damage) {
1596 if (seat->seatop_impl->render) {
1597 seat->seatop_impl->render(seat, output, damage);
1598 }
1599}
1600
1601bool seatop_allows_set_cursor(struct sway_seat *seat) { 1702bool seatop_allows_set_cursor(struct sway_seat *seat) {
1602 return seat->seatop_impl->allow_set_cursor; 1703 return seat->seatop_impl->allow_set_cursor;
1603} 1704}
diff --git a/sway/input/seatop_default.c b/sway/input/seatop_default.c
index f9eb8c8a..e01fa933 100644
--- a/sway/input/seatop_default.c
+++ b/sway/input/seatop_default.c
@@ -1,18 +1,21 @@
1#define _POSIX_C_SOURCE 200809L
2#include <float.h> 1#include <float.h>
3#include <libevdev/libevdev.h> 2#include <libevdev/libevdev.h>
4#include <wlr/types/wlr_cursor.h> 3#include <wlr/types/wlr_cursor.h>
4#include <wlr/types/wlr_subcompositor.h>
5#include <wlr/types/wlr_tablet_v2.h> 5#include <wlr/types/wlr_tablet_v2.h>
6#include <wlr/types/wlr_xcursor_manager.h> 6#include <wlr/types/wlr_xcursor_manager.h>
7#include "gesture.h"
7#include "sway/desktop/transaction.h" 8#include "sway/desktop/transaction.h"
8#include "sway/input/cursor.h" 9#include "sway/input/cursor.h"
9#include "sway/input/seat.h" 10#include "sway/input/seat.h"
10#include "sway/input/tablet.h" 11#include "sway/input/tablet.h"
12#include "sway/layers.h"
11#include "sway/output.h" 13#include "sway/output.h"
14#include "sway/scene_descriptor.h"
12#include "sway/tree/view.h" 15#include "sway/tree/view.h"
13#include "sway/tree/workspace.h" 16#include "sway/tree/workspace.h"
14#include "log.h" 17#include "log.h"
15#if HAVE_XWAYLAND 18#if WLR_HAS_XWAYLAND
16#include "sway/xwayland.h" 19#include "sway/xwayland.h"
17#endif 20#endif
18 21
@@ -20,6 +23,7 @@ struct seatop_default_event {
20 struct sway_node *previous_node; 23 struct sway_node *previous_node;
21 uint32_t pressed_buttons[SWAY_CURSOR_PRESSED_BUTTONS_CAP]; 24 uint32_t pressed_buttons[SWAY_CURSOR_PRESSED_BUTTONS_CAP];
22 size_t pressed_button_count; 25 size_t pressed_button_count;
26 struct gesture_tracker gestures;
23}; 27};
24 28
25/*-----------------------------------------\ 29/*-----------------------------------------\
@@ -51,6 +55,9 @@ static bool edge_is_external(struct sway_container *cont, enum wlr_edges edge) {
51 while (cont) { 55 while (cont) {
52 if (container_parent_layout(cont) == layout) { 56 if (container_parent_layout(cont) == layout) {
53 list_t *siblings = container_get_siblings(cont); 57 list_t *siblings = container_get_siblings(cont);
58 if (!siblings) {
59 return false;
60 }
54 int index = list_find(siblings, cont); 61 int index = list_find(siblings, cont);
55 if (index > 0 && (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_TOP)) { 62 if (index > 0 && (edge == WLR_EDGE_LEFT || edge == WLR_EDGE_TOP)) {
56 return false; 63 return false;
@@ -226,14 +233,15 @@ static void handle_tablet_tool_tip(struct sway_seat *seat,
226 struct sway_container *cont = node && node->type == N_CONTAINER ? 233 struct sway_container *cont = node && node->type == N_CONTAINER ?
227 node->sway_container : NULL; 234 node->sway_container : NULL;
228 235
229 if (wlr_surface_is_layer_surface(surface)) { 236 struct wlr_layer_surface_v1 *layer;
237#if WLR_HAS_XWAYLAND
238 struct wlr_xwayland_surface *xsurface;
239#endif
240 if ((layer = wlr_layer_surface_v1_try_from_wlr_surface(surface)) &&
241 layer->current.keyboard_interactive) {
230 // Handle tapping a layer surface 242 // Handle tapping a layer surface
231 struct wlr_layer_surface_v1 *layer = 243 seat_set_focus_layer(seat, layer);
232 wlr_layer_surface_v1_from_wlr_surface(surface); 244 transaction_commit_dirty();
233 if (layer->current.keyboard_interactive) {
234 seat_set_focus_layer(seat, layer);
235 transaction_commit_dirty();
236 }
237 } else if (cont) { 245 } else if (cont) {
238 bool is_floating_or_child = container_is_floating_or_child(cont); 246 bool is_floating_or_child = container_is_floating_or_child(cont);
239 bool is_fullscreen_or_child = container_is_fullscreen_or_child(cont); 247 bool is_fullscreen_or_child = container_is_fullscreen_or_child(cont);
@@ -258,20 +266,17 @@ static void handle_tablet_tool_tip(struct sway_seat *seat,
258 266
259 // Handle tapping on a container surface 267 // Handle tapping on a container surface
260 seat_set_focus_container(seat, cont); 268 seat_set_focus_container(seat, cont);
261 seatop_begin_down(seat, node->sway_container, time_msec, sx, sy); 269 seatop_begin_down(seat, node->sway_container, sx, sy);
262 } 270 }
263#if HAVE_XWAYLAND 271#if WLR_HAS_XWAYLAND
264 // Handle tapping on an xwayland unmanaged view 272 // Handle tapping on an xwayland unmanaged view
265 else if (wlr_surface_is_xwayland_surface(surface)) { 273 else if ((xsurface = wlr_xwayland_surface_try_from_wlr_surface(surface)) &&
266 struct wlr_xwayland_surface *xsurface = 274 xsurface->override_redirect &&
267 wlr_xwayland_surface_from_wlr_surface(surface); 275 wlr_xwayland_or_surface_wants_focus(xsurface)) {
268 if (xsurface->override_redirect && 276 struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland;
269 wlr_xwayland_or_surface_wants_focus(xsurface)) { 277 wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
270 struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; 278 seat_set_focus_surface(seat, xsurface->surface, false);
271 wlr_xwayland_set_seat(xwayland, seat->wlr_seat); 279 transaction_commit_dirty();
272 seat_set_focus_surface(seat, xsurface->surface, false);
273 transaction_commit_dirty();
274 }
275 } 280 }
276#endif 281#endif
277 282
@@ -285,7 +290,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat,
285 290
286static bool trigger_pointer_button_binding(struct sway_seat *seat, 291static bool trigger_pointer_button_binding(struct sway_seat *seat,
287 struct wlr_input_device *device, uint32_t button, 292 struct wlr_input_device *device, uint32_t button,
288 enum wlr_button_state state, uint32_t modifiers, 293 enum wl_pointer_button_state state, uint32_t modifiers,
289 bool on_titlebar, bool on_border, bool on_contents, bool on_workspace) { 294 bool on_titlebar, bool on_border, bool on_contents, bool on_workspace) {
290 // We can reach this for non-pointer devices if we're currently emulating 295 // We can reach this for non-pointer devices if we're currently emulating
291 // pointer input for one. Emulated input should not trigger bindings. The 296 // pointer input for one. Emulated input should not trigger bindings. The
@@ -299,7 +304,7 @@ static bool trigger_pointer_button_binding(struct sway_seat *seat,
299 char *device_identifier = device ? input_device_get_identifier(device) 304 char *device_identifier = device ? input_device_get_identifier(device)
300 : strdup("*"); 305 : strdup("*");
301 struct sway_binding *binding = NULL; 306 struct sway_binding *binding = NULL;
302 if (state == WLR_BUTTON_PRESSED) { 307 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
303 state_add_button(e, button); 308 state_add_button(e, button);
304 binding = get_active_mouse_binding(e, 309 binding = get_active_mouse_binding(e,
305 config->current_mode->mouse_bindings, modifiers, false, 310 config->current_mode->mouse_bindings, modifiers, false,
@@ -324,7 +329,7 @@ static bool trigger_pointer_button_binding(struct sway_seat *seat,
324 329
325static void handle_button(struct sway_seat *seat, uint32_t time_msec, 330static void handle_button(struct sway_seat *seat, uint32_t time_msec,
326 struct wlr_input_device *device, uint32_t button, 331 struct wlr_input_device *device, uint32_t button,
327 enum wlr_button_state state) { 332 enum wl_pointer_button_state state) {
328 struct sway_cursor *cursor = seat->cursor; 333 struct sway_cursor *cursor = seat->cursor;
329 334
330 // Determine what's under the cursor 335 // Determine what's under the cursor
@@ -357,7 +362,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
357 362
358 // Handle clicking an empty workspace 363 // Handle clicking an empty workspace
359 if (node && node->type == N_WORKSPACE) { 364 if (node && node->type == N_WORKSPACE) {
360 if (state == WLR_BUTTON_PRESSED) { 365 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
361 seat_set_focus(seat, node); 366 seat_set_focus(seat, node);
362 transaction_commit_dirty(); 367 transaction_commit_dirty();
363 } 368 }
@@ -365,21 +370,23 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
365 return; 370 return;
366 } 371 }
367 372
368 // Handle clicking a layer surface 373 // Handle clicking a layer surface and its popups/subsurfaces
369 if (surface && wlr_surface_is_layer_surface(surface)) { 374 struct wlr_layer_surface_v1 *layer = NULL;
370 struct wlr_layer_surface_v1 *layer = 375 if ((layer = toplevel_layer_surface_from_surface(surface))) {
371 wlr_layer_surface_v1_from_wlr_surface(surface);
372 if (layer->current.keyboard_interactive) { 376 if (layer->current.keyboard_interactive) {
373 seat_set_focus_layer(seat, layer); 377 seat_set_focus_layer(seat, layer);
374 transaction_commit_dirty(); 378 transaction_commit_dirty();
375 } 379 }
380 if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
381 seatop_begin_down_on_surface(seat, surface, sx, sy);
382 }
376 seat_pointer_notify_button(seat, time_msec, button, state); 383 seat_pointer_notify_button(seat, time_msec, button, state);
377 return; 384 return;
378 } 385 }
379 386
380 // Handle tiling resize via border 387 // Handle tiling resize via border
381 if (cont && resize_edge && button == BTN_LEFT && 388 if (cont && resize_edge && button == BTN_LEFT &&
382 state == WLR_BUTTON_PRESSED && !is_floating) { 389 state == WL_POINTER_BUTTON_STATE_PRESSED && !is_floating) {
383 // If a resize is triggered on a tabbed or stacked container, change 390 // If a resize is triggered on a tabbed or stacked container, change
384 // focus to the tab which already had inactive focus -- otherwise, we'd 391 // focus to the tab which already had inactive focus -- otherwise, we'd
385 // change the active tab when the user probably just wanted to resize. 392 // change the active tab when the user probably just wanted to resize.
@@ -397,7 +404,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
397 // Handle tiling resize via mod 404 // Handle tiling resize via mod
398 bool mod_pressed = modifiers & config->floating_mod; 405 bool mod_pressed = modifiers & config->floating_mod;
399 if (cont && !is_floating_or_child && mod_pressed && 406 if (cont && !is_floating_or_child && mod_pressed &&
400 state == WLR_BUTTON_PRESSED) { 407 state == WL_POINTER_BUTTON_STATE_PRESSED) {
401 uint32_t btn_resize = config->floating_mod_inverse ? 408 uint32_t btn_resize = config->floating_mod_inverse ?
402 BTN_LEFT : BTN_RIGHT; 409 BTN_LEFT : BTN_RIGHT;
403 if (button == btn_resize) { 410 if (button == btn_resize) {
@@ -424,13 +431,31 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
424 } 431 }
425 } 432 }
426 433
434 // Handle changing focus when clicking on a container
435 if (cont && state == WL_POINTER_BUTTON_STATE_PRESSED) {
436 // Default case: focus the container that was just clicked.
437 node = &cont->node;
438
439 // If the container is a tab/stacked container and the click happened
440 // on a tab, switch to the tab. If the tab contents were already
441 // focused, focus the tab container itself. If the tab container was
442 // already focused, cycle back to focusing the tab contents.
443 if (on_titlebar) {
444 struct sway_container *focus = seat_get_focused_container(seat);
445 if (focus == cont || !container_has_ancestor(focus, cont)) {
446 node = seat_get_focus_inactive(seat, &cont->node);
447 }
448 }
449
450 seat_set_focus(seat, node);
451 transaction_commit_dirty();
452 }
453
427 // Handle beginning floating move 454 // Handle beginning floating move
428 if (cont && is_floating_or_child && !is_fullscreen_or_child && 455 if (cont && is_floating_or_child && !is_fullscreen_or_child &&
429 state == WLR_BUTTON_PRESSED) { 456 state == WL_POINTER_BUTTON_STATE_PRESSED) {
430 uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT; 457 uint32_t btn_move = config->floating_mod_inverse ? BTN_RIGHT : BTN_LEFT;
431 if (button == btn_move && (mod_pressed || on_titlebar)) { 458 if (button == btn_move && (mod_pressed || on_titlebar)) {
432 seat_set_focus_container(seat,
433 seat_get_focus_inactive_view(seat, &cont->node));
434 seatop_begin_move_floating(seat, container_toplevel_ancestor(cont)); 459 seatop_begin_move_floating(seat, container_toplevel_ancestor(cont));
435 return; 460 return;
436 } 461 }
@@ -438,9 +463,10 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
438 463
439 // Handle beginning floating resize 464 // Handle beginning floating resize
440 if (cont && is_floating_or_child && !is_fullscreen_or_child && 465 if (cont && is_floating_or_child && !is_fullscreen_or_child &&
441 state == WLR_BUTTON_PRESSED) { 466 state == WL_POINTER_BUTTON_STATE_PRESSED) {
442 // Via border 467 // Via border
443 if (button == BTN_LEFT && resize_edge != WLR_EDGE_NONE) { 468 if (button == BTN_LEFT && resize_edge != WLR_EDGE_NONE) {
469 seat_set_focus_container(seat, cont);
444 seatop_begin_resize_floating(seat, cont, resize_edge); 470 seatop_begin_resize_floating(seat, cont, resize_edge);
445 return; 471 return;
446 } 472 }
@@ -455,6 +481,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
455 WLR_EDGE_RIGHT : WLR_EDGE_LEFT; 481 WLR_EDGE_RIGHT : WLR_EDGE_LEFT;
456 edge |= cursor->cursor->y > floater->pending.y + floater->pending.height / 2 ? 482 edge |= cursor->cursor->y > floater->pending.y + floater->pending.height / 2 ?
457 WLR_EDGE_BOTTOM : WLR_EDGE_TOP; 483 WLR_EDGE_BOTTOM : WLR_EDGE_TOP;
484 seat_set_focus_container(seat, floater);
458 seatop_begin_resize_floating(seat, floater, edge); 485 seatop_begin_resize_floating(seat, floater, edge);
459 return; 486 return;
460 } 487 }
@@ -462,55 +489,43 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
462 489
463 // Handle moving a tiling container 490 // Handle moving a tiling container
464 if (config->tiling_drag && (mod_pressed || on_titlebar) && 491 if (config->tiling_drag && (mod_pressed || on_titlebar) &&
465 state == WLR_BUTTON_PRESSED && !is_floating_or_child && 492 state == WL_POINTER_BUTTON_STATE_PRESSED && !is_floating_or_child &&
466 cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE) { 493 cont && cont->pending.fullscreen_mode == FULLSCREEN_NONE) {
467 struct sway_container *focus = seat_get_focused_container(seat); 494 // If moving a container by its title bar, use a threshold for the drag
468 bool focused = focus == cont || container_has_ancestor(focus, cont);
469 if (on_titlebar && !focused) {
470 node = seat_get_focus_inactive(seat, &cont->node);
471 seat_set_focus(seat, node);
472 }
473
474 // If moving a container by it's title bar, use a threshold for the drag
475 if (!mod_pressed && config->tiling_drag_threshold > 0) { 495 if (!mod_pressed && config->tiling_drag_threshold > 0) {
476 seatop_begin_move_tiling_threshold(seat, cont); 496 seatop_begin_move_tiling_threshold(seat, cont);
477 } else { 497 } else {
478 seatop_begin_move_tiling(seat, cont); 498 seatop_begin_move_tiling(seat, cont);
479 } 499 }
500
480 return; 501 return;
481 } 502 }
482 503
483 // Handle mousedown on a container surface 504 // Handle mousedown on a container surface
484 if (surface && cont && state == WLR_BUTTON_PRESSED) { 505 if (surface && cont && state == WL_POINTER_BUTTON_STATE_PRESSED) {
485 seat_set_focus_container(seat, cont); 506 seatop_begin_down(seat, cont, sx, sy);
486 seatop_begin_down(seat, cont, time_msec, sx, sy); 507 seat_pointer_notify_button(seat, time_msec, button, WL_POINTER_BUTTON_STATE_PRESSED);
487 seat_pointer_notify_button(seat, time_msec, button, WLR_BUTTON_PRESSED);
488 return; 508 return;
489 } 509 }
490 510
491 // Handle clicking a container surface or decorations 511 // Handle clicking a container surface or decorations
492 if (cont && state == WLR_BUTTON_PRESSED) { 512 if (cont && state == WL_POINTER_BUTTON_STATE_PRESSED) {
493 node = seat_get_focus_inactive(seat, &cont->node);
494 seat_set_focus(seat, node);
495 transaction_commit_dirty();
496 seat_pointer_notify_button(seat, time_msec, button, state); 513 seat_pointer_notify_button(seat, time_msec, button, state);
497 return; 514 return;
498 } 515 }
499 516
500#if HAVE_XWAYLAND 517#if WLR_HAS_XWAYLAND
501 // Handle clicking on xwayland unmanaged view 518 // Handle clicking on xwayland unmanaged view
502 if (surface && wlr_surface_is_xwayland_surface(surface)) { 519 struct wlr_xwayland_surface *xsurface;
503 struct wlr_xwayland_surface *xsurface = 520 if (surface &&
504 wlr_xwayland_surface_from_wlr_surface(surface); 521 (xsurface = wlr_xwayland_surface_try_from_wlr_surface(surface)) &&
505 if (xsurface->override_redirect && 522 xsurface->override_redirect &&
506 wlr_xwayland_or_surface_wants_focus(xsurface)) { 523 wlr_xwayland_or_surface_wants_focus(xsurface)) {
507 struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland; 524 struct wlr_xwayland *xwayland = server.xwayland.wlr_xwayland;
508 wlr_xwayland_set_seat(xwayland, seat->wlr_seat); 525 wlr_xwayland_set_seat(xwayland, seat->wlr_seat);
509 seat_set_focus_surface(seat, xsurface->surface, false); 526 seat_set_focus_surface(seat, xsurface->surface, false);
510 transaction_commit_dirty(); 527 transaction_commit_dirty();
511 seat_pointer_notify_button(seat, time_msec, button, state); 528 seat_pointer_notify_button(seat, time_msec, button, state);
512 return;
513 }
514 } 529 }
515#endif 530#endif
516 531
@@ -533,6 +548,21 @@ static void check_focus_follows_mouse(struct sway_seat *seat,
533 if (wlr_output == NULL) { 548 if (wlr_output == NULL) {
534 return; 549 return;
535 } 550 }
551
552 struct wlr_surface *surface = NULL;
553 double sx, sy;
554 node_at_coords(seat, seat->cursor->cursor->x, seat->cursor->cursor->y,
555 &surface, &sx, &sy);
556
557 // Focus topmost layer surface
558 struct wlr_layer_surface_v1 *layer = NULL;
559 if ((layer = toplevel_layer_surface_from_surface(surface)) &&
560 layer->current.keyboard_interactive) {
561 seat_set_focus_layer(seat, layer);
562 transaction_commit_dirty();
563 return;
564 }
565
536 struct sway_output *hovered_output = wlr_output->data; 566 struct sway_output *hovered_output = wlr_output->data;
537 if (focus && hovered_output != node_get_output(focus)) { 567 if (focus && hovered_output != node_get_output(focus)) {
538 struct sway_workspace *ws = output_get_active_workspace(hovered_output); 568 struct sway_workspace *ws = output_get_active_workspace(hovered_output);
@@ -593,12 +623,7 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) {
593 wlr_seat_pointer_notify_clear_focus(seat->wlr_seat); 623 wlr_seat_pointer_notify_clear_focus(seat->wlr_seat);
594 } 624 }
595 625
596 struct sway_drag_icon *drag_icon; 626 drag_icons_update_position(seat);
597 wl_list_for_each(drag_icon, &root->drag_icons, link) {
598 if (drag_icon->seat == seat) {
599 drag_icon_update_position(drag_icon);
600 }
601 }
602 627
603 e->previous_node = node; 628 e->previous_node = node;
604} 629}
@@ -628,25 +653,50 @@ static void handle_tablet_tool_motion(struct sway_seat *seat,
628 wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool); 653 wlr_tablet_v2_tablet_tool_notify_proximity_out(tool->tablet_v2_tool);
629 } 654 }
630 655
631 struct sway_drag_icon *drag_icon; 656 drag_icons_update_position(seat);
632 wl_list_for_each(drag_icon, &root->drag_icons, link) {
633 if (drag_icon->seat == seat) {
634 drag_icon_update_position(drag_icon);
635 }
636 }
637 657
638 e->previous_node = node; 658 e->previous_node = node;
639} 659}
640 660
661static void handle_touch_down(struct sway_seat *seat,
662 struct wlr_touch_down_event *event, double lx, double ly) {
663 struct wlr_surface *surface = NULL;
664 struct wlr_seat *wlr_seat = seat->wlr_seat;
665 struct sway_cursor *cursor = seat->cursor;
666 double sx, sy;
667 node_at_coords(seat, seat->touch_x, seat->touch_y, &surface, &sx, &sy);
668
669 if (surface && wlr_surface_accepts_touch(wlr_seat, surface)) {
670 if (seat_is_input_allowed(seat, surface)) {
671 cursor->simulating_pointer_from_touch = false;
672 seatop_begin_touch_down(seat, surface, event, sx, sy, lx, ly);
673 }
674 } else if (!cursor->simulating_pointer_from_touch &&
675 (!surface || seat_is_input_allowed(seat, surface))) {
676 // Fallback to cursor simulation.
677 // The pointer_touch_id state is needed, so drags are not aborted when over
678 // a surface supporting touch and multi touch events don't interfere.
679 cursor->simulating_pointer_from_touch = true;
680 cursor->pointer_touch_id = seat->touch_id;
681 double dx, dy;
682 dx = seat->touch_x - cursor->cursor->x;
683 dy = seat->touch_y - cursor->cursor->y;
684 pointer_motion(cursor, event->time_msec, &event->touch->base, dx, dy,
685 dx, dy);
686 dispatch_cursor_button(cursor, &event->touch->base, event->time_msec,
687 BTN_LEFT, WL_POINTER_BUTTON_STATE_PRESSED);
688 }
689}
690
641/*----------------------------------------\ 691/*----------------------------------------\
642 * Functions used by handle_pointer_axis / 692 * Functions used by handle_pointer_axis /
643 *--------------------------------------*/ 693 *--------------------------------------*/
644 694
645static uint32_t wl_axis_to_button(struct wlr_event_pointer_axis *event) { 695static uint32_t wl_axis_to_button(struct wlr_pointer_axis_event *event) {
646 switch (event->orientation) { 696 switch (event->orientation) {
647 case WLR_AXIS_ORIENTATION_VERTICAL: 697 case WL_POINTER_AXIS_VERTICAL_SCROLL:
648 return event->delta < 0 ? SWAY_SCROLL_UP : SWAY_SCROLL_DOWN; 698 return event->delta < 0 ? SWAY_SCROLL_UP : SWAY_SCROLL_DOWN;
649 case WLR_AXIS_ORIENTATION_HORIZONTAL: 699 case WL_POINTER_AXIS_HORIZONTAL_SCROLL:
650 return event->delta < 0 ? SWAY_SCROLL_LEFT : SWAY_SCROLL_RIGHT; 700 return event->delta < 0 ? SWAY_SCROLL_LEFT : SWAY_SCROLL_RIGHT;
651 default: 701 default:
652 sway_log(SWAY_DEBUG, "Unknown axis orientation"); 702 sway_log(SWAY_DEBUG, "Unknown axis orientation");
@@ -655,9 +705,9 @@ static uint32_t wl_axis_to_button(struct wlr_event_pointer_axis *event) {
655} 705}
656 706
657static void handle_pointer_axis(struct sway_seat *seat, 707static void handle_pointer_axis(struct sway_seat *seat,
658 struct wlr_event_pointer_axis *event) { 708 struct wlr_pointer_axis_event *event) {
659 struct sway_input_device *input_device = 709 struct sway_input_device *input_device =
660 event->device ? event->device->data : NULL; 710 event->pointer ? event->pointer->base.data : NULL;
661 struct input_config *ic = 711 struct input_config *ic =
662 input_device ? input_device_get_config(input_device) : NULL; 712 input_device ? input_device_get_config(input_device) : NULL;
663 struct sway_cursor *cursor = seat->cursor; 713 struct sway_cursor *cursor = seat->cursor;
@@ -703,6 +753,7 @@ static void handle_pointer_axis(struct sway_seat *seat,
703 753
704 // Scrolling on a tabbed or stacked title bar (handled as press event) 754 // Scrolling on a tabbed or stacked title bar (handled as press event)
705 if (!handled && (on_titlebar || on_titlebar_border)) { 755 if (!handled && (on_titlebar || on_titlebar_border)) {
756 struct sway_node *new_focus;
706 enum sway_container_layout layout = container_parent_layout(cont); 757 enum sway_container_layout layout = container_parent_layout(cont);
707 if (layout == L_TABBED || layout == L_STACKED) { 758 if (layout == L_TABBED || layout == L_STACKED) {
708 struct sway_node *tabcontainer = node_get_parent(node); 759 struct sway_node *tabcontainer = node_get_parent(node);
@@ -710,7 +761,7 @@ static void handle_pointer_axis(struct sway_seat *seat,
710 seat_get_active_tiling_child(seat, tabcontainer); 761 seat_get_active_tiling_child(seat, tabcontainer);
711 list_t *siblings = container_get_siblings(cont); 762 list_t *siblings = container_get_siblings(cont);
712 int desired = list_find(siblings, active->sway_container) + 763 int desired = list_find(siblings, active->sway_container) +
713 round(scroll_factor * event->delta_discrete); 764 roundf(scroll_factor * event->delta_discrete / WLR_POINTER_AXIS_DISCRETE_STEP);
714 if (desired < 0) { 765 if (desired < 0) {
715 desired = 0; 766 desired = 0;
716 } else if (desired >= siblings->length) { 767 } else if (desired >= siblings->length) {
@@ -719,14 +770,16 @@ static void handle_pointer_axis(struct sway_seat *seat,
719 770
720 struct sway_container *new_sibling_con = siblings->items[desired]; 771 struct sway_container *new_sibling_con = siblings->items[desired];
721 struct sway_node *new_sibling = &new_sibling_con->node; 772 struct sway_node *new_sibling = &new_sibling_con->node;
722 struct sway_node *new_focus =
723 seat_get_focus_inactive(seat, new_sibling);
724 // Use the focused child of the tabbed/stacked container, not the 773 // Use the focused child of the tabbed/stacked container, not the
725 // container the user scrolled on. 774 // container the user scrolled on.
726 seat_set_focus(seat, new_focus); 775 new_focus = seat_get_focus_inactive(seat, new_sibling);
727 transaction_commit_dirty(); 776 } else {
728 handled = true; 777 new_focus = seat_get_focus_inactive(seat, &cont->node);
729 } 778 }
779
780 seat_set_focus(seat, new_focus);
781 transaction_commit_dirty();
782 handled = true;
730 } 783 }
731 784
732 // Handle mouse bindings - x11 mouse buttons 4-7 - release event 785 // Handle mouse bindings - x11 mouse buttons 4-7 - release event
@@ -742,8 +795,307 @@ static void handle_pointer_axis(struct sway_seat *seat,
742 795
743 if (!handled) { 796 if (!handled) {
744 wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec, 797 wlr_seat_pointer_notify_axis(cursor->seat->wlr_seat, event->time_msec,
745 event->orientation, scroll_factor * event->delta, 798 event->orientation, scroll_factor * event->delta,
746 round(scroll_factor * event->delta_discrete), event->source); 799 roundf(scroll_factor * event->delta_discrete), event->source,
800 event->relative_direction);
801 }
802}
803
804/*------------------------------------\
805 * Functions used by gesture support /
806 *----------------------------------*/
807
808/**
809 * Check gesture binding for a specific gesture type and finger count.
810 * Returns true if binding is present, false otherwise
811 */
812static bool gesture_binding_check(list_t *bindings, enum gesture_type type,
813 uint8_t fingers, struct sway_input_device *device) {
814 char *input =
815 device ? input_device_get_identifier(device->wlr_device) : strdup("*");
816
817 for (int i = 0; i < bindings->length; ++i) {
818 struct sway_gesture_binding *binding = bindings->items[i];
819
820 // Check type and finger count
821 if (!gesture_check(&binding->gesture, type, fingers)) {
822 continue;
823 }
824
825 // Check that input matches
826 if (strcmp(binding->input, "*") != 0 &&
827 strcmp(binding->input, input) != 0) {
828 continue;
829 }
830
831 free(input);
832
833 return true;
834 }
835
836 free(input);
837
838 return false;
839}
840
841/**
842 * Return the gesture binding which matches gesture type, finger count
843 * and direction, otherwise return null.
844 */
845static struct sway_gesture_binding* gesture_binding_match(
846 list_t *bindings, struct gesture *gesture, const char *input) {
847 struct sway_gesture_binding *current = NULL;
848
849 // Find best matching binding
850 for (int i = 0; i < bindings->length; ++i) {
851 struct sway_gesture_binding *binding = bindings->items[i];
852 bool exact = binding->flags & BINDING_EXACT;
853
854 // Check gesture matching
855 if (!gesture_match(&binding->gesture, gesture, exact)) {
856 continue;
857 }
858
859 // Check input matching
860 if (strcmp(binding->input, "*") != 0 &&
861 strcmp(binding->input, input) != 0) {
862 continue;
863 }
864
865 // If we already have a match ...
866 if (current) {
867 // ... check if input matching is equivalent
868 if (strcmp(current->input, binding->input) == 0) {
869
870 // ... - do not override an exact binding
871 if (!exact && current->flags & BINDING_EXACT) {
872 continue;
873 }
874
875 // ... - and ensure direction matching is better or equal
876 if (gesture_compare(&current->gesture, &binding->gesture) > 0) {
877 continue;
878 }
879 } else if (strcmp(binding->input, "*") == 0) {
880 // ... do not accept worse input match
881 continue;
882 }
883 }
884
885 // Accept newer or better match
886 current = binding;
887
888 // If exact binding and input is found, quit search
889 if (strcmp(current->input, input) == 0 &&
890 gesture_compare(&current->gesture, gesture) == 0) {
891 break;
892 }
893 } // for all gesture bindings
894
895 return current;
896}
897
898// Wrapper around gesture_tracker_end to use tracker with sway bindings
899static struct sway_gesture_binding* gesture_tracker_end_and_match(
900 struct gesture_tracker *tracker, struct sway_input_device* device) {
901 // Determine name of input that received gesture
902 char *input = device
903 ? input_device_get_identifier(device->wlr_device)
904 : strdup("*");
905
906 // Match tracking result to binding
907 struct gesture *gesture = gesture_tracker_end(tracker);
908 struct sway_gesture_binding *binding = gesture_binding_match(
909 config->current_mode->gesture_bindings, gesture, input);
910 free(gesture);
911 free(input);
912
913 return binding;
914}
915
916// Small wrapper around seat_execute_command to work on gesture bindings
917static void gesture_binding_execute(struct sway_seat *seat,
918 struct sway_gesture_binding *binding) {
919 struct sway_binding *dummy_binding =
920 calloc(1, sizeof(struct sway_binding));
921 dummy_binding->type = BINDING_GESTURE;
922 dummy_binding->command = binding->command;
923
924 char *description = gesture_to_string(&binding->gesture);
925 sway_log(SWAY_DEBUG, "executing gesture binding: %s", description);
926 free(description);
927
928 seat_execute_command(seat, dummy_binding);
929
930 free(dummy_binding);
931}
932
933static void handle_hold_begin(struct sway_seat *seat,
934 struct wlr_pointer_hold_begin_event *event) {
935 // Start tracking gesture if there is a matching binding ...
936 struct sway_input_device *device =
937 event->pointer ? event->pointer->base.data : NULL;
938 list_t *bindings = config->current_mode->gesture_bindings;
939 if (gesture_binding_check(bindings, GESTURE_TYPE_HOLD, event->fingers, device)) {
940 struct seatop_default_event *seatop = seat->seatop_data;
941 gesture_tracker_begin(&seatop->gestures, GESTURE_TYPE_HOLD, event->fingers);
942 } else {
943 // ... otherwise forward to client
944 struct sway_cursor *cursor = seat->cursor;
945 wlr_pointer_gestures_v1_send_hold_begin(
946 server.input->pointer_gestures, cursor->seat->wlr_seat,
947 event->time_msec, event->fingers);
948 }
949}
950
951static void handle_hold_end(struct sway_seat *seat,
952 struct wlr_pointer_hold_end_event *event) {
953 // Ensure that gesture is being tracked and was not cancelled
954 struct seatop_default_event *seatop = seat->seatop_data;
955 if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_HOLD)) {
956 struct sway_cursor *cursor = seat->cursor;
957 wlr_pointer_gestures_v1_send_hold_end(
958 server.input->pointer_gestures, cursor->seat->wlr_seat,
959 event->time_msec, event->cancelled);
960 return;
961 }
962 if (event->cancelled) {
963 gesture_tracker_cancel(&seatop->gestures);
964 return;
965 }
966
967 // End gesture tracking and execute matched binding
968 struct sway_input_device *device =
969 event->pointer ? event->pointer->base.data : NULL;
970 struct sway_gesture_binding *binding = gesture_tracker_end_and_match(
971 &seatop->gestures, device);
972
973 if (binding) {
974 gesture_binding_execute(seat, binding);
975 }
976}
977
978static void handle_pinch_begin(struct sway_seat *seat,
979 struct wlr_pointer_pinch_begin_event *event) {
980 // Start tracking gesture if there is a matching binding ...
981 struct sway_input_device *device =
982 event->pointer ? event->pointer->base.data : NULL;
983 list_t *bindings = config->current_mode->gesture_bindings;
984 if (gesture_binding_check(bindings, GESTURE_TYPE_PINCH, event->fingers, device)) {
985 struct seatop_default_event *seatop = seat->seatop_data;
986 gesture_tracker_begin(&seatop->gestures, GESTURE_TYPE_PINCH, event->fingers);
987 } else {
988 // ... otherwise forward to client
989 struct sway_cursor *cursor = seat->cursor;
990 wlr_pointer_gestures_v1_send_pinch_begin(
991 server.input->pointer_gestures, cursor->seat->wlr_seat,
992 event->time_msec, event->fingers);
993 }
994}
995
996static void handle_pinch_update(struct sway_seat *seat,
997 struct wlr_pointer_pinch_update_event *event) {
998 // Update any ongoing tracking ...
999 struct seatop_default_event *seatop = seat->seatop_data;
1000 if (gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_PINCH)) {
1001 gesture_tracker_update(&seatop->gestures, event->dx, event->dy,
1002 event->scale, event->rotation);
1003 } else {
1004 // ... otherwise forward to client
1005 struct sway_cursor *cursor = seat->cursor;
1006 wlr_pointer_gestures_v1_send_pinch_update(
1007 server.input->pointer_gestures,
1008 cursor->seat->wlr_seat,
1009 event->time_msec, event->dx, event->dy,
1010 event->scale, event->rotation);
1011 }
1012}
1013
1014static void handle_pinch_end(struct sway_seat *seat,
1015 struct wlr_pointer_pinch_end_event *event) {
1016 // Ensure that gesture is being tracked and was not cancelled
1017 struct seatop_default_event *seatop = seat->seatop_data;
1018 if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_PINCH)) {
1019 struct sway_cursor *cursor = seat->cursor;
1020 wlr_pointer_gestures_v1_send_pinch_end(
1021 server.input->pointer_gestures, cursor->seat->wlr_seat,
1022 event->time_msec, event->cancelled);
1023 return;
1024 }
1025 if (event->cancelled) {
1026 gesture_tracker_cancel(&seatop->gestures);
1027 return;
1028 }
1029
1030 // End gesture tracking and execute matched binding
1031 struct sway_input_device *device =
1032 event->pointer ? event->pointer->base.data : NULL;
1033 struct sway_gesture_binding *binding = gesture_tracker_end_and_match(
1034 &seatop->gestures, device);
1035
1036 if (binding) {
1037 gesture_binding_execute(seat, binding);
1038 }
1039}
1040
1041static void handle_swipe_begin(struct sway_seat *seat,
1042 struct wlr_pointer_swipe_begin_event *event) {
1043 // Start tracking gesture if there is a matching binding ...
1044 struct sway_input_device *device =
1045 event->pointer ? event->pointer->base.data : NULL;
1046 list_t *bindings = config->current_mode->gesture_bindings;
1047 if (gesture_binding_check(bindings, GESTURE_TYPE_SWIPE, event->fingers, device)) {
1048 struct seatop_default_event *seatop = seat->seatop_data;
1049 gesture_tracker_begin(&seatop->gestures, GESTURE_TYPE_SWIPE, event->fingers);
1050 } else {
1051 // ... otherwise forward to client
1052 struct sway_cursor *cursor = seat->cursor;
1053 wlr_pointer_gestures_v1_send_swipe_begin(
1054 server.input->pointer_gestures, cursor->seat->wlr_seat,
1055 event->time_msec, event->fingers);
1056 }
1057}
1058
1059static void handle_swipe_update(struct sway_seat *seat,
1060 struct wlr_pointer_swipe_update_event *event) {
1061
1062 // Update any ongoing tracking ...
1063 struct seatop_default_event *seatop = seat->seatop_data;
1064 if (gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_SWIPE)) {
1065 gesture_tracker_update(&seatop->gestures,
1066 event->dx, event->dy, NAN, NAN);
1067 } else {
1068 // ... otherwise forward to client
1069 struct sway_cursor *cursor = seat->cursor;
1070 wlr_pointer_gestures_v1_send_swipe_update(
1071 server.input->pointer_gestures, cursor->seat->wlr_seat,
1072 event->time_msec, event->dx, event->dy);
1073 }
1074}
1075
1076static void handle_swipe_end(struct sway_seat *seat,
1077 struct wlr_pointer_swipe_end_event *event) {
1078 // Ensure gesture is being tracked and was not cancelled
1079 struct seatop_default_event *seatop = seat->seatop_data;
1080 if (!gesture_tracker_check(&seatop->gestures, GESTURE_TYPE_SWIPE)) {
1081 struct sway_cursor *cursor = seat->cursor;
1082 wlr_pointer_gestures_v1_send_swipe_end(server.input->pointer_gestures,
1083 cursor->seat->wlr_seat, event->time_msec, event->cancelled);
1084 return;
1085 }
1086 if (event->cancelled) {
1087 gesture_tracker_cancel(&seatop->gestures);
1088 return;
1089 }
1090
1091 // End gesture tracking and execute matched binding
1092 struct sway_input_device *device =
1093 event->pointer ? event->pointer->base.data : NULL;
1094 struct sway_gesture_binding *binding = gesture_tracker_end_and_match(
1095 &seatop->gestures, device);
1096
1097 if (binding) {
1098 gesture_binding_execute(seat, binding);
747 } 1099 }
748} 1100}
749 1101
@@ -776,6 +1128,15 @@ static const struct sway_seatop_impl seatop_impl = {
776 .pointer_axis = handle_pointer_axis, 1128 .pointer_axis = handle_pointer_axis,
777 .tablet_tool_tip = handle_tablet_tool_tip, 1129 .tablet_tool_tip = handle_tablet_tool_tip,
778 .tablet_tool_motion = handle_tablet_tool_motion, 1130 .tablet_tool_motion = handle_tablet_tool_motion,
1131 .hold_begin = handle_hold_begin,
1132 .hold_end = handle_hold_end,
1133 .pinch_begin = handle_pinch_begin,
1134 .pinch_update = handle_pinch_update,
1135 .pinch_end = handle_pinch_end,
1136 .swipe_begin = handle_swipe_begin,
1137 .swipe_update = handle_swipe_update,
1138 .swipe_end = handle_swipe_end,
1139 .touch_down = handle_touch_down,
779 .rebase = handle_rebase, 1140 .rebase = handle_rebase,
780 .allow_set_cursor = true, 1141 .allow_set_cursor = true,
781}; 1142};
@@ -786,8 +1147,8 @@ void seatop_begin_default(struct sway_seat *seat) {
786 struct seatop_default_event *e = 1147 struct seatop_default_event *e =
787 calloc(1, sizeof(struct seatop_default_event)); 1148 calloc(1, sizeof(struct seatop_default_event));
788 sway_assert(e, "Unable to allocate seatop_default_event"); 1149 sway_assert(e, "Unable to allocate seatop_default_event");
1150
789 seat->seatop_impl = &seatop_impl; 1151 seat->seatop_impl = &seatop_impl;
790 seat->seatop_data = e; 1152 seat->seatop_data = e;
791
792 seatop_rebase(seat, 0); 1153 seatop_rebase(seat, 0);
793} 1154}
diff --git a/sway/input/seatop_down.c b/sway/input/seatop_down.c
index 844cf5ab..340e334b 100644
--- a/sway/input/seatop_down.c
+++ b/sway/input/seatop_down.c
@@ -1,23 +1,138 @@
1#define _POSIX_C_SOURCE 200809L
2#include <float.h> 1#include <float.h>
3#include <wlr/types/wlr_cursor.h> 2#include <wlr/types/wlr_cursor.h>
4#include <wlr/types/wlr_tablet_v2.h> 3#include <wlr/types/wlr_tablet_v2.h>
4#include <wlr/types/wlr_touch.h>
5#include "sway/input/cursor.h" 5#include "sway/input/cursor.h"
6#include "sway/input/seat.h" 6#include "sway/input/seat.h"
7#include "sway/tree/view.h" 7#include "sway/tree/view.h"
8#include "sway/desktop/transaction.h" 8#include "sway/desktop/transaction.h"
9#include "log.h" 9#include "log.h"
10 10
11struct seatop_touch_point_event {
12 double ref_lx, ref_ly; // touch's x/y at start of op
13 double ref_con_lx, ref_con_ly; // container's x/y at start of op
14 int32_t touch_id;
15 struct wl_list link;
16};
17
11struct seatop_down_event { 18struct seatop_down_event {
12 struct sway_container *con; 19 struct sway_container *con;
20 struct sway_seat *seat;
21 struct wl_listener surface_destroy;
22 struct wlr_surface *surface;
13 double ref_lx, ref_ly; // cursor's x/y at start of op 23 double ref_lx, ref_ly; // cursor's x/y at start of op
14 double ref_con_lx, ref_con_ly; // container's x/y at start of op 24 double ref_con_lx, ref_con_ly; // container's x/y at start of op
25 struct wl_list point_events; // seatop_touch_point_event::link
15}; 26};
16 27
28static void handle_touch_motion(struct sway_seat *seat,
29 struct wlr_touch_motion_event *event, double lx, double ly) {
30 struct seatop_down_event *e = seat->seatop_data;
31
32 struct seatop_touch_point_event *point_event;
33 bool found = false;
34 wl_list_for_each(point_event, &e->point_events, link) {
35 if (point_event->touch_id == event->touch_id) {
36 found = true;
37 break;
38 }
39 }
40 if (!found) {
41 return; // Probably not a point_event from this seatop_down
42 }
43
44 double moved_x = lx - point_event->ref_lx;
45 double moved_y = ly - point_event->ref_ly;
46 double sx = point_event->ref_con_lx + moved_x;
47 double sy = point_event->ref_con_ly + moved_y;
48
49 wlr_seat_touch_notify_motion(seat->wlr_seat, event->time_msec,
50 event->touch_id, sx, sy);
51}
52
53static void handle_touch_up(struct sway_seat *seat,
54 struct wlr_touch_up_event *event) {
55 struct seatop_down_event *e = seat->seatop_data;
56 struct seatop_touch_point_event *point_event, *tmp;
57
58 wl_list_for_each_safe(point_event, tmp, &e->point_events, link) {
59 if (point_event->touch_id == event->touch_id) {
60 wl_list_remove(&point_event->link);
61 free(point_event);
62 break;
63 }
64 }
65
66 wlr_seat_touch_notify_up(seat->wlr_seat, event->time_msec, event->touch_id);
67
68 if (wl_list_empty(&e->point_events)) {
69 seatop_begin_default(seat);
70 }
71}
72
73static void handle_touch_down(struct sway_seat *seat,
74 struct wlr_touch_down_event *event, double lx, double ly) {
75 struct seatop_down_event *e = seat->seatop_data;
76 double sx, sy;
77 struct wlr_surface *surface = NULL;
78 struct sway_node *focused_node = node_at_coords(seat, seat->touch_x,
79 seat->touch_y, &surface, &sx, &sy);
80
81 if (!surface || surface != e->surface) { // Must start from the initial surface
82 return;
83 }
84
85 struct seatop_touch_point_event *point_event =
86 calloc(1, sizeof(struct seatop_touch_point_event));
87 if (!sway_assert(point_event, "Unable to allocate point_event")) {
88 return;
89 }
90 point_event->touch_id = event->touch_id;
91 point_event->ref_lx = lx;
92 point_event->ref_ly = ly;
93 point_event->ref_con_lx = sx;
94 point_event->ref_con_ly = sy;
95
96 wl_list_insert(&e->point_events, &point_event->link);
97
98 wlr_seat_touch_notify_down(seat->wlr_seat, surface, event->time_msec,
99 event->touch_id, sx, sy);
100
101 if (focused_node) {
102 seat_set_focus(seat, focused_node);
103 }
104}
105
106static void handle_touch_cancel(struct sway_seat *seat,
107 struct wlr_touch_cancel_event *event) {
108 struct seatop_down_event *e = seat->seatop_data;
109 struct seatop_touch_point_event *point_event, *tmp;
110
111 wl_list_for_each_safe(point_event, tmp, &e->point_events, link) {
112 if (point_event->touch_id == event->touch_id) {
113 wl_list_remove(&point_event->link);
114 free(point_event);
115 break;
116 }
117 }
118
119 if (e->surface) {
120 struct wl_client *client = wl_resource_get_client(e->surface->resource);
121 struct wlr_seat_client *seat_client = wlr_seat_client_for_wl_client(seat->wlr_seat, client);
122 if (seat_client != NULL) {
123 wlr_seat_touch_notify_cancel(seat->wlr_seat, seat_client);
124 }
125 }
126
127 if (wl_list_empty(&e->point_events)) {
128 seatop_begin_default(seat);
129 }
130}
131
17static void handle_pointer_axis(struct sway_seat *seat, 132static void handle_pointer_axis(struct sway_seat *seat,
18 struct wlr_event_pointer_axis *event) { 133 struct wlr_pointer_axis_event *event) {
19 struct sway_input_device *input_device = 134 struct sway_input_device *input_device =
20 event->device ? event->device->data : NULL; 135 event->pointer ? event->pointer->base.data : NULL;
21 struct input_config *ic = 136 struct input_config *ic =
22 input_device ? input_device_get_config(input_device) : NULL; 137 input_device ? input_device_get_config(input_device) : NULL;
23 float scroll_factor = 138 float scroll_factor =
@@ -25,12 +140,13 @@ static void handle_pointer_axis(struct sway_seat *seat,
25 140
26 wlr_seat_pointer_notify_axis(seat->wlr_seat, event->time_msec, 141 wlr_seat_pointer_notify_axis(seat->wlr_seat, event->time_msec,
27 event->orientation, scroll_factor * event->delta, 142 event->orientation, scroll_factor * event->delta,
28 round(scroll_factor * event->delta_discrete), event->source); 143 roundf(scroll_factor * event->delta_discrete), event->source,
144 event->relative_direction);
29} 145}
30 146
31static void handle_button(struct sway_seat *seat, uint32_t time_msec, 147static void handle_button(struct sway_seat *seat, uint32_t time_msec,
32 struct wlr_input_device *device, uint32_t button, 148 struct wlr_input_device *device, uint32_t button,
33 enum wlr_button_state state) { 149 enum wl_pointer_button_state state) {
34 seat_pointer_notify_button(seat, time_msec, button, state); 150 seat_pointer_notify_button(seat, time_msec, button, state);
35 151
36 if (seat->cursor->pressed_button_count == 0) { 152 if (seat->cursor->pressed_button_count == 0) {
@@ -40,8 +156,7 @@ static void handle_button(struct sway_seat *seat, uint32_t time_msec,
40 156
41static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { 157static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) {
42 struct seatop_down_event *e = seat->seatop_data; 158 struct seatop_down_event *e = seat->seatop_data;
43 struct sway_container *con = e->con; 159 if (seat_is_input_allowed(seat, e->surface)) {
44 if (seat_is_input_allowed(seat, con->view->surface)) {
45 double moved_x = seat->cursor->cursor->x - e->ref_lx; 160 double moved_x = seat->cursor->cursor->x - e->ref_lx;
46 double moved_y = seat->cursor->cursor->y - e->ref_ly; 161 double moved_y = seat->cursor->cursor->y - e->ref_ly;
47 double sx = e->ref_con_lx + moved_x; 162 double sx = e->ref_con_lx + moved_x;
@@ -62,8 +177,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat,
62static void handle_tablet_tool_motion(struct sway_seat *seat, 177static void handle_tablet_tool_motion(struct sway_seat *seat,
63 struct sway_tablet_tool *tool, uint32_t time_msec) { 178 struct sway_tablet_tool *tool, uint32_t time_msec) {
64 struct seatop_down_event *e = seat->seatop_data; 179 struct seatop_down_event *e = seat->seatop_data;
65 struct sway_container *con = e->con; 180 if (seat_is_input_allowed(seat, e->surface)) {
66 if (seat_is_input_allowed(seat, con->view->surface)) {
67 double moved_x = seat->cursor->cursor->x - e->ref_lx; 181 double moved_x = seat->cursor->cursor->x - e->ref_lx;
68 double moved_y = seat->cursor->cursor->y - e->ref_ly; 182 double moved_y = seat->cursor->cursor->y - e->ref_ly;
69 double sx = e->ref_con_lx + moved_x; 183 double sx = e->ref_con_lx + moved_x;
@@ -72,6 +186,14 @@ static void handle_tablet_tool_motion(struct sway_seat *seat,
72 } 186 }
73} 187}
74 188
189static void handle_destroy(struct wl_listener *listener, void *data) {
190 struct seatop_down_event *e =
191 wl_container_of(listener, e, surface_destroy);
192 if (e) {
193 seatop_begin_default(e->seat);
194 }
195}
196
75static void handle_unref(struct sway_seat *seat, struct sway_container *con) { 197static void handle_unref(struct sway_seat *seat, struct sway_container *con) {
76 struct seatop_down_event *e = seat->seatop_data; 198 struct seatop_down_event *e = seat->seatop_data;
77 if (e->con == con) { 199 if (e->con == con) {
@@ -79,34 +201,63 @@ static void handle_unref(struct sway_seat *seat, struct sway_container *con) {
79 } 201 }
80} 202}
81 203
204static void handle_end(struct sway_seat *seat) {
205 struct seatop_down_event *e = seat->seatop_data;
206 wl_list_remove(&e->surface_destroy.link);
207}
208
82static const struct sway_seatop_impl seatop_impl = { 209static const struct sway_seatop_impl seatop_impl = {
83 .button = handle_button, 210 .button = handle_button,
84 .pointer_motion = handle_pointer_motion, 211 .pointer_motion = handle_pointer_motion,
85 .pointer_axis = handle_pointer_axis, 212 .pointer_axis = handle_pointer_axis,
86 .tablet_tool_tip = handle_tablet_tool_tip, 213 .tablet_tool_tip = handle_tablet_tool_tip,
87 .tablet_tool_motion = handle_tablet_tool_motion, 214 .tablet_tool_motion = handle_tablet_tool_motion,
215 .touch_motion = handle_touch_motion,
216 .touch_up = handle_touch_up,
217 .touch_down = handle_touch_down,
218 .touch_cancel = handle_touch_cancel,
88 .unref = handle_unref, 219 .unref = handle_unref,
220 .end = handle_end,
89 .allow_set_cursor = true, 221 .allow_set_cursor = true,
90}; 222};
91 223
92void seatop_begin_down(struct sway_seat *seat, struct sway_container *con, 224void seatop_begin_down(struct sway_seat *seat, struct sway_container *con,
93 uint32_t time_msec, int sx, int sy) { 225 double sx, double sy) {
226 seatop_begin_down_on_surface(seat, con->view->surface, sx, sy);
227 struct seatop_down_event *e = seat->seatop_data;
228 e->con = con;
229
230 container_raise_floating(con);
231 transaction_commit_dirty();
232}
233
234void seatop_begin_touch_down(struct sway_seat *seat,
235 struct wlr_surface *surface, struct wlr_touch_down_event *event,
236 double sx, double sy, double lx, double ly) {
237 seatop_begin_down_on_surface(seat, surface, sx, sy);
238 handle_touch_down(seat, event, lx, ly);
239}
240
241void seatop_begin_down_on_surface(struct sway_seat *seat,
242 struct wlr_surface *surface, double sx, double sy) {
94 seatop_end(seat); 243 seatop_end(seat);
95 244
96 struct seatop_down_event *e = 245 struct seatop_down_event *e =
97 calloc(1, sizeof(struct seatop_down_event)); 246 calloc(1, sizeof(struct seatop_down_event));
98 if (!e) { 247 if (!sway_assert(e, "Unable to allocate e")) {
99 return; 248 return;
100 } 249 }
101 e->con = con; 250 e->con = NULL;
251 e->seat = seat;
252 e->surface = surface;
253 wl_signal_add(&e->surface->events.destroy, &e->surface_destroy);
254 e->surface_destroy.notify = handle_destroy;
102 e->ref_lx = seat->cursor->cursor->x; 255 e->ref_lx = seat->cursor->cursor->x;
103 e->ref_ly = seat->cursor->cursor->y; 256 e->ref_ly = seat->cursor->cursor->y;
104 e->ref_con_lx = sx; 257 e->ref_con_lx = sx;
105 e->ref_con_ly = sy; 258 e->ref_con_ly = sy;
259 wl_list_init(&e->point_events);
106 260
107 seat->seatop_impl = &seatop_impl; 261 seat->seatop_impl = &seatop_impl;
108 seat->seatop_data = e; 262 seat->seatop_data = e;
109
110 container_raise_floating(con);
111 transaction_commit_dirty();
112} 263}
diff --git a/sway/input/seatop_move_floating.c b/sway/input/seatop_move_floating.c
index ddcd4c53..83668d88 100644
--- a/sway/input/seatop_move_floating.c
+++ b/sway/input/seatop_move_floating.c
@@ -1,6 +1,4 @@
1#define _POSIX_C_SOURCE 200809L
2#include <wlr/types/wlr_cursor.h> 1#include <wlr/types/wlr_cursor.h>
3#include "sway/desktop.h"
4#include "sway/desktop/transaction.h" 2#include "sway/desktop/transaction.h"
5#include "sway/input/cursor.h" 3#include "sway/input/cursor.h"
6#include "sway/input/seat.h" 4#include "sway/input/seat.h"
@@ -23,7 +21,7 @@ static void finalize_move(struct sway_seat *seat) {
23 21
24static void handle_button(struct sway_seat *seat, uint32_t time_msec, 22static void handle_button(struct sway_seat *seat, uint32_t time_msec,
25 struct wlr_input_device *device, uint32_t button, 23 struct wlr_input_device *device, uint32_t button,
26 enum wlr_button_state state) { 24 enum wl_pointer_button_state state) {
27 if (seat->cursor->pressed_button_count == 0) { 25 if (seat->cursor->pressed_button_count == 0) {
28 finalize_move(seat); 26 finalize_move(seat);
29 } 27 }
@@ -39,9 +37,7 @@ static void handle_tablet_tool_tip(struct sway_seat *seat,
39static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { 37static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) {
40 struct seatop_move_floating_event *e = seat->seatop_data; 38 struct seatop_move_floating_event *e = seat->seatop_data;
41 struct wlr_cursor *cursor = seat->cursor->cursor; 39 struct wlr_cursor *cursor = seat->cursor->cursor;
42 desktop_damage_whole_container(e->con);
43 container_floating_move_to(e->con, cursor->x - e->dx, cursor->y - e->dy); 40 container_floating_move_to(e->con, cursor->x - e->dx, cursor->y - e->dy);
44 desktop_damage_whole_container(e->con);
45 transaction_commit_dirty(); 41 transaction_commit_dirty();
46} 42}
47 43
diff --git a/sway/input/seatop_move_tiling.c b/sway/input/seatop_move_tiling.c
index 223c6c08..c525b77a 100644
--- a/sway/input/seatop_move_tiling.c
+++ b/sway/input/seatop_move_tiling.c
@@ -1,8 +1,6 @@
1#define _POSIX_C_SOURCE 200809L
2#include <limits.h> 1#include <limits.h>
3#include <wlr/types/wlr_cursor.h> 2#include <wlr/types/wlr_cursor.h>
4#include <wlr/util/edges.h> 3#include <wlr/util/edges.h>
5#include "sway/desktop.h"
6#include "sway/desktop/transaction.h" 4#include "sway/desktop/transaction.h"
7#include "sway/input/cursor.h" 5#include "sway/input/cursor.h"
8#include "sway/input/seat.h" 6#include "sway/input/seat.h"
@@ -24,29 +22,17 @@ struct seatop_move_tiling_event {
24 struct sway_container *con; 22 struct sway_container *con;
25 struct sway_node *target_node; 23 struct sway_node *target_node;
26 enum wlr_edges target_edge; 24 enum wlr_edges target_edge;
27 struct wlr_box drop_box;
28 double ref_lx, ref_ly; // cursor's x/y at start of op 25 double ref_lx, ref_ly; // cursor's x/y at start of op
29 bool threshold_reached; 26 bool threshold_reached;
30 bool split_target; 27 bool split_target;
31 bool insert_after_target; 28 bool insert_after_target;
29 struct wlr_scene_rect *indicator_rect;
32}; 30};
33 31
34static void handle_render(struct sway_seat *seat, 32static void handle_end(struct sway_seat *seat) {
35 struct sway_output *output, pixman_region32_t *damage) {
36 struct seatop_move_tiling_event *e = seat->seatop_data; 33 struct seatop_move_tiling_event *e = seat->seatop_data;
37 if (!e->threshold_reached) { 34 wlr_scene_node_destroy(&e->indicator_rect->node);
38 return; 35 e->indicator_rect = NULL;
39 }
40 if (e->target_node && node_get_output(e->target_node) == output) {
41 float color[4];
42 memcpy(&color, config->border_colors.focused.indicator,
43 sizeof(float) * 4);
44 premultiply_alpha(color, 0.5);
45 struct wlr_box box;
46 memcpy(&box, &e->drop_box, sizeof(struct wlr_box));
47 scale_box(&box, output->wlr_output->scale);
48 render_rect(output, damage, &box, color);
49 }
50} 36}
51 37
52static void handle_motion_prethreshold(struct sway_seat *seat) { 38static void handle_motion_prethreshold(struct sway_seat *seat) {
@@ -67,6 +53,7 @@ static void handle_motion_prethreshold(struct sway_seat *seat) {
67 53
68 // If the threshold has been exceeded, start the actual drag 54 // If the threshold has been exceeded, start the actual drag
69 if ((cx - sx) * (cx - sx) + (cy - sy) * (cy - sy) > threshold) { 55 if ((cx - sx) * (cx - sx) + (cy - sy) * (cy - sy) > threshold) {
56 wlr_scene_node_set_enabled(&e->indicator_rect->node, true);
70 e->threshold_reached = true; 57 e->threshold_reached = true;
71 cursor_set_image(seat->cursor, "grab", NULL); 58 cursor_set_image(seat->cursor, "grab", NULL);
72 } 59 }
@@ -165,6 +152,11 @@ static bool split_titlebar(struct sway_node *node, struct sway_container *avoid,
165 return false; 152 return false;
166} 153}
167 154
155static void update_indicator(struct seatop_move_tiling_event *e, struct wlr_box *box) {
156 wlr_scene_node_set_position(&e->indicator_rect->node, box->x, box->y);
157 wlr_scene_rect_set_size(e->indicator_rect, box->width, box->height);
158}
159
168static void handle_motion_postthreshold(struct sway_seat *seat) { 160static void handle_motion_postthreshold(struct sway_seat *seat) {
169 struct seatop_move_tiling_event *e = seat->seatop_data; 161 struct seatop_move_tiling_event *e = seat->seatop_data;
170 e->split_target = false; 162 e->split_target = false;
@@ -173,8 +165,6 @@ static void handle_motion_postthreshold(struct sway_seat *seat) {
173 struct sway_cursor *cursor = seat->cursor; 165 struct sway_cursor *cursor = seat->cursor;
174 struct sway_node *node = node_at_coords(seat, 166 struct sway_node *node = node_at_coords(seat,
175 cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); 167 cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy);
176 // Damage the old location
177 desktop_damage_box(&e->drop_box);
178 168
179 if (!node) { 169 if (!node) {
180 // Eg. hovered over a layer surface such as swaybar 170 // Eg. hovered over a layer surface such as swaybar
@@ -187,8 +177,10 @@ static void handle_motion_postthreshold(struct sway_seat *seat) {
187 // Empty workspace 177 // Empty workspace
188 e->target_node = node; 178 e->target_node = node;
189 e->target_edge = WLR_EDGE_NONE; 179 e->target_edge = WLR_EDGE_NONE;
190 workspace_get_box(node->sway_workspace, &e->drop_box); 180
191 desktop_damage_box(&e->drop_box); 181 struct wlr_box drop_box;
182 workspace_get_box(node->sway_workspace, &drop_box);
183 update_indicator(e, &drop_box);
192 return; 184 return;
193 } 185 }
194 186
@@ -201,11 +193,18 @@ static void handle_motion_postthreshold(struct sway_seat *seat) {
201 return; 193 return;
202 } 194 }
203 195
196 struct wlr_box drop_box = {
197 .x = con->pending.content_x,
198 .y = con->pending.content_y,
199 .width = con->pending.content_width,
200 .height = con->pending.content_height,
201 };
202
204 // Check if the cursor is over a tilebar only if the destination 203 // Check if the cursor is over a tilebar only if the destination
205 // container is not a descendant of the source container. 204 // container is not a descendant of the source container.
206 if (!surface && !container_has_ancestor(con, e->con) && 205 if (!surface && !container_has_ancestor(con, e->con) &&
207 split_titlebar(node, e->con, cursor->cursor, 206 split_titlebar(node, e->con, cursor->cursor,
208 &e->drop_box, &e->insert_after_target)) { 207 &drop_box, &e->insert_after_target)) {
209 // Don't allow dropping over the source container's titlebar 208 // Don't allow dropping over the source container's titlebar
210 // to give users a chance to cancel a drag operation. 209 // to give users a chance to cancel a drag operation.
211 if (con == e->con) { 210 if (con == e->con) {
@@ -215,6 +214,7 @@ static void handle_motion_postthreshold(struct sway_seat *seat) {
215 e->split_target = true; 214 e->split_target = true;
216 } 215 }
217 e->target_edge = WLR_EDGE_NONE; 216 e->target_edge = WLR_EDGE_NONE;
217 update_indicator(e, &drop_box);
218 return; 218 return;
219 } 219 }
220 220
@@ -256,8 +256,7 @@ static void handle_motion_postthreshold(struct sway_seat *seat) {
256 e->target_node = node_get_parent(e->target_node); 256 e->target_node = node_get_parent(e->target_node);
257 } 257 }
258 e->target_edge = edge; 258 e->target_edge = edge;
259 e->drop_box = box; 259 update_indicator(e, &box);
260 desktop_damage_box(&e->drop_box);
261 return; 260 return;
262 } 261 }
263 con = con->pending.parent; 262 con = con->pending.parent;
@@ -299,12 +298,8 @@ static void handle_motion_postthreshold(struct sway_seat *seat) {
299 } 298 }
300 299
301 e->target_node = node; 300 e->target_node = node;
302 e->drop_box.x = con->pending.content_x; 301 resize_box(&drop_box, e->target_edge, thickness);
303 e->drop_box.y = con->pending.content_y; 302 update_indicator(e, &drop_box);
304 e->drop_box.width = con->pending.content_width;
305 e->drop_box.height = con->pending.content_height;
306 resize_box(&e->drop_box, e->target_edge, thickness);
307 desktop_damage_box(&e->drop_box);
308} 303}
309 304
310static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) { 305static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) {
@@ -410,7 +405,7 @@ static void finalize_move(struct sway_seat *seat) {
410 405
411static void handle_button(struct sway_seat *seat, uint32_t time_msec, 406static void handle_button(struct sway_seat *seat, uint32_t time_msec,
412 struct wlr_input_device *device, uint32_t button, 407 struct wlr_input_device *device, uint32_t button,
413 enum wlr_button_state state) { 408 enum wl_pointer_button_state state) {
414 if (seat->cursor->pressed_button_count == 0) { 409 if (seat->cursor->pressed_button_count == 0) {
415 finalize_move(seat); 410 finalize_move(seat);
416 } 411 }
@@ -439,7 +434,7 @@ static const struct sway_seatop_impl seatop_impl = {
439 .pointer_motion = handle_pointer_motion, 434 .pointer_motion = handle_pointer_motion,
440 .tablet_tool_tip = handle_tablet_tool_tip, 435 .tablet_tool_tip = handle_tablet_tool_tip,
441 .unref = handle_unref, 436 .unref = handle_unref,
442 .render = handle_render, 437 .end = handle_end,
443}; 438};
444 439
445void seatop_begin_move_tiling_threshold(struct sway_seat *seat, 440void seatop_begin_move_tiling_threshold(struct sway_seat *seat,
@@ -451,6 +446,20 @@ void seatop_begin_move_tiling_threshold(struct sway_seat *seat,
451 if (!e) { 446 if (!e) {
452 return; 447 return;
453 } 448 }
449
450 const float *indicator = config->border_colors.focused.indicator;
451 float color[4] = {
452 indicator[0] * .5,
453 indicator[1] * .5,
454 indicator[2] * .5,
455 indicator[3] * .5,
456 };
457 e->indicator_rect = wlr_scene_rect_create(seat->scene_tree, 0, 0, color);
458 if (!e->indicator_rect) {
459 free(e);
460 return;
461 }
462
454 e->con = con; 463 e->con = con;
455 e->ref_lx = seat->cursor->cursor->x; 464 e->ref_lx = seat->cursor->cursor->x;
456 e->ref_ly = seat->cursor->cursor->y; 465 e->ref_ly = seat->cursor->cursor->y;
diff --git a/sway/input/seatop_resize_floating.c b/sway/input/seatop_resize_floating.c
index 8400a4b3..bec86e33 100644
--- a/sway/input/seatop_resize_floating.c
+++ b/sway/input/seatop_resize_floating.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <limits.h> 1#include <limits.h>
3#include <wlr/types/wlr_cursor.h> 2#include <wlr/types/wlr_cursor.h>
4#include <wlr/types/wlr_xcursor_manager.h> 3#include <wlr/types/wlr_xcursor_manager.h>
@@ -21,7 +20,7 @@ struct seatop_resize_floating_event {
21 20
22static void handle_button(struct sway_seat *seat, uint32_t time_msec, 21static void handle_button(struct sway_seat *seat, uint32_t time_msec,
23 struct wlr_input_device *device, uint32_t button, 22 struct wlr_input_device *device, uint32_t button,
24 enum wlr_button_state state) { 23 enum wl_pointer_button_state state) {
25 struct seatop_resize_floating_event *e = seat->seatop_data; 24 struct seatop_resize_floating_event *e = seat->seatop_data;
26 struct sway_container *con = e->con; 25 struct sway_container *con = e->con;
27 26
@@ -80,17 +79,25 @@ static void handle_pointer_motion(struct sway_seat *seat, uint32_t time_msec) {
80 double height = e->ref_height + grow_height; 79 double height = e->ref_height + grow_height;
81 int min_width, max_width, min_height, max_height; 80 int min_width, max_width, min_height, max_height;
82 floating_calculate_constraints(&min_width, &max_width, 81 floating_calculate_constraints(&min_width, &max_width,
83 &min_height, &max_height); 82 &min_height, &max_height);
84 width = fmax(min_width + border_width, fmin(width, max_width)); 83 width = fmin(width, max_width - border_width);
85 height = fmax(min_height + border_height, fmin(height, max_height)); 84 width = fmax(width, min_width + border_width);
85 width = fmax(width, 1);
86 height = fmin(height, max_height - border_height);
87 height = fmax(height, min_height + border_height);
88 height = fmax(height, 1);
86 89
87 // Apply the view's min/max size 90 // Apply the view's min/max size
88 if (con->view) { 91 if (con->view) {
89 double view_min_width, view_max_width, view_min_height, view_max_height; 92 double view_min_width, view_max_width, view_min_height, view_max_height;
90 view_get_constraints(con->view, &view_min_width, &view_max_width, 93 view_get_constraints(con->view, &view_min_width, &view_max_width,
91 &view_min_height, &view_max_height); 94 &view_min_height, &view_max_height);
92 width = fmax(view_min_width + border_width, fmin(width, view_max_width)); 95 width = fmin(width, view_max_width - border_width);
93 height = fmax(view_min_height + border_height, fmin(height, view_max_height)); 96 width = fmax(width, view_min_width + border_width);
97 width = fmax(width, 1);
98 height = fmin(height, view_max_height - border_height);
99 height = fmax(height, view_min_height + border_height);
100 height = fmax(height, 1);
94 101
95 } 102 }
96 103
diff --git a/sway/input/seatop_resize_tiling.c b/sway/input/seatop_resize_tiling.c
index 869d11b5..15fd333b 100644
--- a/sway/input/seatop_resize_tiling.c
+++ b/sway/input/seatop_resize_tiling.c
@@ -1,4 +1,3 @@
1#define _POSIX_C_SOURCE 200809L
2#include <wlr/types/wlr_cursor.h> 1#include <wlr/types/wlr_cursor.h>
3#include <wlr/util/edges.h> 2#include <wlr/util/edges.h>
4#include "sway/commands.h" 3#include "sway/commands.h"
@@ -46,7 +45,7 @@ static struct sway_container *container_get_resize_sibling(
46 45
47static void handle_button(struct sway_seat *seat, uint32_t time_msec, 46static void handle_button(struct sway_seat *seat, uint32_t time_msec,
48 struct wlr_input_device *device, uint32_t button, 47 struct wlr_input_device *device, uint32_t button,
49 enum wlr_button_state state) { 48 enum wl_pointer_button_state state) {
50 struct seatop_resize_tiling_event *e = seat->seatop_data; 49 struct seatop_resize_tiling_event *e = seat->seatop_data;
51 50
52 if (seat->cursor->pressed_button_count == 0) { 51 if (seat->cursor->pressed_button_count == 0) {
diff --git a/sway/input/switch.c b/sway/input/switch.c
index 9ea87a1a..831f4dbf 100644
--- a/sway/input/switch.c
+++ b/sway/input/switch.c
@@ -1,6 +1,5 @@
1#include "sway/config.h" 1#include "sway/config.h"
2#include "sway/input/switch.h" 2#include "sway/input/switch.h"
3#include <wlr/types/wlr_idle.h>
4#include "log.h" 3#include "log.h"
5 4
6struct sway_switch *sway_switch_create(struct sway_seat *seat, 5struct sway_switch *sway_switch_create(struct sway_seat *seat,
@@ -11,6 +10,7 @@ struct sway_switch *sway_switch_create(struct sway_seat *seat,
11 return NULL; 10 return NULL;
12 } 11 }
13 device->switch_device = switch_device; 12 device->switch_device = switch_device;
13 switch_device->wlr = wlr_switch_from_input_device(device->input_device->wlr_device);
14 switch_device->seat_device = device; 14 switch_device->seat_device = device;
15 switch_device->state = WLR_SWITCH_STATE_OFF; 15 switch_device->state = WLR_SWITCH_STATE_OFF;
16 wl_list_init(&switch_device->switch_toggle.link); 16 wl_list_init(&switch_device->switch_toggle.link);
@@ -19,9 +19,22 @@ struct sway_switch *sway_switch_create(struct sway_seat *seat,
19 return switch_device; 19 return switch_device;
20} 20}
21 21
22static bool sway_switch_trigger_test(enum sway_switch_trigger trigger,
23 enum wlr_switch_state state) {
24 switch (trigger) {
25 case SWAY_SWITCH_TRIGGER_ON:
26 return state == WLR_SWITCH_STATE_ON;
27 case SWAY_SWITCH_TRIGGER_OFF:
28 return state == WLR_SWITCH_STATE_OFF;
29 case SWAY_SWITCH_TRIGGER_TOGGLE:
30 return true;
31 }
32 abort(); // unreachable
33}
34
22static void execute_binding(struct sway_switch *sway_switch) { 35static void execute_binding(struct sway_switch *sway_switch) {
23 struct sway_seat* seat = sway_switch->seat_device->sway_seat; 36 struct sway_seat *seat = sway_switch->seat_device->sway_seat;
24 bool input_inhibited = seat->exclusive_client != NULL; 37 bool locked = server.session_lock.lock;
25 38
26 list_t *bindings = config->current_mode->switch_bindings; 39 list_t *bindings = config->current_mode->switch_bindings;
27 struct sway_switch_binding *matched_binding = NULL; 40 struct sway_switch_binding *matched_binding = NULL;
@@ -30,22 +43,21 @@ static void execute_binding(struct sway_switch *sway_switch) {
30 if (binding->type != sway_switch->type) { 43 if (binding->type != sway_switch->type) {
31 continue; 44 continue;
32 } 45 }
33 if (binding->state != WLR_SWITCH_STATE_TOGGLE && 46 if (!sway_switch_trigger_test(binding->trigger, sway_switch->state)) {
34 binding->state != sway_switch->state) {
35 continue; 47 continue;
36 } 48 }
37 if (config->reloading && (binding->state == WLR_SWITCH_STATE_TOGGLE 49 if (config->reloading && (binding->trigger == SWAY_SWITCH_TRIGGER_TOGGLE
38 || (binding->flags & BINDING_RELOAD) == 0)) { 50 || (binding->flags & BINDING_RELOAD) == 0)) {
39 continue; 51 continue;
40 } 52 }
41 bool binding_locked = binding->flags & BINDING_LOCKED; 53 bool binding_locked = binding->flags & BINDING_LOCKED;
42 if (!binding_locked && input_inhibited) { 54 if (!binding_locked && locked) {
43 continue; 55 continue;
44 } 56 }
45 57
46 matched_binding = binding; 58 matched_binding = binding;
47 59
48 if (binding_locked == input_inhibited) { 60 if (binding_locked == locked) {
49 break; 61 break;
50 } 62 }
51 } 63 }
@@ -65,7 +77,7 @@ static void execute_binding(struct sway_switch *sway_switch) {
65static void handle_switch_toggle(struct wl_listener *listener, void *data) { 77static void handle_switch_toggle(struct wl_listener *listener, void *data) {
66 struct sway_switch *sway_switch = 78 struct sway_switch *sway_switch =
67 wl_container_of(listener, sway_switch, switch_toggle); 79 wl_container_of(listener, sway_switch, switch_toggle);
68 struct wlr_event_switch_toggle *event = data; 80 struct wlr_switch_toggle_event *event = data;
69 struct sway_seat *seat = sway_switch->seat_device->sway_seat; 81 struct sway_seat *seat = sway_switch->seat_device->sway_seat;
70 seat_idle_notify_activity(seat, IDLE_SOURCE_SWITCH); 82 seat_idle_notify_activity(seat, IDLE_SOURCE_SWITCH);
71 83
@@ -82,10 +94,8 @@ static void handle_switch_toggle(struct wl_listener *listener, void *data) {
82} 94}
83 95
84void sway_switch_configure(struct sway_switch *sway_switch) { 96void sway_switch_configure(struct sway_switch *sway_switch) {
85 struct wlr_input_device *wlr_device =
86 sway_switch->seat_device->input_device->wlr_device;
87 wl_list_remove(&sway_switch->switch_toggle.link); 97 wl_list_remove(&sway_switch->switch_toggle.link);
88 wl_signal_add(&wlr_device->switch_device->events.toggle, 98 wl_signal_add(&sway_switch->wlr->events.toggle,
89 &sway_switch->switch_toggle); 99 &sway_switch->switch_toggle);
90 sway_switch->switch_toggle.notify = handle_switch_toggle; 100 sway_switch->switch_toggle.notify = handle_switch_toggle;
91 sway_log(SWAY_DEBUG, "Configured switch for device"); 101 sway_log(SWAY_DEBUG, "Configured switch for device");
diff --git a/sway/input/tablet.c b/sway/input/tablet.c
index 26e86e36..2863642a 100644
--- a/sway/input/tablet.c
+++ b/sway/input/tablet.c
@@ -1,6 +1,5 @@
1#define _POSIX_C_SOURCE 200809L
2#include <stdlib.h> 1#include <stdlib.h>
3#include <wlr/backend/libinput.h> 2#include <wlr/config.h>
4#include <wlr/types/wlr_tablet_v2.h> 3#include <wlr/types/wlr_tablet_v2.h>
5#include <wlr/types/wlr_tablet_tool.h> 4#include <wlr/types/wlr_tablet_tool.h>
6#include <wlr/types/wlr_tablet_pad.h> 5#include <wlr/types/wlr_tablet_pad.h>
@@ -9,6 +8,10 @@
9#include "sway/input/seat.h" 8#include "sway/input/seat.h"
10#include "sway/input/tablet.h" 9#include "sway/input/tablet.h"
11 10
11#if WLR_HAS_LIBINPUT_BACKEND
12#include <wlr/backend/libinput.h>
13#endif
14
12static void handle_pad_tablet_destroy(struct wl_listener *listener, void *data) { 15static void handle_pad_tablet_destroy(struct wl_listener *listener, void *data) {
13 struct sway_tablet_pad *pad = 16 struct sway_tablet_pad *pad =
14 wl_container_of(listener, pad, tablet_destroy); 17 wl_container_of(listener, pad, tablet_destroy);
@@ -54,15 +57,14 @@ void sway_configure_tablet(struct sway_tablet *tablet) {
54 tablet->seat_device->input_device->wlr_device; 57 tablet->seat_device->input_device->wlr_device;
55 struct sway_seat *seat = tablet->seat_device->sway_seat; 58 struct sway_seat *seat = tablet->seat_device->sway_seat;
56 59
57 if ((seat->wlr_seat->capabilities & WL_SEAT_CAPABILITY_POINTER) == 0) { 60 seat_configure_xcursor(seat);
58 seat_configure_xcursor(seat);
59 }
60 61
61 if (!tablet->tablet_v2) { 62 if (!tablet->tablet_v2) {
62 tablet->tablet_v2 = 63 tablet->tablet_v2 =
63 wlr_tablet_create(server.tablet_v2, seat->wlr_seat, device); 64 wlr_tablet_create(server.tablet_v2, seat->wlr_seat, device);
64 } 65 }
65 66
67#if WLR_HAS_LIBINPUT_BACKEND
66 /* Search for a sibling tablet pad */ 68 /* Search for a sibling tablet pad */
67 if (!wlr_input_device_is_libinput(device)) { 69 if (!wlr_input_device_is_libinput(device)) {
68 /* We can only do this on libinput devices */ 70 /* We can only do this on libinput devices */
@@ -87,6 +89,7 @@ void sway_configure_tablet(struct sway_tablet *tablet) {
87 break; 89 break;
88 } 90 }
89 } 91 }
92#endif
90} 93}
91 94
92void sway_tablet_destroy(struct sway_tablet *tablet) { 95void sway_tablet_destroy(struct sway_tablet *tablet) {
@@ -196,7 +199,7 @@ static void handle_tablet_pad_attach(struct wl_listener *listener,
196 199
197static void handle_tablet_pad_ring(struct wl_listener *listener, void *data) { 200static void handle_tablet_pad_ring(struct wl_listener *listener, void *data) {
198 struct sway_tablet_pad *pad = wl_container_of(listener, pad, ring); 201 struct sway_tablet_pad *pad = wl_container_of(listener, pad, ring);
199 struct wlr_event_tablet_pad_ring *event = data; 202 struct wlr_tablet_pad_ring_event *event = data;
200 203
201 if (!pad->current_surface) { 204 if (!pad->current_surface) {
202 return; 205 return;
@@ -210,7 +213,7 @@ static void handle_tablet_pad_ring(struct wl_listener *listener, void *data) {
210 213
211static void handle_tablet_pad_strip(struct wl_listener *listener, void *data) { 214static void handle_tablet_pad_strip(struct wl_listener *listener, void *data) {
212 struct sway_tablet_pad *pad = wl_container_of(listener, pad, strip); 215 struct sway_tablet_pad *pad = wl_container_of(listener, pad, strip);
213 struct wlr_event_tablet_pad_strip *event = data; 216 struct wlr_tablet_pad_strip_event *event = data;
214 217
215 if (!pad->current_surface) { 218 if (!pad->current_surface) {
216 return; 219 return;
@@ -224,7 +227,7 @@ static void handle_tablet_pad_strip(struct wl_listener *listener, void *data) {
224 227
225static void handle_tablet_pad_button(struct wl_listener *listener, void *data) { 228static void handle_tablet_pad_button(struct wl_listener *listener, void *data) {
226 struct sway_tablet_pad *pad = wl_container_of(listener, pad, button); 229 struct sway_tablet_pad *pad = wl_container_of(listener, pad, button);
227 struct wlr_event_tablet_pad_button *event = data; 230 struct wlr_tablet_pad_button_event *event = data;
228 231
229 if (!pad->current_surface) { 232 if (!pad->current_surface) {
230 return; 233 return;
@@ -246,6 +249,7 @@ struct sway_tablet_pad *sway_tablet_pad_create(struct sway_seat *seat,
246 return NULL; 249 return NULL;
247 } 250 }
248 251
252 tablet_pad->wlr = wlr_tablet_pad_from_input_device(device->input_device->wlr_device);
249 tablet_pad->seat_device = device; 253 tablet_pad->seat_device = device;
250 wl_list_init(&tablet_pad->attach.link); 254 wl_list_init(&tablet_pad->attach.link);
251 wl_list_init(&tablet_pad->button.link); 255 wl_list_init(&tablet_pad->button.link);
@@ -260,40 +264,41 @@ struct sway_tablet_pad *sway_tablet_pad_create(struct sway_seat *seat,
260} 264}
261 265
262void sway_configure_tablet_pad(struct sway_tablet_pad *tablet_pad) { 266void sway_configure_tablet_pad(struct sway_tablet_pad *tablet_pad) {
263 struct wlr_input_device *device = 267 struct wlr_input_device *wlr_device =
264 tablet_pad->seat_device->input_device->wlr_device; 268 tablet_pad->seat_device->input_device->wlr_device;
265 struct sway_seat *seat = tablet_pad->seat_device->sway_seat; 269 struct sway_seat *seat = tablet_pad->seat_device->sway_seat;
266 270
267 if (!tablet_pad->tablet_v2_pad) { 271 if (!tablet_pad->tablet_v2_pad) {
268 tablet_pad->tablet_v2_pad = 272 tablet_pad->tablet_v2_pad =
269 wlr_tablet_pad_create(server.tablet_v2, seat->wlr_seat, device); 273 wlr_tablet_pad_create(server.tablet_v2, seat->wlr_seat, wlr_device);
270 } 274 }
271 275
272 wl_list_remove(&tablet_pad->attach.link); 276 wl_list_remove(&tablet_pad->attach.link);
273 tablet_pad->attach.notify = handle_tablet_pad_attach; 277 tablet_pad->attach.notify = handle_tablet_pad_attach;
274 wl_signal_add(&device->tablet_pad->events.attach_tablet, 278 wl_signal_add(&tablet_pad->wlr->events.attach_tablet,
275 &tablet_pad->attach); 279 &tablet_pad->attach);
276 280
277 wl_list_remove(&tablet_pad->button.link); 281 wl_list_remove(&tablet_pad->button.link);
278 tablet_pad->button.notify = handle_tablet_pad_button; 282 tablet_pad->button.notify = handle_tablet_pad_button;
279 wl_signal_add(&device->tablet_pad->events.button, &tablet_pad->button); 283 wl_signal_add(&tablet_pad->wlr->events.button, &tablet_pad->button);
280 284
281 wl_list_remove(&tablet_pad->strip.link); 285 wl_list_remove(&tablet_pad->strip.link);
282 tablet_pad->strip.notify = handle_tablet_pad_strip; 286 tablet_pad->strip.notify = handle_tablet_pad_strip;
283 wl_signal_add(&device->tablet_pad->events.strip, &tablet_pad->strip); 287 wl_signal_add(&tablet_pad->wlr->events.strip, &tablet_pad->strip);
284 288
285 wl_list_remove(&tablet_pad->ring.link); 289 wl_list_remove(&tablet_pad->ring.link);
286 tablet_pad->ring.notify = handle_tablet_pad_ring; 290 tablet_pad->ring.notify = handle_tablet_pad_ring;
287 wl_signal_add(&device->tablet_pad->events.ring, &tablet_pad->ring); 291 wl_signal_add(&tablet_pad->wlr->events.ring, &tablet_pad->ring);
288 292
293#if WLR_HAS_LIBINPUT_BACKEND
289 /* Search for a sibling tablet */ 294 /* Search for a sibling tablet */
290 if (!wlr_input_device_is_libinput(device)) { 295 if (!wlr_input_device_is_libinput(wlr_device)) {
291 /* We can only do this on libinput devices */ 296 /* We can only do this on libinput devices */
292 return; 297 return;
293 } 298 }
294 299
295 struct libinput_device_group *group = 300 struct libinput_device_group *group =
296 libinput_device_get_device_group(wlr_libinput_get_device_handle(device)); 301 libinput_device_get_device_group(wlr_libinput_get_device_handle(wlr_device));
297 struct sway_tablet *tool; 302 struct sway_tablet *tool;
298 wl_list_for_each(tool, &seat->cursor->tablets, link) { 303 wl_list_for_each(tool, &seat->cursor->tablets, link) {
299 struct wlr_input_device *tablet = 304 struct wlr_input_device *tablet =
@@ -310,6 +315,7 @@ void sway_configure_tablet_pad(struct sway_tablet_pad *tablet_pad) {
310 break; 315 break;
311 } 316 }
312 } 317 }
318#endif
313} 319}
314 320
315void sway_tablet_pad_destroy(struct sway_tablet_pad *tablet_pad) { 321void sway_tablet_pad_destroy(struct sway_tablet_pad *tablet_pad) {
@@ -333,14 +339,10 @@ static void handle_pad_tablet_surface_destroy(struct wl_listener *listener,
333 struct sway_tablet_pad *tablet_pad = 339 struct sway_tablet_pad *tablet_pad =
334 wl_container_of(listener, tablet_pad, surface_destroy); 340 wl_container_of(listener, tablet_pad, surface_destroy);
335 341
336 wlr_tablet_v2_tablet_pad_notify_leave(tablet_pad->tablet_v2_pad, 342 sway_tablet_pad_set_focus(tablet_pad, NULL);
337 tablet_pad->current_surface);
338 wl_list_remove(&tablet_pad->surface_destroy.link);
339 wl_list_init(&tablet_pad->surface_destroy.link);
340 tablet_pad->current_surface = NULL;
341} 343}
342 344
343void sway_tablet_pad_notify_enter(struct sway_tablet_pad *tablet_pad, 345void sway_tablet_pad_set_focus(struct sway_tablet_pad *tablet_pad,
344 struct wlr_surface *surface) { 346 struct wlr_surface *surface) {
345 if (!tablet_pad || !tablet_pad->tablet) { 347 if (!tablet_pad || !tablet_pad->tablet) {
346 return; 348 return;
@@ -359,7 +361,8 @@ void sway_tablet_pad_notify_enter(struct sway_tablet_pad *tablet_pad,
359 tablet_pad->current_surface = NULL; 361 tablet_pad->current_surface = NULL;
360 } 362 }
361 363
362 if (!wlr_surface_accepts_tablet_v2(tablet_pad->tablet->tablet_v2, surface)) { 364 if (surface == NULL ||
365 !wlr_surface_accepts_tablet_v2(tablet_pad->tablet->tablet_v2, surface)) {
363 return; 366 return;
364 } 367 }
365 368
@@ -367,7 +370,6 @@ void sway_tablet_pad_notify_enter(struct sway_tablet_pad *tablet_pad,
367 tablet_pad->tablet->tablet_v2, surface); 370 tablet_pad->tablet->tablet_v2, surface);
368 371
369 tablet_pad->current_surface = surface; 372 tablet_pad->current_surface = surface;
370 wl_list_remove(&tablet_pad->surface_destroy.link);
371 tablet_pad->surface_destroy.notify = handle_pad_tablet_surface_destroy; 373 tablet_pad->surface_destroy.notify = handle_pad_tablet_surface_destroy;
372 wl_signal_add(&surface->events.destroy, &tablet_pad->surface_destroy); 374 wl_signal_add(&surface->events.destroy, &tablet_pad->surface_destroy);
373} 375}
diff --git a/sway/input/text_input.c b/sway/input/text_input.c
index b8c19c17..c38a3bb2 100644
--- a/sway/input/text_input.c
+++ b/sway/input/text_input.c
@@ -2,7 +2,14 @@
2#include <stdlib.h> 2#include <stdlib.h>
3#include "log.h" 3#include "log.h"
4#include "sway/input/seat.h" 4#include "sway/input/seat.h"
5#include "sway/scene_descriptor.h"
6#include "sway/tree/root.h"
7#include "sway/tree/view.h"
8#include "sway/output.h"
5#include "sway/input/text_input.h" 9#include "sway/input/text_input.h"
10#include "sway/input/text_input_popup.h"
11#include "sway/layers.h"
12static void input_popup_update(struct sway_input_popup *popup);
6 13
7static struct sway_text_input *relay_get_focusable_text_input( 14static struct sway_text_input *relay_get_focusable_text_input(
8 struct sway_input_method_relay *relay) { 15 struct sway_input_method_relay *relay) {
@@ -77,8 +84,6 @@ static void handle_im_grab_keyboard(struct wl_listener *listener, void *data) {
77 struct wlr_keyboard *active_keyboard = wlr_seat_get_keyboard(relay->seat->wlr_seat); 84 struct wlr_keyboard *active_keyboard = wlr_seat_get_keyboard(relay->seat->wlr_seat);
78 wlr_input_method_keyboard_grab_v2_set_keyboard(keyboard_grab, 85 wlr_input_method_keyboard_grab_v2_set_keyboard(keyboard_grab,
79 active_keyboard); 86 active_keyboard);
80 wlr_input_method_keyboard_grab_v2_send_modifiers(keyboard_grab,
81 &active_keyboard->modifiers);
82 87
83 wl_signal_add(&keyboard_grab->events.destroy, 88 wl_signal_add(&keyboard_grab->events.destroy,
84 &relay->input_method_keyboard_grab_destroy); 89 &relay->input_method_keyboard_grab_destroy);
@@ -104,6 +109,10 @@ static void handle_im_destroy(struct wl_listener *listener, void *data) {
104 input_method_destroy); 109 input_method_destroy);
105 struct wlr_input_method_v2 *context = data; 110 struct wlr_input_method_v2 *context = data;
106 assert(context == relay->input_method); 111 assert(context == relay->input_method);
112 wl_list_remove(&relay->input_method_commit.link);
113 wl_list_remove(&relay->input_method_grab_keyboard.link);
114 wl_list_remove(&relay->input_method_destroy.link);
115 wl_list_remove(&relay->input_method_new_popup_surface.link);
107 relay->input_method = NULL; 116 relay->input_method = NULL;
108 struct sway_text_input *text_input = relay_get_focused_text_input(relay); 117 struct sway_text_input *text_input = relay_get_focused_text_input(relay);
109 if (text_input) { 118 if (text_input) {
@@ -135,6 +144,11 @@ static void relay_send_im_state(struct sway_input_method_relay *relay,
135 input->current.content_type.hint, 144 input->current.content_type.hint,
136 input->current.content_type.purpose); 145 input->current.content_type.purpose);
137 } 146 }
147 struct sway_input_popup *popup;
148 wl_list_for_each(popup, &relay->input_popups, link) {
149 // send_text_input_rectangle is called in this function
150 input_popup_update(popup);
151 }
138 wlr_input_method_v2_send_done(input_method); 152 wlr_input_method_v2_send_done(input_method);
139 // TODO: pass intent, display popup size 153 // TODO: pass intent, display popup size
140} 154}
@@ -257,6 +271,211 @@ static void relay_handle_text_input(struct wl_listener *listener,
257 sway_text_input_create(relay, wlr_text_input); 271 sway_text_input_create(relay, wlr_text_input);
258} 272}
259 273
274static void input_popup_update(struct sway_input_popup *popup) {
275 struct sway_text_input *text_input =
276 relay_get_focused_text_input(popup->relay);
277
278 if (text_input == NULL || text_input->input->focused_surface == NULL) {
279 return;
280 }
281
282 if (popup->scene_tree != NULL) {
283 wlr_scene_node_destroy(&popup->scene_tree->node);
284 popup->scene_tree = NULL;
285 }
286 if (popup->desc.relative != NULL) {
287 wlr_scene_node_destroy(popup->desc.relative);
288 popup->desc.relative = NULL;
289 }
290 popup->desc.view = NULL;
291
292 if (!popup->popup_surface->surface->mapped) {
293 return;
294 }
295
296 bool cursor_rect = text_input->input->current.features
297 & WLR_TEXT_INPUT_V3_FEATURE_CURSOR_RECTANGLE;
298 struct wlr_surface *focused_surface = text_input->input->focused_surface;
299 struct wlr_box cursor_area = text_input->input->current.cursor_rectangle;
300
301 struct wlr_box output_box;
302 struct wlr_box parent = {0};
303 struct wlr_layer_surface_v1 *layer_surface =
304 wlr_layer_surface_v1_try_from_wlr_surface(focused_surface);
305 struct wlr_scene_tree *relative_parent;
306
307 struct wlr_box geo = {0};
308
309 popup->scene_tree = wlr_scene_subsurface_tree_create(root->layers.popup, popup->popup_surface->surface);
310 if (layer_surface != NULL) {
311 struct sway_layer_surface *layer =
312 layer_surface->data;
313 if (layer == NULL) {
314 return;
315 }
316
317 relative_parent = layer->scene->tree;
318 struct wlr_output *output = layer->layer_surface->output;
319 wlr_output_layout_get_box(root->output_layout, output, &output_box);
320 int lx, ly;
321 wlr_scene_node_coords(&layer->tree->node, &lx, &ly);
322 parent.x = lx;
323 parent.y = ly;
324 popup->desc.view = NULL;
325 } else {
326 struct sway_view *view = view_from_wlr_surface(focused_surface);
327 relative_parent = view->scene_tree;
328 geo = view->geometry;
329 int lx, ly;
330 wlr_scene_node_coords(&view->scene_tree->node, &lx, &ly);
331 struct wlr_output *output = wlr_output_layout_output_at(root->output_layout,
332 view->container->pending.content_x + view->geometry.x,
333 view->container->pending.content_y + view->geometry.y);
334 wlr_output_layout_get_box(root->output_layout, output, &output_box);
335 parent.x = lx;
336 parent.y = ly;
337
338 parent.width = view->geometry.width;
339 parent.height = view->geometry.height;
340 popup->desc.view = view;
341 }
342
343 struct wlr_scene_tree *relative = wlr_scene_tree_create(relative_parent);
344
345 popup->desc.relative = &relative->node;
346 if (!scene_descriptor_assign(&popup->scene_tree->node,
347 SWAY_SCENE_DESC_POPUP, &popup->desc)) {
348 wlr_scene_node_destroy(&popup->scene_tree->node);
349 popup->scene_tree = NULL;
350 return;
351 }
352
353 if (!cursor_rect) {
354 cursor_area.x = 0;
355 cursor_area.y = 0;
356 cursor_area.width = parent.width;
357 cursor_area.height = parent.height;
358 }
359
360 int popup_width = popup->popup_surface->surface->current.width;
361 int popup_height = popup->popup_surface->surface->current.height;
362 int x1 = parent.x + cursor_area.x;
363 int x2 = parent.x + cursor_area.x + cursor_area.width;
364 int y1 = parent.y + cursor_area.y;
365 int y2 = parent.y + cursor_area.y + cursor_area.height;
366 int x = x1;
367 int y = y2;
368
369 int available_right = output_box.x + output_box.width - x1;
370 int available_left = x2 - output_box.x;
371 if (available_right < popup_width && available_left > available_right) {
372 x = x2 - popup_width;
373 }
374
375 int available_down = output_box.y + output_box.height - y2;
376 int available_up = y1 - output_box.y;
377 if (available_down < popup_height && available_up > available_down) {
378 y = y1 - popup_height;
379 }
380
381 wlr_scene_node_set_position(&relative->node, x - parent.x - geo.x, y - parent.y - geo.y);
382 if (cursor_rect) {
383 struct wlr_box box = {
384 .x = x1 - x,
385 .y = y1 - y,
386 .width = cursor_area.width,
387 .height = cursor_area.height,
388 };
389 wlr_input_popup_surface_v2_send_text_input_rectangle(
390 popup->popup_surface, &box);
391 }
392 wlr_scene_node_set_position(&popup->scene_tree->node, x - geo.x, y - geo.y);
393}
394
395static void input_popup_set_focus(struct sway_input_popup *popup,
396 struct wlr_surface *surface) {
397 wl_list_remove(&popup->focused_surface_unmap.link);
398
399 if (surface == NULL) {
400 wl_list_init(&popup->focused_surface_unmap.link);
401 input_popup_update(popup);
402 return;
403 }
404 struct wlr_layer_surface_v1 *layer_surface =
405 wlr_layer_surface_v1_try_from_wlr_surface(surface);
406 if (layer_surface != NULL) {
407 wl_signal_add(
408 &layer_surface->surface->events.unmap, &popup->focused_surface_unmap);
409 input_popup_update(popup);
410 return;
411 }
412
413 struct sway_view *view = view_from_wlr_surface(surface);
414 wl_signal_add(&view->events.unmap, &popup->focused_surface_unmap);
415}
416
417static void handle_im_popup_destroy(struct wl_listener *listener, void *data) {
418 struct sway_input_popup *popup =
419 wl_container_of(listener, popup, popup_destroy);
420 wl_list_remove(&popup->focused_surface_unmap.link);
421 wl_list_remove(&popup->popup_surface_commit.link);
422 wl_list_remove(&popup->popup_destroy.link);
423 wl_list_remove(&popup->link);
424
425 free(popup);
426}
427
428static void handle_im_popup_surface_commit(struct wl_listener *listener,
429 void *data) {
430 struct sway_input_popup *popup =
431 wl_container_of(listener, popup, popup_surface_commit);
432 input_popup_update(popup);
433}
434
435static void handle_im_focused_surface_unmap(
436 struct wl_listener *listener, void *data) {
437 struct sway_input_popup *popup =
438 wl_container_of(listener, popup, focused_surface_unmap);
439 input_popup_update(popup);
440}
441
442static void handle_im_new_popup_surface(struct wl_listener *listener,
443 void *data) {
444 struct sway_input_method_relay *relay = wl_container_of(listener, relay,
445 input_method_new_popup_surface);
446 struct sway_input_popup *popup = calloc(1, sizeof(*popup));
447 popup->relay = relay;
448 popup->popup_surface = data;
449 popup->popup_surface->data = popup;
450
451 wl_signal_add(
452 &popup->popup_surface->events.destroy, &popup->popup_destroy);
453 popup->popup_destroy.notify = handle_im_popup_destroy;
454 wl_signal_add(&popup->popup_surface->surface->events.commit,
455 &popup->popup_surface_commit);
456 popup->popup_surface_commit.notify = handle_im_popup_surface_commit;
457 wl_list_init(&popup->focused_surface_unmap.link);
458 popup->focused_surface_unmap.notify = handle_im_focused_surface_unmap;
459
460 struct sway_text_input *text_input = relay_get_focused_text_input(relay);
461 if (text_input != NULL) {
462 input_popup_set_focus(popup, text_input->input->focused_surface);
463 } else {
464 input_popup_set_focus(popup, NULL);
465 }
466
467 wl_list_insert(&relay->input_popups, &popup->link);
468}
469
470static void text_input_send_enter(struct sway_text_input *text_input,
471 struct wlr_surface *surface) {
472 wlr_text_input_v3_send_enter(text_input->input, surface);
473 struct sway_input_popup *popup;
474 wl_list_for_each(popup, &text_input->relay->input_popups, link) {
475 input_popup_set_focus(popup, surface);
476 }
477}
478
260static void relay_handle_input_method(struct wl_listener *listener, 479static void relay_handle_input_method(struct wl_listener *listener,
261 void *data) { 480 void *data) {
262 struct sway_input_method_relay *relay = wl_container_of(listener, relay, 481 struct sway_input_method_relay *relay = wl_container_of(listener, relay,
@@ -282,10 +501,13 @@ static void relay_handle_input_method(struct wl_listener *listener,
282 wl_signal_add(&relay->input_method->events.destroy, 501 wl_signal_add(&relay->input_method->events.destroy,
283 &relay->input_method_destroy); 502 &relay->input_method_destroy);
284 relay->input_method_destroy.notify = handle_im_destroy; 503 relay->input_method_destroy.notify = handle_im_destroy;
504 wl_signal_add(&relay->input_method->events.new_popup_surface,
505 &relay->input_method_new_popup_surface);
506 relay->input_method_new_popup_surface.notify = handle_im_new_popup_surface;
285 507
286 struct sway_text_input *text_input = relay_get_focusable_text_input(relay); 508 struct sway_text_input *text_input = relay_get_focusable_text_input(relay);
287 if (text_input) { 509 if (text_input) {
288 wlr_text_input_v3_send_enter(text_input->input, 510 text_input_send_enter(text_input,
289 text_input->pending_focused_surface); 511 text_input->pending_focused_surface);
290 text_input_set_pending_focused_surface(text_input, NULL); 512 text_input_set_pending_focused_surface(text_input, NULL);
291 } 513 }
@@ -295,6 +517,7 @@ void sway_input_method_relay_init(struct sway_seat *seat,
295 struct sway_input_method_relay *relay) { 517 struct sway_input_method_relay *relay) {
296 relay->seat = seat; 518 relay->seat = seat;
297 wl_list_init(&relay->text_inputs); 519 wl_list_init(&relay->text_inputs);
520 wl_list_init(&relay->input_popups);
298 521
299 relay->text_input_new.notify = relay_handle_text_input; 522 relay->text_input_new.notify = relay_handle_text_input;
300 wl_signal_add(&server.text_input->events.text_input, 523 wl_signal_add(&server.text_input->events.text_input,