--- a/plugins/grid/grid.cpp +++ b/plugins/grid/grid.cpp @@ -24,8 +24,18 @@ #include #include "wayfire/plugins/ipc/ipc-activator.hpp" #include "wayfire/signal-provider.hpp" - +#include + +namespace +{ const std::string grid_view_id = "grid-view"; + +class grid_scope_toggle_data_t : public wf::custom_data_t +{ + public: + std::string monitor; + std::string physical_policy = "physical"; +}; class wf_grid_slot_data : public wf::custom_data_t { @@ -63,6 +73,7 @@ wf::ipc_activator_t bindings[10]; wf::ipc_activator_t restore{"grid/restore"}; wf::ipc_activator_t zone_maximize{"grid/zone_maximize"}; + wf::ipc_activator_t toggle_scope{"grid/toggle_scope"}; wf::ipc_activator_t use_virtual{"grid/use_virtual"}, use_physical{"grid/use_physical"}, reset_scope{"grid/reset_scope"}, next_monitor{"grid/next_monitor"}; wf::option_wrapper_t default_scope{"core/window_scope"}, scope_rules{"core/window_scope_rules"}; @@ -262,6 +273,46 @@ use_virtual.set_handler(scope_handler("virtual")); use_physical.set_handler(scope_handler("physical")); reset_scope.set_handler(scope_handler("auto")); + toggle_scope.set_handler([this] (wf::output_t*, wayfire_view view) + { + auto top = wf::toplevel_cast(wf::find_topmost_parent(view)); + auto wo = top ? top->get_output() : nullptr; + auto layout = wo ? wo->get_data() : nullptr; + // Scope changes are valid for simpletile-owned views too. Ordinary + // Grid movement remains subject to can_adjust_view(). + if (!top || !top->is_mapped() || !layout || layout->zones.empty() || + !wo->can_activate_plugin(&grab_interface)) return false; + + auto remembered = top->get_data_safe(); + auto policy = wf::window_scope_policy(top); + top->get_data_safe()->zone.clear(); + if (policy != "virtual") + { + auto physical = wf::window_scope_zone(top); + if (!physical) return false; + remembered->monitor = physical->name; + remembered->physical_policy = policy; + wf::set_window_scope(top, "virtual"); + } else + { + auto physical = find_zone(wo, remembered->monitor); + if (!physical) + { + physical = zone_for_window(top); + remembered->physical_policy = "physical"; + } + + if (!physical) return false; + // Place in the remembered zone first. Returning to the ordinary + // physical policy then keeps that monitor without pinning the + // window there, so subsequent dragging can change monitors. + wf::set_window_scope(top, physical->name); + if (remembered->physical_policy == "physical") + wf::set_window_scope(top, "physical"); + } + + return true; + }); next_monitor.set_handler([this] (wf::output_t *wo, wayfire_view view) { auto top = wf::toplevel_cast(view); @@ -636,4 +687,5 @@ }; }; +} DECLARE_WAYFIRE_PLUGIN(wayfire_grid); --- a/metadata/grid.xml +++ b/metadata/grid.xml @@ -4,6 +4,11 @@ <_short>Grid <_long>A plugin to position the windows in certain regions of the output. Window Management +