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.
This commit is contained in:
tokyo4j 2026-03-08 18:44:59 +09:00 committed by Hiroaki Yamamoto
parent 1f776466a8
commit 3bb4ccd22d
4 changed files with 16 additions and 5 deletions

View file

@ -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_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_set_decorations(struct view *view, enum lab_ssd_mode mode, bool force_ssd);
void view_toggle_fullscreen(struct view *view); 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_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_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_grow_to_edge(struct view *view, enum lab_edge direction);
void view_shrink_to_edge(struct view *view, enum lab_edge direction); void view_shrink_to_edge(struct view *view, enum lab_edge direction);

View file

@ -568,8 +568,6 @@ view_moved(struct view *view)
} }
} }
static void save_last_placement(struct view *view);
void void
view_move_resize(struct view *view, struct wlr_box geo) 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. * Not sure if it might have other side-effects though.
*/ */
if (!view->adjusting_for_layout_change) { 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); cursor_update_focus(view->server);
} }
static void void
save_last_placement(struct view *view) view_save_last_placement(struct view *view)
{ {
assert(view); assert(view);
struct output *output = view->output; struct output *output = view->output;

View file

@ -148,6 +148,8 @@ set_initial_position(struct view *view)
/* allow_cursor */ true, rc.placement_policy); /* allow_cursor */ true, rc.placement_policy);
} }
} }
view_save_last_placement(view);
} }
static void static void

View file

@ -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 * Always make sure the view is onscreen and adjusted for any
* layout changes that could have occurred between map_request * layout changes that could have occurred between map_request