aboutsummaryrefslogtreecommitdiffstats
path: root/sway/input/seat.c
diff options
context:
space:
mode:
Diffstat (limited to 'sway/input/seat.c')
-rw-r--r--sway/input/seat.c508
1 files changed, 320 insertions, 188 deletions
diff --git a/sway/input/seat.c b/sway/input/seat.c
index 1f5865ee..75fea484 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -4,22 +4,25 @@
4#include <string.h> 4#include <string.h>
5#include <strings.h> 5#include <strings.h>
6#include <time.h> 6#include <time.h>
7#include <wlr/config.h>
7#include <wlr/types/wlr_cursor.h> 8#include <wlr/types/wlr_cursor.h>
8#include <wlr/types/wlr_data_device.h> 9#include <wlr/types/wlr_data_device.h>
9#include <wlr/types/wlr_idle.h> 10#include <wlr/types/wlr_idle_notify_v1.h>
10#include <wlr/types/wlr_keyboard_group.h> 11#include <wlr/types/wlr_keyboard_group.h>
11#include <wlr/types/wlr_output_layout.h> 12#include <wlr/types/wlr_output_layout.h>
12#include <wlr/types/wlr_primary_selection.h> 13#include <wlr/types/wlr_primary_selection.h>
13#include <wlr/types/wlr_tablet_v2.h> 14#include <wlr/types/wlr_tablet_v2.h>
15#include <wlr/types/wlr_touch.h>
14#include <wlr/types/wlr_xcursor_manager.h> 16#include <wlr/types/wlr_xcursor_manager.h>
15#include "config.h" 17#include "config.h"
16#include "list.h" 18#include "list.h"
17#include "log.h" 19#include "log.h"
18#include "sway/config.h" 20#include "sway/config.h"
19#include "sway/desktop.h" 21#include "sway/scene_descriptor.h"
20#include "sway/input/cursor.h" 22#include "sway/input/cursor.h"
21#include "sway/input/input-manager.h" 23#include "sway/input/input-manager.h"
22#include "sway/input/keyboard.h" 24#include "sway/input/keyboard.h"
25#include "sway/input/libinput.h"
23#include "sway/input/seat.h" 26#include "sway/input/seat.h"
24#include "sway/input/switch.h" 27#include "sway/input/switch.h"
25#include "sway/input/tablet.h" 28#include "sway/input/tablet.h"
@@ -41,6 +44,7 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) {
41 sway_keyboard_destroy(seat_device->keyboard); 44 sway_keyboard_destroy(seat_device->keyboard);
42 sway_tablet_destroy(seat_device->tablet); 45 sway_tablet_destroy(seat_device->tablet);
43 sway_tablet_pad_destroy(seat_device->tablet_pad); 46 sway_tablet_pad_destroy(seat_device->tablet_pad);
47 sway_switch_destroy(seat_device->switch_device);
44 wlr_cursor_detach_input_device(seat_device->sway_seat->cursor->cursor, 48 wlr_cursor_detach_input_device(seat_device->sway_seat->cursor->cursor,
45 seat_device->input_device->wlr_device); 49 seat_device->input_device->wlr_device);
46 wl_list_remove(&seat_device->link); 50 wl_list_remove(&seat_device->link);
@@ -50,6 +54,16 @@ static void seat_device_destroy(struct sway_seat_device *seat_device) {
50static void seat_node_destroy(struct sway_seat_node *seat_node) { 54static void seat_node_destroy(struct sway_seat_node *seat_node) {
51 wl_list_remove(&seat_node->destroy.link); 55 wl_list_remove(&seat_node->destroy.link);
52 wl_list_remove(&seat_node->link); 56 wl_list_remove(&seat_node->link);
57
58 /*
59 * This is the only time we remove items from the focus stack without
60 * immediately re-adding them. If we just removed the last thing,
61 * mark that nothing has focus anymore.
62 */
63 if (wl_list_empty(&seat_node->seat->focus_stack)) {
64 seat_node->seat->has_focus = false;
65 }
66
53 free(seat_node); 67 free(seat_node);
54} 68}
55 69
@@ -78,6 +92,7 @@ void seat_destroy(struct sway_seat *seat) {
78 for (int i = 0; i < seat->deferred_bindings->length; i++) { 92 for (int i = 0; i < seat->deferred_bindings->length; i++) {
79 free_sway_binding(seat->deferred_bindings->items[i]); 93 free_sway_binding(seat->deferred_bindings->items[i]);
80 } 94 }
95 wlr_scene_node_destroy(&seat->scene_tree->node);
81 list_free(seat->deferred_bindings); 96 list_free(seat->deferred_bindings);
82 free(seat->prev_workspace_name); 97 free(seat->prev_workspace_name);
83 free(seat); 98 free(seat);
@@ -85,21 +100,10 @@ void seat_destroy(struct sway_seat *seat) {
85 100
86void seat_idle_notify_activity(struct sway_seat *seat, 101void seat_idle_notify_activity(struct sway_seat *seat,
87 enum sway_input_idle_source source) { 102 enum sway_input_idle_source source) {
88 uint32_t mask = seat->idle_inhibit_sources; 103 if ((source & seat->idle_inhibit_sources) == 0) {
89 struct wlr_idle_timeout *timeout; 104 return;
90 int ntimers = 0, nidle = 0;
91 wl_list_for_each(timeout, &server.idle->idle_timers, link) {
92 ++ntimers;
93 if (timeout->idle_state) {
94 ++nidle;
95 }
96 }
97 if (nidle == ntimers) {
98 mask = seat->idle_wake_sources;
99 }
100 if ((source & mask) > 0) {
101 wlr_idle_notify_activity(server.idle, seat->wlr_seat);
102 } 105 }
106 wlr_idle_notifier_v1_notify_activity(server.idle_notifier_v1, seat->wlr_seat);
103} 107}
104 108
105/** 109/**
@@ -129,7 +133,7 @@ static struct sway_keyboard *sway_keyboard_for_wlr_keyboard(
129 if (input_device->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) { 133 if (input_device->wlr_device->type != WLR_INPUT_DEVICE_KEYBOARD) {
130 continue; 134 continue;
131 } 135 }
132 if (input_device->wlr_device->keyboard == wlr_keyboard) { 136 if (input_device->wlr_device == &wlr_keyboard->base) {
133 return seat_device->keyboard; 137 return seat_device->keyboard;
134 } 138 }
135 } 139 }
@@ -137,7 +141,7 @@ static struct sway_keyboard *sway_keyboard_for_wlr_keyboard(
137 wl_list_for_each(group, &seat->keyboard_groups, link) { 141 wl_list_for_each(group, &seat->keyboard_groups, link) {
138 struct sway_input_device *input_device = 142 struct sway_input_device *input_device =
139 group->seat_device->input_device; 143 group->seat_device->input_device;
140 if (input_device->wlr_device->keyboard == wlr_keyboard) { 144 if (input_device->wlr_device == &wlr_keyboard->base) {
141 return group->seat_device->keyboard; 145 return group->seat_device->keyboard;
142 } 146 }
143 } 147 }
@@ -161,11 +165,11 @@ static void seat_keyboard_notify_enter(struct sway_seat *seat,
161 state->pressed_keycodes, state->npressed, &keyboard->modifiers); 165 state->pressed_keycodes, state->npressed, &keyboard->modifiers);
162} 166}
163 167
164static void seat_tablet_pads_notify_enter(struct sway_seat *seat, 168static void seat_tablet_pads_set_focus(struct sway_seat *seat,
165 struct wlr_surface *surface) { 169 struct wlr_surface *surface) {
166 struct sway_seat_device *seat_device; 170 struct sway_seat_device *seat_device;
167 wl_list_for_each(seat_device, &seat->devices, link) { 171 wl_list_for_each(seat_device, &seat->devices, link) {
168 sway_tablet_pad_notify_enter(seat_device->tablet_pad, surface); 172 sway_tablet_pad_set_focus(seat_device->tablet_pad, surface);
169 } 173 }
170} 174}
171 175
@@ -189,7 +193,7 @@ static void seat_send_focus(struct sway_node *node, struct sway_seat *seat) {
189#endif 193#endif
190 194
191 seat_keyboard_notify_enter(seat, view->surface); 195 seat_keyboard_notify_enter(seat, view->surface);
192 seat_tablet_pads_notify_enter(seat, view->surface); 196 seat_tablet_pads_set_focus(seat, view->surface);
193 sway_input_method_relay_set_focus(&seat->im_relay, view->surface); 197 sway_input_method_relay_set_focus(&seat->im_relay, view->surface);
194 198
195 struct wlr_pointer_constraint_v1 *constraint = 199 struct wlr_pointer_constraint_v1 *constraint =
@@ -209,14 +213,13 @@ void seat_for_each_node(struct sway_seat *seat,
209 213
210struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat, 214struct sway_container *seat_get_focus_inactive_view(struct sway_seat *seat,
211 struct sway_node *ancestor) { 215 struct sway_node *ancestor) {
212 if (ancestor->type == N_CONTAINER && ancestor->sway_container->view) { 216 if (node_is_view(ancestor)) {
213 return ancestor->sway_container; 217 return ancestor->sway_container;
214 } 218 }
215 struct sway_seat_node *current; 219 struct sway_seat_node *current;
216 wl_list_for_each(current, &seat->focus_stack, link) { 220 wl_list_for_each(current, &seat->focus_stack, link) {
217 struct sway_node *node = current->node; 221 struct sway_node *node = current->node;
218 if (node->type == N_CONTAINER && node->sway_container->view && 222 if (node_is_view(node) && node_has_ancestor(node, ancestor)) {
219 node_has_ancestor(node, ancestor)) {
220 return node->sway_container; 223 return node->sway_container;
221 } 224 }
222 } 225 }
@@ -235,7 +238,7 @@ static void handle_seat_node_destroy(struct wl_listener *listener, void *data) {
235 seat_node_destroy(seat_node); 238 seat_node_destroy(seat_node);
236 // If an unmanaged or layer surface is focused when an output gets 239 // If an unmanaged or layer surface is focused when an output gets
237 // disabled and an empty workspace on the output was focused by the 240 // disabled and an empty workspace on the output was focused by the
238 // seat, the seat needs to refocus it's focus inactive to update the 241 // seat, the seat needs to refocus its focus inactive to update the
239 // value of seat->workspace. 242 // value of seat->workspace.
240 if (seat->workspace == node->sway_workspace) { 243 if (seat->workspace == node->sway_workspace) {
241 struct sway_node *node = seat_get_focus_inactive(seat, &root->node); 244 struct sway_node *node = seat_get_focus_inactive(seat, &root->node);
@@ -309,8 +312,8 @@ static void handle_seat_node_destroy(struct wl_listener *listener, void *data) {
309 // Setting focus_inactive 312 // Setting focus_inactive
310 focus = seat_get_focus_inactive(seat, &root->node); 313 focus = seat_get_focus_inactive(seat, &root->node);
311 seat_set_raw_focus(seat, next_focus); 314 seat_set_raw_focus(seat, next_focus);
312 if (focus->type == N_CONTAINER && focus->sway_container->workspace) { 315 if (focus->type == N_CONTAINER && focus->sway_container->pending.workspace) {
313 seat_set_raw_focus(seat, &focus->sway_container->workspace->node); 316 seat_set_raw_focus(seat, &focus->sway_container->pending.workspace->node);
314 } 317 }
315 seat_set_raw_focus(seat, focus); 318 seat_set_raw_focus(seat, focus);
316 } 319 }
@@ -351,25 +354,15 @@ static void handle_new_node(struct wl_listener *listener, void *data) {
351 seat_node_from_node(seat, node); 354 seat_node_from_node(seat, node);
352} 355}
353 356
354static void drag_icon_damage_whole(struct sway_drag_icon *icon) { 357static void drag_icon_update_position(struct sway_seat *seat, struct wlr_scene_node *node) {
355 if (!icon->wlr_drag_icon->mapped) { 358 struct wlr_drag_icon *wlr_icon = scene_descriptor_try_get(node, SWAY_SCENE_DESC_DRAG_ICON);
356 return;
357 }
358 desktop_damage_surface(icon->wlr_drag_icon->surface, icon->x, icon->y, true);
359}
360
361void drag_icon_update_position(struct sway_drag_icon *icon) {
362 drag_icon_damage_whole(icon);
363
364 struct wlr_drag_icon *wlr_icon = icon->wlr_drag_icon;
365 struct sway_seat *seat = icon->seat;
366 struct wlr_cursor *cursor = seat->cursor->cursor; 359 struct wlr_cursor *cursor = seat->cursor->cursor;
360
367 switch (wlr_icon->drag->grab_type) { 361 switch (wlr_icon->drag->grab_type) {
368 case WLR_DRAG_GRAB_KEYBOARD: 362 case WLR_DRAG_GRAB_KEYBOARD:
369 return; 363 return;
370 case WLR_DRAG_GRAB_KEYBOARD_POINTER: 364 case WLR_DRAG_GRAB_KEYBOARD_POINTER:
371 icon->x = cursor->x; 365 wlr_scene_node_set_position(node, cursor->x, cursor->y);
372 icon->y = cursor->y;
373 break; 366 break;
374 case WLR_DRAG_GRAB_KEYBOARD_TOUCH:; 367 case WLR_DRAG_GRAB_KEYBOARD_TOUCH:;
375 struct wlr_touch_point *point = 368 struct wlr_touch_point *point =
@@ -377,39 +370,15 @@ void drag_icon_update_position(struct sway_drag_icon *icon) {
377 if (point == NULL) { 370 if (point == NULL) {
378 return; 371 return;
379 } 372 }
380 icon->x = seat->touch_x; 373 wlr_scene_node_set_position(node, seat->touch_x, seat->touch_y);
381 icon->y = seat->touch_y;
382 } 374 }
383
384 drag_icon_damage_whole(icon);
385}
386
387static void drag_icon_handle_surface_commit(struct wl_listener *listener,
388 void *data) {
389 struct sway_drag_icon *icon =
390 wl_container_of(listener, icon, surface_commit);
391 drag_icon_update_position(icon);
392}
393
394static void drag_icon_handle_map(struct wl_listener *listener, void *data) {
395 struct sway_drag_icon *icon = wl_container_of(listener, icon, map);
396 drag_icon_damage_whole(icon);
397}
398
399static void drag_icon_handle_unmap(struct wl_listener *listener, void *data) {
400 struct sway_drag_icon *icon = wl_container_of(listener, icon, unmap);
401 drag_icon_damage_whole(icon);
402} 375}
403 376
404static void drag_icon_handle_destroy(struct wl_listener *listener, void *data) { 377void drag_icons_update_position(struct sway_seat *seat) {
405 struct sway_drag_icon *icon = wl_container_of(listener, icon, destroy); 378 struct wlr_scene_node *node;
406 icon->wlr_drag_icon->data = NULL; 379 wl_list_for_each(node, &seat->drag_icons->children, link) {
407 wl_list_remove(&icon->link); 380 drag_icon_update_position(seat, node);
408 wl_list_remove(&icon->surface_commit.link); 381 }
409 wl_list_remove(&icon->unmap.link);
410 wl_list_remove(&icon->map.link);
411 wl_list_remove(&icon->destroy.link);
412 free(icon);
413} 382}
414 383
415static void drag_handle_destroy(struct wl_listener *listener, void *data) { 384static void drag_handle_destroy(struct wl_listener *listener, void *data) {
@@ -481,27 +450,20 @@ static void handle_start_drag(struct wl_listener *listener, void *data) {
481 450
482 struct wlr_drag_icon *wlr_drag_icon = wlr_drag->icon; 451 struct wlr_drag_icon *wlr_drag_icon = wlr_drag->icon;
483 if (wlr_drag_icon != NULL) { 452 if (wlr_drag_icon != NULL) {
484 struct sway_drag_icon *icon = calloc(1, sizeof(struct sway_drag_icon)); 453 struct wlr_scene_tree *tree = wlr_scene_drag_icon_create(seat->drag_icons, wlr_drag_icon);
485 if (icon == NULL) { 454 if (!tree) {
486 sway_log(SWAY_ERROR, "Allocation failed"); 455 sway_log(SWAY_ERROR, "Failed to allocate a drag icon scene tree");
487 return; 456 return;
488 } 457 }
489 icon->seat = seat;
490 icon->wlr_drag_icon = wlr_drag_icon;
491 wlr_drag_icon->data = icon;
492
493 icon->surface_commit.notify = drag_icon_handle_surface_commit;
494 wl_signal_add(&wlr_drag_icon->surface->events.commit, &icon->surface_commit);
495 icon->unmap.notify = drag_icon_handle_unmap;
496 wl_signal_add(&wlr_drag_icon->events.unmap, &icon->unmap);
497 icon->map.notify = drag_icon_handle_map;
498 wl_signal_add(&wlr_drag_icon->events.map, &icon->map);
499 icon->destroy.notify = drag_icon_handle_destroy;
500 wl_signal_add(&wlr_drag_icon->events.destroy, &icon->destroy);
501 458
502 wl_list_insert(&root->drag_icons, &icon->link); 459 if (!scene_descriptor_assign(&tree->node, SWAY_SCENE_DESC_DRAG_ICON,
460 wlr_drag_icon)) {
461 sway_log(SWAY_ERROR, "Failed to allocate a drag icon scene descriptor");
462 wlr_scene_node_destroy(&tree->node);
463 return;
464 }
503 465
504 drag_icon_update_position(icon); 466 drag_icon_update_position(seat, &tree->node);
505 } 467 }
506 seatop_begin_default(seat); 468 seatop_begin_default(seat);
507} 469}
@@ -548,8 +510,18 @@ struct sway_seat *seat_create(const char *seat_name) {
548 return NULL; 510 return NULL;
549 } 511 }
550 512
513 bool failed = false;
514 seat->scene_tree = alloc_scene_tree(root->layers.seat, &failed);
515 seat->drag_icons = alloc_scene_tree(seat->scene_tree, &failed);
516 if (failed) {
517 wlr_scene_node_destroy(&seat->scene_tree->node);
518 free(seat);
519 return NULL;
520 }
521
551 seat->wlr_seat = wlr_seat_create(server.wl_display, seat_name); 522 seat->wlr_seat = wlr_seat_create(server.wl_display, seat_name);
552 if (!sway_assert(seat->wlr_seat, "could not allocate seat")) { 523 if (!sway_assert(seat->wlr_seat, "could not allocate seat")) {
524 wlr_scene_node_destroy(&seat->scene_tree->node);
553 free(seat); 525 free(seat);
554 return NULL; 526 return NULL;
555 } 527 }
@@ -557,6 +529,7 @@ struct sway_seat *seat_create(const char *seat_name) {
557 529
558 seat->cursor = sway_cursor_create(seat); 530 seat->cursor = sway_cursor_create(seat);
559 if (!seat->cursor) { 531 if (!seat->cursor) {
532 wlr_scene_node_destroy(&seat->scene_tree->node);
560 wlr_seat_destroy(seat->wlr_seat); 533 wlr_seat_destroy(seat->wlr_seat);
561 free(seat); 534 free(seat);
562 return NULL; 535 return NULL;
@@ -653,7 +626,7 @@ static void seat_update_capabilities(struct sway_seat *seat) {
653 } else { 626 } else {
654 wlr_seat_set_capabilities(seat->wlr_seat, caps); 627 wlr_seat_set_capabilities(seat->wlr_seat, caps);
655 if ((previous_caps & WL_SEAT_CAPABILITY_POINTER) == 0) { 628 if ((previous_caps & WL_SEAT_CAPABILITY_POINTER) == 0) {
656 cursor_set_image(seat->cursor, "left_ptr", NULL); 629 cursor_set_image(seat->cursor, "default", NULL);
657 } 630 }
658 } 631 }
659} 632}
@@ -666,12 +639,55 @@ static void seat_reset_input_config(struct sway_seat *seat,
666 sway_device->input_device->wlr_device, NULL); 639 sway_device->input_device->wlr_device, NULL);
667} 640}
668 641
669static void seat_apply_input_config(struct sway_seat *seat, 642static bool has_prefix(const char *str, const char *prefix) {
643 return strncmp(str, prefix, strlen(prefix)) == 0;
644}
645
646/**
647 * Get the name of the built-in output, if any. Returns NULL if there isn't
648 * exactly one built-in output.
649 */
650static const char *get_builtin_output_name(void) {
651 const char *match = NULL;
652 for (int i = 0; i < root->outputs->length; ++i) {
653 struct sway_output *output = root->outputs->items[i];
654 const char *name = output->wlr_output->name;
655 if (has_prefix(name, "eDP-") || has_prefix(name, "LVDS-") ||
656 has_prefix(name, "DSI-")) {
657 if (match != NULL) {
658 return NULL;
659 }
660 match = name;
661 }
662 }
663 return match;
664}
665
666static bool is_touch_or_tablet_tool(struct sway_seat_device *seat_device) {
667 switch (seat_device->input_device->wlr_device->type) {
668 case WLR_INPUT_DEVICE_TOUCH:
669 case WLR_INPUT_DEVICE_TABLET_TOOL:
670 return true;
671 default:
672 return false;
673 }
674}
675
676static void seat_apply_input_mapping(struct sway_seat *seat,
670 struct sway_seat_device *sway_device) { 677 struct sway_seat_device *sway_device) {
671 struct input_config *ic = 678 struct input_config *ic =
672 input_device_get_config(sway_device->input_device); 679 input_device_get_config(sway_device->input_device);
673 680
674 sway_log(SWAY_DEBUG, "Applying input config to %s", 681 switch (sway_device->input_device->wlr_device->type) {
682 case WLR_INPUT_DEVICE_POINTER:
683 case WLR_INPUT_DEVICE_TOUCH:
684 case WLR_INPUT_DEVICE_TABLET_TOOL:
685 break;
686 default:
687 return; // these devices don't support mappings
688 }
689
690 sway_log(SWAY_DEBUG, "Applying input mapping to %s",
675 sway_device->input_device->identifier); 691 sway_device->input_device->identifier);
676 692
677 const char *mapped_to_output = ic == NULL ? NULL : ic->mapped_to_output; 693 const char *mapped_to_output = ic == NULL ? NULL : ic->mapped_to_output;
@@ -680,8 +696,38 @@ static void seat_apply_input_config(struct sway_seat *seat,
680 ic == NULL ? MAPPED_TO_DEFAULT : ic->mapped_to; 696 ic == NULL ? MAPPED_TO_DEFAULT : ic->mapped_to;
681 697
682 switch (mapped_to) { 698 switch (mapped_to) {
683 case MAPPED_TO_DEFAULT: 699 case MAPPED_TO_DEFAULT:;
684 mapped_to_output = sway_device->input_device->wlr_device->output_name; 700 /*
701 * If the wlroots backend provides an output name, use that.
702 *
703 * Otherwise, try to map built-in touch and pointer devices to the
704 * built-in output.
705 */
706 struct wlr_input_device *dev = sway_device->input_device->wlr_device;
707 switch (dev->type) {
708 case WLR_INPUT_DEVICE_POINTER:
709 mapped_to_output = wlr_pointer_from_input_device(dev)->output_name;
710 break;
711 case WLR_INPUT_DEVICE_TOUCH:
712 mapped_to_output = wlr_touch_from_input_device(dev)->output_name;
713 break;
714 default:
715 mapped_to_output = NULL;
716 break;
717 }
718#if WLR_HAS_LIBINPUT_BACKEND
719 if (mapped_to_output == NULL && is_touch_or_tablet_tool(sway_device) &&
720 sway_libinput_device_is_builtin(sway_device->input_device)) {
721 mapped_to_output = get_builtin_output_name();
722 if (mapped_to_output) {
723 sway_log(SWAY_DEBUG, "Auto-detected output '%s' for device '%s'",
724 mapped_to_output, sway_device->input_device->identifier);
725 }
726 }
727#else
728 (void)is_touch_or_tablet_tool;
729 (void)get_builtin_output_name;
730#endif
685 if (mapped_to_output == NULL) { 731 if (mapped_to_output == NULL) {
686 return; 732 return;
687 } 733 }
@@ -725,12 +771,9 @@ static void seat_apply_input_config(struct sway_seat *seat,
725 771
726static void seat_configure_pointer(struct sway_seat *seat, 772static void seat_configure_pointer(struct sway_seat *seat,
727 struct sway_seat_device *sway_device) { 773 struct sway_seat_device *sway_device) {
728 if ((seat->wlr_seat->capabilities & WL_SEAT_CAPABILITY_POINTER) == 0) { 774 seat_configure_xcursor(seat);
729 seat_configure_xcursor(seat);
730 }
731 wlr_cursor_attach_input_device(seat->cursor->cursor, 775 wlr_cursor_attach_input_device(seat->cursor->cursor,
732 sway_device->input_device->wlr_device); 776 sway_device->input_device->wlr_device);
733 seat_apply_input_config(seat, sway_device);
734 wl_event_source_timer_update( 777 wl_event_source_timer_update(
735 seat->cursor->hide_source, cursor_get_timeout(seat->cursor)); 778 seat->cursor->hide_source, cursor_get_timeout(seat->cursor));
736} 779}
@@ -741,13 +784,22 @@ static void seat_configure_keyboard(struct sway_seat *seat,
741 sway_keyboard_create(seat, seat_device); 784 sway_keyboard_create(seat, seat_device);
742 } 785 }
743 sway_keyboard_configure(seat_device->keyboard); 786 sway_keyboard_configure(seat_device->keyboard);
744 wlr_seat_set_keyboard(seat->wlr_seat, 787
745 seat_device->input_device->wlr_device); 788 // We only need to update the current keyboard, as the rest will be updated
746 struct sway_node *focus = seat_get_focus(seat); 789 // as they are activated.
747 if (focus && node_is_view(focus)) { 790 struct wlr_keyboard *wlr_keyboard =
748 // force notify reenter to pick up the new configuration 791 wlr_keyboard_from_input_device(seat_device->input_device->wlr_device);
792 struct wlr_keyboard *current_keyboard = seat->wlr_seat->keyboard_state.keyboard;
793 if (wlr_keyboard != current_keyboard) {
794 return;
795 }
796
797 // force notify reenter to pick up the new configuration. This reuses
798 // the current focused surface to avoid breaking input grabs.
799 struct wlr_surface *surface = seat->wlr_seat->keyboard_state.focused_surface;
800 if (surface) {
749 wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat); 801 wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat);
750 seat_keyboard_notify_enter(seat, focus->sway_container->view->surface); 802 seat_keyboard_notify_enter(seat, surface);
751 } 803 }
752} 804}
753 805
@@ -756,7 +808,6 @@ static void seat_configure_switch(struct sway_seat *seat,
756 if (!seat_device->switch_device) { 808 if (!seat_device->switch_device) {
757 sway_switch_create(seat, seat_device); 809 sway_switch_create(seat, seat_device);
758 } 810 }
759 seat_apply_input_config(seat, seat_device);
760 sway_switch_configure(seat_device->switch_device); 811 sway_switch_configure(seat_device->switch_device);
761} 812}
762 813
@@ -764,7 +815,6 @@ static void seat_configure_touch(struct sway_seat *seat,
764 struct sway_seat_device *sway_device) { 815 struct sway_seat_device *sway_device) {
765 wlr_cursor_attach_input_device(seat->cursor->cursor, 816 wlr_cursor_attach_input_device(seat->cursor->cursor,
766 sway_device->input_device->wlr_device); 817 sway_device->input_device->wlr_device);
767 seat_apply_input_config(seat, sway_device);
768} 818}
769 819
770static void seat_configure_tablet_tool(struct sway_seat *seat, 820static void seat_configure_tablet_tool(struct sway_seat *seat,
@@ -775,7 +825,6 @@ static void seat_configure_tablet_tool(struct sway_seat *seat,
775 sway_configure_tablet(sway_device->tablet); 825 sway_configure_tablet(sway_device->tablet);
776 wlr_cursor_attach_input_device(seat->cursor->cursor, 826 wlr_cursor_attach_input_device(seat->cursor->cursor,
777 sway_device->input_device->wlr_device); 827 sway_device->input_device->wlr_device);
778 seat_apply_input_config(seat, sway_device);
779} 828}
780 829
781static void seat_configure_tablet_pad(struct sway_seat *seat, 830static void seat_configure_tablet_pad(struct sway_seat *seat,
@@ -832,6 +881,18 @@ void seat_configure_device(struct sway_seat *seat,
832 seat_configure_tablet_pad(seat, seat_device); 881 seat_configure_tablet_pad(seat, seat_device);
833 break; 882 break;
834 } 883 }
884
885 seat_apply_input_mapping(seat, seat_device);
886}
887
888void seat_configure_device_mapping(struct sway_seat *seat,
889 struct sway_input_device *input_device) {
890 struct sway_seat_device *seat_device = seat_get_device(seat, input_device);
891 if (!seat_device) {
892 return;
893 }
894
895 seat_apply_input_mapping(seat, seat_device);
835} 896}
836 897
837void seat_reset_device(struct sway_seat *seat, 898void seat_reset_device(struct sway_seat *seat,
@@ -948,7 +1009,7 @@ void seat_configure_xcursor(struct sway_seat *seat) {
948 1009
949 wlr_xcursor_manager_load(server.xwayland.xcursor_manager, 1); 1010 wlr_xcursor_manager_load(server.xwayland.xcursor_manager, 1);
950 struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( 1011 struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor(
951 server.xwayland.xcursor_manager, "left_ptr", 1); 1012 server.xwayland.xcursor_manager, "default", 1);
952 if (xcursor != NULL) { 1013 if (xcursor != NULL) {
953 struct wlr_xcursor_image *image = xcursor->images[0]; 1014 struct wlr_xcursor_image *image = xcursor->images[0];
954 wlr_xwayland_set_cursor( 1015 wlr_xwayland_set_cursor(
@@ -974,32 +1035,35 @@ void seat_configure_xcursor(struct sway_seat *seat) {
974 sway_log(SWAY_ERROR, 1035 sway_log(SWAY_ERROR,
975 "Cannot create XCursor manager for theme '%s'", cursor_theme); 1036 "Cannot create XCursor manager for theme '%s'", cursor_theme);
976 } 1037 }
977 }
978 1038
979 for (int i = 0; i < root->outputs->length; ++i) { 1039
980 struct sway_output *sway_output = root->outputs->items[i]; 1040 for (int i = 0; i < root->outputs->length; ++i) {
981 struct wlr_output *output = sway_output->wlr_output; 1041 struct sway_output *sway_output = root->outputs->items[i];
982 bool result = 1042 struct wlr_output *output = sway_output->wlr_output;
983 wlr_xcursor_manager_load(seat->cursor->xcursor_manager, 1043 bool result =
984 output->scale); 1044 wlr_xcursor_manager_load(seat->cursor->xcursor_manager,
985 if (!result) { 1045 output->scale);
986 sway_log(SWAY_ERROR, 1046 if (!result) {
987 "Cannot load xcursor theme for output '%s' with scale %f", 1047 sway_log(SWAY_ERROR,
988 output->name, output->scale); 1048 "Cannot load xcursor theme for output '%s' with scale %f",
1049 output->name, output->scale);
1050 }
989 } 1051 }
990 }
991 1052
992 // Reset the cursor so that we apply it to outputs that just appeared 1053 // Reset the cursor so that we apply it to outputs that just appeared
993 cursor_set_image(seat->cursor, NULL, NULL); 1054 cursor_set_image(seat->cursor, NULL, NULL);
994 cursor_set_image(seat->cursor, "left_ptr", NULL); 1055 cursor_set_image(seat->cursor, "default", NULL);
995 wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, 1056 wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x,
996 seat->cursor->cursor->y); 1057 seat->cursor->cursor->y);
1058 }
997} 1059}
998 1060
999bool seat_is_input_allowed(struct sway_seat *seat, 1061bool seat_is_input_allowed(struct sway_seat *seat,
1000 struct wlr_surface *surface) { 1062 struct wlr_surface *surface) {
1001 struct wl_client *client = wl_resource_get_client(surface->resource); 1063 if (server.session_lock.lock) {
1002 return !seat->exclusive_client || seat->exclusive_client == client; 1064 return sway_session_lock_has_surface(server.session_lock.lock, surface);
1065 }
1066 return true;
1003} 1067}
1004 1068
1005static void send_unfocus(struct sway_container *con, void *data) { 1069static void send_unfocus(struct sway_container *con, void *data) {
@@ -1058,15 +1122,7 @@ void seat_set_raw_focus(struct sway_seat *seat, struct sway_node *node) {
1058 } 1122 }
1059} 1123}
1060 1124
1061void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { 1125static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *node) {
1062 if (seat->focused_layer) {
1063 struct wlr_layer_surface_v1 *layer = seat->focused_layer;
1064 seat_set_focus_layer(seat, NULL);
1065 seat_set_focus(seat, node);
1066 seat_set_focus_layer(seat, layer);
1067 return;
1068 }
1069
1070 struct sway_node *last_focus = seat_get_focus(seat); 1126 struct sway_node *last_focus = seat_get_focus(seat);
1071 if (last_focus == node) { 1127 if (last_focus == node) {
1072 return; 1128 return;
@@ -1086,30 +1142,19 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) {
1086 } 1142 }
1087 1143
1088 struct sway_workspace *new_workspace = node->type == N_WORKSPACE ? 1144 struct sway_workspace *new_workspace = node->type == N_WORKSPACE ?
1089 node->sway_workspace : node->sway_container->workspace; 1145 node->sway_workspace : node->sway_container->pending.workspace;
1090 struct sway_container *container = node->type == N_CONTAINER ? 1146 struct sway_container *container = node->type == N_CONTAINER ?
1091 node->sway_container : NULL; 1147 node->sway_container : NULL;
1092 1148
1093 // Deny setting focus to a view which is hidden by a fullscreen container 1149 // Deny setting focus to a view which is hidden by a fullscreen container or global
1094 if (new_workspace && new_workspace->fullscreen && container && 1150 if (container && container_obstructing_fullscreen_container(container)) {
1095 !container_is_fullscreen_or_child(container)) { 1151 return;
1096 // Unless it's a transient container
1097 if (!container_is_transient_for(container, new_workspace->fullscreen)) {
1098 return;
1099 }
1100 } 1152 }
1153
1101 // Deny setting focus to a workspace node when using fullscreen global 1154 // Deny setting focus to a workspace node when using fullscreen global
1102 if (root->fullscreen_global && !container && new_workspace) { 1155 if (root->fullscreen_global && !container && new_workspace) {
1103 return; 1156 return;
1104 } 1157 }
1105 // Deny setting focus to a view which is hidden by a fullscreen global
1106 if (root->fullscreen_global && container != root->fullscreen_global &&
1107 !container_has_ancestor(container, root->fullscreen_global)) {
1108 // Unless it's a transient container
1109 if (!container_is_transient_for(container, root->fullscreen_global)) {
1110 return;
1111 }
1112 }
1113 1158
1114 struct sway_output *new_output = 1159 struct sway_output *new_output =
1115 new_workspace ? new_workspace->output : NULL; 1160 new_workspace ? new_workspace->output : NULL;
@@ -1135,10 +1180,10 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) {
1135 // Put the container parents on the focus stack, then the workspace, then 1180 // Put the container parents on the focus stack, then the workspace, then
1136 // the focused container. 1181 // the focused container.
1137 if (container) { 1182 if (container) {
1138 struct sway_container *parent = container->parent; 1183 struct sway_container *parent = container->pending.parent;
1139 while (parent) { 1184 while (parent) {
1140 seat_set_raw_focus(seat, &parent->node); 1185 seat_set_raw_focus(seat, &parent->node);
1141 parent = parent->parent; 1186 parent = parent->pending.parent;
1142 } 1187 }
1143 } 1188 }
1144 if (new_workspace) { 1189 if (new_workspace) {
@@ -1210,6 +1255,24 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) {
1210 } 1255 }
1211} 1256}
1212 1257
1258void seat_set_focus(struct sway_seat *seat, struct sway_node *node) {
1259 // Prevents the layer from losing focus if it has keyboard exclusivity
1260 if (seat->has_exclusive_layer) {
1261 struct wlr_layer_surface_v1 *layer = seat->focused_layer;
1262 seat_set_focus_layer(seat, NULL);
1263 seat_set_workspace_focus(seat, node);
1264 seat_set_focus_layer(seat, layer);
1265 } else if (seat->focused_layer) {
1266 seat_set_focus_layer(seat, NULL);
1267 seat_set_workspace_focus(seat, node);
1268 } else {
1269 seat_set_workspace_focus(seat, node);
1270 }
1271 if (server.session_lock.lock) {
1272 seat_set_focus_surface(seat, server.session_lock.lock->focused, false);
1273 }
1274}
1275
1213void seat_set_focus_container(struct sway_seat *seat, 1276void seat_set_focus_container(struct sway_seat *seat,
1214 struct sway_container *con) { 1277 struct sway_container *con) {
1215 seat_set_focus(seat, con ? &con->node : NULL); 1278 seat_set_focus(seat, con ? &con->node : NULL);
@@ -1234,7 +1297,8 @@ void seat_set_focus_surface(struct sway_seat *seat,
1234 wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat); 1297 wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat);
1235 } 1298 }
1236 1299
1237 seat_tablet_pads_notify_enter(seat, surface); 1300 sway_input_method_relay_set_focus(&seat->im_relay, surface);
1301 seat_tablet_pads_set_focus(seat, surface);
1238} 1302}
1239 1303
1240void seat_set_focus_layer(struct sway_seat *seat, 1304void seat_set_focus_layer(struct sway_seat *seat,
@@ -1248,28 +1312,23 @@ void seat_set_focus_layer(struct sway_seat *seat,
1248 seat_set_focus(seat, previous); 1312 seat_set_focus(seat, previous);
1249 } 1313 }
1250 return; 1314 return;
1251 } else if (!layer || seat->focused_layer == layer) { 1315 } else if (!layer) {
1252 return; 1316 return;
1253 } 1317 }
1254 assert(layer->mapped); 1318 assert(layer->surface->mapped);
1255 seat_set_focus_surface(seat, layer->surface, true); 1319 if (layer->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP &&
1256 if (layer->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { 1320 layer->current.keyboard_interactive
1257 seat->focused_layer = layer; 1321 == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) {
1322 seat->has_exclusive_layer = true;
1258 } 1323 }
1259} 1324 if (seat->focused_layer == layer) {
1260
1261void seat_set_exclusive_client(struct sway_seat *seat,
1262 struct wl_client *client) {
1263 if (!client) {
1264 seat->exclusive_client = client;
1265 // Triggers a refocus of the topmost surface layer if necessary
1266 // TODO: Make layer surface focus per-output based on cursor position
1267 for (int i = 0; i < root->outputs->length; ++i) {
1268 struct sway_output *output = root->outputs->items[i];
1269 arrange_layers(output);
1270 }
1271 return; 1325 return;
1272 } 1326 }
1327 seat_set_focus_surface(seat, layer->surface, true);
1328 seat->focused_layer = layer;
1329}
1330
1331void seat_unfocus_unless_client(struct sway_seat *seat, struct wl_client *client) {
1273 if (seat->focused_layer) { 1332 if (seat->focused_layer) {
1274 if (wl_resource_get_client(seat->focused_layer->resource) != client) { 1333 if (wl_resource_get_client(seat->focused_layer->resource) != client) {
1275 seat_set_focus_layer(seat, NULL); 1334 seat_set_focus_layer(seat, NULL);
@@ -1296,7 +1355,6 @@ void seat_set_exclusive_client(struct sway_seat *seat,
1296 now.tv_nsec / 1000, point->touch_id); 1355 now.tv_nsec / 1000, point->touch_id);
1297 } 1356 }
1298 } 1357 }
1299 seat->exclusive_client = client;
1300} 1358}
1301 1359
1302struct sway_node *seat_get_focus_inactive(struct sway_seat *seat, 1360struct sway_node *seat_get_focus_inactive(struct sway_seat *seat,
@@ -1326,7 +1384,7 @@ struct sway_container *seat_get_focus_inactive_tiling(struct sway_seat *seat,
1326 struct sway_node *node = current->node; 1384 struct sway_node *node = current->node;
1327 if (node->type == N_CONTAINER && 1385 if (node->type == N_CONTAINER &&
1328 !container_is_floating_or_child(node->sway_container) && 1386 !container_is_floating_or_child(node->sway_container) &&
1329 node->sway_container->workspace == workspace) { 1387 node->sway_container->pending.workspace == workspace) {
1330 return node->sway_container; 1388 return node->sway_container;
1331 } 1389 }
1332 } 1390 }
@@ -1343,7 +1401,7 @@ struct sway_container *seat_get_focus_inactive_floating(struct sway_seat *seat,
1343 struct sway_node *node = current->node; 1401 struct sway_node *node = current->node;
1344 if (node->type == N_CONTAINER && 1402 if (node->type == N_CONTAINER &&
1345 container_is_floating_or_child(node->sway_container) && 1403 container_is_floating_or_child(node->sway_container) &&
1346 node->sway_container->workspace == workspace) { 1404 node->sway_container->pending.workspace == workspace) {
1347 return node->sway_container; 1405 return node->sway_container;
1348 } 1406 }
1349 } 1407 }
@@ -1377,9 +1435,8 @@ struct sway_node *seat_get_focus(struct sway_seat *seat) {
1377 if (!seat->has_focus) { 1435 if (!seat->has_focus) {
1378 return NULL; 1436 return NULL;
1379 } 1437 }
1380 if (wl_list_empty(&seat->focus_stack)) { 1438 sway_assert(!wl_list_empty(&seat->focus_stack),
1381 return NULL; 1439 "focus_stack is empty, but has_focus is true");
1382 }
1383 struct sway_seat_node *current = 1440 struct sway_seat_node *current =
1384 wl_container_of(seat->focus_stack.next, current, link); 1441 wl_container_of(seat->focus_stack.next, current, link);
1385 return current->node; 1442 return current->node;
@@ -1391,7 +1448,7 @@ struct sway_workspace *seat_get_focused_workspace(struct sway_seat *seat) {
1391 return NULL; 1448 return NULL;
1392 } 1449 }
1393 if (focus->type == N_CONTAINER) { 1450 if (focus->type == N_CONTAINER) {
1394 return focus->sway_container->workspace; 1451 return focus->sway_container->pending.workspace;
1395 } 1452 }
1396 if (focus->type == N_WORKSPACE) { 1453 if (focus->type == N_WORKSPACE) {
1397 return focus->sway_workspace; 1454 return focus->sway_workspace;
@@ -1404,8 +1461,8 @@ struct sway_workspace *seat_get_last_known_workspace(struct sway_seat *seat) {
1404 wl_list_for_each(current, &seat->focus_stack, link) { 1461 wl_list_for_each(current, &seat->focus_stack, link) {
1405 struct sway_node *node = current->node; 1462 struct sway_node *node = current->node;
1406 if (node->type == N_CONTAINER && 1463 if (node->type == N_CONTAINER &&
1407 node->sway_container->workspace) { 1464 node->sway_container->pending.workspace) {
1408 return node->sway_container->workspace; 1465 return node->sway_container->pending.workspace;
1409 } else if (node->type == N_WORKSPACE) { 1466 } else if (node->type == N_WORKSPACE) {
1410 return node->sway_workspace; 1467 return node->sway_workspace;
1411 } 1468 }
@@ -1514,12 +1571,38 @@ void seatop_pointer_motion(struct sway_seat *seat, uint32_t time_msec) {
1514} 1571}
1515 1572
1516void seatop_pointer_axis(struct sway_seat *seat, 1573void seatop_pointer_axis(struct sway_seat *seat,
1517 struct wlr_event_pointer_axis *event) { 1574 struct wlr_pointer_axis_event *event) {
1518 if (seat->seatop_impl->pointer_axis) { 1575 if (seat->seatop_impl->pointer_axis) {
1519 seat->seatop_impl->pointer_axis(seat, event); 1576 seat->seatop_impl->pointer_axis(seat, event);
1520 } 1577 }
1521} 1578}
1522 1579
1580void seatop_touch_motion(struct sway_seat *seat, struct wlr_touch_motion_event *event,
1581 double lx, double ly) {
1582 if (seat->seatop_impl->touch_motion) {
1583 seat->seatop_impl->touch_motion(seat, event, lx, ly);
1584 }
1585}
1586
1587void seatop_touch_up(struct sway_seat *seat, struct wlr_touch_up_event *event) {
1588 if (seat->seatop_impl->touch_up) {
1589 seat->seatop_impl->touch_up(seat, event);
1590 }
1591}
1592
1593void seatop_touch_down(struct sway_seat *seat, struct wlr_touch_down_event *event,
1594 double lx, double ly) {
1595 if (seat->seatop_impl->touch_down) {
1596 seat->seatop_impl->touch_down(seat, event, lx, ly);
1597 }
1598}
1599
1600void seatop_touch_cancel(struct sway_seat *seat, struct wlr_touch_cancel_event *event) {
1601 if (seat->seatop_impl->touch_cancel) {
1602 seat->seatop_impl->touch_cancel(seat, event);
1603 }
1604}
1605
1523void seatop_tablet_tool_tip(struct sway_seat *seat, 1606void seatop_tablet_tool_tip(struct sway_seat *seat,
1524 struct sway_tablet_tool *tool, uint32_t time_msec, 1607 struct sway_tablet_tool *tool, uint32_t time_msec,
1525 enum wlr_tablet_tool_tip_state state) { 1608 enum wlr_tablet_tool_tip_state state) {
@@ -1537,6 +1620,62 @@ void seatop_tablet_tool_motion(struct sway_seat *seat,
1537 } 1620 }
1538} 1621}
1539 1622
1623void seatop_hold_begin(struct sway_seat *seat,
1624 struct wlr_pointer_hold_begin_event *event) {
1625 if (seat->seatop_impl->hold_begin) {
1626 seat->seatop_impl->hold_begin(seat, event);
1627 }
1628}
1629
1630void seatop_hold_end(struct sway_seat *seat,
1631 struct wlr_pointer_hold_end_event *event) {
1632 if (seat->seatop_impl->hold_end) {
1633 seat->seatop_impl->hold_end(seat, event);
1634 }
1635}
1636
1637void seatop_pinch_begin(struct sway_seat *seat,
1638 struct wlr_pointer_pinch_begin_event *event) {
1639 if (seat->seatop_impl->pinch_begin) {
1640 seat->seatop_impl->pinch_begin(seat, event);
1641 }
1642}
1643
1644void seatop_pinch_update(struct sway_seat *seat,
1645 struct wlr_pointer_pinch_update_event *event) {
1646 if (seat->seatop_impl->pinch_update) {
1647 seat->seatop_impl->pinch_update(seat, event);
1648 }
1649}
1650
1651void seatop_pinch_end(struct sway_seat *seat,
1652 struct wlr_pointer_pinch_end_event *event) {
1653 if (seat->seatop_impl->pinch_end) {
1654 seat->seatop_impl->pinch_end(seat, event);
1655 }
1656}
1657
1658void seatop_swipe_begin(struct sway_seat *seat,
1659 struct wlr_pointer_swipe_begin_event *event) {
1660 if (seat->seatop_impl->swipe_begin) {
1661 seat->seatop_impl->swipe_begin(seat, event);
1662 }
1663}
1664
1665void seatop_swipe_update(struct sway_seat *seat,
1666 struct wlr_pointer_swipe_update_event *event) {
1667 if (seat->seatop_impl->swipe_update) {
1668 seat->seatop_impl->swipe_update(seat, event);
1669 }
1670}
1671
1672void seatop_swipe_end(struct sway_seat *seat,
1673 struct wlr_pointer_swipe_end_event *event) {
1674 if (seat->seatop_impl->swipe_end) {
1675 seat->seatop_impl->swipe_end(seat, event);
1676 }
1677}
1678
1540void seatop_rebase(struct sway_seat *seat, uint32_t time_msec) { 1679void seatop_rebase(struct sway_seat *seat, uint32_t time_msec) {
1541 if (seat->seatop_impl->rebase) { 1680 if (seat->seatop_impl->rebase) {
1542 seat->seatop_impl->rebase(seat, time_msec); 1681 seat->seatop_impl->rebase(seat, time_msec);
@@ -1552,13 +1691,6 @@ void seatop_end(struct sway_seat *seat) {
1552 seat->seatop_impl = NULL; 1691 seat->seatop_impl = NULL;
1553} 1692}
1554 1693
1555void seatop_render(struct sway_seat *seat, struct sway_output *output,
1556 pixman_region32_t *damage) {
1557 if (seat->seatop_impl->render) {
1558 seat->seatop_impl->render(seat, output, damage);
1559 }
1560}
1561
1562bool seatop_allows_set_cursor(struct sway_seat *seat) { 1694bool seatop_allows_set_cursor(struct sway_seat *seat) {
1563 return seat->seatop_impl->allow_set_cursor; 1695 return seat->seatop_impl->allow_set_cursor;
1564} 1696}