From 35c4736c4c3aa4fa46b39f358ff959d70e143231 Mon Sep 17 00:00:00 2001 From: BwackNinja Date: Mon, 1 Dec 2025 00:19:05 -0500 Subject: [PATCH] Move detection and calculation of grid snapping to grid plugin from move plugin --- plugins/grid/grid.cpp | 36 +++++++ plugins/grid/wayfire/plugins/grid.hpp | 79 ++++++++++++--- plugins/single_plugins/move.cpp | 138 +++++++++----------------- 3 files changed, 148 insertions(+), 105 deletions(-) diff --git a/plugins/grid/grid.cpp b/plugins/grid/grid.cpp index a8d33627f..ab6fa017d 100644 --- a/plugins/grid/grid.cpp +++ b/plugins/grid/grid.cpp @@ -10,6 +10,7 @@ #include "wayfire/plugin.hpp" #include "wayfire/signal-definitions.hpp" #include +#include #include "wayfire/plugins/grid.hpp" #include "wayfire/plugins/crossfade.hpp" #include @@ -55,6 +56,7 @@ class wayfire_grid : public wf::plugin_interface_t, public wf::per_output_tracke std::vector slots = {"unused", "bl", "b", "br", "l", "c", "r", "tl", "t", "tr"}; wf::ipc_activator_t bindings[10]; wf::ipc_activator_t restore{"grid/restore"}; + std::shared_ptr slot_preview; wf::plugin_activation_data_t grab_interface{ .name = "grid", @@ -109,6 +111,40 @@ class wayfire_grid : public wf::plugin_interface_t, public wf::per_output_tracke [=] (wf::grid::grid_request_signal *ev) { ev->carried_out = true; + wf::grid::slot_t new_slot_id = ev->force_off ? wf::grid::slot_t::SLOT_NONE : + wf::grid::calc_slot(ev->output, ev->input, ev->snap_threshold, ev->quarter_snap_threshold); + + /* No changes in the slot, just return */ + if (ev->slot_id == new_slot_id) + { + return; + } + + /* Destroy previous preview */ + if (slot_preview) + { + auto input = ev->input; + slot_preview->set_target_geometry({input.x, input.y, 1, 1}, 0, true); + slot_preview = nullptr; + } + + ev->slot_id = new_slot_id; + + /* Show a preview overlay */ + if (new_slot_id) + { + wf::geometry_t slot_geometry = wf::grid::get_slot_dimensions(ev->output, new_slot_id); + /* Unknown slot geometry, can't show a preview */ + if ((slot_geometry.width <= 0) || (slot_geometry.height <= 0)) + { + return; + } + + auto input = ev->input; + slot_preview = std::make_shared( + wf::geometry_t{input.x, input.y, 1, 1}, ev->output, "move"); + slot_preview->set_target_geometry(slot_geometry, 1); + } }; void handle_new_output(wf::output_t *output) override diff --git a/plugins/grid/wayfire/plugins/grid.hpp b/plugins/grid/wayfire/plugins/grid.hpp index a94171c18..9277ede3b 100644 --- a/plugins/grid/wayfire/plugins/grid.hpp +++ b/plugins/grid/wayfire/plugins/grid.hpp @@ -8,18 +8,6 @@ namespace wf { namespace grid { -/** - * name: request - * on: core - * when: Emitted before move renders a grid indicator and sets the slot. - * carried_out: true if a plugin can handle move request to grid. - */ -struct grid_request_signal -{ - /* True if a plugin handled this signal */ - bool carried_out = false; -}; - /** * The slot where a view can be placed with grid. * BL = bottom-left, TR = top-right, etc. @@ -38,6 +26,24 @@ enum slot_t SLOT_TR = 9, }; +/** + * name: request + * on: core + * when: Emitted before move renders a grid indicator and sets the slot. + * carried_out: true if a plugin can handle move request to grid. + */ +struct grid_request_signal +{ + /* True if a plugin handled this signal */ + bool carried_out = false; + bool force_off = false; + wf::output_t *output; + wf::point_t input; + int snap_threshold = 0; + int quarter_snap_threshold = 0; + wf::grid::slot_t slot_id = SLOT_NONE; +}; + /* * 7 8 9 * 4 5 6 @@ -118,5 +124,54 @@ inline wf::geometry_t get_slot_dimensions(wf::output_t *output, int n) return area; } + +/* Calculate the slot to which the view would be snapped if the input + * is released at output-local coordinates (x, y) */ +inline wf::grid::slot_t calc_slot(wf::output_t *output, wf::point_t point, int snap_threshold, int quarter_snap_threshold) +{ + auto g = output->workarea->get_workarea(); + + int threshold = snap_threshold; + + bool is_left = point.x - g.x <= threshold; + bool is_right = g.x + g.width - point.x <= threshold; + bool is_top = point.y - g.y < threshold; + bool is_bottom = g.x + g.height - point.y < threshold; + + bool is_far_left = point.x - g.x <= quarter_snap_threshold; + bool is_far_right = g.x + g.width - point.x <= quarter_snap_threshold; + bool is_far_top = point.y - g.y < quarter_snap_threshold; + bool is_far_bottom = g.x + g.height - point.y < quarter_snap_threshold; + + wf::grid::slot_t slot = wf::grid::SLOT_NONE; + if ((is_left && is_far_top) || (is_far_left && is_top)) + { + slot = wf::grid::SLOT_TL; + } else if ((is_right && is_far_top) || (is_far_right && is_top)) + { + slot = wf::grid::SLOT_TR; + } else if ((is_right && is_far_bottom) || (is_far_right && is_bottom)) + { + slot = wf::grid::SLOT_BR; + } else if ((is_left && is_far_bottom) || (is_far_left && is_bottom)) + { + slot = wf::grid::SLOT_BL; + } else if (is_right) + { + slot = wf::grid::SLOT_RIGHT; + } else if (is_left) + { + slot = wf::grid::SLOT_LEFT; + } else if (is_top) + { + // Maximize when dragging to the top + slot = wf::grid::SLOT_CENTER; + } else if (is_bottom) + { + slot = wf::grid::SLOT_BOTTOM; + } + + return slot; +} } } diff --git a/plugins/single_plugins/move.cpp b/plugins/single_plugins/move.cpp index 1406230d8..531864a96 100644 --- a/plugins/single_plugins/move.cpp +++ b/plugins/single_plugins/move.cpp @@ -47,7 +47,6 @@ class wayfire_move : public wf::per_output_plugin_instance_t, wf::grid::slot_t slot_id = wf::grid::SLOT_NONE; } slot; - wf::wl_timer workspace_switch_timer; wf::shared_data::ref_ptr_t drag_helper; @@ -72,11 +71,11 @@ class wayfire_move : public wf::per_output_plugin_instance_t, } else { input_grab->regrab_input(); - update_slot(calc_slot(get_input_coords())); + update_slot(false); } } else { - update_slot(wf::grid::SLOT_NONE); + update_slot(true); } }; @@ -111,7 +110,7 @@ class wayfire_move : public wf::per_output_plugin_instance_t, wf::grid::get_tiled_edges_for_slot(slot.slot_id)); /* Update slot, will hide the preview as well */ - update_slot(wf::grid::SLOT_NONE); + update_slot(true); } wf::get_core().default_wm->set_view_grabbed(ev->main_view, false); @@ -296,7 +295,7 @@ class wayfire_move : public wf::per_output_plugin_instance_t, } this->input_grab->grab_input(wf::scene::layer::OVERLAY); - update_slot(wf::grid::SLOT_NONE); + update_slot(true); return true; } @@ -348,7 +347,7 @@ class wayfire_move : public wf::per_output_plugin_instance_t, drag_helper->set_pending_drag(grab_position); drag_helper->start_drag(view, opts); drag_helper->handle_motion(get_global_input_coords()); - update_slot(wf::grid::SLOT_NONE); + update_slot(true); return true; } @@ -368,64 +367,6 @@ class wayfire_move : public wf::per_output_plugin_instance_t, drag_helper->handle_input_released(); } - /* Calculate the slot to which the view would be snapped if the input - * is released at output-local coordinates (x, y) */ - wf::grid::slot_t calc_slot(wf::point_t point) - { - if (!is_snap_enabled()) - { - return wf::grid::SLOT_NONE; - } - - auto g = output->workarea->get_workarea(); - if (!(output->get_relative_geometry() & point)) - { - return wf::grid::SLOT_NONE; - } - - int threshold = snap_threshold; - - bool is_left = point.x - g.x <= threshold; - bool is_right = g.x + g.width - point.x <= threshold; - bool is_top = point.y - g.y < threshold; - bool is_bottom = g.x + g.height - point.y < threshold; - - bool is_far_left = point.x - g.x <= quarter_snap_threshold; - bool is_far_right = g.x + g.width - point.x <= quarter_snap_threshold; - bool is_far_top = point.y - g.y < quarter_snap_threshold; - bool is_far_bottom = g.x + g.height - point.y < quarter_snap_threshold; - - wf::grid::slot_t slot = wf::grid::SLOT_NONE; - if ((is_left && is_far_top) || (is_far_left && is_top)) - { - slot = wf::grid::SLOT_TL; - } else if ((is_right && is_far_top) || (is_far_right && is_top)) - { - slot = wf::grid::SLOT_TR; - } else if ((is_right && is_far_bottom) || (is_far_right && is_bottom)) - { - slot = wf::grid::SLOT_BR; - } else if ((is_left && is_far_bottom) || (is_far_left && is_bottom)) - { - slot = wf::grid::SLOT_BL; - } else if (is_right) - { - slot = wf::grid::SLOT_RIGHT; - } else if (is_left) - { - slot = wf::grid::SLOT_LEFT; - } else if (is_top) - { - // Maximize when dragging to the top - slot = wf::grid::SLOT_CENTER; - } else if (is_bottom) - { - slot = wf::grid::SLOT_BOTTOM; - } - - return slot; - } - void update_workspace_switch_timeout(wf::grid::slot_t slot_id) { if ((workspace_switch_after == -1) || (slot_id == wf::grid::SLOT_NONE)) @@ -484,50 +425,61 @@ class wayfire_move : public wf::per_output_plugin_instance_t, }); } - void update_slot(wf::grid::slot_t new_slot_id) + void update_slot(bool force_off) { - /* No changes in the slot, just return */ - if (slot.slot_id == new_slot_id) - { - return; - } - - /* Destroy previous preview */ - if (slot.preview) + auto input = get_input_coords(); + if (!is_snap_enabled() || !(output->get_relative_geometry() & input)) { - auto input = get_input_coords(); - slot.preview->set_target_geometry({input.x, input.y, 1, 1}, 0, true); - slot.preview = nullptr; + force_off = true; } - + wf::grid::slot_t old_slot_id = slot.slot_id; wf::grid::grid_request_signal grid_signal; + grid_signal.output = output; + grid_signal.input = input; + grid_signal.snap_threshold = snap_threshold; + grid_signal.quarter_snap_threshold = quarter_snap_threshold; + grid_signal.slot_id = slot.slot_id; + grid_signal.force_off = force_off; wf::get_core().emit(&grid_signal); - if (grid_signal.carried_out || (new_slot_id == wf::grid::slot_t::SLOT_CENTER)) + if (grid_signal.carried_out) { - slot.slot_id = new_slot_id; + slot.slot_id = grid_signal.slot_id; } else { - slot.slot_id = new_slot_id = wf::grid::slot_t::SLOT_NONE; + slot.slot_id = wf::grid::calc_slot(output, input, snap_threshold, quarter_snap_threshold); + if (slot.slot_id != wf::grid::slot_t::SLOT_CENTER) + { + slot.slot_id = wf::grid::slot_t::SLOT_NONE; + } } - /* Show a preview overlay */ - if (new_slot_id) + if (old_slot_id == slot.slot_id) { - wf::geometry_t slot_geometry = wf::grid::get_slot_dimensions(output, new_slot_id); - /* Unknown slot geometry, can't show a preview */ - if ((slot_geometry.width <= 0) || (slot_geometry.height <= 0)) + return; + } + + /* if the grid plugin isn't loaded, we're handling the preview for maximize */ + if (!grid_signal.carried_out) { + if (slot.preview) { - return; + slot.preview->set_target_geometry({input.x, input.y, 1, 1}, 0, true); + slot.preview = nullptr; } - auto input = get_input_coords(); - slot.preview = std::make_shared( - wf::geometry_t{input.x, input.y, 1, 1}, output, "move"); - slot.preview->set_target_geometry(slot_geometry, 1); + if (slot.slot_id) + { + wf::geometry_t slot_geometry = output->workarea->get_workarea(); + /* only show a preview with valid geometry */ + if ((slot_geometry.width > 0) || (slot_geometry.height > 0)) + { + slot.preview = std::make_shared( + wf::geometry_t{input.x, input.y, 1, 1}, output, "move"); + slot.preview->set_target_geometry(slot_geometry, 1); + } + } } - - update_workspace_switch_timeout(new_slot_id); + update_workspace_switch_timeout(slot.slot_id); } /* Returns the currently used input coordinates in global compositor space */ @@ -582,7 +534,7 @@ class wayfire_move : public wf::per_output_plugin_instance_t, void handle_input_motion() { drag_helper->handle_motion(get_global_input_coords()); - update_slot(calc_slot(get_input_coords())); + update_slot(false); } void fini() override