diff options
Diffstat (limited to 'sway/input/seat.c')
-rw-r--r-- | sway/input/seat.c | 347 |
1 files changed, 177 insertions, 170 deletions
diff --git a/sway/input/seat.c b/sway/input/seat.c index b21e1b86..0c5672bc 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -1,12 +1,12 @@ | |||
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> |
@@ -17,7 +17,7 @@ | |||
17 | #include "list.h" | 17 | #include "list.h" |
18 | #include "log.h" | 18 | #include "log.h" |
19 | #include "sway/config.h" | 19 | #include "sway/config.h" |
20 | #include "sway/desktop.h" | 20 | #include "sway/scene_descriptor.h" |
21 | #include "sway/input/cursor.h" | 21 | #include "sway/input/cursor.h" |
22 | #include "sway/input/input-manager.h" | 22 | #include "sway/input/input-manager.h" |
23 | #include "sway/input/keyboard.h" | 23 | #include "sway/input/keyboard.h" |
@@ -67,6 +67,12 @@ static void seat_node_destroy(struct sway_seat_node *seat_node) { | |||
67 | } | 67 | } |
68 | 68 | ||
69 | void seat_destroy(struct sway_seat *seat) { | 69 | void seat_destroy(struct sway_seat *seat) { |
70 | wlr_seat_destroy(seat->wlr_seat); | ||
71 | } | ||
72 | |||
73 | static void handle_seat_destroy(struct wl_listener *listener, void *data) { | ||
74 | struct sway_seat *seat = wl_container_of(listener, seat, destroy); | ||
75 | |||
70 | if (seat == config->handler_context.seat) { | 76 | if (seat == config->handler_context.seat) { |
71 | config->handler_context.seat = input_manager_get_default_seat(); | 77 | config->handler_context.seat = input_manager_get_default_seat(); |
72 | } | 78 | } |
@@ -87,10 +93,11 @@ void seat_destroy(struct sway_seat *seat) { | |||
87 | wl_list_remove(&seat->request_set_selection.link); | 93 | wl_list_remove(&seat->request_set_selection.link); |
88 | wl_list_remove(&seat->request_set_primary_selection.link); | 94 | wl_list_remove(&seat->request_set_primary_selection.link); |
89 | wl_list_remove(&seat->link); | 95 | wl_list_remove(&seat->link); |
90 | wlr_seat_destroy(seat->wlr_seat); | 96 | wl_list_remove(&seat->destroy.link); |
91 | for (int i = 0; i < seat->deferred_bindings->length; i++) { | 97 | for (int i = 0; i < seat->deferred_bindings->length; i++) { |
92 | free_sway_binding(seat->deferred_bindings->items[i]); | 98 | free_sway_binding(seat->deferred_bindings->items[i]); |
93 | } | 99 | } |
100 | wlr_scene_node_destroy(&seat->scene_tree->node); | ||
94 | list_free(seat->deferred_bindings); | 101 | list_free(seat->deferred_bindings); |
95 | free(seat->prev_workspace_name); | 102 | free(seat->prev_workspace_name); |
96 | free(seat); | 103 | free(seat); |
@@ -98,21 +105,10 @@ void seat_destroy(struct sway_seat *seat) { | |||
98 | 105 | ||
99 | void seat_idle_notify_activity(struct sway_seat *seat, | 106 | void seat_idle_notify_activity(struct sway_seat *seat, |
100 | enum sway_input_idle_source source) { | 107 | enum sway_input_idle_source source) { |
101 | uint32_t mask = seat->idle_inhibit_sources; | 108 | if ((source & seat->idle_inhibit_sources) == 0) { |
102 | struct wlr_idle_timeout *timeout; | 109 | return; |
103 | int ntimers = 0, nidle = 0; | ||
104 | wl_list_for_each(timeout, &server.idle->idle_timers, link) { | ||
105 | ++ntimers; | ||
106 | if (timeout->idle_state) { | ||
107 | ++nidle; | ||
108 | } | ||
109 | } | ||
110 | if (nidle == ntimers) { | ||
111 | mask = seat->idle_wake_sources; | ||
112 | } | ||
113 | if ((source & mask) > 0) { | ||
114 | wlr_idle_notify_activity(server.idle, seat->wlr_seat); | ||
115 | } | 110 | } |
111 | wlr_idle_notifier_v1_notify_activity(server.idle_notifier_v1, seat->wlr_seat); | ||
116 | } | 112 | } |
117 | 113 | ||
118 | /** | 114 | /** |
@@ -174,11 +170,11 @@ static void seat_keyboard_notify_enter(struct sway_seat *seat, | |||
174 | state->pressed_keycodes, state->npressed, &keyboard->modifiers); | 170 | state->pressed_keycodes, state->npressed, &keyboard->modifiers); |
175 | } | 171 | } |
176 | 172 | ||
177 | static void seat_tablet_pads_notify_enter(struct sway_seat *seat, | 173 | static void seat_tablet_pads_set_focus(struct sway_seat *seat, |
178 | struct wlr_surface *surface) { | 174 | struct wlr_surface *surface) { |
179 | struct sway_seat_device *seat_device; | 175 | struct sway_seat_device *seat_device; |
180 | wl_list_for_each(seat_device, &seat->devices, link) { | 176 | wl_list_for_each(seat_device, &seat->devices, link) { |
181 | sway_tablet_pad_notify_enter(seat_device->tablet_pad, surface); | 177 | sway_tablet_pad_set_focus(seat_device->tablet_pad, surface); |
182 | } | 178 | } |
183 | } | 179 | } |
184 | 180 | ||
@@ -202,7 +198,7 @@ static void seat_send_focus(struct sway_node *node, struct sway_seat *seat) { | |||
202 | #endif | 198 | #endif |
203 | 199 | ||
204 | seat_keyboard_notify_enter(seat, view->surface); | 200 | seat_keyboard_notify_enter(seat, view->surface); |
205 | seat_tablet_pads_notify_enter(seat, view->surface); | 201 | seat_tablet_pads_set_focus(seat, view->surface); |
206 | sway_input_method_relay_set_focus(&seat->im_relay, view->surface); | 202 | sway_input_method_relay_set_focus(&seat->im_relay, view->surface); |
207 | 203 | ||
208 | struct wlr_pointer_constraint_v1 *constraint = | 204 | struct wlr_pointer_constraint_v1 *constraint = |
@@ -212,15 +208,6 @@ static void seat_send_focus(struct sway_node *node, struct sway_seat *seat) { | |||
212 | } | 208 | } |
213 | } | 209 | } |
214 | 210 | ||
215 | void sway_force_focus(struct wlr_surface *surface) { | ||
216 | struct sway_seat *seat; | ||
217 | wl_list_for_each(seat, &server.input->seats, link) { | ||
218 | seat_keyboard_notify_enter(seat, surface); | ||
219 | seat_tablet_pads_notify_enter(seat, surface); | ||
220 | sway_input_method_relay_set_focus(&seat->im_relay, surface); | ||
221 | } | ||
222 | } | ||
223 | |||
224 | void seat_for_each_node(struct sway_seat *seat, | 211 | void seat_for_each_node(struct sway_seat *seat, |
225 | void (*f)(struct sway_node *node, void *data), void *data) { | 212 | void (*f)(struct sway_node *node, void *data), void *data) { |
226 | struct sway_seat_node *current = NULL; | 213 | struct sway_seat_node *current = NULL; |
@@ -372,25 +359,15 @@ static void handle_new_node(struct wl_listener *listener, void *data) { | |||
372 | seat_node_from_node(seat, node); | 359 | seat_node_from_node(seat, node); |
373 | } | 360 | } |
374 | 361 | ||
375 | static void drag_icon_damage_whole(struct sway_drag_icon *icon) { | 362 | static void drag_icon_update_position(struct sway_seat *seat, struct wlr_scene_node *node) { |
376 | if (!icon->wlr_drag_icon->mapped) { | 363 | struct wlr_drag_icon *wlr_icon = scene_descriptor_try_get(node, SWAY_SCENE_DESC_DRAG_ICON); |
377 | return; | ||
378 | } | ||
379 | desktop_damage_surface(icon->wlr_drag_icon->surface, icon->x, icon->y, true); | ||
380 | } | ||
381 | |||
382 | void drag_icon_update_position(struct sway_drag_icon *icon) { | ||
383 | drag_icon_damage_whole(icon); | ||
384 | |||
385 | struct wlr_drag_icon *wlr_icon = icon->wlr_drag_icon; | ||
386 | struct sway_seat *seat = icon->seat; | ||
387 | struct wlr_cursor *cursor = seat->cursor->cursor; | 364 | struct wlr_cursor *cursor = seat->cursor->cursor; |
365 | |||
388 | switch (wlr_icon->drag->grab_type) { | 366 | switch (wlr_icon->drag->grab_type) { |
389 | case WLR_DRAG_GRAB_KEYBOARD: | 367 | case WLR_DRAG_GRAB_KEYBOARD: |
390 | return; | 368 | return; |
391 | case WLR_DRAG_GRAB_KEYBOARD_POINTER: | 369 | case WLR_DRAG_GRAB_KEYBOARD_POINTER: |
392 | icon->x = cursor->x + wlr_icon->surface->sx; | 370 | wlr_scene_node_set_position(node, cursor->x, cursor->y); |
393 | icon->y = cursor->y + wlr_icon->surface->sy; | ||
394 | break; | 371 | break; |
395 | case WLR_DRAG_GRAB_KEYBOARD_TOUCH:; | 372 | case WLR_DRAG_GRAB_KEYBOARD_TOUCH:; |
396 | struct wlr_touch_point *point = | 373 | struct wlr_touch_point *point = |
@@ -398,39 +375,15 @@ void drag_icon_update_position(struct sway_drag_icon *icon) { | |||
398 | if (point == NULL) { | 375 | if (point == NULL) { |
399 | return; | 376 | return; |
400 | } | 377 | } |
401 | icon->x = seat->touch_x + wlr_icon->surface->sx; | 378 | wlr_scene_node_set_position(node, seat->touch_x, seat->touch_y); |
402 | icon->y = seat->touch_y + wlr_icon->surface->sy; | ||
403 | } | 379 | } |
404 | |||
405 | drag_icon_damage_whole(icon); | ||
406 | } | ||
407 | |||
408 | static void drag_icon_handle_surface_commit(struct wl_listener *listener, | ||
409 | void *data) { | ||
410 | struct sway_drag_icon *icon = | ||
411 | wl_container_of(listener, icon, surface_commit); | ||
412 | drag_icon_update_position(icon); | ||
413 | } | ||
414 | |||
415 | static void drag_icon_handle_map(struct wl_listener *listener, void *data) { | ||
416 | struct sway_drag_icon *icon = wl_container_of(listener, icon, map); | ||
417 | drag_icon_damage_whole(icon); | ||
418 | } | 380 | } |
419 | 381 | ||
420 | static void drag_icon_handle_unmap(struct wl_listener *listener, void *data) { | 382 | void drag_icons_update_position(struct sway_seat *seat) { |
421 | struct sway_drag_icon *icon = wl_container_of(listener, icon, unmap); | 383 | struct wlr_scene_node *node; |
422 | drag_icon_damage_whole(icon); | 384 | wl_list_for_each(node, &seat->drag_icons->children, link) { |
423 | } | 385 | drag_icon_update_position(seat, node); |
424 | 386 | } | |
425 | static void drag_icon_handle_destroy(struct wl_listener *listener, void *data) { | ||
426 | struct sway_drag_icon *icon = wl_container_of(listener, icon, destroy); | ||
427 | icon->wlr_drag_icon->data = NULL; | ||
428 | wl_list_remove(&icon->link); | ||
429 | wl_list_remove(&icon->surface_commit.link); | ||
430 | wl_list_remove(&icon->unmap.link); | ||
431 | wl_list_remove(&icon->map.link); | ||
432 | wl_list_remove(&icon->destroy.link); | ||
433 | free(icon); | ||
434 | } | 387 | } |
435 | 388 | ||
436 | static void drag_handle_destroy(struct wl_listener *listener, void *data) { | 389 | static void drag_handle_destroy(struct wl_listener *listener, void *data) { |
@@ -502,27 +455,20 @@ static void handle_start_drag(struct wl_listener *listener, void *data) { | |||
502 | 455 | ||
503 | struct wlr_drag_icon *wlr_drag_icon = wlr_drag->icon; | 456 | struct wlr_drag_icon *wlr_drag_icon = wlr_drag->icon; |
504 | if (wlr_drag_icon != NULL) { | 457 | if (wlr_drag_icon != NULL) { |
505 | 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); |
506 | if (icon == NULL) { | 459 | if (!tree) { |
507 | sway_log(SWAY_ERROR, "Allocation failed"); | 460 | sway_log(SWAY_ERROR, "Failed to allocate a drag icon scene tree"); |
508 | return; | 461 | return; |
509 | } | 462 | } |
510 | icon->seat = seat; | ||
511 | icon->wlr_drag_icon = wlr_drag_icon; | ||
512 | wlr_drag_icon->data = icon; | ||
513 | 463 | ||
514 | icon->surface_commit.notify = drag_icon_handle_surface_commit; | 464 | if (!scene_descriptor_assign(&tree->node, SWAY_SCENE_DESC_DRAG_ICON, |
515 | wl_signal_add(&wlr_drag_icon->surface->events.commit, &icon->surface_commit); | 465 | wlr_drag_icon)) { |
516 | icon->unmap.notify = drag_icon_handle_unmap; | 466 | sway_log(SWAY_ERROR, "Failed to allocate a drag icon scene descriptor"); |
517 | wl_signal_add(&wlr_drag_icon->events.unmap, &icon->unmap); | 467 | wlr_scene_node_destroy(&tree->node); |
518 | icon->map.notify = drag_icon_handle_map; | 468 | return; |
519 | wl_signal_add(&wlr_drag_icon->events.map, &icon->map); | 469 | } |
520 | icon->destroy.notify = drag_icon_handle_destroy; | ||
521 | wl_signal_add(&wlr_drag_icon->events.destroy, &icon->destroy); | ||
522 | |||
523 | wl_list_insert(&root->drag_icons, &icon->link); | ||
524 | 470 | ||
525 | drag_icon_update_position(icon); | 471 | drag_icon_update_position(seat, &tree->node); |
526 | } | 472 | } |
527 | seatop_begin_default(seat); | 473 | seatop_begin_default(seat); |
528 | } | 474 | } |
@@ -569,8 +515,18 @@ struct sway_seat *seat_create(const char *seat_name) { | |||
569 | return NULL; | 515 | return NULL; |
570 | } | 516 | } |
571 | 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 | |||
572 | seat->wlr_seat = wlr_seat_create(server.wl_display, seat_name); | 527 | seat->wlr_seat = wlr_seat_create(server.wl_display, seat_name); |
573 | 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); | ||
574 | free(seat); | 530 | free(seat); |
575 | return NULL; | 531 | return NULL; |
576 | } | 532 | } |
@@ -578,11 +534,15 @@ struct sway_seat *seat_create(const char *seat_name) { | |||
578 | 534 | ||
579 | seat->cursor = sway_cursor_create(seat); | 535 | seat->cursor = sway_cursor_create(seat); |
580 | if (!seat->cursor) { | 536 | if (!seat->cursor) { |
537 | wlr_scene_node_destroy(&seat->scene_tree->node); | ||
581 | wlr_seat_destroy(seat->wlr_seat); | 538 | wlr_seat_destroy(seat->wlr_seat); |
582 | free(seat); | 539 | free(seat); |
583 | return NULL; | 540 | return NULL; |
584 | } | 541 | } |
585 | 542 | ||
543 | seat->destroy.notify = handle_seat_destroy; | ||
544 | wl_signal_add(&seat->wlr_seat->events.destroy, &seat->destroy); | ||
545 | |||
586 | seat->idle_inhibit_sources = seat->idle_wake_sources = | 546 | seat->idle_inhibit_sources = seat->idle_wake_sources = |
587 | IDLE_SOURCE_KEYBOARD | | 547 | IDLE_SOURCE_KEYBOARD | |
588 | IDLE_SOURCE_POINTER | | 548 | IDLE_SOURCE_POINTER | |
@@ -656,7 +616,7 @@ static void seat_update_capabilities(struct sway_seat *seat) { | |||
656 | case WLR_INPUT_DEVICE_TOUCH: | 616 | case WLR_INPUT_DEVICE_TOUCH: |
657 | caps |= WL_SEAT_CAPABILITY_TOUCH; | 617 | caps |= WL_SEAT_CAPABILITY_TOUCH; |
658 | break; | 618 | break; |
659 | case WLR_INPUT_DEVICE_TABLET_TOOL: | 619 | case WLR_INPUT_DEVICE_TABLET: |
660 | caps |= WL_SEAT_CAPABILITY_POINTER; | 620 | caps |= WL_SEAT_CAPABILITY_POINTER; |
661 | break; | 621 | break; |
662 | case WLR_INPUT_DEVICE_SWITCH: | 622 | case WLR_INPUT_DEVICE_SWITCH: |
@@ -674,7 +634,7 @@ static void seat_update_capabilities(struct sway_seat *seat) { | |||
674 | } else { | 634 | } else { |
675 | wlr_seat_set_capabilities(seat->wlr_seat, caps); | 635 | wlr_seat_set_capabilities(seat->wlr_seat, caps); |
676 | if ((previous_caps & WL_SEAT_CAPABILITY_POINTER) == 0) { | 636 | if ((previous_caps & WL_SEAT_CAPABILITY_POINTER) == 0) { |
677 | cursor_set_image(seat->cursor, "left_ptr", NULL); | 637 | cursor_set_image(seat->cursor, "default", NULL); |
678 | } | 638 | } |
679 | } | 639 | } |
680 | } | 640 | } |
@@ -714,19 +674,28 @@ static const char *get_builtin_output_name(void) { | |||
714 | static bool is_touch_or_tablet_tool(struct sway_seat_device *seat_device) { | 674 | static bool is_touch_or_tablet_tool(struct sway_seat_device *seat_device) { |
715 | switch (seat_device->input_device->wlr_device->type) { | 675 | switch (seat_device->input_device->wlr_device->type) { |
716 | case WLR_INPUT_DEVICE_TOUCH: | 676 | case WLR_INPUT_DEVICE_TOUCH: |
717 | case WLR_INPUT_DEVICE_TABLET_TOOL: | 677 | case WLR_INPUT_DEVICE_TABLET: |
718 | return true; | 678 | return true; |
719 | default: | 679 | default: |
720 | return false; | 680 | return false; |
721 | } | 681 | } |
722 | } | 682 | } |
723 | 683 | ||
724 | static void seat_apply_input_config(struct sway_seat *seat, | 684 | static void seat_apply_input_mapping(struct sway_seat *seat, |
725 | struct sway_seat_device *sway_device) { | 685 | struct sway_seat_device *sway_device) { |
726 | struct input_config *ic = | 686 | struct input_config *ic = |
727 | input_device_get_config(sway_device->input_device); | 687 | input_device_get_config(sway_device->input_device); |
728 | 688 | ||
729 | 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", | ||
730 | sway_device->input_device->identifier); | 699 | sway_device->input_device->identifier); |
731 | 700 | ||
732 | 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; |
@@ -754,6 +723,7 @@ static void seat_apply_input_config(struct sway_seat *seat, | |||
754 | mapped_to_output = NULL; | 723 | mapped_to_output = NULL; |
755 | break; | 724 | break; |
756 | } | 725 | } |
726 | #if WLR_HAS_LIBINPUT_BACKEND | ||
757 | 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) && |
758 | sway_libinput_device_is_builtin(sway_device->input_device)) { | 728 | sway_libinput_device_is_builtin(sway_device->input_device)) { |
759 | mapped_to_output = get_builtin_output_name(); | 729 | mapped_to_output = get_builtin_output_name(); |
@@ -762,6 +732,10 @@ static void seat_apply_input_config(struct sway_seat *seat, | |||
762 | mapped_to_output, sway_device->input_device->identifier); | 732 | mapped_to_output, sway_device->input_device->identifier); |
763 | } | 733 | } |
764 | } | 734 | } |
735 | #else | ||
736 | (void)is_touch_or_tablet_tool; | ||
737 | (void)get_builtin_output_name; | ||
738 | #endif | ||
765 | if (mapped_to_output == NULL) { | 739 | if (mapped_to_output == NULL) { |
766 | return; | 740 | return; |
767 | } | 741 | } |
@@ -805,12 +779,9 @@ static void seat_apply_input_config(struct sway_seat *seat, | |||
805 | 779 | ||
806 | static void seat_configure_pointer(struct sway_seat *seat, | 780 | static void seat_configure_pointer(struct sway_seat *seat, |
807 | struct sway_seat_device *sway_device) { | 781 | struct sway_seat_device *sway_device) { |
808 | if ((seat->wlr_seat->capabilities & WL_SEAT_CAPABILITY_POINTER) == 0) { | 782 | seat_configure_xcursor(seat); |
809 | seat_configure_xcursor(seat); | ||
810 | } | ||
811 | wlr_cursor_attach_input_device(seat->cursor->cursor, | 783 | wlr_cursor_attach_input_device(seat->cursor->cursor, |
812 | sway_device->input_device->wlr_device); | 784 | sway_device->input_device->wlr_device); |
813 | seat_apply_input_config(seat, sway_device); | ||
814 | wl_event_source_timer_update( | 785 | wl_event_source_timer_update( |
815 | seat->cursor->hide_source, cursor_get_timeout(seat->cursor)); | 786 | seat->cursor->hide_source, cursor_get_timeout(seat->cursor)); |
816 | } | 787 | } |
@@ -821,8 +792,15 @@ static void seat_configure_keyboard(struct sway_seat *seat, | |||
821 | sway_keyboard_create(seat, seat_device); | 792 | sway_keyboard_create(seat, seat_device); |
822 | } | 793 | } |
823 | sway_keyboard_configure(seat_device->keyboard); | 794 | sway_keyboard_configure(seat_device->keyboard); |
824 | wlr_seat_set_keyboard(seat->wlr_seat, | 795 | |
825 | wlr_keyboard_from_input_device(seat_device->input_device->wlr_device)); | 796 | // We only need to update the current keyboard, as the rest will be updated |
797 | // as they are activated. | ||
798 | struct wlr_keyboard *wlr_keyboard = | ||
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 | } | ||
826 | 804 | ||
827 | // force notify reenter to pick up the new configuration. This reuses | 805 | // force notify reenter to pick up the new configuration. This reuses |
828 | // the current focused surface to avoid breaking input grabs. | 806 | // the current focused surface to avoid breaking input grabs. |
@@ -838,7 +816,6 @@ static void seat_configure_switch(struct sway_seat *seat, | |||
838 | if (!seat_device->switch_device) { | 816 | if (!seat_device->switch_device) { |
839 | sway_switch_create(seat, seat_device); | 817 | sway_switch_create(seat, seat_device); |
840 | } | 818 | } |
841 | seat_apply_input_config(seat, seat_device); | ||
842 | sway_switch_configure(seat_device->switch_device); | 819 | sway_switch_configure(seat_device->switch_device); |
843 | } | 820 | } |
844 | 821 | ||
@@ -846,7 +823,6 @@ static void seat_configure_touch(struct sway_seat *seat, | |||
846 | struct sway_seat_device *sway_device) { | 823 | struct sway_seat_device *sway_device) { |
847 | wlr_cursor_attach_input_device(seat->cursor->cursor, | 824 | wlr_cursor_attach_input_device(seat->cursor->cursor, |
848 | sway_device->input_device->wlr_device); | 825 | sway_device->input_device->wlr_device); |
849 | seat_apply_input_config(seat, sway_device); | ||
850 | } | 826 | } |
851 | 827 | ||
852 | static void seat_configure_tablet_tool(struct sway_seat *seat, | 828 | static void seat_configure_tablet_tool(struct sway_seat *seat, |
@@ -857,7 +833,6 @@ static void seat_configure_tablet_tool(struct sway_seat *seat, | |||
857 | sway_configure_tablet(sway_device->tablet); | 833 | sway_configure_tablet(sway_device->tablet); |
858 | wlr_cursor_attach_input_device(seat->cursor->cursor, | 834 | wlr_cursor_attach_input_device(seat->cursor->cursor, |
859 | sway_device->input_device->wlr_device); | 835 | sway_device->input_device->wlr_device); |
860 | seat_apply_input_config(seat, sway_device); | ||
861 | } | 836 | } |
862 | 837 | ||
863 | static void seat_configure_tablet_pad(struct sway_seat *seat, | 838 | static void seat_configure_tablet_pad(struct sway_seat *seat, |
@@ -907,13 +882,25 @@ void seat_configure_device(struct sway_seat *seat, | |||
907 | case WLR_INPUT_DEVICE_TOUCH: | 882 | case WLR_INPUT_DEVICE_TOUCH: |
908 | seat_configure_touch(seat, seat_device); | 883 | seat_configure_touch(seat, seat_device); |
909 | break; | 884 | break; |
910 | case WLR_INPUT_DEVICE_TABLET_TOOL: | 885 | case WLR_INPUT_DEVICE_TABLET: |
911 | seat_configure_tablet_tool(seat, seat_device); | 886 | seat_configure_tablet_tool(seat, seat_device); |
912 | break; | 887 | break; |
913 | case WLR_INPUT_DEVICE_TABLET_PAD: | 888 | case WLR_INPUT_DEVICE_TABLET_PAD: |
914 | seat_configure_tablet_pad(seat, seat_device); | 889 | seat_configure_tablet_pad(seat, seat_device); |
915 | break; | 890 | break; |
916 | } | 891 | } |
892 | |||
893 | seat_apply_input_mapping(seat, seat_device); | ||
894 | } | ||
895 | |||
896 | void 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); | ||
917 | } | 904 | } |
918 | 905 | ||
919 | void seat_reset_device(struct sway_seat *seat, | 906 | void seat_reset_device(struct sway_seat *seat, |
@@ -934,7 +921,7 @@ void seat_reset_device(struct sway_seat *seat, | |||
934 | case WLR_INPUT_DEVICE_TOUCH: | 921 | case WLR_INPUT_DEVICE_TOUCH: |
935 | seat_reset_input_config(seat, seat_device); | 922 | seat_reset_input_config(seat, seat_device); |
936 | break; | 923 | break; |
937 | case WLR_INPUT_DEVICE_TABLET_TOOL: | 924 | case WLR_INPUT_DEVICE_TABLET: |
938 | seat_reset_input_config(seat, seat_device); | 925 | seat_reset_input_config(seat, seat_device); |
939 | break; | 926 | break; |
940 | case WLR_INPUT_DEVICE_TABLET_PAD: | 927 | case WLR_INPUT_DEVICE_TABLET_PAD: |
@@ -1030,7 +1017,7 @@ void seat_configure_xcursor(struct sway_seat *seat) { | |||
1030 | 1017 | ||
1031 | wlr_xcursor_manager_load(server.xwayland.xcursor_manager, 1); | 1018 | wlr_xcursor_manager_load(server.xwayland.xcursor_manager, 1); |
1032 | struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( | 1019 | struct wlr_xcursor *xcursor = wlr_xcursor_manager_get_xcursor( |
1033 | server.xwayland.xcursor_manager, "left_ptr", 1); | 1020 | server.xwayland.xcursor_manager, "default", 1); |
1034 | if (xcursor != NULL) { | 1021 | if (xcursor != NULL) { |
1035 | struct wlr_xcursor_image *image = xcursor->images[0]; | 1022 | struct wlr_xcursor_image *image = xcursor->images[0]; |
1036 | wlr_xwayland_set_cursor( | 1023 | wlr_xwayland_set_cursor( |
@@ -1056,33 +1043,35 @@ void seat_configure_xcursor(struct sway_seat *seat) { | |||
1056 | sway_log(SWAY_ERROR, | 1043 | sway_log(SWAY_ERROR, |
1057 | "Cannot create XCursor manager for theme '%s'", cursor_theme); | 1044 | "Cannot create XCursor manager for theme '%s'", cursor_theme); |
1058 | } | 1045 | } |
1059 | } | ||
1060 | 1046 | ||
1061 | for (int i = 0; i < root->outputs->length; ++i) { | 1047 | |
1062 | struct sway_output *sway_output = root->outputs->items[i]; | 1048 | for (int i = 0; i < root->outputs->length; ++i) { |
1063 | struct wlr_output *output = sway_output->wlr_output; | 1049 | struct sway_output *sway_output = root->outputs->items[i]; |
1064 | bool result = | 1050 | struct wlr_output *output = sway_output->wlr_output; |
1065 | wlr_xcursor_manager_load(seat->cursor->xcursor_manager, | 1051 | bool result = |
1066 | output->scale); | 1052 | wlr_xcursor_manager_load(seat->cursor->xcursor_manager, |
1067 | if (!result) { | 1053 | output->scale); |
1068 | sway_log(SWAY_ERROR, | 1054 | if (!result) { |
1069 | "Cannot load xcursor theme for output '%s' with scale %f", | 1055 | sway_log(SWAY_ERROR, |
1070 | output->name, output->scale); | 1056 | "Cannot load xcursor theme for output '%s' with scale %f", |
1057 | output->name, output->scale); | ||
1058 | } | ||
1071 | } | 1059 | } |
1072 | } | ||
1073 | 1060 | ||
1074 | // 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 |
1075 | cursor_set_image(seat->cursor, NULL, NULL); | 1062 | cursor_set_image(seat->cursor, NULL, NULL); |
1076 | cursor_set_image(seat->cursor, "left_ptr", NULL); | 1063 | cursor_set_image(seat->cursor, "default", NULL); |
1077 | wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, | 1064 | wlr_cursor_warp(seat->cursor->cursor, NULL, seat->cursor->cursor->x, |
1078 | seat->cursor->cursor->y); | 1065 | seat->cursor->cursor->y); |
1066 | } | ||
1079 | } | 1067 | } |
1080 | 1068 | ||
1081 | bool seat_is_input_allowed(struct sway_seat *seat, | 1069 | bool seat_is_input_allowed(struct sway_seat *seat, |
1082 | struct wlr_surface *surface) { | 1070 | struct wlr_surface *surface) { |
1083 | struct wl_client *client = wl_resource_get_client(surface->resource); | 1071 | if (server.session_lock.lock) { |
1084 | return seat->exclusive_client == client || | 1072 | return sway_session_lock_has_surface(server.session_lock.lock, surface); |
1085 | (seat->exclusive_client == NULL && !server.session_lock.locked); | 1073 | } |
1074 | return true; | ||
1086 | } | 1075 | } |
1087 | 1076 | ||
1088 | static void send_unfocus(struct sway_container *con, void *data) { | 1077 | static void send_unfocus(struct sway_container *con, void *data) { |
@@ -1141,15 +1130,7 @@ void seat_set_raw_focus(struct sway_seat *seat, struct sway_node *node) { | |||
1141 | } | 1130 | } |
1142 | } | 1131 | } |
1143 | 1132 | ||
1144 | void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { | 1133 | static void seat_set_workspace_focus(struct sway_seat *seat, struct sway_node *node) { |
1145 | if (seat->focused_layer) { | ||
1146 | struct wlr_layer_surface_v1 *layer = seat->focused_layer; | ||
1147 | seat_set_focus_layer(seat, NULL); | ||
1148 | seat_set_focus(seat, node); | ||
1149 | seat_set_focus_layer(seat, layer); | ||
1150 | return; | ||
1151 | } | ||
1152 | |||
1153 | struct sway_node *last_focus = seat_get_focus(seat); | 1134 | struct sway_node *last_focus = seat_get_focus(seat); |
1154 | if (last_focus == node) { | 1135 | if (last_focus == node) { |
1155 | return; | 1136 | return; |
@@ -1183,11 +1164,6 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { | |||
1183 | return; | 1164 | return; |
1184 | } | 1165 | } |
1185 | 1166 | ||
1186 | // Deny setting focus when an input grab or lockscreen is active | ||
1187 | if (container && container->view && !seat_is_input_allowed(seat, container->view->surface)) { | ||
1188 | return; | ||
1189 | } | ||
1190 | |||
1191 | struct sway_output *new_output = | 1167 | struct sway_output *new_output = |
1192 | new_workspace ? new_workspace->output : NULL; | 1168 | new_workspace ? new_workspace->output : NULL; |
1193 | 1169 | ||
@@ -1287,6 +1263,24 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { | |||
1287 | } | 1263 | } |
1288 | } | 1264 | } |
1289 | 1265 | ||
1266 | void 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 | |||
1290 | void seat_set_focus_container(struct sway_seat *seat, | 1284 | void seat_set_focus_container(struct sway_seat *seat, |
1291 | struct sway_container *con) { | 1285 | struct sway_container *con) { |
1292 | seat_set_focus(seat, con ? &con->node : NULL); | 1286 | seat_set_focus(seat, con ? &con->node : NULL); |
@@ -1312,7 +1306,7 @@ void seat_set_focus_surface(struct sway_seat *seat, | |||
1312 | } | 1306 | } |
1313 | 1307 | ||
1314 | sway_input_method_relay_set_focus(&seat->im_relay, surface); | 1308 | sway_input_method_relay_set_focus(&seat->im_relay, surface); |
1315 | seat_tablet_pads_notify_enter(seat, surface); | 1309 | seat_tablet_pads_set_focus(seat, surface); |
1316 | } | 1310 | } |
1317 | 1311 | ||
1318 | void seat_set_focus_layer(struct sway_seat *seat, | 1312 | void seat_set_focus_layer(struct sway_seat *seat, |
@@ -1326,28 +1320,23 @@ void seat_set_focus_layer(struct sway_seat *seat, | |||
1326 | seat_set_focus(seat, previous); | 1320 | seat_set_focus(seat, previous); |
1327 | } | 1321 | } |
1328 | return; | 1322 | return; |
1329 | } else if (!layer || seat->focused_layer == layer) { | 1323 | } else if (!layer) { |
1330 | return; | 1324 | return; |
1331 | } | 1325 | } |
1332 | assert(layer->mapped); | 1326 | assert(layer->surface->mapped); |
1333 | seat_set_focus_surface(seat, layer->surface, true); | 1327 | if (layer->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP && |
1334 | if (layer->current.layer >= ZWLR_LAYER_SHELL_V1_LAYER_TOP) { | 1328 | layer->current.keyboard_interactive |
1335 | seat->focused_layer = layer; | 1329 | == ZWLR_LAYER_SURFACE_V1_KEYBOARD_INTERACTIVITY_EXCLUSIVE) { |
1330 | seat->has_exclusive_layer = true; | ||
1336 | } | 1331 | } |
1337 | } | 1332 | if (seat->focused_layer == layer) { |
1338 | |||
1339 | void seat_set_exclusive_client(struct sway_seat *seat, | ||
1340 | struct wl_client *client) { | ||
1341 | if (!client) { | ||
1342 | seat->exclusive_client = client; | ||
1343 | // Triggers a refocus of the topmost surface layer if necessary | ||
1344 | // TODO: Make layer surface focus per-output based on cursor position | ||
1345 | for (int i = 0; i < root->outputs->length; ++i) { | ||
1346 | struct sway_output *output = root->outputs->items[i]; | ||
1347 | arrange_layers(output); | ||
1348 | } | ||
1349 | return; | 1333 | return; |
1350 | } | 1334 | } |
1335 | seat_set_focus_surface(seat, layer->surface, true); | ||
1336 | seat->focused_layer = layer; | ||
1337 | } | ||
1338 | |||
1339 | void seat_unfocus_unless_client(struct sway_seat *seat, struct wl_client *client) { | ||
1351 | if (seat->focused_layer) { | 1340 | if (seat->focused_layer) { |
1352 | if (wl_resource_get_client(seat->focused_layer->resource) != client) { | 1341 | if (wl_resource_get_client(seat->focused_layer->resource) != client) { |
1353 | seat_set_focus_layer(seat, NULL); | 1342 | seat_set_focus_layer(seat, NULL); |
@@ -1374,7 +1363,6 @@ void seat_set_exclusive_client(struct sway_seat *seat, | |||
1374 | now.tv_nsec / 1000, point->touch_id); | 1363 | now.tv_nsec / 1000, point->touch_id); |
1375 | } | 1364 | } |
1376 | } | 1365 | } |
1377 | seat->exclusive_client = client; | ||
1378 | } | 1366 | } |
1379 | 1367 | ||
1380 | struct sway_node *seat_get_focus_inactive(struct sway_seat *seat, | 1368 | struct sway_node *seat_get_focus_inactive(struct sway_seat *seat, |
@@ -1541,7 +1529,7 @@ struct seat_config *seat_get_config_by_name(const char *name) { | |||
1541 | } | 1529 | } |
1542 | 1530 | ||
1543 | void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, | 1531 | void seat_pointer_notify_button(struct sway_seat *seat, uint32_t time_msec, |
1544 | uint32_t button, enum wlr_button_state state) { | 1532 | uint32_t button, enum wl_pointer_button_state state) { |
1545 | 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, |
1546 | time_msec, button, state); | 1534 | time_msec, button, state); |
1547 | } | 1535 | } |
@@ -1578,7 +1566,7 @@ void seatop_unref(struct sway_seat *seat, struct sway_container *con) { | |||
1578 | 1566 | ||
1579 | void seatop_button(struct sway_seat *seat, uint32_t time_msec, | 1567 | void seatop_button(struct sway_seat *seat, uint32_t time_msec, |
1580 | struct wlr_input_device *device, uint32_t button, | 1568 | struct wlr_input_device *device, uint32_t button, |
1581 | enum wlr_button_state state) { | 1569 | enum wl_pointer_button_state state) { |
1582 | if (seat->seatop_impl->button) { | 1570 | if (seat->seatop_impl->button) { |
1583 | seat->seatop_impl->button(seat, time_msec, device, button, state); | 1571 | seat->seatop_impl->button(seat, time_msec, device, button, state); |
1584 | } | 1572 | } |
@@ -1597,6 +1585,32 @@ void seatop_pointer_axis(struct sway_seat *seat, | |||
1597 | } | 1585 | } |
1598 | } | 1586 | } |
1599 | 1587 | ||
1588 | void 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 | |||
1595 | void 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 | |||
1601 | void 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 | |||
1608 | void 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 | |||
1600 | void seatop_tablet_tool_tip(struct sway_seat *seat, | 1614 | void seatop_tablet_tool_tip(struct sway_seat *seat, |
1601 | struct sway_tablet_tool *tool, uint32_t time_msec, | 1615 | struct sway_tablet_tool *tool, uint32_t time_msec, |
1602 | enum wlr_tablet_tool_tip_state state) { | 1616 | enum wlr_tablet_tool_tip_state state) { |
@@ -1685,13 +1699,6 @@ void seatop_end(struct sway_seat *seat) { | |||
1685 | seat->seatop_impl = NULL; | 1699 | seat->seatop_impl = NULL; |
1686 | } | 1700 | } |
1687 | 1701 | ||
1688 | void seatop_render(struct sway_seat *seat, struct sway_output *output, | ||
1689 | pixman_region32_t *damage) { | ||
1690 | if (seat->seatop_impl->render) { | ||
1691 | seat->seatop_impl->render(seat, output, damage); | ||
1692 | } | ||
1693 | } | ||
1694 | |||
1695 | bool seatop_allows_set_cursor(struct sway_seat *seat) { | 1702 | bool seatop_allows_set_cursor(struct sway_seat *seat) { |
1696 | return seat->seatop_impl->allow_set_cursor; | 1703 | return seat->seatop_impl->allow_set_cursor; |
1697 | } | 1704 | } |