diff options
Diffstat (limited to 'sway/input/seat.c')
-rw-r--r-- | sway/input/seat.c | 89 |
1 files changed, 64 insertions, 25 deletions
diff --git a/sway/input/seat.c b/sway/input/seat.c index 1f5865ee..2d714acd 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include "sway/input/cursor.h" | 20 | #include "sway/input/cursor.h" |
21 | #include "sway/input/input-manager.h" | 21 | #include "sway/input/input-manager.h" |
22 | #include "sway/input/keyboard.h" | 22 | #include "sway/input/keyboard.h" |
23 | #include "sway/input/libinput.h" | ||
23 | #include "sway/input/seat.h" | 24 | #include "sway/input/seat.h" |
24 | #include "sway/input/switch.h" | 25 | #include "sway/input/switch.h" |
25 | #include "sway/input/tablet.h" | 26 | #include "sway/input/tablet.h" |
@@ -309,8 +310,8 @@ static void handle_seat_node_destroy(struct wl_listener *listener, void *data) { | |||
309 | // Setting focus_inactive | 310 | // Setting focus_inactive |
310 | focus = seat_get_focus_inactive(seat, &root->node); | 311 | focus = seat_get_focus_inactive(seat, &root->node); |
311 | seat_set_raw_focus(seat, next_focus); | 312 | seat_set_raw_focus(seat, next_focus); |
312 | if (focus->type == N_CONTAINER && focus->sway_container->workspace) { | 313 | if (focus->type == N_CONTAINER && focus->sway_container->pending.workspace) { |
313 | seat_set_raw_focus(seat, &focus->sway_container->workspace->node); | 314 | seat_set_raw_focus(seat, &focus->sway_container->pending.workspace->node); |
314 | } | 315 | } |
315 | seat_set_raw_focus(seat, focus); | 316 | seat_set_raw_focus(seat, focus); |
316 | } | 317 | } |
@@ -666,6 +667,40 @@ static void seat_reset_input_config(struct sway_seat *seat, | |||
666 | sway_device->input_device->wlr_device, NULL); | 667 | sway_device->input_device->wlr_device, NULL); |
667 | } | 668 | } |
668 | 669 | ||
670 | static bool has_prefix(const char *str, const char *prefix) { | ||
671 | return strncmp(str, prefix, strlen(prefix)) == 0; | ||
672 | } | ||
673 | |||
674 | /** | ||
675 | * Get the name of the built-in output, if any. Returns NULL if there isn't | ||
676 | * exactly one built-in output. | ||
677 | */ | ||
678 | static const char *get_builtin_output_name(void) { | ||
679 | const char *match = NULL; | ||
680 | for (int i = 0; i < root->outputs->length; ++i) { | ||
681 | struct sway_output *output = root->outputs->items[i]; | ||
682 | const char *name = output->wlr_output->name; | ||
683 | if (has_prefix(name, "eDP-") || has_prefix(name, "LVDS-") || | ||
684 | has_prefix(name, "DSI-")) { | ||
685 | if (match != NULL) { | ||
686 | return NULL; | ||
687 | } | ||
688 | match = name; | ||
689 | } | ||
690 | } | ||
691 | return match; | ||
692 | } | ||
693 | |||
694 | static bool is_touch_or_tablet_tool(struct sway_seat_device *seat_device) { | ||
695 | switch (seat_device->input_device->wlr_device->type) { | ||
696 | case WLR_INPUT_DEVICE_TOUCH: | ||
697 | case WLR_INPUT_DEVICE_TABLET_TOOL: | ||
698 | return true; | ||
699 | default: | ||
700 | return false; | ||
701 | } | ||
702 | } | ||
703 | |||
669 | static void seat_apply_input_config(struct sway_seat *seat, | 704 | static void seat_apply_input_config(struct sway_seat *seat, |
670 | struct sway_seat_device *sway_device) { | 705 | struct sway_seat_device *sway_device) { |
671 | struct input_config *ic = | 706 | struct input_config *ic = |
@@ -681,7 +716,21 @@ static void seat_apply_input_config(struct sway_seat *seat, | |||
681 | 716 | ||
682 | switch (mapped_to) { | 717 | switch (mapped_to) { |
683 | case MAPPED_TO_DEFAULT: | 718 | case MAPPED_TO_DEFAULT: |
719 | /* | ||
720 | * If the wlroots backend provides an output name, use that. | ||
721 | * | ||
722 | * Otherwise, try to map built-in touch and tablet tool devices to the | ||
723 | * built-in output. | ||
724 | */ | ||
684 | mapped_to_output = sway_device->input_device->wlr_device->output_name; | 725 | mapped_to_output = sway_device->input_device->wlr_device->output_name; |
726 | if (mapped_to_output == NULL && is_touch_or_tablet_tool(sway_device) && | ||
727 | sway_libinput_device_is_builtin(sway_device->input_device)) { | ||
728 | mapped_to_output = get_builtin_output_name(); | ||
729 | if (mapped_to_output) { | ||
730 | sway_log(SWAY_DEBUG, "Auto-detected output '%s' for device '%s'", | ||
731 | mapped_to_output, sway_device->input_device->identifier); | ||
732 | } | ||
733 | } | ||
685 | if (mapped_to_output == NULL) { | 734 | if (mapped_to_output == NULL) { |
686 | return; | 735 | return; |
687 | } | 736 | } |
@@ -1086,30 +1135,19 @@ void seat_set_focus(struct sway_seat *seat, struct sway_node *node) { | |||
1086 | } | 1135 | } |
1087 | 1136 | ||
1088 | struct sway_workspace *new_workspace = node->type == N_WORKSPACE ? | 1137 | struct sway_workspace *new_workspace = node->type == N_WORKSPACE ? |
1089 | node->sway_workspace : node->sway_container->workspace; | 1138 | node->sway_workspace : node->sway_container->pending.workspace; |
1090 | struct sway_container *container = node->type == N_CONTAINER ? | 1139 | struct sway_container *container = node->type == N_CONTAINER ? |
1091 | node->sway_container : NULL; | 1140 | node->sway_container : NULL; |
1092 | 1141 | ||
1093 | // Deny setting focus to a view which is hidden by a fullscreen container | 1142 | // Deny setting focus to a view which is hidden by a fullscreen container or global |
1094 | if (new_workspace && new_workspace->fullscreen && container && | 1143 | if (container && container_obstructing_fullscreen_container(container)) { |
1095 | !container_is_fullscreen_or_child(container)) { | 1144 | return; |
1096 | // Unless it's a transient container | ||
1097 | if (!container_is_transient_for(container, new_workspace->fullscreen)) { | ||
1098 | return; | ||
1099 | } | ||
1100 | } | 1145 | } |
1146 | |||
1101 | // Deny setting focus to a workspace node when using fullscreen global | 1147 | // Deny setting focus to a workspace node when using fullscreen global |
1102 | if (root->fullscreen_global && !container && new_workspace) { | 1148 | if (root->fullscreen_global && !container && new_workspace) { |
1103 | return; | 1149 | return; |
1104 | } | 1150 | } |
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 | 1151 | ||
1114 | struct sway_output *new_output = | 1152 | struct sway_output *new_output = |
1115 | new_workspace ? new_workspace->output : NULL; | 1153 | new_workspace ? new_workspace->output : NULL; |
@@ -1135,10 +1173,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 | 1173 | // Put the container parents on the focus stack, then the workspace, then |
1136 | // the focused container. | 1174 | // the focused container. |
1137 | if (container) { | 1175 | if (container) { |
1138 | struct sway_container *parent = container->parent; | 1176 | struct sway_container *parent = container->pending.parent; |
1139 | while (parent) { | 1177 | while (parent) { |
1140 | seat_set_raw_focus(seat, &parent->node); | 1178 | seat_set_raw_focus(seat, &parent->node); |
1141 | parent = parent->parent; | 1179 | parent = parent->pending.parent; |
1142 | } | 1180 | } |
1143 | } | 1181 | } |
1144 | if (new_workspace) { | 1182 | if (new_workspace) { |
@@ -1234,6 +1272,7 @@ void seat_set_focus_surface(struct sway_seat *seat, | |||
1234 | wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat); | 1272 | wlr_seat_keyboard_notify_clear_focus(seat->wlr_seat); |
1235 | } | 1273 | } |
1236 | 1274 | ||
1275 | sway_input_method_relay_set_focus(&seat->im_relay, surface); | ||
1237 | seat_tablet_pads_notify_enter(seat, surface); | 1276 | seat_tablet_pads_notify_enter(seat, surface); |
1238 | } | 1277 | } |
1239 | 1278 | ||
@@ -1326,7 +1365,7 @@ struct sway_container *seat_get_focus_inactive_tiling(struct sway_seat *seat, | |||
1326 | struct sway_node *node = current->node; | 1365 | struct sway_node *node = current->node; |
1327 | if (node->type == N_CONTAINER && | 1366 | if (node->type == N_CONTAINER && |
1328 | !container_is_floating_or_child(node->sway_container) && | 1367 | !container_is_floating_or_child(node->sway_container) && |
1329 | node->sway_container->workspace == workspace) { | 1368 | node->sway_container->pending.workspace == workspace) { |
1330 | return node->sway_container; | 1369 | return node->sway_container; |
1331 | } | 1370 | } |
1332 | } | 1371 | } |
@@ -1343,7 +1382,7 @@ struct sway_container *seat_get_focus_inactive_floating(struct sway_seat *seat, | |||
1343 | struct sway_node *node = current->node; | 1382 | struct sway_node *node = current->node; |
1344 | if (node->type == N_CONTAINER && | 1383 | if (node->type == N_CONTAINER && |
1345 | container_is_floating_or_child(node->sway_container) && | 1384 | container_is_floating_or_child(node->sway_container) && |
1346 | node->sway_container->workspace == workspace) { | 1385 | node->sway_container->pending.workspace == workspace) { |
1347 | return node->sway_container; | 1386 | return node->sway_container; |
1348 | } | 1387 | } |
1349 | } | 1388 | } |
@@ -1391,7 +1430,7 @@ struct sway_workspace *seat_get_focused_workspace(struct sway_seat *seat) { | |||
1391 | return NULL; | 1430 | return NULL; |
1392 | } | 1431 | } |
1393 | if (focus->type == N_CONTAINER) { | 1432 | if (focus->type == N_CONTAINER) { |
1394 | return focus->sway_container->workspace; | 1433 | return focus->sway_container->pending.workspace; |
1395 | } | 1434 | } |
1396 | if (focus->type == N_WORKSPACE) { | 1435 | if (focus->type == N_WORKSPACE) { |
1397 | return focus->sway_workspace; | 1436 | return focus->sway_workspace; |
@@ -1404,8 +1443,8 @@ struct sway_workspace *seat_get_last_known_workspace(struct sway_seat *seat) { | |||
1404 | wl_list_for_each(current, &seat->focus_stack, link) { | 1443 | wl_list_for_each(current, &seat->focus_stack, link) { |
1405 | struct sway_node *node = current->node; | 1444 | struct sway_node *node = current->node; |
1406 | if (node->type == N_CONTAINER && | 1445 | if (node->type == N_CONTAINER && |
1407 | node->sway_container->workspace) { | 1446 | node->sway_container->pending.workspace) { |
1408 | return node->sway_container->workspace; | 1447 | return node->sway_container->pending.workspace; |
1409 | } else if (node->type == N_WORKSPACE) { | 1448 | } else if (node->type == N_WORKSPACE) { |
1410 | return node->sway_workspace; | 1449 | return node->sway_workspace; |
1411 | } | 1450 | } |