diff --git a/src/api/wayfire/core.hpp b/src/api/wayfire/core.hpp index 7f6c9c5b5..3519266b2 100644 --- a/src/api/wayfire/core.hpp +++ b/src/api/wayfire/core.hpp @@ -309,11 +309,37 @@ class compositor_core_t : public wf::object_base_t, public signal::provider_t }; /** - * Change the view's output to new_output. If the reconfigure flag is - * set, it will adjust the view geometry for the new output and clamp - * it to the output geometry so it is at an expected size and position. + * Flags for move_view_to_output. */ -void move_view_to_output(wayfire_toplevel_view v, wf::output_t *new_output, bool reconfigure); +enum +{ + /** + * Adjust the view geometry for the new output and clamp it to the output geometry so it is + * at an expected size and position. + */ + VIEW_TO_OUTPUT_FLAG_RECONFIGURE = 1 << 0, + /** + * If the new output has the same workspace geometry as the current output, move the view to the + * same workspace as it is currently on. + */ + VIEW_TO_OUTPUT_FLAG_SAME_WORKSPACE = 1 << 1, +}; + +/** + * Change the view's output to new_output. + */ +void move_view_to_output(wayfire_toplevel_view v, wf::output_t *new_output, unsigned flags); + +/** + * Change the view's output to new_output. Equivalent to calling the move_view_to_output with + * the RECONFIGURE flag set to the specified value and no other flags set. + */ +inline void move_view_to_output(wayfire_toplevel_view v, wf::output_t *new_output, + bool reconfigure) +{ + unsigned flags = reconfigure ? VIEW_TO_OUTPUT_FLAG_RECONFIGURE : 0; + move_view_to_output(v, new_output, flags); +} /** * Start a move of a view to a new workspace set (and thus potentially to a new output). diff --git a/src/core/core.cpp b/src/core/core.cpp index 84baa8a78..906328bb0 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -492,13 +492,17 @@ void wf::start_move_view_to_wset(wayfire_toplevel_view v, std::shared_ptradd_view(v); } -void wf::move_view_to_output(wayfire_toplevel_view v, wf::output_t *new_output, bool reconfigure) +void wf::move_view_to_output(wayfire_toplevel_view v, wf::output_t *new_output, unsigned flags) { auto old_output = v->get_output(); auto old_wset = v->get_wset(); + auto old_ws = old_wset->get_view_main_workspace(v); + auto new_wset = new_output->wset(); uint32_t edges; bool fullscreen; + bool reconfigure = flags & VIEW_TO_OUTPUT_FLAG_RECONFIGURE; + bool same_workspace = flags & VIEW_TO_OUTPUT_FLAG_SAME_WORKSPACE; wf::geometry_t view_g; wf::geometry_t old_output_g; wf::geometry_t new_output_g; @@ -518,7 +522,7 @@ void wf::move_view_to_output(wayfire_toplevel_view v, wf::output_t *new_output, assert(new_output); - start_move_view_to_wset(v, new_output->wset()); + start_move_view_to_wset(v, new_wset); if (new_output == wf::get_core().seat->get_active_output()) { wf::get_core().seat->focus_view(v); @@ -536,6 +540,11 @@ void wf::move_view_to_output(wayfire_toplevel_view v, wf::output_t *new_output, { auto new_g = wf::clamp(view_g, new_output->workarea->get_workarea()); v->set_geometry(new_g); + if (same_workspace && + (old_wset->get_workspace_grid_size() == new_wset->get_workspace_grid_size())) + { + v->get_wset()->move_to_workspace(v, old_ws); + } } } diff --git a/src/core/output-layout.cpp b/src/core/output-layout.cpp index c2a4741cd..410f8f0b1 100644 --- a/src/core/output-layout.cpp +++ b/src/core/output-layout.cpp @@ -165,7 +165,8 @@ void transfer_views(wf::output_t *from, wf::output_t *to) auto views = from->wset()->get_views(WSET_SORT_STACKING); for (auto& view : views) { - move_view_to_output(view, to, true); + unsigned flags = VIEW_TO_OUTPUT_FLAG_RECONFIGURE | VIEW_TO_OUTPUT_FLAG_SAME_WORKSPACE; + move_view_to_output(view, to, flags); } } @@ -546,7 +547,13 @@ struct output_layout_output_t /* It doesn't make sense to transfer to another output if we're * going to shut down the compositor */ - transfer_views(wo, shutdown ? nullptr : get_core().seat->get_active_output()); + wf::output_t *new_output = shutdown ? nullptr : get_core().seat->get_active_output(); + transfer_views(wo, new_output); + if (new_output && + (wo->wset()->get_workspace_grid_size() == new_output->wset()->get_workspace_grid_size())) + { + new_output->wset()->set_workspace(wo->wset()->get_current_workspace()); + } wf::output_removed_signal data2; data2.output = wo; @@ -1119,7 +1126,9 @@ class output_layout_t::impl if (!noop_output) { - auto handle = wlr_headless_add_output(noop_backend, 1280, 720); + // NOOP output should be at least as large as actual screen sizes. Otherwise, when + // when windows are temporarily mapped to it, they will be moved/cropped to match it. + auto handle = wlr_headless_add_output(noop_backend, 3840, 2160); handle->data = WF_NOOP_OUTPUT_MAGIC; strcpy(handle->name, "NOOP-1");