diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-04-03 17:03:29 -0400 |
---|---|---|
committer | Drew DeVault <sir@cmpwn.com> | 2018-04-04 18:47:48 -0400 |
commit | b7e779491232b825f6edc0b199e7564e93f1e332 (patch) | |
tree | 00457213fa57ec07692bb093392a83203e0e9960 /sway/input/seat.c | |
parent | Add input inhibitor to input manager (diff) | |
download | sway-b7e779491232b825f6edc0b199e7564e93f1e332.tar.gz sway-b7e779491232b825f6edc0b199e7564e93f1e332.tar.zst sway-b7e779491232b825f6edc0b199e7564e93f1e332.zip |
Implement input-inhibit in sway, swaylock
Diffstat (limited to 'sway/input/seat.c')
-rw-r--r-- | sway/input/seat.c | 68 |
1 files changed, 61 insertions, 7 deletions
diff --git a/sway/input/seat.c b/sway/input/seat.c index 318fa9f6..0e26dde4 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -1,5 +1,7 @@ | |||
1 | #define _XOPEN_SOURCE 700 | 1 | #define _XOPEN_SOURCE 700 |
2 | #define _POSIX_C_SOURCE 199309L | ||
2 | #include <assert.h> | 3 | #include <assert.h> |
4 | #include <time.h> | ||
3 | #include <wlr/types/wlr_cursor.h> | 5 | #include <wlr/types/wlr_cursor.h> |
4 | #include <wlr/types/wlr_output_layout.h> | 6 | #include <wlr/types/wlr_output_layout.h> |
5 | #include <wlr/types/wlr_xcursor_manager.h> | 7 | #include <wlr/types/wlr_xcursor_manager.h> |
@@ -9,6 +11,7 @@ | |||
9 | #include "sway/input/input-manager.h" | 11 | #include "sway/input/input-manager.h" |
10 | #include "sway/input/keyboard.h" | 12 | #include "sway/input/keyboard.h" |
11 | #include "sway/ipc-server.h" | 13 | #include "sway/ipc-server.h" |
14 | #include "sway/layers.h" | ||
12 | #include "sway/output.h" | 15 | #include "sway/output.h" |
13 | #include "sway/tree/container.h" | 16 | #include "sway/tree/container.h" |
14 | #include "sway/tree/view.h" | 17 | #include "sway/tree/view.h" |
@@ -350,6 +353,11 @@ void seat_configure_xcursor(struct sway_seat *seat) { | |||
350 | seat->cursor->cursor->y); | 353 | seat->cursor->cursor->y); |
351 | } | 354 | } |
352 | 355 | ||
356 | bool seat_allow_input(struct sway_seat *seat, struct wlr_surface *surface) { | ||
357 | struct wl_client *client = wl_resource_get_client(surface->resource); | ||
358 | return !seat->exclusive_client || seat->exclusive_client == client; | ||
359 | } | ||
360 | |||
353 | void seat_set_focus_warp(struct sway_seat *seat, | 361 | void seat_set_focus_warp(struct sway_seat *seat, |
354 | struct sway_container *container, bool warp) { | 362 | struct sway_container *container, bool warp) { |
355 | if (seat->focused_layer) { | 363 | if (seat->focused_layer) { |
@@ -371,6 +379,12 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
371 | wl_list_remove(&seat_con->link); | 379 | wl_list_remove(&seat_con->link); |
372 | wl_list_insert(&seat->focus_stack, &seat_con->link); | 380 | wl_list_insert(&seat->focus_stack, &seat_con->link); |
373 | 381 | ||
382 | if (container->type == C_VIEW && !seat_allow_input( | ||
383 | seat, container->sway_view->surface)) { | ||
384 | wlr_log(L_DEBUG, "Refusing to set focus, input is inhibited"); | ||
385 | return; | ||
386 | } | ||
387 | |||
374 | if (container->type == C_VIEW) { | 388 | if (container->type == C_VIEW) { |
375 | seat_send_focus(seat, container); | 389 | seat_send_focus(seat, container); |
376 | } | 390 | } |
@@ -426,13 +440,13 @@ void seat_set_focus_layer(struct sway_seat *seat, | |||
426 | struct wlr_layer_surface *layer) { | 440 | struct wlr_layer_surface *layer) { |
427 | if (!layer && seat->focused_layer) { | 441 | if (!layer && seat->focused_layer) { |
428 | seat->focused_layer = NULL; | 442 | seat->focused_layer = NULL; |
429 | struct sway_container *c = seat_get_focus(seat); | 443 | struct sway_container *previous = seat_get_focus(seat); |
430 | if (c) { | 444 | if (previous) { |
431 | wlr_log(L_DEBUG, "Returning focus to %p %s '%s'", c, | 445 | wlr_log(L_DEBUG, "Returning focus to %p %s '%s'", previous, |
432 | container_type_to_str(c->type), c->name); | 446 | container_type_to_str(previous->type), previous->name); |
433 | // Hack to get seat to re-focus the return value of get_focus | 447 | // Hack to get seat to re-focus the return value of get_focus |
434 | seat_set_focus(seat, c->parent); | 448 | seat_set_focus(seat, previous->parent); |
435 | seat_set_focus(seat, c); | 449 | seat_set_focus(seat, previous); |
436 | } | 450 | } |
437 | return; | 451 | return; |
438 | } else if (!layer || seat->focused_layer == layer) { | 452 | } else if (!layer || seat->focused_layer == layer) { |
@@ -462,7 +476,47 @@ void seat_set_focus_layer(struct sway_seat *seat, | |||
462 | 476 | ||
463 | void seat_set_exclusive_client(struct sway_seat *seat, | 477 | void seat_set_exclusive_client(struct sway_seat *seat, |
464 | struct wl_client *client) { | 478 | struct wl_client *client) { |
465 | // TODO | 479 | if (!client) { |
480 | seat->exclusive_client = client; | ||
481 | // Triggers a refocus of the topmost surface layer if necessary | ||
482 | // TODO: Make layer surface focus per-output based on cursor position | ||
483 | for (int i = 0; i < root_container.children->length; ++i) { | ||
484 | struct sway_container *output = root_container.children->items[i]; | ||
485 | if (!sway_assert(output->type == C_OUTPUT, | ||
486 | "root container has non-output child")) { | ||
487 | continue; | ||
488 | } | ||
489 | arrange_layers(output->sway_output); | ||
490 | } | ||
491 | return; | ||
492 | } | ||
493 | if (seat->focused_layer) { | ||
494 | if (wl_resource_get_client(seat->focused_layer->resource) != client) { | ||
495 | seat_set_focus_layer(seat, NULL); | ||
496 | } | ||
497 | } | ||
498 | if (seat->has_focus) { | ||
499 | struct sway_container *focus = seat_get_focus(seat); | ||
500 | if (focus->type == C_VIEW && wl_resource_get_client( | ||
501 | focus->sway_view->surface->resource) != client) { | ||
502 | seat_set_focus(seat, NULL); | ||
503 | } | ||
504 | } | ||
505 | if (seat->wlr_seat->pointer_state.focused_client) { | ||
506 | if (seat->wlr_seat->pointer_state.focused_client->client != client) { | ||
507 | wlr_seat_pointer_clear_focus(seat->wlr_seat); | ||
508 | } | ||
509 | } | ||
510 | struct timespec now; | ||
511 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
512 | struct wlr_touch_point *point; | ||
513 | wl_list_for_each(point, &seat->wlr_seat->touch_state.touch_points, link) { | ||
514 | if (point->client->client != client) { | ||
515 | wlr_seat_touch_point_clear_focus(seat->wlr_seat, | ||
516 | now.tv_nsec / 1000, point->touch_id); | ||
517 | } | ||
518 | } | ||
519 | seat->exclusive_client = client; | ||
466 | } | 520 | } |
467 | 521 | ||
468 | struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, | 522 | struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, |