Skip to content

Commit 0bdb2e0

Browse files
authored
Move detection and calculation of grid snapping to grid plugin from move plugin (#2916)
1 parent 86fe042 commit 0bdb2e0

File tree

3 files changed

+186
-99
lines changed

3 files changed

+186
-99
lines changed

plugins/grid/grid.cpp

Lines changed: 58 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
#include "wayfire/plugin.hpp"
1111
#include "wayfire/signal-definitions.hpp"
1212
#include <wayfire/plugins/common/geometry-animation.hpp>
13+
#include <wayfire/plugins/common/preview-indication.hpp>
1314
#include "wayfire/plugins/grid.hpp"
1415
#include "wayfire/plugins/crossfade.hpp"
1516
#include <wayfire/window-manager.hpp>
@@ -55,6 +56,13 @@ class wayfire_grid : public wf::plugin_interface_t, public wf::per_output_tracke
5556
std::vector<std::string> slots = {"unused", "bl", "b", "br", "l", "c", "r", "tl", "t", "tr"};
5657
wf::ipc_activator_t bindings[10];
5758
wf::ipc_activator_t restore{"grid/restore"};
59+
wf::option_wrapper_t<int> snap_threshold{"move/snap_threshold"};
60+
wf::option_wrapper_t<int> quarter_snap_threshold{"move/quarter_snap_threshold"};
61+
struct
62+
{
63+
std::shared_ptr<wf::preview_indication_t> preview;
64+
wf::grid::slot_t slot_id = wf::grid::SLOT_NONE;
65+
} slot;
5866

5967
wf::plugin_activation_data_t grab_interface{
6068
.name = "grid",
@@ -102,13 +110,60 @@ class wayfire_grid : public wf::plugin_interface_t, public wf::per_output_tracke
102110
});
103111
}
104112

105-
wf::get_core().connect(&grid_request_signal_cb);
113+
wf::get_core().connect(&grid_handle_move_signal_cb);
106114
}
107115

108-
wf::signal::connection_t<wf::grid::grid_request_signal> grid_request_signal_cb =
109-
[=] (wf::grid::grid_request_signal *ev)
116+
wf::signal::connection_t<wf::grid::grid_handle_move_signal> grid_handle_move_signal_cb =
117+
[=] (wf::grid::grid_handle_move_signal *ev)
110118
{
111119
ev->carried_out = true;
120+
wf::grid::slot_t new_slot_id = ev->operation == wf::grid::MOVE_OP_CLEAR_PREVIEW ?
121+
wf::grid::slot_t::SLOT_NONE :
122+
wf::grid::calc_slot(ev->output, ev->input, snap_threshold, quarter_snap_threshold);
123+
124+
if ((ev->operation == wf::grid::MOVE_OP_DROP) && new_slot_id)
125+
{
126+
ev->view->toplevel()->pending().tiled_edges = wf::grid::get_tiled_edges_for_slot(new_slot_id);
127+
auto desired_size = wf::grid::get_slot_dimensions(ev->view->get_output(), new_slot_id);
128+
ev->view->get_data_safe<wf_grid_slot_data>()->slot = new_slot_id;
129+
ensure_grid_view(ev->view)->adjust_target_geometry(
130+
adjust_for_workspace(ev->view->get_wset(), desired_size,
131+
ev->view->get_output()->wset()->get_current_workspace()),
132+
ev->view->toplevel()->pending().tiled_edges);
133+
new_slot_id = wf::grid::slot_t::SLOT_NONE;
134+
}
135+
136+
/* No changes in the slot, just return */
137+
if (slot.slot_id == new_slot_id)
138+
{
139+
return;
140+
}
141+
142+
/* Destroy previous preview */
143+
if (slot.preview)
144+
{
145+
auto input = ev->input;
146+
slot.preview->set_target_geometry({input.x, input.y, 1, 1}, 0, true);
147+
slot.preview = nullptr;
148+
}
149+
150+
slot.slot_id = new_slot_id;
151+
152+
/* Show a preview overlay */
153+
if (new_slot_id)
154+
{
155+
wf::geometry_t slot_geometry = wf::grid::get_slot_dimensions(ev->output, new_slot_id);
156+
/* Unknown slot geometry, can't show a preview */
157+
if ((slot_geometry.width <= 0) || (slot_geometry.height <= 0))
158+
{
159+
return;
160+
}
161+
162+
auto input = ev->input;
163+
slot.preview = std::make_shared<wf::preview_indication_t>(
164+
wf::geometry_t{input.x, input.y, 1, 1}, ev->output, "move");
165+
slot.preview->set_target_geometry(slot_geometry, 1);
166+
}
112167
};
113168

114169
void handle_new_output(wf::output_t *output) override

plugins/grid/wayfire/plugins/grid.hpp

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,28 @@ namespace wf
88
{
99
namespace grid
1010
{
11+
enum move_op_t
12+
{
13+
MOVE_OP_CLEAR_PREVIEW = 0,
14+
MOVE_OP_UPDATE_PREVIEW = 1,
15+
MOVE_OP_DROP = 2,
16+
};
17+
1118
/**
1219
* name: request
1320
* on: core
1421
* when: Emitted before move renders a grid indicator and sets the slot.
1522
* carried_out: true if a plugin can handle move request to grid.
1623
*/
17-
struct grid_request_signal
24+
struct grid_handle_move_signal
1825
{
1926
/* True if a plugin handled this signal */
2027
bool carried_out = false;
28+
move_op_t operation;
29+
wf::output_t *output;
30+
/* input coordinates in output-local space */
31+
wf::point_t input;
32+
wayfire_toplevel_view view;
2133
};
2234

2335
/**
@@ -118,5 +130,55 @@ inline wf::geometry_t get_slot_dimensions(wf::output_t *output, int n)
118130

119131
return area;
120132
}
133+
134+
/* Calculate the slot to which the view would be snapped if the input
135+
* is released at output-local coordinates (x, y) */
136+
inline wf::grid::slot_t calc_slot(wf::output_t *output, wf::point_t point, int snap_threshold,
137+
int quarter_snap_threshold)
138+
{
139+
auto g = output->workarea->get_workarea();
140+
141+
int threshold = snap_threshold;
142+
143+
bool is_left = point.x - g.x <= threshold;
144+
bool is_right = g.x + g.width - point.x <= threshold;
145+
bool is_top = point.y - g.y < threshold;
146+
bool is_bottom = g.x + g.height - point.y < threshold;
147+
148+
bool is_far_left = point.x - g.x <= quarter_snap_threshold;
149+
bool is_far_right = g.x + g.width - point.x <= quarter_snap_threshold;
150+
bool is_far_top = point.y - g.y < quarter_snap_threshold;
151+
bool is_far_bottom = g.x + g.height - point.y < quarter_snap_threshold;
152+
153+
wf::grid::slot_t slot = wf::grid::SLOT_NONE;
154+
if ((is_left && is_far_top) || (is_far_left && is_top))
155+
{
156+
slot = wf::grid::SLOT_TL;
157+
} else if ((is_right && is_far_top) || (is_far_right && is_top))
158+
{
159+
slot = wf::grid::SLOT_TR;
160+
} else if ((is_right && is_far_bottom) || (is_far_right && is_bottom))
161+
{
162+
slot = wf::grid::SLOT_BR;
163+
} else if ((is_left && is_far_bottom) || (is_far_left && is_bottom))
164+
{
165+
slot = wf::grid::SLOT_BL;
166+
} else if (is_right)
167+
{
168+
slot = wf::grid::SLOT_RIGHT;
169+
} else if (is_left)
170+
{
171+
slot = wf::grid::SLOT_LEFT;
172+
} else if (is_top)
173+
{
174+
// Maximize when dragging to the top
175+
slot = wf::grid::SLOT_CENTER;
176+
} else if (is_bottom)
177+
{
178+
slot = wf::grid::SLOT_BOTTOM;
179+
}
180+
181+
return slot;
182+
}
121183
}
122184
}

0 commit comments

Comments
 (0)