From 3bb4ccd22d55a787d4e2288185ae547b1da324a3 Mon Sep 17 00:00:00 2001 From: tokyo4j Date: Sun, 8 Mar 2026 18:44:59 +0900 Subject: [PATCH] view: save `view->last_placement` on initial positioning Fix a regression introduced in 3f223fe5 where output layout changes may move xdg views outside of the output layout with the error: `view has no last placement info`. This happens also for X11 views if they don't specify its own geometry on map. Recent changes introduced `view->last_placement` which is used to restore view positions after layout changes. This is supposed to be updated when a view is mapped or manually moved by the user. However, 3f223fe5 replaced `view_place_by_policy()` with `view_compute_position_by_policy()` in the xdg view map handler. Unlike `view_place_by_policy()`, this function does not update `view->last_placement`, leaving it unset at the time of output layout changes. Therefore, this patch adds explicit calls to `view_save_last_placement()` in the map handler to ensure `view->last_placement` is always set for mapped views. --- include/view.h | 8 ++++++++ src/view.c | 8 +++----- src/xdg.c | 2 ++ src/xwayland.c | 3 +++ 4 files changed, 16 insertions(+), 5 deletions(-) diff --git a/include/view.h b/include/view.h index f5590fa2..6c0fdf58 100644 --- a/include/view.h +++ b/include/view.h @@ -564,7 +564,15 @@ 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); + +/* + * Saves the window position in view->last_placement. This should be called + * when a view is first mapped or manually moved by the user. + */ +void view_save_last_placement(struct view *view); +/* Restores and adjusts the view's position from the view->last_placement */ 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); void view_shrink_to_edge(struct view *view, enum lab_edge direction); diff --git a/src/view.c b/src/view.c index ecbcb7a1..e833d264 100644 --- a/src/view.c +++ b/src/view.c @@ -568,8 +568,6 @@ view_moved(struct view *view) } } -static void save_last_placement(struct view *view); - void view_move_resize(struct view *view, struct wlr_box geo) { @@ -589,7 +587,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) { - save_last_placement(view); + view_save_last_placement(view); } } @@ -1722,8 +1720,8 @@ view_set_fullscreen(struct view *view, bool fullscreen) cursor_update_focus(view->server); } -static void -save_last_placement(struct view *view) +void +view_save_last_placement(struct view *view) { assert(view); struct output *output = view->output; diff --git a/src/xdg.c b/src/xdg.c index b2889a21..d3b96d48 100644 --- a/src/xdg.c +++ b/src/xdg.c @@ -148,6 +148,8 @@ set_initial_position(struct view *view) /* allow_cursor */ true, rc.placement_policy); } } + + view_save_last_placement(view); } static void diff --git a/src/xwayland.c b/src/xwayland.c index 5ddff9df..6050c21b 100644 --- a/src/xwayland.c +++ b/src/xwayland.c @@ -786,6 +786,9 @@ set_initial_position(struct view *view, } } + /* view->last_placement is still unset if has_position=true */ + view_save_last_placement(view); + /* * Always make sure the view is onscreen and adjusted for any * layout changes that could have occurred between map_request