diff options
Diffstat (limited to 'sway/input')
-rw-r--r-- | sway/input/cursor.c | 6 | ||||
-rw-r--r-- | sway/input/input-manager.c | 35 | ||||
-rw-r--r-- | sway/input/seat.c | 73 |
3 files changed, 109 insertions, 5 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 9229e92d..195ddce9 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -146,8 +146,10 @@ static void cursor_send_pointer_motion(struct sway_cursor *cursor, | |||
146 | 146 | ||
147 | // send pointer enter/leave | 147 | // send pointer enter/leave |
148 | if (surface != NULL) { | 148 | if (surface != NULL) { |
149 | wlr_seat_pointer_notify_enter(seat, surface, sx, sy); | 149 | if (seat_is_input_allowed(cursor->seat, surface)) { |
150 | wlr_seat_pointer_notify_motion(seat, time, sx, sy); | 150 | wlr_seat_pointer_notify_enter(seat, surface, sx, sy); |
151 | wlr_seat_pointer_notify_motion(seat, time, sx, sy); | ||
152 | } | ||
151 | } else { | 153 | } else { |
152 | wlr_seat_pointer_clear_focus(seat); | 154 | wlr_seat_pointer_clear_focus(seat); |
153 | } | 155 | } |
diff --git a/sway/input/input-manager.c b/sway/input/input-manager.c index c3507f65..f71a06e4 100644 --- a/sway/input/input-manager.c +++ b/sway/input/input-manager.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <libinput.h> | 7 | #include <libinput.h> |
8 | #include <math.h> | 8 | #include <math.h> |
9 | #include <wlr/backend/libinput.h> | 9 | #include <wlr/backend/libinput.h> |
10 | #include <wlr/types/wlr_input_inhibitor.h> | ||
10 | #include "sway/config.h" | 11 | #include "sway/config.h" |
11 | #include "sway/input/input-manager.h" | 12 | #include "sway/input/input-manager.h" |
12 | #include "sway/input/seat.h" | 13 | #include "sway/input/seat.h" |
@@ -263,6 +264,32 @@ static void handle_new_input(struct wl_listener *listener, void *data) { | |||
263 | input_device->device_destroy.notify = handle_device_destroy; | 264 | input_device->device_destroy.notify = handle_device_destroy; |
264 | } | 265 | } |
265 | 266 | ||
267 | static void handle_inhibit_activate(struct wl_listener *listener, void *data) { | ||
268 | struct sway_input_manager *input_manager = wl_container_of( | ||
269 | listener, input_manager, inhibit_activate); | ||
270 | struct sway_seat *seat; | ||
271 | wl_list_for_each(seat, &input_manager->seats, link) { | ||
272 | seat_set_exclusive_client(seat, input_manager->inhibit->active_client); | ||
273 | } | ||
274 | } | ||
275 | |||
276 | static void handle_inhibit_deactivate(struct wl_listener *listener, void *data) { | ||
277 | struct sway_input_manager *input_manager = wl_container_of( | ||
278 | listener, input_manager, inhibit_deactivate); | ||
279 | struct sway_seat *seat; | ||
280 | wl_list_for_each(seat, &input_manager->seats, link) { | ||
281 | seat_set_exclusive_client(seat, NULL); | ||
282 | struct sway_container *previous = seat_get_focus(seat); | ||
283 | if (previous) { | ||
284 | wlr_log(L_DEBUG, "Returning focus to %p %s '%s'", previous, | ||
285 | container_type_to_str(previous->type), previous->name); | ||
286 | // Hack to get seat to re-focus the return value of get_focus | ||
287 | seat_set_focus(seat, previous->parent); | ||
288 | seat_set_focus(seat, previous); | ||
289 | } | ||
290 | } | ||
291 | } | ||
292 | |||
266 | struct sway_input_manager *input_manager_create( | 293 | struct sway_input_manager *input_manager_create( |
267 | struct sway_server *server) { | 294 | struct sway_server *server) { |
268 | struct sway_input_manager *input = | 295 | struct sway_input_manager *input = |
@@ -281,6 +308,14 @@ struct sway_input_manager *input_manager_create( | |||
281 | input->new_input.notify = handle_new_input; | 308 | input->new_input.notify = handle_new_input; |
282 | wl_signal_add(&server->backend->events.new_input, &input->new_input); | 309 | wl_signal_add(&server->backend->events.new_input, &input->new_input); |
283 | 310 | ||
311 | input->inhibit = wlr_input_inhibit_manager_create(server->wl_display); | ||
312 | input->inhibit_activate.notify = handle_inhibit_activate; | ||
313 | wl_signal_add(&input->inhibit->events.activate, | ||
314 | &input->inhibit_activate); | ||
315 | input->inhibit_deactivate.notify = handle_inhibit_deactivate; | ||
316 | wl_signal_add(&input->inhibit->events.deactivate, | ||
317 | &input->inhibit_deactivate); | ||
318 | |||
284 | return input; | 319 | return input; |
285 | } | 320 | } |
286 | 321 | ||
diff --git a/sway/input/seat.c b/sway/input/seat.c index 4a99e9eb..0699324a 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,12 @@ 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_is_input_allowed(struct sway_seat *seat, | ||
357 | struct wlr_surface *surface) { | ||
358 | struct wl_client *client = wl_resource_get_client(surface->resource); | ||
359 | return !seat->exclusive_client || seat->exclusive_client == client; | ||
360 | } | ||
361 | |||
353 | void seat_set_focus_warp(struct sway_seat *seat, | 362 | void seat_set_focus_warp(struct sway_seat *seat, |
354 | struct sway_container *container, bool warp) { | 363 | struct sway_container *container, bool warp) { |
355 | if (seat->focused_layer) { | 364 | if (seat->focused_layer) { |
@@ -371,6 +380,12 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
371 | wl_list_remove(&seat_con->link); | 380 | wl_list_remove(&seat_con->link); |
372 | wl_list_insert(&seat->focus_stack, &seat_con->link); | 381 | wl_list_insert(&seat->focus_stack, &seat_con->link); |
373 | 382 | ||
383 | if (container->type == C_VIEW && !seat_is_input_allowed( | ||
384 | seat, container->sway_view->surface)) { | ||
385 | wlr_log(L_DEBUG, "Refusing to set focus, input is inhibited"); | ||
386 | return; | ||
387 | } | ||
388 | |||
374 | if (container->type == C_VIEW) { | 389 | if (container->type == C_VIEW) { |
375 | seat_send_focus(seat, container); | 390 | seat_send_focus(seat, container); |
376 | } | 391 | } |
@@ -424,11 +439,18 @@ void seat_set_focus(struct sway_seat *seat, | |||
424 | 439 | ||
425 | void seat_set_focus_layer(struct sway_seat *seat, | 440 | void seat_set_focus_layer(struct sway_seat *seat, |
426 | struct wlr_layer_surface *layer) { | 441 | struct wlr_layer_surface *layer) { |
427 | if (!layer) { | 442 | if (!layer && seat->focused_layer) { |
428 | seat->focused_layer = NULL; | 443 | seat->focused_layer = NULL; |
444 | struct sway_container *previous = seat_get_focus(seat); | ||
445 | if (previous) { | ||
446 | wlr_log(L_DEBUG, "Returning focus to %p %s '%s'", previous, | ||
447 | container_type_to_str(previous->type), previous->name); | ||
448 | // Hack to get seat to re-focus the return value of get_focus | ||
449 | seat_set_focus(seat, previous->parent); | ||
450 | seat_set_focus(seat, previous); | ||
451 | } | ||
429 | return; | 452 | return; |
430 | } | 453 | } else if (!layer || seat->focused_layer == layer) { |
431 | if (seat->focused_layer == layer) { | ||
432 | return; | 454 | return; |
433 | } | 455 | } |
434 | if (seat->has_focus) { | 456 | if (seat->has_focus) { |
@@ -453,6 +475,51 @@ void seat_set_focus_layer(struct sway_seat *seat, | |||
453 | } | 475 | } |
454 | } | 476 | } |
455 | 477 | ||
478 | void seat_set_exclusive_client(struct sway_seat *seat, | ||
479 | struct wl_client *client) { | ||
480 | if (!client) { | ||
481 | seat->exclusive_client = client; | ||
482 | // Triggers a refocus of the topmost surface layer if necessary | ||
483 | // TODO: Make layer surface focus per-output based on cursor position | ||
484 | for (int i = 0; i < root_container.children->length; ++i) { | ||
485 | struct sway_container *output = root_container.children->items[i]; | ||
486 | if (!sway_assert(output->type == C_OUTPUT, | ||
487 | "root container has non-output child")) { | ||
488 | continue; | ||
489 | } | ||
490 | arrange_layers(output->sway_output); | ||
491 | } | ||
492 | return; | ||
493 | } | ||
494 | if (seat->focused_layer) { | ||
495 | if (wl_resource_get_client(seat->focused_layer->resource) != client) { | ||
496 | seat_set_focus_layer(seat, NULL); | ||
497 | } | ||
498 | } | ||
499 | if (seat->has_focus) { | ||
500 | struct sway_container *focus = seat_get_focus(seat); | ||
501 | if (focus->type == C_VIEW && wl_resource_get_client( | ||
502 | focus->sway_view->surface->resource) != client) { | ||
503 | seat_set_focus(seat, NULL); | ||
504 | } | ||
505 | } | ||
506 | if (seat->wlr_seat->pointer_state.focused_client) { | ||
507 | if (seat->wlr_seat->pointer_state.focused_client->client != client) { | ||
508 | wlr_seat_pointer_clear_focus(seat->wlr_seat); | ||
509 | } | ||
510 | } | ||
511 | struct timespec now; | ||
512 | clock_gettime(CLOCK_MONOTONIC, &now); | ||
513 | struct wlr_touch_point *point; | ||
514 | wl_list_for_each(point, &seat->wlr_seat->touch_state.touch_points, link) { | ||
515 | if (point->client->client != client) { | ||
516 | wlr_seat_touch_point_clear_focus(seat->wlr_seat, | ||
517 | now.tv_nsec / 1000, point->touch_id); | ||
518 | } | ||
519 | } | ||
520 | seat->exclusive_client = client; | ||
521 | } | ||
522 | |||
456 | struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, | 523 | struct sway_container *seat_get_focus_inactive(struct sway_seat *seat, |
457 | struct sway_container *container) { | 524 | struct sway_container *container) { |
458 | return seat_get_focus_by_type(seat, container, C_TYPES); | 525 | return seat_get_focus_by_type(seat, container, C_TYPES); |