From dd28e6a6d6abf06d2d16e6c91aeaf942bf225af7 Mon Sep 17 00:00:00 2001 From: Brian Ashworth Date: Wed, 27 Mar 2019 14:00:19 -0400 Subject: [PATCH] Fix xwayland configure request scratchpad crash This fixes a crash in `container_init_floating` when a xwayland view sends a configure request while in the scratchpad. `container_init_floating` gets called so the configured minimum and maximum sizes gets respected when resizing to the requested size. Since the workspace was NULL, it would SIGSEGV when attempting to get the workspace's output for the output box retrieval. This extracts the resizing portion of `container_init_floating` into a separate function. If the container is in the scratchpad, it will just be resized and skip the centering. Additionally, `container_init_floating` has been renamed to `container_floating_resize_and_center` to more accurately describe what it does. --- include/sway/tree/container.h | 5 +---- sway/desktop/xwayland.c | 2 +- sway/tree/container.c | 41 +++++++++++++++++++++++------------ sway/tree/output.c | 2 +- sway/tree/root.c | 10 +-------- 5 files changed, 31 insertions(+), 29 deletions(-) diff --git a/include/sway/tree/container.h b/include/sway/tree/container.h index d25089949..964061db6 100644 --- a/include/sway/tree/container.h +++ b/include/sway/tree/container.h @@ -215,10 +215,7 @@ size_t container_titlebar_height(void); void floating_calculate_constraints(int *min_width, int *max_width, int *min_height, int *max_height); -/** - * Resize and center the container in its workspace. - */ -void container_init_floating(struct sway_container *container); +void container_floating_resize_and_center(struct sway_container *con); void container_set_floating(struct sway_container *container, bool enable); diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index f5ade8dcb..37d0b986a 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c @@ -435,7 +435,7 @@ static void handle_request_configure(struct wl_listener *listener, void *data) { // Respect minimum and maximum sizes view->natural_width = ev->width; view->natural_height = ev->height; - container_init_floating(view->container); + container_floating_resize_and_center(view->container); configure(view, view->container->content_x, view->container->content_y, diff --git a/sway/tree/container.c b/sway/tree/container.c index f84ce3602..b7ea2b7e2 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c @@ -649,8 +649,31 @@ void floating_calculate_constraints(int *min_width, int *max_width, } -void container_init_floating(struct sway_container *con) { +static void floating_natural_resize(struct sway_container *con) { + int min_width, max_width, min_height, max_height; + floating_calculate_constraints(&min_width, &max_width, + &min_height, &max_height); + if (!con->view) { + con->width = max_width; + con->height = max_height; + } else { + struct sway_view *view = con->view; + con->content_width = + fmax(min_width, fmin(view->natural_width, max_width)); + con->content_height = + fmax(min_height, fmin(view->natural_height, max_height)); + container_set_geometry_from_content(con); + } +} + +void container_floating_resize_and_center(struct sway_container *con) { struct sway_workspace *ws = con->workspace; + if (!ws) { + // On scratchpad, just resize + floating_natural_resize(con); + return; + } + struct wlr_box *ob = wlr_output_layout_get_box(root->output_layout, ws->output->wlr_output); if (!ob) { @@ -662,13 +685,8 @@ void container_init_floating(struct sway_container *con) { return; } - int min_width, max_width, min_height, max_height; - floating_calculate_constraints(&min_width, &max_width, - &min_height, &max_height); - + floating_natural_resize(con); if (!con->view) { - con->width = max_width; - con->height = max_height; if (con->width > ws->width || con->height > ws->height) { con->x = ob->x + (ob->width - con->width) / 2; con->y = ob->y + (ob->height - con->height) / 2; @@ -677,11 +695,6 @@ void container_init_floating(struct sway_container *con) { con->y = ws->y + (ws->height - con->height) / 2; } } else { - struct sway_view *view = con->view; - con->content_width = - fmax(min_width, fmin(view->natural_width, max_width)); - con->content_height = - fmax(min_height, fmin(view->natural_height, max_height)); if (con->content_width > ws->width || con->content_height > ws->height) { con->content_x = ob->x + (ob->width - con->content_width) / 2; @@ -711,7 +724,7 @@ void container_set_floating(struct sway_container *container, bool enable) { struct sway_container *old_parent = container->parent; container_detach(container); workspace_add_floating(workspace, container); - container_init_floating(container); + container_floating_resize_and_center(container); if (container->view) { view_set_tiled(container->view, false); if (container->view->using_csd) { @@ -995,7 +1008,7 @@ void container_fullscreen_disable(struct sway_container *con) { // criteria, it needs to be reinitialized as floating to get the proper // size and location if (container_is_floating(con) && (con->width == 0 || con->height == 0)) { - container_init_floating(con); + container_floating_resize_and_center(con); } con->fullscreen_mode = FULLSCREEN_NONE; diff --git a/sway/tree/output.c b/sway/tree/output.c index 283036524..b3589be5d 100644 --- a/sway/tree/output.c +++ b/sway/tree/output.c @@ -77,7 +77,7 @@ static void restore_workspaces(struct sway_output *output) { floater->y > output->ly + output->height || floater->x + floater->width < output->lx || floater->y + floater->height < output->ly) { - container_init_floating(floater); + container_floating_resize_and_center(floater); } } diff --git a/sway/tree/root.c b/sway/tree/root.c index 5dde9f22d..bc9c610df 100644 --- a/sway/tree/root.c +++ b/sway/tree/root.c @@ -124,15 +124,7 @@ void root_scratchpad_show(struct sway_container *con) { struct wlr_box workspace_box; workspace_get_box(new_ws, &workspace_box); if (!wlr_box_contains_point(&workspace_box, center_lx, center_ly)) { - // Maybe resize it - if (con->width > new_ws->width || con->height > new_ws->height) { - container_init_floating(con); - } - - // Center it - double new_lx = new_ws->x + (new_ws->width - con->width) / 2; - double new_ly = new_ws->y + (new_ws->height - con->height) / 2; - container_floating_move_to(con, new_lx, new_ly); + container_floating_resize_and_center(con); } arrange_workspace(new_ws);