diff --git a/README.md b/README.md index 8df9b4c..c770f66 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t ### Changelog: -2019-09-14 - Added setborderpx, selfrestart and push (no master variant) patches +2019-09-14 - Added setborderpx, selfrestart and push (no master variant), sticky and warp patches 2019-09-13 - Added titlecolor and push patches @@ -128,12 +128,15 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t - [statuspadding](https://dwm.suckless.org/patches/statuspadding/) - adds configuration options for horizontal and vertical padding in the status bar - - [systray](https://dwm.suckless.org/patches/systray/) - - adds system tray in the status bar + - [sticky](https://dwm.suckless.org/patches/sticky/) + - adds toggleable keyboard shortcut to make a client 'sticky', i.e. visible on all tags - [switchtag](https://github.com/bakkeby/dwm-vanitygaps/blob/master/patches/dwm-switchtag-6.2.diff) - when an application opens on a specific tab this patch adds the option to also switch to that tag when the application starts + - [systray](https://dwm.suckless.org/patches/systray/) + - adds system tray in the status bar + - [tagallmon](https://github.com/bakkeby/dwm-vanitygaps/blob/master/patches/dwm-tagallmon-6.2.diff) - move all visible windows to an adjacent monitor @@ -152,6 +155,9 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t - [vanitygaps](https://github.com/bakkeby/dwm-vanitygaps/blob/master/patches/dwm-vanitygaps-6.2.diff) - adds configurable gaps between windows differentiating between outer, inner, horizontal and vertical gaps + - [warp](https://dwm.suckless.org/patches/warp/) + - warps the mouse cursor to the center of the currently focused window or screen when the mouse cursor is (a) on a different screen or (b) on top of a different window + - [windowrolerule](https://github.com/bakkeby/dwm-vanitygaps/blob/master/patches/dwm-windowrolerule-6.2.diff) - sometimes a single application opens different windows depending on the task at hand and this is often reflected in the WM_WINDOW_ROLE(STRING) x property - this patch adds the role field to the rule configuration so that one can differentiate between, say, Firefox "browser" vs "Preferences" vs "Manager" or Google-chrome "browser" vs "pop-up". diff --git a/config.def.h b/config.def.h index 11301d7..8a26760 100644 --- a/config.def.h +++ b/config.def.h @@ -299,6 +299,9 @@ static Key keys[] = { #if TOGGLEFULLSCREEN_PATCH { MODKEY, XK_y, togglefullscreen, {0} }, #endif // TOGGLEFULLSCREEN_PATCH + #if STICKY_PATCH + { MODKEY, XK_s, togglesticky, {0} }, + #endif // STICKY_PATCH { MODKEY, XK_0, view, {.ui = ~0 } }, { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, { MODKEY, XK_comma, focusmon, {.i = -1 } }, diff --git a/dwm.c b/dwm.c index 059d5b8..1d4f2c4 100644 --- a/dwm.c +++ b/dwm.c @@ -50,9 +50,14 @@ #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) #define INTERSECT(x,y,w,h,m) (MAX(0, MIN((x)+(w),(m)->wx+(m)->ww) - MAX((x),(m)->wx)) \ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) -#if ATTACHASIDE_PATCH +#if ATTACHASIDE_PATCH && STICKY_PATCH +#define ISVISIBLEONTAG(C, T) ((C->tags & T) || C->issticky) +#define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) +#elif ATTACHASIDE_PATCH #define ISVISIBLEONTAG(C, T) ((C->tags & T)) #define ISVISIBLE(C) ISVISIBLEONTAG(C, C->mon->tagset[C->mon->seltags]) +#elif STICKY_PATCH +#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]) || C->issticky) #else #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) #endif // ATTACHASIDE_PATCH @@ -138,6 +143,9 @@ struct Client { #if CENTER_PATCH int iscentered; #endif // CENTER_PATCH + #if STICKY_PATCH + int issticky; + #endif // STICKY_PATCH Client *next; Client *snext; Monitor *mon; @@ -1323,6 +1331,9 @@ focusmon(const Arg *arg) unfocus(selmon->sel, 0); selmon = m; focus(NULL); + #if WARP_PATCH + warp(selmon->sel); + #endif // WARP_PATCH } void @@ -2007,6 +2018,10 @@ restack(Monitor *m) } XSync(dpy, False); while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + #if WARP_PATCH + if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && selmon->lt[selmon->sellt] != &layouts[2]) + warp(m->sel); + #endif // WARP_PATCH } void diff --git a/patch/include.c b/patch/include.c index 86de400..cc528bc 100644 --- a/patch/include.c +++ b/patch/include.c @@ -58,6 +58,10 @@ #include "setborderpx.c" #endif +#if STICKY_PATCH +#include "sticky.c" +#endif + #if SYSTRAY_PATCH #include "systray.c" #endif @@ -78,6 +82,10 @@ #include "vanitygaps.c" #endif +#if WARP_PATCH +#include "warp.c" +#endif + #if ZOOMSWAP_PATCH #include "zoomswap.c" #endif diff --git a/patch/include.h b/patch/include.h index e2d73df..4957e09 100644 --- a/patch/include.h +++ b/patch/include.h @@ -54,6 +54,10 @@ #include "setborderpx.h" #endif +#if STICKY_PATCH +#include "sticky.h" +#endif + #if SYSTRAY_PATCH #include "systray.h" #endif diff --git a/patch/push.c b/patch/push.c index beeea91..ae35928 100644 --- a/patch/push.c +++ b/patch/push.c @@ -34,7 +34,7 @@ pushup(const Arg *arg) if (selmon->clients == c) selmon->clients = sel; else { - for (c f selmon->clients; c->next != sel->next; c = c->next); + for (c = selmon->clients; c->next != sel->next; c = c->next); c->next = sel; } } else { diff --git a/patch/sticky.c b/patch/sticky.c new file mode 100644 index 0000000..54bd403 --- /dev/null +++ b/patch/sticky.c @@ -0,0 +1,8 @@ +void +togglesticky(const Arg *arg) +{ + if (!selmon->sel) + return; + selmon->sel->issticky = !selmon->sel->issticky; + arrange(selmon); +} \ No newline at end of file diff --git a/patch/sticky.h b/patch/sticky.h new file mode 100644 index 0000000..a7c35ab --- /dev/null +++ b/patch/sticky.h @@ -0,0 +1 @@ +static void togglesticky(const Arg *arg); \ No newline at end of file diff --git a/patch/warp.c b/patch/warp.c new file mode 100644 index 0000000..0989de7 --- /dev/null +++ b/patch/warp.c @@ -0,0 +1,21 @@ +void +warp(const Client *c) +{ + int x, y; + + if (!c) { + XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww/2, selmon->wy + selmon->wh/2); + return; + } + + if (!getrootptr(&x, &y) || + (x > c->x - c->bw && + y > c->y - c->bw && + x < c->x + c->w + c->bw*2 && + y < c->y + c->h + c->bw*2) || + (y > c->mon->by && y < c->mon->by + bh) || + (c->mon->topbar && !y)) + return; + + XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2); +} \ No newline at end of file diff --git a/patch/warp.h b/patch/warp.h new file mode 100644 index 0000000..6657dc1 --- /dev/null +++ b/patch/warp.h @@ -0,0 +1 @@ +static void warp(const Client *c); \ No newline at end of file diff --git a/patches.h b/patches.h index f19a125..bd5359f 100644 --- a/patches.h +++ b/patches.h @@ -210,6 +210,11 @@ */ #define STATUSPADDING_PATCH 0 +/* Adds toggleable keyboard shortcut to make a client 'sticky', i.e. visible on all tags. + * https://dwm.suckless.org/patches/sticky/ + */ +#define STICKY_PATCH 0 + /* The systray patch adds systray for the status bar. * https://dwm.suckless.org/patches/systray/ */ @@ -265,6 +270,12 @@ */ #define VANITYGAPS_PATCH 0 +/* This patch warps the mouse cursor to the center of the currently focused window or screen + * when the mouse cursor is (a) on a different screen or (b) on top of a different window. + * https://dwm.suckless.org/patches/warp/ + */ +#define WARP_PATCH 0 + /* Sometimes a single application opens different windows depending on the task * at hand and this is often reflected in the WM_WINDOW_ROLE(STRING) x property. * This patch adds the role field to the rule configuration so that one can