diff --git a/README.md b/README.md index ac86e79..8c9d09d 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t ### Changelog: -2019-09-07 - Added cyclelayouts, resizecorners, rotatestack, savefloats and statuspadding patches +2019-09-07 - Added cyclelayouts, resizecorners, rotatestack, savefloats, statuspadding and windowrolerule patches 2019-09-06 - Added attachabove, attachaside, attachbelow, attachbottom, autostart, fancybar, focusonnetactive and losefullscreen patches @@ -84,5 +84,9 @@ Refer to [https://dwm.suckless.org/](https://dwm.suckless.org/) for details on t - [togglefullscreen](https://github.com/bakkeby/dwm-vanitygaps/blob/master/patches/dwm-togglefullscreen-6.2.diff) - allows you to toggle fullscreen on and off using a single shortcut key + - [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". + - [zoomswap](https://dwm.suckless.org/patches/zoomswap/) - allows a master and a stack window to swap places rather than every window on the screen changing position diff --git a/config.def.h b/config.def.h index 3f203bf..e8edf1b 100644 --- a/config.def.h +++ b/config.def.h @@ -44,10 +44,17 @@ static const Rule rules[] = { /* xprop(1): * WM_CLASS(STRING) = instance, class * WM_NAME(STRING) = title + * WM_WINDOW_ROLE(STRING) = role */ + #if WINDOWROLERULE_PATCH + /* class role instance title tags mask isfloating monitor */ + { "Gimp", NULL, NULL, NULL, 0, 1, -1 }, + { "Firefox", NULL, NULL, NULL, 1 << 8, 0, -1 }, + #else /* class instance title tags mask isfloating monitor */ { "Gimp", NULL, NULL, 0, 1, -1 }, { "Firefox", NULL, NULL, 1 << 8, 0, -1 }, + #endif }; /* layout(s) */ diff --git a/dwm.c b/dwm.c index 6edeb9a..9293609 100644 --- a/dwm.c +++ b/dwm.c @@ -75,7 +75,11 @@ enum { NetSupported, NetWMName, NetWMState, NetWMCheck, NetWMFullscreen, NetActiveWindow, NetWMWindowType, NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ #endif // SYSTRAY_PATCH +#if WINDOWROLERULE_PATCH +enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMWindowRole, WMLast }; /* default atoms */ +#else enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ +#endif // WINDOWROLERULE_PATCH enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ @@ -155,6 +159,9 @@ struct Monitor { typedef struct { const char *class; + #if WINDOWROLERULE_PATCH + const char *role; + #endif // WINDOWROLERULE_PATCH const char *instance; const char *title; unsigned int tags; @@ -317,6 +324,9 @@ void applyrules(Client *c) { const char *class, *instance; + #if WINDOWROLERULE_PATCH + char role[64]; + #endif // WINDOWROLERULE_PATCH unsigned int i; const Rule *r; Monitor *m; @@ -328,11 +338,17 @@ applyrules(Client *c) XGetClassHint(dpy, c->win, &ch); class = ch.res_class ? ch.res_class : broken; instance = ch.res_name ? ch.res_name : broken; + #if WINDOWROLERULE_PATCH + gettextprop(c->win, wmatom[WMWindowRole], role, sizeof(role)); + #endif // WINDOWROLERULE_PATCH for (i = 0; i < LENGTH(rules); i++) { r = &rules[i]; if ((!r->title || strstr(c->name, r->title)) && (!r->class || strstr(class, r->class)) + #if WINDOWROLERULE_PATCH + && (!r->role || strstr(role, r->role)) + #endif // WINDOWROLERULE_PATCH && (!r->instance || strstr(instance, r->instance))) { c->isfloating = r->isfloating; @@ -1981,6 +1997,9 @@ setup(void) wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); + #if WINDOWROLERULE_PATCH + wmatom[WMWindowRole] = XInternAtom(dpy, "WM_WINDOW_ROLE", False); + #endif // WINDOWROLERULE_PATCH netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); #if SYSTRAY_PATCH diff --git a/patches.h b/patches.h index e5fdbb1..00e3d26 100644 --- a/patches.h +++ b/patches.h @@ -134,6 +134,16 @@ */ #define TOGGLEFULLSCREEN_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 + * differentiate between, say, Firefox "browser" vs "Preferences" vs "Manager" + * or Google-chrome "browser" vs "pop-up". + * https://github.com/bakkeby/dwm-vanitygaps/blob/master/patches/dwm-windowrolerule-6.2.diff + */ +#define WINDOWROLERULE_PATCH 0 + /* The zoomswap patch allows a master and a stack window to swap places * rather than every window on the screen changing position. * https://dwm.suckless.org/patches/zoomswap/