diff options
Diffstat (limited to 'dwl-patches/patches/swapandfocusdir/swapandfocusdir.patch')
-rw-r--r-- | dwl-patches/patches/swapandfocusdir/swapandfocusdir.patch | 221 |
1 files changed, 221 insertions, 0 deletions
diff --git a/dwl-patches/patches/swapandfocusdir/swapandfocusdir.patch b/dwl-patches/patches/swapandfocusdir/swapandfocusdir.patch new file mode 100644 index 0000000..3636387 --- /dev/null +++ b/dwl-patches/patches/swapandfocusdir/swapandfocusdir.patch @@ -0,0 +1,221 @@ +From 285470897406b653e77d732a77356aaf9a70b799 Mon Sep 17 00:00:00 2001 +From: wochap <gean.marroquin@gmail.com> +Date: Fri, 5 Jul 2024 12:37:39 -0500 +Subject: [PATCH] implement swapandfocusdir + +--- + config.def.h | 8 +++ + dwl.c | 164 +++++++++++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 172 insertions(+) + +diff --git a/config.def.h b/config.def.h +index 22d2171..724e15e 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -129,6 +129,14 @@ static const Key keys[] = { + { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Return, spawn, {.v = termcmd} }, + { MODKEY, XKB_KEY_j, focusstack, {.i = +1} }, + { MODKEY, XKB_KEY_k, focusstack, {.i = -1} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Left, focusdir, {.ui = 0} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Right, focusdir, {.ui = 1} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Up, focusdir, {.ui = 2} }, ++ { MODKEY|WLR_MODIFIER_CTRL, XKB_KEY_Down, focusdir, {.ui = 3} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Left, swapdir, {.ui = 0} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Right, swapdir, {.ui = 1} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Up, swapdir, {.ui = 2} }, ++ { MODKEY|WLR_MODIFIER_SHIFT, XKB_KEY_Down, swapdir, {.ui = 3} }, + { MODKEY, XKB_KEY_i, incnmaster, {.i = +1} }, + { MODKEY, XKB_KEY_d, incnmaster, {.i = -1} }, + { MODKEY, XKB_KEY_h, setmfact, {.f = -0.05f} }, +diff --git a/dwl.c b/dwl.c +index dc0437e..844c1f5 100644 +--- a/dwl.c ++++ b/dwl.c +@@ -241,6 +241,11 @@ typedef struct { + struct wl_listener destroy; + } SessionLock; + ++typedef struct { ++ int x; ++ int y; ++} Vector; ++ + /* function declarations */ + static void applybounds(Client *c, struct wlr_box *bbox); + static void applyrules(Client *c); +@@ -285,6 +290,8 @@ static Monitor *dirtomon(enum wlr_direction dir); + static void focusclient(Client *c, int lift); + static void focusmon(const Arg *arg); + static void focusstack(const Arg *arg); ++static void focusdir(const Arg *arg); ++static void swapdir(const Arg *arg); + static Client *focustop(Monitor *m); + static void fullscreennotify(struct wl_listener *listener, void *data); + static void handlesig(int signo); +@@ -1425,6 +1432,163 @@ focusstack(const Arg *arg) + focusclient(c, 1); + } + ++Vector ++position_of_box(const struct wlr_box *box) ++{ ++ return (Vector){ ++ .x = box->x + box->width / 2, ++ .y = box->y + box->height / 2, ++ }; ++} ++ ++Vector ++diff_of_vectors(Vector *a, Vector *b) ++{ ++ return (Vector){ ++ .x = b->x - a->x, ++ .y = b->y - a->y, ++ }; ++} ++ ++const char * ++direction_of_vector(Vector *vector) ++{ ++ // A zero length vector has no direction ++ if (vector->x == 0 && vector->y == 0) return ""; ++ ++ if (abs(vector->y) > abs(vector->x)) { ++ // Careful: We are operating in a Y-inverted coordinate system. ++ return (vector->y > 0) ? "bottom" : "top"; ++ } else { ++ return (vector->x > 0) ? "right" : "left"; ++ } ++} ++ ++uint32_t ++vector_length(Vector *vector) ++{ ++ // Euclidean distance formula ++ return (uint32_t)sqrt(vector->x * vector->x + vector->y * vector->y); ++} ++ ++// Spatial direction, based on focused client position. ++Client * ++client_in_direction(const char *direction, const int *skipfloat) ++{ ++ Client *cfocused = focustop(selmon); ++ Vector cfocusedposition; ++ Client *ctarget = NULL; ++ double targetdistance = INFINITY; ++ Client *c; ++ ++ if (!cfocused || cfocused->isfullscreen || (skipfloat && cfocused->isfloating)) ++ return NULL; ++ ++ cfocusedposition = position_of_box(&cfocused->geom); ++ ++ wl_list_for_each(c, &clients, link) { ++ Vector cposition; ++ Vector positiondiff; ++ uint32_t distance; ++ ++ if (c == cfocused) ++ continue; ++ ++ if (skipfloat && c->isfloating) ++ continue; ++ ++ if (!VISIBLEON(c, selmon)) ++ continue; ++ ++ cposition = position_of_box(&c->geom); ++ positiondiff = diff_of_vectors(&cfocusedposition, &cposition); ++ ++ if (strcmp(direction, direction_of_vector(&positiondiff)) != 0) ++ continue; ++ ++ distance = vector_length(&positiondiff); ++ ++ if (distance < targetdistance) { ++ ctarget = c; ++ targetdistance = distance; ++ } ++ } ++ ++ return ctarget; ++} ++ ++void ++focusdir(const Arg *arg) ++{ ++ Client *c = NULL; ++ ++ if (arg->ui == 0) ++ c = client_in_direction("left", (int *)0); ++ if (arg->ui == 1) ++ c = client_in_direction("right", (int *)0); ++ if (arg->ui == 2) ++ c = client_in_direction("top", (int *)0); ++ if (arg->ui == 3) ++ c = client_in_direction("bottom", (int *)0); ++ ++ if (c != NULL) ++ focusclient(c, 1); ++} ++ ++void ++wl_list_swap(struct wl_list *list1, struct wl_list *list2) ++{ ++ struct wl_list *prev1, *next1, *prev2, *next2; ++ struct wl_list temp; ++ ++ if (list1 == list2) { ++ // No need to swap the same list ++ return; ++ } ++ ++ // Get the lists before and after list1 ++ prev1 = list1->prev; ++ next1 = list1->next; ++ ++ // Get the lists before and after list2 ++ prev2 = list2->prev; ++ next2 = list2->next; ++ ++ // Update the next and previous pointers of adjacent lists ++ prev1->next = list2; ++ next1->prev = list2; ++ prev2->next = list1; ++ next2->prev = list1; ++ ++ // Swap the next and previous pointers of the lists to actually swap them ++ temp = *list1; ++ *list1 = *list2; ++ *list2 = temp; ++} ++ ++void ++swapdir(const Arg *arg) ++{ ++ Client *c = NULL; ++ Client *cfocused; ++ ++ if (arg->ui == 0) ++ c = client_in_direction("left", (int *)1); ++ if (arg->ui == 1) ++ c = client_in_direction("right", (int *)1); ++ if (arg->ui == 2) ++ c = client_in_direction("top", (int *)1); ++ if (arg->ui == 3) ++ c = client_in_direction("bottom", (int *)1); ++ ++ if (c == NULL) ++ return; ++ ++ cfocused = focustop(selmon); ++ wl_list_swap(&cfocused->link, &c->link); ++ arrange(selmon); ++} ++ + /* We probably should change the name of this, it sounds like + * will focus the topmost client of this mon, when actually will + * only return that client */ +-- +2.45.1 + |