From a365060566fa0295f62b982c82456092774b79fa Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Tue, 16 Apr 2024 12:40:50 +0200 Subject: [PATCH 01/19] directional target window draft --- src/action.c | 53 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/action.c b/src/action.c index 677e13da..d85d1920 100644 --- a/src/action.c +++ b/src/action.c @@ -1,4 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only +#include +#include #define _POSIX_C_SOURCE 200809L #include #include @@ -71,6 +73,7 @@ enum action_type { ACTION_TYPE_SNAP_TO_EDGE, ACTION_TYPE_GROW_TO_EDGE, ACTION_TYPE_SHRINK_TO_EDGE, + ACTION_TYPE_DIRECTIONAL_TARGET_WINDOW, ACTION_TYPE_NEXT_WINDOW, ACTION_TYPE_PREVIOUS_WINDOW, ACTION_TYPE_RECONFIGURE, @@ -124,6 +127,7 @@ const char *action_names[] = { "SnapToEdge", "GrowToEdge", "ShrinkToEdge", + "DirectionalTargetWindow", "NextWindow", "PreviousWindow", "Reconfigure", @@ -304,6 +308,7 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char /* Falls through */ case ACTION_TYPE_SNAP_TO_EDGE: case ACTION_TYPE_GROW_TO_EDGE: + case ACTION_TYPE_DIRECTIONAL_TARGET_WINDOW: case ACTION_TYPE_SHRINK_TO_EDGE: if (!strcmp(argument, "direction")) { enum view_edge edge = view_edge_parse(content); @@ -492,6 +497,7 @@ action_is_valid(struct action *action) case ACTION_TYPE_EXECUTE: arg_name = "command"; break; + case ACTION_TYPE_DIRECTIONAL_TARGET_WINDOW: case ACTION_TYPE_MOVE_TO_EDGE: case ACTION_TYPE_SNAP_TO_EDGE: case ACTION_TYPE_GROW_TO_EDGE: @@ -748,6 +754,53 @@ actions_run(struct view *activator, struct server *server, view_shrink_to_edge(view, edge); } break; + case ACTION_TYPE_DIRECTIONAL_TARGET_WINDOW: + if (view) { + /* Config parsing makes sure that direction is a valid direction */ + struct wl_array views; + struct view **item; + enum view_edge direction = action_get_int(action, "direction", 0); + int distance, dx, dy; + int min_distance = INT_MAX; + struct view *nearest_view = NULL; + wl_array_init(&views); + view_array_append(server, &views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE); + wl_array_for_each(item, &views) { + if (*item == view) { + continue; + } + if ((*item)->minimized) { + continue; + } + dx = (*item)->current.x - view->current.x; + dy = (*item)->current.y - view->current.y; + switch (direction) { + case VIEW_EDGE_LEFT: + if (dx >= 0) continue; + break; + case VIEW_EDGE_RIGHT: + if (dx <= 0) continue; + break; + case VIEW_EDGE_DOWN: + if (dy <= 0) continue; + break; + case VIEW_EDGE_UP: + if (dy >= 0) continue; + break; + default: + continue; + } + distance = dx*dx + dy*dy; + if (distance < min_distance) { + min_distance = distance; + nearest_view = *item; + } + } + if (nearest_view) { + desktop_focus_view(nearest_view, /*raise*/ true); + } + } + break; case ACTION_TYPE_NEXT_WINDOW: server->osd_state.cycle_view = desktop_cycle_view(server, server->osd_state.cycle_view, LAB_CYCLE_DIR_FORWARD); From ca3f58c1ffc07687312186d5da13298a23190798 Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Tue, 16 Apr 2024 12:48:15 +0200 Subject: [PATCH 02/19] move down imports --- src/action.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/action.c b/src/action.c index d85d1920..db7b7a4f 100644 --- a/src/action.c +++ b/src/action.c @@ -1,12 +1,12 @@ // SPDX-License-Identifier: GPL-2.0-only -#include -#include #define _POSIX_C_SOURCE 200809L #include #include #include #include #include +#include +#include #include #include "action.h" #include "common/macros.h" From 766e506500df6e768df913dfbfa038a42e336e2d Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Tue, 16 Apr 2024 22:36:48 +0200 Subject: [PATCH 03/19] cleaned up --- src/action.c | 48 ++++++++++++++++-------------------------------- 1 file changed, 16 insertions(+), 32 deletions(-) diff --git a/src/action.c b/src/action.c index db7b7a4f..3f579093 100644 --- a/src/action.c +++ b/src/action.c @@ -756,48 +756,32 @@ actions_run(struct view *activator, struct server *server, break; case ACTION_TYPE_DIRECTIONAL_TARGET_WINDOW: if (view) { - /* Config parsing makes sure that direction is a valid direction */ - struct wl_array views; - struct view **item; + int dx, dy, distance; enum view_edge direction = action_get_int(action, "direction", 0); - int distance, dx, dy; + struct view *v; + struct view *closest_view = NULL; int min_distance = INT_MAX; - struct view *nearest_view = NULL; - wl_array_init(&views); - view_array_append(server, &views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE); - wl_array_for_each(item, &views) { - if (*item == view) { + for_each_view(v, &server->views, + LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) { + if (v->minimized) { continue; } - if ((*item)->minimized) { + dx = v->current.x - view->current.x; + dy = v->current.y - view->current.y; + distance = dx * dx + dy * dy; + if ((direction == VIEW_EDGE_UP && dy >= 0) + || (direction == VIEW_EDGE_LEFT && dx >= 0) + || (direction == VIEW_EDGE_DOWN && dy <= 0) + || (direction == VIEW_EDGE_RIGHT && dx <= 0)) { continue; } - dx = (*item)->current.x - view->current.x; - dy = (*item)->current.y - view->current.y; - switch (direction) { - case VIEW_EDGE_LEFT: - if (dx >= 0) continue; - break; - case VIEW_EDGE_RIGHT: - if (dx <= 0) continue; - break; - case VIEW_EDGE_DOWN: - if (dy <= 0) continue; - break; - case VIEW_EDGE_UP: - if (dy >= 0) continue; - break; - default: - continue; - } - distance = dx*dx + dy*dy; if (distance < min_distance) { min_distance = distance; - nearest_view = *item; + closest_view = v; } } - if (nearest_view) { - desktop_focus_view(nearest_view, /*raise*/ true); + if (closest_view) { + desktop_focus_view(closest_view, /*raise*/ true); } } break; From b35256831ea118798cbeb48aec7d05d326f782d7 Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Tue, 16 Apr 2024 22:45:09 +0200 Subject: [PATCH 04/19] manpage --- docs/labwc-actions.5.scd | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd index 3353fcfa..b6722d3b 100644 --- a/docs/labwc-actions.5.scd +++ b/docs/labwc-actions.5.scd @@ -70,6 +70,11 @@ Actions are used in menus and keyboard/mouse bindings. *direction* [left|up|right|down] Direction in which to shrink. +** + Focus jumps to closest window in given direction. + + *direction* [left|up|right|down] Direction in which to shrink. + ** Move to position (x, y). From ddaca80d2ad057605bec13523a4eeef46bcff564 Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Tue, 16 Apr 2024 23:00:19 +0200 Subject: [PATCH 05/19] remove spaces --- src/action.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/action.c b/src/action.c index 3f579093..6edfd457 100644 --- a/src/action.c +++ b/src/action.c @@ -762,7 +762,7 @@ actions_run(struct view *activator, struct server *server, struct view *closest_view = NULL; int min_distance = INT_MAX; for_each_view(v, &server->views, - LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) { + LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) { if (v->minimized) { continue; } @@ -770,9 +770,9 @@ actions_run(struct view *activator, struct server *server, dy = v->current.y - view->current.y; distance = dx * dx + dy * dy; if ((direction == VIEW_EDGE_UP && dy >= 0) - || (direction == VIEW_EDGE_LEFT && dx >= 0) - || (direction == VIEW_EDGE_DOWN && dy <= 0) - || (direction == VIEW_EDGE_RIGHT && dx <= 0)) { + || (direction == VIEW_EDGE_LEFT && dx >= 0) + || (direction == VIEW_EDGE_DOWN && dy <= 0) + || (direction == VIEW_EDGE_RIGHT && dx <= 0)) { continue; } if (distance < min_distance) { From 97c6531d4c2bfb3c0657eb0803d00574dfad5218 Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Tue, 16 Apr 2024 23:09:40 +0200 Subject: [PATCH 06/19] removed space --- docs/labwc-actions.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd index b6722d3b..885bf711 100644 --- a/docs/labwc-actions.5.scd +++ b/docs/labwc-actions.5.scd @@ -71,7 +71,7 @@ Actions are used in menus and keyboard/mouse bindings. *direction* [left|up|right|down] Direction in which to shrink. ** - Focus jumps to closest window in given direction. + Focus jumps to closest window in given direction. *direction* [left|up|right|down] Direction in which to shrink. From c0d15bbab4caceca1799090628411067a2fd571a Mon Sep 17 00:00:00 2001 From: nicolas3121 <107558544+nicolas3121@users.noreply.github.com> Date: Tue, 16 Apr 2024 23:15:39 +0200 Subject: [PATCH 07/19] Update labwc-actions.5.scd left mistake in manpage --- docs/labwc-actions.5.scd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd index 885bf711..66f7fac4 100644 --- a/docs/labwc-actions.5.scd +++ b/docs/labwc-actions.5.scd @@ -73,7 +73,7 @@ Actions are used in menus and keyboard/mouse bindings. ** Focus jumps to closest window in given direction. - *direction* [left|up|right|down] Direction in which to shrink. + *direction* [left|up|right|down] Direction in which to jump. ** Move to position (x, y). From c4f32e3ba80fb42081815b12edc7f4fbd7719285 Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Sat, 20 Apr 2024 10:24:44 +0200 Subject: [PATCH 08/19] moved logic into seperate function and got wrapping working --- src/action.c | 105 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 24 deletions(-) diff --git a/src/action.c b/src/action.c index 6edfd457..fce668cb 100644 --- a/src/action.c +++ b/src/action.c @@ -668,6 +668,85 @@ run_if_action(struct view *view, struct server *server, struct action *action) return !strcmp(branch, "then"); } +static struct view* +directional_target_window(struct view *view, struct server *server, enum view_edge direction, bool wrap) +{ + int dx, dy, distance, distance_wrap; + struct view *v; + struct view *closest_view = NULL; + struct view *closest_view_wrap = NULL; + int min_distance = INT_MAX; + int min_distance_wrap = INT_MAX; + struct output *output = view->output; + struct wlr_box usable = output_usable_area_in_layout_coords(output); + int cx = view->current.x + view->current.width/2; + int cy = view->current.y + view-> current.height/2; + for_each_view(v, &server->views, + LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) { + if (v->minimized) { + continue; + } + if (v == view) { + continue; + } + dx = v->current.x + v->current.width/2 - cx; + dy = v->current.y + v->current.height/2 - cy; + distance = dx * dx + dy * dy; + distance_wrap = INT_MAX; + switch(direction) { + case VIEW_EDGE_LEFT: + if (dx == 0) continue; + if (dx > 0) { + distance = INT_MAX; + dx = usable.width - dx; + distance_wrap = dx * dx + dy * dy; + } + break; + case VIEW_EDGE_RIGHT: + if (dx == 0) continue; + if (dx < 0) { + distance = INT_MAX; + dx = usable.width + dx; + distance_wrap = dx * dx + dy * dy; + } + break; + case VIEW_EDGE_UP: + if (dy == 0) continue; + if (dy > 0) { + distance = INT_MAX; + dy = usable.height - dy; + distance_wrap = dx * dx + dy * dy; + } + break; + case VIEW_EDGE_DOWN: + if (dy == 0) continue; + if (dy < 0) { + distance = INT_MAX; + dy = usable.height + dy; + distance_wrap = dx * dx + dy * dy; + } + break; + default: + wlr_log(WLR_ERROR, "invalid direction"); + return NULL; + } + if (distance < min_distance) { + min_distance = distance; + closest_view = v; + } else if (distance_wrap < min_distance_wrap) { + min_distance_wrap = distance_wrap; + closest_view_wrap = v; + } + } + if (closest_view) { + return closest_view; + } + if (closest_view_wrap && wrap) { + return closest_view_wrap; + } + return NULL; +} + void actions_run(struct view *activator, struct server *server, struct wl_list *actions, uint32_t resize_edges) @@ -756,32 +835,10 @@ actions_run(struct view *activator, struct server *server, break; case ACTION_TYPE_DIRECTIONAL_TARGET_WINDOW: if (view) { - int dx, dy, distance; enum view_edge direction = action_get_int(action, "direction", 0); - struct view *v; - struct view *closest_view = NULL; - int min_distance = INT_MAX; - for_each_view(v, &server->views, - LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) { - if (v->minimized) { - continue; - } - dx = v->current.x - view->current.x; - dy = v->current.y - view->current.y; - distance = dx * dx + dy * dy; - if ((direction == VIEW_EDGE_UP && dy >= 0) - || (direction == VIEW_EDGE_LEFT && dx >= 0) - || (direction == VIEW_EDGE_DOWN && dy <= 0) - || (direction == VIEW_EDGE_RIGHT && dx <= 0)) { - continue; - } - if (distance < min_distance) { - min_distance = distance; - closest_view = v; - } - } + struct view* closest_view = directional_target_window(view, server, direction, true); if (closest_view) { - desktop_focus_view(closest_view, /*raise*/ true); + desktop_focus_view(closest_view, true); } } break; From e059e781f332792b3b0ac70f1f6134da32a920a8 Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Sat, 20 Apr 2024 10:45:10 +0200 Subject: [PATCH 09/19] style issues --- src/action.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/action.c b/src/action.c index fce668cb..d016249c 100644 --- a/src/action.c +++ b/src/action.c @@ -679,8 +679,8 @@ directional_target_window(struct view *view, struct server *server, enum view_ed int min_distance_wrap = INT_MAX; struct output *output = view->output; struct wlr_box usable = output_usable_area_in_layout_coords(output); - int cx = view->current.x + view->current.width/2; - int cy = view->current.y + view-> current.height/2; + int cx = view->current.x + view->current.width / 2; + int cy = view->current.y + view->current.height / 2; for_each_view(v, &server->views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) { if (v->minimized) { @@ -693,9 +693,11 @@ directional_target_window(struct view *view, struct server *server, enum view_ed dy = v->current.y + v->current.height/2 - cy; distance = dx * dx + dy * dy; distance_wrap = INT_MAX; - switch(direction) { + switch (direction) { case VIEW_EDGE_LEFT: - if (dx == 0) continue; + if (dx == 0) { + continue; + } if (dx > 0) { distance = INT_MAX; dx = usable.width - dx; @@ -703,7 +705,9 @@ directional_target_window(struct view *view, struct server *server, enum view_ed } break; case VIEW_EDGE_RIGHT: - if (dx == 0) continue; + if (dx == 0) { + continue; + } if (dx < 0) { distance = INT_MAX; dx = usable.width + dx; @@ -711,7 +715,9 @@ directional_target_window(struct view *view, struct server *server, enum view_ed } break; case VIEW_EDGE_UP: - if (dy == 0) continue; + if (dy == 0) { + continue; + } if (dy > 0) { distance = INT_MAX; dy = usable.height - dy; @@ -719,7 +725,9 @@ directional_target_window(struct view *view, struct server *server, enum view_ed } break; case VIEW_EDGE_DOWN: - if (dy == 0) continue; + if (dy == 0) { + continue; + } if (dy < 0) { distance = INT_MAX; dy = usable.height + dy; @@ -836,9 +844,10 @@ actions_run(struct view *activator, struct server *server, case ACTION_TYPE_DIRECTIONAL_TARGET_WINDOW: if (view) { enum view_edge direction = action_get_int(action, "direction", 0); - struct view* closest_view = directional_target_window(view, server, direction, true); + struct view *closest_view = directional_target_window(view, server, direction, + /*wrap*/ true); if (closest_view) { - desktop_focus_view(closest_view, true); + desktop_focus_view(closest_view, /*raise*/ true); } } break; From 8c737d6e231c97e78dc230fc5881417336f4829e Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Sat, 20 Apr 2024 10:49:20 +0200 Subject: [PATCH 10/19] trailing whitespace --- src/action.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/action.c b/src/action.c index d016249c..eda1ff51 100644 --- a/src/action.c +++ b/src/action.c @@ -734,7 +734,7 @@ directional_target_window(struct view *view, struct server *server, enum view_ed distance_wrap = dx * dx + dy * dy; } break; - default: + default: wlr_log(WLR_ERROR, "invalid direction"); return NULL; } @@ -844,8 +844,7 @@ actions_run(struct view *activator, struct server *server, case ACTION_TYPE_DIRECTIONAL_TARGET_WINDOW: if (view) { enum view_edge direction = action_get_int(action, "direction", 0); - struct view *closest_view = directional_target_window(view, server, direction, - /*wrap*/ true); + struct view *closest_view = directional_target_window(view, server, direction, /*wrap*/ true); if (closest_view) { desktop_focus_view(closest_view, /*raise*/ true); } From 4a96d1edddb7088b25ba32366e9814fbcac470c6 Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Sat, 20 Apr 2024 11:06:36 +0200 Subject: [PATCH 11/19] broke up long lines --- src/action.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/action.c b/src/action.c index eda1ff51..0d2d00a3 100644 --- a/src/action.c +++ b/src/action.c @@ -669,7 +669,8 @@ run_if_action(struct view *view, struct server *server, struct action *action) } static struct view* -directional_target_window(struct view *view, struct server *server, enum view_edge direction, bool wrap) +directional_target_window(struct view *view, struct server *server, + enum view_edge direction, bool wrap) { int dx, dy, distance, distance_wrap; struct view *v; @@ -844,7 +845,8 @@ actions_run(struct view *activator, struct server *server, case ACTION_TYPE_DIRECTIONAL_TARGET_WINDOW: if (view) { enum view_edge direction = action_get_int(action, "direction", 0); - struct view *closest_view = directional_target_window(view, server, direction, /*wrap*/ true); + struct view *closest_view = directional_target_window(view, server, + direction, /*wrap*/ true); if (closest_view) { desktop_focus_view(closest_view, /*raise*/ true); } From 9b079b70a06ced2c5b2be70b67a0c696a618300f Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Sat, 20 Apr 2024 11:10:22 +0200 Subject: [PATCH 12/19] update manpage --- docs/labwc-actions.5.scd | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd index 66f7fac4..f3e6fb49 100644 --- a/docs/labwc-actions.5.scd +++ b/docs/labwc-actions.5.scd @@ -71,9 +71,9 @@ Actions are used in menus and keyboard/mouse bindings. *direction* [left|up|right|down] Direction in which to shrink. ** - Focus jumps to closest window in given direction. + Move focus to closest window in given direction. - *direction* [left|up|right|down] Direction in which to jump. + *direction* [left|up|right|down] Direction in which to move. ** Move to position (x, y). From 2de12b59793f7e55e7e97ebf08f0833486dd10a8 Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Sat, 20 Apr 2024 11:12:34 +0200 Subject: [PATCH 13/19] forgot to double indent line --- src/action.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/action.c b/src/action.c index 0d2d00a3..10edafc6 100644 --- a/src/action.c +++ b/src/action.c @@ -683,7 +683,7 @@ directional_target_window(struct view *view, struct server *server, int cx = view->current.x + view->current.width / 2; int cy = view->current.y + view->current.height / 2; for_each_view(v, &server->views, - LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) { + LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) { if (v->minimized) { continue; } From 197eabf26150c6a2e26eae8f54aeba64950a4100 Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Sat, 20 Apr 2024 11:16:00 +0200 Subject: [PATCH 14/19] removed redundant check --- src/action.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/action.c b/src/action.c index 10edafc6..51edf5b7 100644 --- a/src/action.c +++ b/src/action.c @@ -687,9 +687,6 @@ directional_target_window(struct view *view, struct server *server, if (v->minimized) { continue; } - if (v == view) { - continue; - } dx = v->current.x + v->current.width/2 - cx; dy = v->current.y + v->current.height/2 - cy; distance = dx * dx + dy * dy; From 7a69fffe443b2e9b272f2c7a1e740b427547fee0 Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Sat, 20 Apr 2024 17:33:19 +0200 Subject: [PATCH 15/19] fixed wrapping issues with multiple outputs --- src/action.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/action.c b/src/action.c index 51edf5b7..1d764f43 100644 --- a/src/action.c +++ b/src/action.c @@ -674,6 +674,8 @@ directional_target_window(struct view *view, struct server *server, { int dx, dy, distance, distance_wrap; struct view *v; + struct output *v_output; + struct wlr_box v_usable; struct view *closest_view = NULL; struct view *closest_view_wrap = NULL; int min_distance = INT_MAX; @@ -682,11 +684,14 @@ directional_target_window(struct view *view, struct server *server, struct wlr_box usable = output_usable_area_in_layout_coords(output); int cx = view->current.x + view->current.width / 2; int cy = view->current.y + view->current.height / 2; + assert(view); for_each_view(v, &server->views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) { if (v->minimized) { continue; } + v_output = v->output; + v_usable = output_usable_area_in_layout_coords(v_output); dx = v->current.x + v->current.width/2 - cx; dy = v->current.y + v->current.height/2 - cy; distance = dx * dx + dy * dy; @@ -698,7 +703,7 @@ directional_target_window(struct view *view, struct server *server, } if (dx > 0) { distance = INT_MAX; - dx = usable.width - dx; + dx = v_usable.x + v_usable.width - dx; distance_wrap = dx * dx + dy * dy; } break; @@ -708,7 +713,7 @@ directional_target_window(struct view *view, struct server *server, } if (dx < 0) { distance = INT_MAX; - dx = usable.width + dx; + dx = usable.x + usable.width + dx; distance_wrap = dx * dx + dy * dy; } break; @@ -718,7 +723,7 @@ directional_target_window(struct view *view, struct server *server, } if (dy > 0) { distance = INT_MAX; - dy = usable.height - dy; + dy = v_usable.y + v_usable.height - dy; distance_wrap = dx * dx + dy * dy; } break; @@ -728,12 +733,11 @@ directional_target_window(struct view *view, struct server *server, } if (dy < 0) { distance = INT_MAX; - dy = usable.height + dy; + dy = usable.y + usable.height + dy; distance_wrap = dx * dx + dy * dy; } break; default: - wlr_log(WLR_ERROR, "invalid direction"); return NULL; } if (distance < min_distance) { From f9017b389b038bebd063dc56c43f5d1c9639e370 Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Sat, 20 Apr 2024 18:23:11 +0200 Subject: [PATCH 16/19] add wrap argument --- docs/labwc-actions.5.scd | 5 ++++- src/action.c | 11 +++++++++-- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/docs/labwc-actions.5.scd b/docs/labwc-actions.5.scd index f3e6fb49..dc7e234d 100644 --- a/docs/labwc-actions.5.scd +++ b/docs/labwc-actions.5.scd @@ -70,11 +70,14 @@ Actions are used in menus and keyboard/mouse bindings. *direction* [left|up|right|down] Direction in which to shrink. -** +** Move focus to closest window in given direction. *direction* [left|up|right|down] Direction in which to move. + *wrap* [yes|no] Wrap around from right-to-left or top-to-bottom, + and vice versa. Default no. + ** Move to position (x, y). diff --git a/src/action.c b/src/action.c index 1d764f43..f0ad0993 100644 --- a/src/action.c +++ b/src/action.c @@ -300,6 +300,12 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char goto cleanup; } break; + case ACTION_TYPE_DIRECTIONAL_TARGET_WINDOW: + if (!strcasecmp(argument, "wrap")) { + action_arg_add_bool(action, argument, parse_bool(content, false)); + goto cleanup; + } + /* Falls through */ case ACTION_TYPE_MOVE_TO_EDGE: if (!strcasecmp(argument, "snapWindows")) { action_arg_add_bool(action, argument, parse_bool(content, true)); @@ -308,7 +314,6 @@ action_arg_from_xml_node(struct action *action, const char *nodename, const char /* Falls through */ case ACTION_TYPE_SNAP_TO_EDGE: case ACTION_TYPE_GROW_TO_EDGE: - case ACTION_TYPE_DIRECTIONAL_TARGET_WINDOW: case ACTION_TYPE_SHRINK_TO_EDGE: if (!strcmp(argument, "direction")) { enum view_edge edge = view_edge_parse(content); @@ -845,9 +850,11 @@ actions_run(struct view *activator, struct server *server, break; case ACTION_TYPE_DIRECTIONAL_TARGET_WINDOW: if (view) { + /* Config parsing makes sure that direction is a valid direction */ enum view_edge direction = action_get_int(action, "direction", 0); + bool wrap = action_get_bool(action, "wrap", false); struct view *closest_view = directional_target_window(view, server, - direction, /*wrap*/ true); + direction, wrap); if (closest_view) { desktop_focus_view(closest_view, /*raise*/ true); } From 29cb8078504c40d257156796b47beed4e7602d0b Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Sat, 20 Apr 2024 18:51:44 +0200 Subject: [PATCH 17/19] trailing space --- src/action.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/action.c b/src/action.c index f0ad0993..204f9775 100644 --- a/src/action.c +++ b/src/action.c @@ -850,7 +850,7 @@ actions_run(struct view *activator, struct server *server, break; case ACTION_TYPE_DIRECTIONAL_TARGET_WINDOW: if (view) { - /* Config parsing makes sure that direction is a valid direction */ + /* Config parsing makes sure that direction is a valid direction */ enum view_edge direction = action_get_int(action, "direction", 0); bool wrap = action_get_bool(action, "wrap", false); struct view *closest_view = directional_target_window(view, server, From f37fecd04d7073480a911be6a5c3b0bd305283c2 Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Mon, 22 Apr 2024 21:08:12 +0200 Subject: [PATCH 18/19] added functions to find lowest and rightmost point to fix wrapping --- src/action.c | 115 +++++++++++++++++++++++++++++++++------------------ 1 file changed, 75 insertions(+), 40 deletions(-) diff --git a/src/action.c b/src/action.c index 204f9775..32245f10 100644 --- a/src/action.c +++ b/src/action.c @@ -673,73 +673,108 @@ run_if_action(struct view *view, struct server *server, struct action *action) return !strcmp(branch, "then"); } +static int +rightmost_visible_point(struct server *server, struct view *view) +{ + struct output *output = view->output; + struct wlr_box usable = output_usable_area_in_layout_coords(output); + struct wlr_box o_usable; + struct output *o; + int rightmost_point = usable.x + usable.width; + int cy = view->current.y + view->current.height/2; + wl_list_for_each(o, &server->outputs, link) { + if (!output_is_usable(o)) { + continue; + } + o_usable = output_usable_area_in_layout_coords(o); + if (o_usable.x >= rightmost_point + && o_usable.y <= cy + && o_usable.y + o_usable.height >= cy) { + rightmost_point = o_usable.x + o_usable.width; + } + } + return rightmost_point; +} + +static int +lowest_visible_point(struct server *server, struct view *view) +{ + struct output *output = view->output; + struct wlr_box usable = output_usable_area_in_layout_coords(output); + struct wlr_box o_usable; + struct output *o; + int lowest_point = usable.y + usable.height; + int cx = view->current.x + view->current.width/2; + wl_list_for_each(o, &server->outputs, link) { + if (!output_is_usable(o)) { + continue; + } + o_usable = output_usable_area_in_layout_coords(o); + if (o_usable.y >= lowest_point + && o_usable.x <= cx + && o_usable.x + o_usable.width >= cx) { + lowest_point = o_usable.y + o_usable.height; + } + } + return lowest_point; +} + static struct view* directional_target_window(struct view *view, struct server *server, enum view_edge direction, bool wrap) { - int dx, dy, distance, distance_wrap; + assert(view); struct view *v; - struct output *v_output; - struct wlr_box v_usable; struct view *closest_view = NULL; struct view *closest_view_wrap = NULL; - int min_distance = INT_MAX; - int min_distance_wrap = INT_MAX; struct output *output = view->output; struct wlr_box usable = output_usable_area_in_layout_coords(output); - int cx = view->current.x + view->current.width / 2; - int cy = view->current.y + view->current.height / 2; - assert(view); + float dx, dy, distance, distance_wrap; + int min_distance = INT_MAX; + int min_distance_wrap = INT_MAX; for_each_view(v, &server->views, LAB_VIEW_CRITERIA_CURRENT_WORKSPACE) { if (v->minimized) { continue; } - v_output = v->output; - v_usable = output_usable_area_in_layout_coords(v_output); - dx = v->current.x + v->current.width/2 - cx; - dy = v->current.y + v->current.height/2 - cy; - distance = dx * dx + dy * dy; + distance = INT_MAX; distance_wrap = INT_MAX; + dx = v->current.x + v->current.width/2. + - view->current.x - view->current.width/2.; + dy = v->current.y + v->current.height/2. + - view->current.y - view->current.height/2.; switch (direction) { case VIEW_EDGE_LEFT: - if (dx == 0) { - continue; - } - if (dx > 0) { - distance = INT_MAX; - dx = v_usable.x + v_usable.width - dx; - distance_wrap = dx * dx + dy * dy; + if (dx < 0 && dy*dy/(dx*dx) < 2) { + distance = (dx*dx + dy*dy) * (1 + dy*dy/(dx*dx)); + } else if (dx > 0 && dy*dy/(dx*dx) < 2) { + dx = rightmost_visible_point(server, v) - dx; + distance_wrap = (dx*dx + dy*dy) * (1 + dy*dy/(dx*dx)); } break; case VIEW_EDGE_RIGHT: - if (dx == 0) { - continue; - } - if (dx < 0) { - distance = INT_MAX; + if (dx > 0 && dy*dy/(dx*dx) < 2) { + distance = (dx*dx + dy*dy) * (1 + dy*dy/(dx*dx)); + } else if (dx < 0 && dy*dy/(dx*dx) < 2) { dx = usable.x + usable.width + dx; - distance_wrap = dx * dx + dy * dy; + distance_wrap = (dx*dx + dy*dy) * (1 + dy*dy/(dx*dx)); } + break; case VIEW_EDGE_UP: - if (dy == 0) { - continue; - } - if (dy > 0) { - distance = INT_MAX; - dy = v_usable.y + v_usable.height - dy; - distance_wrap = dx * dx + dy * dy; + if (dy < 0 && dx*dx/(dy*dy) < 2) { + distance = (dx * dx + dy * dy) * (1 + dx*dx/(dy*dy)); + } else if (dy > 0 && dx*dx/(dy*dy) < 2) { + dy = lowest_visible_point(server, v) - dy; + distance_wrap = (dx*dx + dy*dy) * (1 + dx*dx/(dy*dy)); } break; case VIEW_EDGE_DOWN: - if (dy == 0) { - continue; - } - if (dy < 0) { - distance = INT_MAX; + if (dy > 0 && dx*dx/(dy*dy) < 2) { + distance = (dx*dx + dy*dy) * (1 + dx*dx/(dy*dy)); + } else if (dy < 0 && dx*dx/(dy*dy) < 2) { dy = usable.y + usable.height + dy; - distance_wrap = dx * dx + dy * dy; + distance_wrap = (dx*dx + dy*dy) * (1 + dx*dx/(dy*dy)); } break; default: @@ -756,7 +791,7 @@ directional_target_window(struct view *view, struct server *server, if (closest_view) { return closest_view; } - if (closest_view_wrap && wrap) { + if (wrap && closest_view_wrap) { return closest_view_wrap; } return NULL; From 60b7104c9e74f23f665602add47bdb305e788458 Mon Sep 17 00:00:00 2001 From: nicolas3121 Date: Mon, 22 Apr 2024 21:19:20 +0200 Subject: [PATCH 19/19] changed distances back to int --- src/action.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/action.c b/src/action.c index 32245f10..1499e47b 100644 --- a/src/action.c +++ b/src/action.c @@ -729,7 +729,8 @@ directional_target_window(struct view *view, struct server *server, struct view *closest_view_wrap = NULL; struct output *output = view->output; struct wlr_box usable = output_usable_area_in_layout_coords(output); - float dx, dy, distance, distance_wrap; + float dx, dy; + int distance, distance_wrap; int min_distance = INT_MAX; int min_distance_wrap = INT_MAX; for_each_view(v, &server->views,