aboutsummaryrefslogtreecommitdiffstats
path: root/sway/input/seat.c
diff options
context:
space:
mode:
authorLibravatar Kenny Levinsen <kl@kl.wtf>2020-06-28 15:33:03 +0200
committerLibravatar Simon Ser <contact@emersion.fr>2020-06-30 13:27:51 +0200
commit492267a5d6924e4f3a2e2326240eb064c3d2d7c2 (patch)
tree148ca8c082dfb1971e2c7237bba1143c546bc860 /sway/input/seat.c
parenttransaction: Mark client resize immediately ready (diff)
downloadsway-492267a5d6924e4f3a2e2326240eb064c3d2d7c2.tar.gz
sway-492267a5d6924e4f3a2e2326240eb064c3d2d7c2.tar.zst
sway-492267a5d6924e4f3a2e2326240eb064c3d2d7c2.zip
seat: Refocus seat when wlr_drag is destroyed
wlr_drag installs grabs for the full duration of the drag, leading to the drag target not being focused when the drag ends. This leads to unexpected focus behavior, especially for the keyboard which requires toggling focus away and back to set. We can only fix the focus once the grabs are released, so refocus the seat when the wlr_drag destroy event is received. Closes: https://github.com/swaywm/sway/issues/5116
Diffstat (limited to 'sway/input/seat.c')
-rw-r--r--sway/input/seat.c38
1 files changed, 38 insertions, 0 deletions
diff --git a/sway/input/seat.c b/sway/input/seat.c
index aa56394a..a54bc2e7 100644
--- a/sway/input/seat.c
+++ b/sway/input/seat.c
@@ -402,6 +402,31 @@ static void drag_icon_handle_destroy(struct wl_listener *listener, void *data) {
402 free(icon); 402 free(icon);
403} 403}
404 404
405static void drag_handle_destroy(struct wl_listener *listener, void *data) {
406 struct sway_drag *drag = wl_container_of(listener, drag, destroy);
407
408 // Focus enter isn't sent during drag, so refocus the focused node, layer
409 // surface or unmanaged surface.
410 struct sway_seat *seat = drag->seat;
411 struct sway_node *focus = seat_get_focus(seat);
412 if (focus) {
413 seat_set_focus(seat, NULL);
414 seat_set_focus(seat, focus);
415 } else if (seat->focused_layer) {
416 struct wlr_layer_surface_v1 *layer = seat->focused_layer;
417 seat_set_focus_layer(seat, NULL);
418 seat_set_focus_layer(seat, layer);
419 } else {
420 struct wlr_surface *unmanaged = seat->wlr_seat->keyboard_state.focused_surface;
421 seat_set_focus_surface(seat, NULL, false);
422 seat_set_focus_surface(seat, unmanaged, false);
423 }
424
425 drag->wlr_drag->data = NULL;
426 wl_list_remove(&drag->destroy.link);
427 free(drag);
428}
429
405static void handle_request_start_drag(struct wl_listener *listener, 430static void handle_request_start_drag(struct wl_listener *listener,
406 void *data) { 431 void *data) {
407 struct sway_seat *seat = wl_container_of(listener, seat, request_start_drag); 432 struct sway_seat *seat = wl_container_of(listener, seat, request_start_drag);
@@ -431,6 +456,19 @@ static void handle_request_start_drag(struct wl_listener *listener,
431static void handle_start_drag(struct wl_listener *listener, void *data) { 456static void handle_start_drag(struct wl_listener *listener, void *data) {
432 struct sway_seat *seat = wl_container_of(listener, seat, start_drag); 457 struct sway_seat *seat = wl_container_of(listener, seat, start_drag);
433 struct wlr_drag *wlr_drag = data; 458 struct wlr_drag *wlr_drag = data;
459
460 struct sway_drag *drag = calloc(1, sizeof(struct sway_drag));
461 if (drag == NULL) {
462 sway_log(SWAY_ERROR, "Allocation failed");
463 return;
464 }
465 drag->seat = seat;
466 drag->wlr_drag = wlr_drag;
467 wlr_drag->data = drag;
468
469 drag->destroy.notify = drag_handle_destroy;
470 wl_signal_add(&wlr_drag->events.destroy, &drag->destroy);
471
434 struct wlr_drag_icon *wlr_drag_icon = wlr_drag->icon; 472 struct wlr_drag_icon *wlr_drag_icon = wlr_drag->icon;
435 if (wlr_drag_icon == NULL) { 473 if (wlr_drag_icon == NULL) {
436 return; 474 return;