From 892446a0b6eba9d14cdf7462c86565a7a60d12ae Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Sat, 13 Oct 2018 21:01:02 +0200 Subject: [PATCH 1/4] view: move arrange_workspace into view_map For mouse_warping cursor to correctly work on newly spawned containers, the workspace needs to be arranged before the cursor is warped. The shell functions each implement their own fullscreen and arrange checks, move them into the view_map function and pass their states via boolean arguments. Fixes #2819 --- include/sway/tree/view.h | 3 ++- sway/desktop/xdg_shell.c | 20 ++++++-------------- sway/desktop/xdg_shell_v6.c | 23 ++++++----------------- sway/desktop/xwayland.c | 12 +----------- sway/tree/view.c | 26 +++++++++++++++++++++----- 5 files changed, 36 insertions(+), 48 deletions(-) diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 870ef2e0e..dc1f0b023 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h @@ -329,7 +329,8 @@ void view_destroy(struct sway_view *view); void view_begin_destroy(struct sway_view *view); -void view_map(struct sway_view *view, struct wlr_surface *wlr_surface); +void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, + bool fullscreen, bool decoration); void view_unmap(struct sway_view *view); diff --git a/sway/desktop/xdg_shell.c b/sway/desktop/xdg_shell.c index 465822046..1ed45a6b7 100644 --- a/sway/desktop/xdg_shell.c +++ b/sway/desktop/xdg_shell.c @@ -406,26 +406,18 @@ static void handle_map(struct wl_listener *listener, void *data) { view->natural_height = view->wlr_xdg_surface->surface->current.height; } - view_map(view, view->wlr_xdg_surface->surface); + bool csd = false; if (!view->xdg_decoration) { struct sway_server_decoration *deco = - decoration_from_surface(xdg_surface->surface); - bool csd = !deco || deco->wlr_server_decoration->mode == + decoration_from_surface(xdg_surface->surface); + csd = !deco || deco->wlr_server_decoration->mode == WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT; - view_update_csd_from_client(view, csd); + } - if (xdg_surface->toplevel->client_pending.fullscreen) { - container_set_fullscreen(view->container, true); - arrange_workspace(view->container->workspace); - } else { - if (view->container->parent) { - arrange_container(view->container->parent); - } else if (view->container->workspace) { - arrange_workspace(view->container->workspace); - } - } + view_map(view, view->wlr_xdg_surface->surface, + xdg_surface->toplevel->client_pending.fullscreen, csd); transaction_commit_dirty(); diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index 165cc7eb2..eb8ba853b 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c @@ -402,25 +402,14 @@ static void handle_map(struct wl_listener *listener, void *data) { view->natural_width = view->wlr_xdg_surface_v6->surface->current.width; view->natural_height = view->wlr_xdg_surface_v6->surface->current.height; } - - view_map(view, view->wlr_xdg_surface_v6->surface); - struct sway_server_decoration *deco = - decoration_from_surface(xdg_surface->surface); - bool csd = !deco || deco->wlr_server_decoration->mode == - WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT; - view_update_csd_from_client(view, csd); + decoration_from_surface(xdg_surface->surface); + bool csd = !deco || deco->wlr_server_decoration->mode + == WLR_SERVER_DECORATION_MANAGER_MODE_CLIENT; + + view_map(view, view->wlr_xdg_surface_v6->surface, + xdg_surface->toplevel->client_pending.fullscreen, csd); - if (xdg_surface->toplevel->client_pending.fullscreen) { - container_set_fullscreen(view->container, true); - arrange_workspace(view->container->workspace); - } else { - if (view->container->parent) { - arrange_container(view->container->parent); - } else if (view->container->workspace) { - arrange_workspace(view->container->workspace); - } - } transaction_commit_dirty(); xdg_shell_v6_view->commit.notify = handle_commit; diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index ebf2131e8..066556b8f 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -405,18 +405,8 @@ static void handle_map(struct wl_listener *listener, void *data) { xwayland_view->commit.notify = handle_commit; // Put it back into the tree - view_map(view, xsurface->surface); + view_map(view, xsurface->surface, xsurface->fullscreen, false); - if (xsurface->fullscreen) { - container_set_fullscreen(view->container, true); - arrange_workspace(view->container->workspace); - } else { - if (view->container->parent) { - arrange_container(view->container->parent); - } else if (view->container->workspace) { - arrange_workspace(view->container->workspace); - } - } transaction_commit_dirty(); } diff --git a/sway/tree/view.c b/sway/tree/view.c index e613ac0b0..bdd5f8302 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -535,7 +535,8 @@ static bool should_focus(struct sway_view *view) { return len == 0; } -void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { +void view_map(struct sway_view *view, struct wlr_surface *wlr_surface, + bool fullscreen, bool decoration) { if (!sway_assert(view->surface == NULL, "cannot map mapped view")) { return; } @@ -586,13 +587,28 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { } } - if (should_focus(view)) { - input_manager_set_focus(input_manager, &view->container->node); - } - view_update_title(view, false); container_update_representation(view->container); view_execute_criteria(view); + + if (decoration) { + view_update_csd_from_client(view, decoration); + } + + if (fullscreen) { + container_set_fullscreen(view->container, true); + arrange_workspace(view->container->workspace); + } else { + if (view->container->parent) { + arrange_container(view->container->parent); + } else if (view->container->workspace) { + arrange_workspace(view->container->workspace); + } + } + + if (should_focus(view)) { + input_manager_set_focus(input_manager, &view->container->node); + } } void view_unmap(struct sway_view *view) { From 0969bf758b258b328f48ee360b30764b08a7d145 Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Mon, 15 Oct 2018 16:18:46 +0200 Subject: [PATCH 2/4] cursor: functions to warp cursor to container and workspace The new functions allow a cursor to be warped without changing the focus. This is a preparation commit to handle cursor warping not only in seat_set_focus_warp. --- include/sway/input/cursor.h | 7 ++++++- sway/input/cursor.c | 41 +++++++++++++++++++++++++++++++++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/include/sway/input/cursor.h b/include/sway/input/cursor.h index 4d47ab429..5556ea11b 100644 --- a/include/sway/input/cursor.h +++ b/include/sway/input/cursor.h @@ -46,6 +46,11 @@ void dispatch_cursor_button(struct sway_cursor *cursor, uint32_t time_msec, uint32_t button, enum wlr_button_state state); void cursor_set_image(struct sway_cursor *cursor, const char *image, - struct wl_client *client); + struct wl_client *client); +void cursor_warp_to_container(struct sway_cursor *cursor, + struct sway_container *container); + +void cursor_warp_to_workspace(struct sway_cursor *cursor, + struct sway_workspace *workspace); #endif diff --git a/sway/input/cursor.c b/sway/input/cursor.c index 5c4462997..21e104ecb 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c @@ -9,6 +9,7 @@ #include #include #include +#include #include "list.h" #include "log.h" #include "config.h" @@ -1271,4 +1272,44 @@ struct sway_cursor *sway_cursor_create(struct sway_seat *seat) { cursor->cursor = wlr_cursor; return cursor; + +} + +/** + * Warps the cursor to the middle of the container argument. + * Does nothing if the cursor is already inside the container. + * If container is NULL, returns without doing anything. + */ +void cursor_warp_to_container(struct sway_cursor *cursor, + struct sway_container *container) { + if (!container) { + return; + } + + struct wlr_box box; + container_get_box(container, &box); + if (wlr_box_contains_point(&box, cursor->cursor->x, cursor->cursor->y)) { + return; + } + + double x = container->x + container->width / 2.0; + double y = container->y + container->height / 2.0; + + wlr_cursor_warp(cursor->cursor, NULL, x, y); +} + +/** + * Warps the cursor to the middle of the workspace argument. + * If workspace is NULL, returns without doing anything. + */ +void cursor_warp_to_workspace(struct sway_cursor *cursor, + struct sway_workspace *workspace) { + if (!workspace) { + return; + } + + double x = workspace->x + workspace->width / 2.0; + double y = workspace->y + workspace->height / 2.0; + + wlr_cursor_warp(cursor->cursor, NULL, x, y); } From d69cf4c23c437b9ff724869f380e5c6cd03b091e Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Mon, 15 Oct 2018 16:20:18 +0200 Subject: [PATCH 3/4] seat: use new warping functions for cursor warping during focus warp --- sway/input/seat.c | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/sway/input/seat.c b/sway/input/seat.c index 03ed638ed..23f582cac 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c @@ -771,27 +771,18 @@ void seat_set_focus_warp(struct sway_seat *seat, struct sway_node *node, workspace_consider_destroy(last_workspace); } - if (last_focus) { - if (config->mouse_warping && warp && - (new_output != last_output || - config->mouse_warping == WARP_CONTAINER)) { - double x = 0; - double y = 0; + if (last_focus && warp) { + if (container && config->mouse_warping == WARP_CONTAINER) { + cursor_warp_to_container(seat->cursor, container); + cursor_send_pointer_motion(seat->cursor, 0, true); + } else if (new_output != last_output && + config->mouse_warping >= WARP_OUTPUT) { if (container) { - x = container->x + container->width / 2.0; - y = container->y + container->height / 2.0; + cursor_warp_to_container(seat->cursor, container); } else { - x = new_workspace->x + new_workspace->width / 2.0; - y = new_workspace->y + new_workspace->height / 2.0; - } - - if (!wlr_output_layout_contains_point(root->output_layout, - new_output->wlr_output, seat->cursor->cursor->x, - seat->cursor->cursor->y) - || config->mouse_warping == WARP_CONTAINER) { - wlr_cursor_warp(seat->cursor->cursor, NULL, x, y); - cursor_send_pointer_motion(seat->cursor, 0, true); + cursor_warp_to_workspace(seat->cursor, new_workspace); } + cursor_send_pointer_motion(seat->cursor, 0, true); } } From 1f0aeae33591fb46b3f8a91ca91975daf2a8bbf9 Mon Sep 17 00:00:00 2001 From: Rouven Czerwinski Date: Mon, 15 Oct 2018 16:21:38 +0200 Subject: [PATCH 4/4] view: rewarp cursor during view_unmap If the cursor is warped during the destruction of the workspace, we end up in the wrong position. Warp the cursor after arrange_workspace() so we end up in the correct position. --- sway/tree/view.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/sway/tree/view.c b/sway/tree/view.c index bdd5f8302..4b9bbfd03 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c @@ -637,7 +637,16 @@ void view_unmap(struct sway_view *view) { struct sway_seat *seat; wl_list_for_each(seat, &input_manager->seats, link) { - cursor_send_pointer_motion(seat->cursor, 0, true); + if (config->mouse_warping == WARP_CONTAINER) { + struct sway_node *node = seat_get_focus(seat); + if (node && node->type == N_CONTAINER) { + cursor_warp_to_container(seat->cursor, node->sway_container); + } else if (node && node->type == N_WORKSPACE) { + cursor_warp_to_workspace(seat->cursor, node->sway_workspace); + } + } else { + cursor_send_pointer_motion(seat->cursor, 0, true); + } } transaction_commit_dirty();