From ed31381eb888a6fa8eaf379f2ff7f34ceadebdf4 Mon Sep 17 00:00:00 2001 From: John Lindgren Date: Wed, 16 Nov 2022 12:43:59 -0500 Subject: [PATCH] output: Add output_update_usable_area/all_usable_areas() Move the desktop_arrange_all_views() call outside layers_arrange() into a new function, output_update_usable_area(). The new function currently does exactly what layers_arrange() used to, but will be expanded in a later commit. Add output_update_all_usable_areas(), which is the same as calling output_update_usable_area() for each output, but only calls desktop_arrange_all_views() once. Rebased and slightly modified by @Consolatis --- include/labwc.h | 2 ++ src/layers.c | 29 ++++++++++++++++++----------- src/output.c | 40 +++++++++++++++++++++++++++++++++------- src/server.c | 5 +---- 4 files changed, 54 insertions(+), 22 deletions(-) diff --git a/include/labwc.h b/include/labwc.h index f12d225d..bb212a6e 100644 --- a/include/labwc.h +++ b/include/labwc.h @@ -423,6 +423,8 @@ void output_init(struct server *server); void output_manager_init(struct server *server); struct output *output_from_wlr_output(struct server *server, struct wlr_output *wlr_output); +void output_update_usable_area(struct output *output); +void output_update_all_usable_areas(struct server *server, bool enforce_view_arrange); struct wlr_box output_usable_area_in_layout_coords(struct output *output); struct wlr_box output_usable_area_from_cursor_coords(struct server *server); void handle_output_power_manager_set_mode(struct wl_listener *listener, diff --git a/src/layers.c b/src/layers.c index 220914d1..4859c402 100644 --- a/src/layers.c +++ b/src/layers.c @@ -35,6 +35,11 @@ arrange_one_layer(struct output *output, const struct wlr_box *full_area, } } +/* + * To ensure outputs/views are left in a consistent state, this + * function should be called ONLY from output_update_usable_area() + * or output_update_all_usable_areas(). + */ void layers_arrange(struct output *output) { @@ -43,7 +48,6 @@ layers_arrange(struct output *output) wlr_output_effective_resolution(output->wlr_output, &full_area.width, &full_area.height); struct wlr_box usable_area = full_area; - struct wlr_box old_usable_area = output->usable_area; struct server *server = output->server; struct wlr_scene_output *scene_output = @@ -103,12 +107,6 @@ layers_arrange(struct output *output) !seat->focused_layer->current.keyboard_interactive) { seat_set_focus_layer(seat, NULL); } - - /* Finally re-arrange all views based on usable_area */ - if (!wlr_box_equal(&old_usable_area, &usable_area)) { - desktop_arrange_all_views(server); - } - cursor_update_focus(output->server); } static void @@ -145,7 +143,12 @@ handle_surface_commit(struct wl_listener *listener, void *data) if (committed || layer->mapped != layer_surface->mapped) { layer->mapped = layer_surface->mapped; - layers_arrange(output); + output_update_usable_area(output); + /* + * Update cursor focus here to ensure we + * enter a new/moved/resized layer surface. + */ + cursor_update_focus(layer->server); } } @@ -171,7 +174,7 @@ handle_unmap(struct wl_listener *listener, void *data) struct wlr_layer_surface_v1 *layer_surface = layer->scene_layer_surface->layer_surface; if (layer_surface->output) { - layers_arrange(layer_surface->output->data); + output_update_usable_area(layer_surface->output->data); } struct seat *seat = &layer->server->seat; if (seat->focused_layer == layer_surface) { @@ -183,7 +186,11 @@ static void handle_map(struct wl_listener *listener, void *data) { struct lab_layer_surface *layer = wl_container_of(listener, layer, map); - layers_arrange(layer->scene_layer_surface->layer_surface->output->data); + struct wlr_output *wlr_output = + layer->scene_layer_surface->layer_surface->output; + if (wlr_output) { + output_update_usable_area(wlr_output->data); + } /* * Since moving to the wlroots scene-graph API, there is no need to * call wlr_surface_send_enter() from here since that will be done @@ -374,7 +381,7 @@ handle_new_layer_surface(struct wl_listener *listener, void *data) */ struct wlr_layer_surface_v1_state old_state = layer_surface->current; layer_surface->current = layer_surface->pending; - layers_arrange(output); + output_update_usable_area(output); layer_surface->current = old_state; } diff --git a/src/output.c b/src/output.c index e8030718..0726c405 100644 --- a/src/output.c +++ b/src/output.c @@ -240,8 +240,7 @@ output_init(struct server *server) static void output_update_for_layout_change(struct server *server) { - /* Adjust window positions/sizes */ - desktop_arrange_all_views(server); + output_update_all_usable_areas(server, /*enforce_view_arrange*/ true); /* * "Move" each wlr_output_cursor (in per-output coordinates) to @@ -395,11 +394,6 @@ do_output_layout_change(struct server *server) wlr_log(WLR_ERROR, "wlr_output_manager_v1_set_configuration()"); } - struct output *output; - - wl_list_for_each(output, &server->outputs, link) { - layers_arrange(output); - } output_update_for_layout_change(server); } } @@ -438,6 +432,38 @@ output_from_wlr_output(struct server *server, struct wlr_output *wlr_output) return NULL; } +/* returns true if usable area changed */ +static bool +update_usable_area(struct output *output) +{ + struct wlr_box old = output->usable_area; + layers_arrange(output); + + return !wlr_box_equal(&old, &output->usable_area); +} + +void +output_update_usable_area(struct output *output) +{ + if (update_usable_area(output)) { + desktop_arrange_all_views(output->server); + } +} + +void +output_update_all_usable_areas(struct server *server, bool enforce_view_arrange) +{ + bool usable_area_changed = false; + struct output *output; + + wl_list_for_each(output, &server->outputs, link) { + usable_area_changed |= update_usable_area(output); + } + if (usable_area_changed || enforce_view_arrange) { + desktop_arrange_all_views(server); + } +} + struct wlr_box output_usable_area_in_layout_coords(struct output *output) { diff --git a/src/server.c b/src/server.c index 5a0b19e5..ac6665ca 100644 --- a/src/server.c +++ b/src/server.c @@ -97,10 +97,7 @@ seat_disinhibit_input(struct seat *seat) * Triggers a refocus of the topmost surface layer if necessary * TODO: Make layer surface focus per-output based on cursor position */ - struct output *output; - wl_list_for_each(output, &seat->server->outputs, link) { - layers_arrange(output); - } + output_update_all_usable_areas(seat->server, /*enforce_view_arrange*/ false); } static void