From f21d3c7d34ca0bd754c5f58295ba065a6b52c072 Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Wed, 28 Jan 2026 14:28:34 +0900 Subject: [PATCH] view: fix error messages on region or usable area changes f58b532 implemented output-relative position saving/restoring on output un-plugging/re-plugging. It worked as follows: 1. Store the output-relative view geometry in `view->last_placement` (if not set) before adding/removing an output from the layout. 2. After adding/removing an output, call `view_adjust_for_layout_change()` after the layout change to restore the output-relative view geometry based on `view->last_placement`. However, it didn't consider `view_adjust_for_layout_change()` being called from other places such as `regions_reconfigure()` and `output_update_all_usable_areas()`. In such cases, `view->last_placement` is empty and it emits an error message "view has no last placement info". This can happen when a panel is mapped or unmapped, or on Reconfigure. This commit fixes it by changing the life cycle of `view->last_placement`. It used to be set only before output layout changes and cleared on user-initiated moves/resizes, but now it is always set and updated on user-initiated moves/resizes. I think this is more intuitive, too. --- include/view.h | 13 +++++++------ src/output.c | 4 ---- src/view.c | 30 ++++-------------------------- 3 files changed, 11 insertions(+), 36 deletions(-) diff --git a/include/view.h b/include/view.h index b1c7b65d..24f33290 100644 --- a/include/view.h +++ b/include/view.h @@ -214,11 +214,13 @@ struct view { */ struct wlr_box natural_geometry; /* - * last_placement represents the last view position set by the user - * before layout changes. output_name and relative_geo are used to - * keep or restore the view position relative to the output and - * layout_geo is used to keep the global position when the output is - * lost. + * last_placement represents the last view position set by the user. + * This is used to keep or restore the view position when the output + * layout changes. + * + * output_name and relative_geo are used to keep or restore the view + * position relative to the output and layout_geo is used to keep the + * global position when the output is lost. */ struct { char *output_name; @@ -542,7 +544,6 @@ bool view_titlebar_visible(struct view *view); void view_set_ssd_mode(struct view *view, enum lab_ssd_mode mode); void view_set_decorations(struct view *view, enum lab_ssd_mode mode, bool force_ssd); void view_toggle_fullscreen(struct view *view); -void views_save_last_placement(struct server *server); void view_adjust_for_layout_change(struct view *view); void view_move_to_edge(struct view *view, enum lab_edge direction, bool snap_to_windows); void view_grow_to_edge(struct view *view, enum lab_edge direction); diff --git a/src/output.c b/src/output.c index 85968c25..b70861a1 100644 --- a/src/output.c +++ b/src/output.c @@ -190,9 +190,6 @@ handle_output_destroy(struct wl_listener *listener, void *data) output->workspace_osd = NULL; } - /* save the last placement before clearing view->output */ - views_save_last_placement(server); - struct view *view; wl_list_for_each(view, &server->views, link) { if (view->output == output) { @@ -662,7 +659,6 @@ output_config_apply(struct server *server, { bool success = true; server->pending_output_layout_change++; - views_save_last_placement(server); struct wlr_output_configuration_head_v1 *head; wl_list_for_each(head, &config->heads, link) { diff --git a/src/view.c b/src/view.c index 5271404b..25887c99 100644 --- a/src/view.c +++ b/src/view.c @@ -577,7 +577,7 @@ view_moved(struct view *view) } } -static void clear_last_placement(struct view *view); +static void save_last_placement(struct view *view); void view_move_resize(struct view *view, struct wlr_box geo) @@ -589,7 +589,7 @@ view_move_resize(struct view *view, struct wlr_box geo) /* * If the move/resize was user-initiated (rather than due to - * output layout change), then invalidate the saved geometry. + * output layout change), then update the last placement info. * * TODO: consider also updating view->output here for floating * views (based on view->pending) rather than waiting until @@ -598,7 +598,7 @@ view_move_resize(struct view *view, struct wlr_box geo) * Not sure if it might have other side-effects though. */ if (!view->adjusting_for_layout_change) { - clear_last_placement(view); + save_last_placement(view); } } @@ -1748,16 +1748,6 @@ save_last_placement(struct view *view) { assert(view); struct output *output = view->output; - /* - * Save the view's geometry if this is the first layout change - * since a user-initiated move/resize. Do not save it again for - * subsequent layout changes, since the point is to be able to - * restore to the original location after multiple changes - * (e.g. output disconnected and then reconnected). - */ - if (!wlr_box_empty(&view->last_placement.layout_geo)) { - return; - } if (!output_is_usable(output)) { wlr_log(WLR_ERROR, "cannot save last placement in unusable output"); return; @@ -1769,15 +1759,6 @@ save_last_placement(struct view *view) view->last_placement.relative_geo.y -= output->scene_output->y; } -void -views_save_last_placement(struct server *server) -{ - struct view *view; - wl_list_for_each(view, &server->views, link) { - save_last_placement(view); - } -} - static void clear_last_placement(struct view *view) { @@ -1792,10 +1773,7 @@ view_adjust_for_layout_change(struct view *view) { assert(view); if (wlr_box_empty(&view->last_placement.layout_geo)) { - /* - * views_save_last_placement() should be called before layout - * changes. Not using assert() just in case. - */ + /* Not using assert() just in case */ wlr_log(WLR_ERROR, "view has no last placement info"); return; }