diff options
author | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-09-11 21:34:21 +1000 |
---|---|---|
committer | Ryan Dwyer <ryandwyer1@gmail.com> | 2018-09-11 21:34:21 +1000 |
commit | 8bb40c24c7b045df0d43e9f22c096d1473f6f9f6 (patch) | |
tree | 0c4dbac1173f92337e2cff63d45c7d8fe7a3557f /sway/input/cursor.c | |
parent | Introduce tiling_drag directive (diff) | |
download | sway-8bb40c24c7b045df0d43e9f22c096d1473f6f9f6.tar.gz sway-8bb40c24c7b045df0d43e9f22c096d1473f6f9f6.tar.zst sway-8bb40c24c7b045df0d43e9f22c096d1473f6f9f6.zip |
Implement tiling drag
Hold floating_modifier and drag a tiling view to a new location.
Diffstat (limited to 'sway/input/cursor.c')
-rw-r--r-- | sway/input/cursor.c | 146 |
1 files changed, 146 insertions, 0 deletions
diff --git a/sway/input/cursor.c b/sway/input/cursor.c index cd87e976..b0f8e531 100644 --- a/sway/input/cursor.c +++ b/sway/input/cursor.c | |||
@@ -228,6 +228,141 @@ static void handle_move_floating_motion(struct sway_seat *seat, | |||
228 | desktop_damage_whole_container(con); | 228 | desktop_damage_whole_container(con); |
229 | } | 229 | } |
230 | 230 | ||
231 | static void resize_box(struct wlr_box *box, enum wlr_edges edge, | ||
232 | size_t thickness) { | ||
233 | switch (edge) { | ||
234 | case WLR_EDGE_TOP: | ||
235 | box->height = thickness; | ||
236 | break; | ||
237 | case WLR_EDGE_LEFT: | ||
238 | box->width = thickness; | ||
239 | break; | ||
240 | case WLR_EDGE_RIGHT: | ||
241 | box->x = box->x + box->width - thickness; | ||
242 | box->width = thickness; | ||
243 | break; | ||
244 | case WLR_EDGE_BOTTOM: | ||
245 | box->y = box->y + box->height - thickness; | ||
246 | box->height = thickness; | ||
247 | break; | ||
248 | case WLR_EDGE_NONE: | ||
249 | box->x += thickness; | ||
250 | box->y += thickness; | ||
251 | box->width -= thickness * 2; | ||
252 | box->height -= thickness * 2; | ||
253 | break; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | static void handle_move_tiling_motion(struct sway_seat *seat, | ||
258 | struct sway_cursor *cursor) { | ||
259 | struct wlr_surface *surface = NULL; | ||
260 | double sx, sy; | ||
261 | struct sway_node *node = node_at_coords(seat, | ||
262 | cursor->cursor->x, cursor->cursor->y, &surface, &sx, &sy); | ||
263 | // Damage the old location | ||
264 | desktop_damage_box(&seat->op_drop_box); | ||
265 | |||
266 | if (!node) { | ||
267 | // Eg. hovered over a layer surface such as swaybar | ||
268 | seat->op_target_node = NULL; | ||
269 | seat->op_target_edge = WLR_EDGE_NONE; | ||
270 | return; | ||
271 | } | ||
272 | |||
273 | if (node->type == N_WORKSPACE) { | ||
274 | // Emtpy workspace | ||
275 | seat->op_target_node = node; | ||
276 | seat->op_target_edge = WLR_EDGE_NONE; | ||
277 | workspace_get_box(node->sway_workspace, &seat->op_drop_box); | ||
278 | desktop_damage_box(&seat->op_drop_box); | ||
279 | return; | ||
280 | } | ||
281 | |||
282 | // Deny moving within own workspace if this is the only child | ||
283 | struct sway_container *con = node->sway_container; | ||
284 | if (workspace_num_tiling_views(seat->op_container->workspace) == 1 && | ||
285 | con->workspace == seat->op_container->workspace) { | ||
286 | seat->op_target_node = NULL; | ||
287 | seat->op_target_edge = WLR_EDGE_NONE; | ||
288 | return; | ||
289 | } | ||
290 | |||
291 | // Traverse the ancestors, trying to find a layout container perpendicular | ||
292 | // to the edge. Eg. close to the top or bottom of a horiz layout. | ||
293 | while (con) { | ||
294 | enum wlr_edges edge = WLR_EDGE_NONE; | ||
295 | enum sway_container_layout layout = container_parent_layout(con); | ||
296 | struct wlr_box parent; | ||
297 | con->parent ? container_get_box(con->parent, &parent) : | ||
298 | workspace_get_box(con->workspace, &parent); | ||
299 | if (layout == L_HORIZ || layout == L_TABBED) { | ||
300 | if (cursor->cursor->y < parent.y + 30) { | ||
301 | edge = WLR_EDGE_TOP; | ||
302 | } else if (cursor->cursor->y > parent.y + parent.height - 30) { | ||
303 | edge = WLR_EDGE_BOTTOM; | ||
304 | } | ||
305 | } else if (layout == L_VERT || layout == L_STACKED) { | ||
306 | if (cursor->cursor->x < parent.x + 30) { | ||
307 | edge = WLR_EDGE_LEFT; | ||
308 | } else if (cursor->cursor->x > parent.x + parent.width - 30) { | ||
309 | edge = WLR_EDGE_RIGHT; | ||
310 | } | ||
311 | } | ||
312 | if (edge) { | ||
313 | seat->op_target_node = node_get_parent(&con->node); | ||
314 | seat->op_target_edge = edge; | ||
315 | node_get_box(seat->op_target_node, &seat->op_drop_box); | ||
316 | resize_box(&seat->op_drop_box, edge, 30); | ||
317 | desktop_damage_box(&seat->op_drop_box); | ||
318 | return; | ||
319 | } | ||
320 | con = con->parent; | ||
321 | } | ||
322 | |||
323 | // Use the hovered view - but we must be over the actual surface | ||
324 | con = node->sway_container; | ||
325 | if (!con->view->surface || node == &seat->op_container->node) { | ||
326 | seat->op_target_node = NULL; | ||
327 | seat->op_target_edge = WLR_EDGE_NONE; | ||
328 | return; | ||
329 | } | ||
330 | |||
331 | // Find the closest edge | ||
332 | size_t thickness = fmin(con->view->width, con->view->height) * 0.3; | ||
333 | size_t closest_dist = INT_MAX; | ||
334 | size_t dist; | ||
335 | seat->op_target_edge = WLR_EDGE_NONE; | ||
336 | if ((dist = cursor->cursor->y - con->y) < closest_dist) { | ||
337 | closest_dist = dist; | ||
338 | seat->op_target_edge = WLR_EDGE_TOP; | ||
339 | } | ||
340 | if ((dist = cursor->cursor->x - con->x) < closest_dist) { | ||
341 | closest_dist = dist; | ||
342 | seat->op_target_edge = WLR_EDGE_LEFT; | ||
343 | } | ||
344 | if ((dist = con->x + con->width - cursor->cursor->x) < closest_dist) { | ||
345 | closest_dist = dist; | ||
346 | seat->op_target_edge = WLR_EDGE_RIGHT; | ||
347 | } | ||
348 | if ((dist = con->y + con->height - cursor->cursor->y) < closest_dist) { | ||
349 | closest_dist = dist; | ||
350 | seat->op_target_edge = WLR_EDGE_BOTTOM; | ||
351 | } | ||
352 | |||
353 | if (closest_dist > thickness) { | ||
354 | seat->op_target_edge = WLR_EDGE_NONE; | ||
355 | } | ||
356 | |||
357 | seat->op_target_node = node; | ||
358 | seat->op_drop_box.x = con->view->x; | ||
359 | seat->op_drop_box.y = con->view->y; | ||
360 | seat->op_drop_box.width = con->view->width; | ||
361 | seat->op_drop_box.height = con->view->height; | ||
362 | resize_box(&seat->op_drop_box, seat->op_target_edge, thickness); | ||
363 | desktop_damage_box(&seat->op_drop_box); | ||
364 | } | ||
365 | |||
231 | static void calculate_floating_constraints(struct sway_container *con, | 366 | static void calculate_floating_constraints(struct sway_container *con, |
232 | int *min_width, int *max_width, int *min_height, int *max_height) { | 367 | int *min_width, int *max_width, int *min_height, int *max_height) { |
233 | if (config->floating_minimum_width == -1) { // no minimum | 368 | if (config->floating_minimum_width == -1) { // no minimum |
@@ -405,6 +540,9 @@ void cursor_send_pointer_motion(struct sway_cursor *cursor, uint32_t time_msec, | |||
405 | case OP_MOVE_FLOATING: | 540 | case OP_MOVE_FLOATING: |
406 | handle_move_floating_motion(seat, cursor); | 541 | handle_move_floating_motion(seat, cursor); |
407 | break; | 542 | break; |
543 | case OP_MOVE_TILING: | ||
544 | handle_move_tiling_motion(seat, cursor); | ||
545 | break; | ||
408 | case OP_RESIZE_FLOATING: | 546 | case OP_RESIZE_FLOATING: |
409 | handle_resize_floating_motion(seat, cursor); | 547 | handle_resize_floating_motion(seat, cursor); |
410 | break; | 548 | break; |
@@ -751,6 +889,14 @@ void dispatch_cursor_button(struct sway_cursor *cursor, | |||
751 | } | 889 | } |
752 | } | 890 | } |
753 | 891 | ||
892 | // Handle moving a tiling container | ||
893 | if (config->tiling_drag && mod_pressed && !is_floating_or_child && | ||
894 | !cont->is_fullscreen) { | ||
895 | seat_pointer_notify_button(seat, time_msec, button, state); | ||
896 | seat_begin_move_tiling(seat, cont, button); | ||
897 | return; | ||
898 | } | ||
899 | |||
754 | // Handle mousedown on a container surface | 900 | // Handle mousedown on a container surface |
755 | if (surface && cont && state == WLR_BUTTON_PRESSED) { | 901 | if (surface && cont && state == WLR_BUTTON_PRESSED) { |
756 | seat_set_focus_container(seat, cont); | 902 | seat_set_focus_container(seat, cont); |