diff --git a/include/view.h b/include/view.h index 84a91e07..a7c1dff0 100644 --- a/include/view.h +++ b/include/view.h @@ -538,6 +538,7 @@ 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 d25d2736..7a42a7df 100644 --- a/src/output.c +++ b/src/output.c @@ -166,7 +166,8 @@ static void handle_output_destroy(struct wl_listener *listener, void *data) { struct output *output = wl_container_of(listener, output, destroy); - struct seat *seat = &output->server->seat; + struct server *server = output->server; + struct seat *seat = &server->seat; regions_evacuate_output(output); regions_destroy(seat, &output->regions); if (seat->overlay.active.output == output) { @@ -189,8 +190,10 @@ 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; - struct server *server = output->server; wl_list_for_each(view, &server->views, link) { if (view->output == output) { view_on_output_destroy(view); @@ -659,6 +662,7 @@ 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 7eec3c1b..d4220b90 100644 --- a/src/view.c +++ b/src/view.c @@ -1725,6 +1725,37 @@ view_set_fullscreen(struct view *view, bool fullscreen) cursor_update_focus(view->server); } +static void +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; + } + view->last_placement.layout_geo = view->pending; +} + +void +views_save_last_placement(struct server *server) +{ + struct view *view; + wl_list_for_each(view, &server->views, link) { + save_last_placement(view); + } +} + void view_adjust_for_layout_change(struct view *view) { @@ -1733,25 +1764,13 @@ view_adjust_for_layout_change(struct view *view) bool is_floating = view_is_floating(view); view->adjusting_for_layout_change = true; - if (!output_is_usable(view->output)) { - view->lost_output_due_to_layout_change = true; - } - - /* - * 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). - * - * Note that it's important to do this even if an output change - * is not (yet) required, to properly handle cases of multiple - * outputs being disconnected/reconnected in any order. In that - * case, there can be multiple layout change events, and a view - * can be moved first and only later lose its own output. - */ if (wlr_box_empty(&view->last_placement.layout_geo)) { - view->last_placement.layout_geo = view->pending; + /* + * views_save_last_placement() should be called before layout + * changes. Not using assert() just in case. + */ + wlr_log(WLR_ERROR, "view has no last placement info"); + goto out; } /* * Check if an output change is required: @@ -1780,6 +1799,7 @@ view_adjust_for_layout_change(struct view *view) } view_update_outputs(view); +out: view->adjusting_for_layout_change = false; }