From 82a127630d4af24b587a575df50c564705c93e27 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sun, 18 Sep 2022 20:39:31 +0200 Subject: [PATCH 1/6] fullscreen: don't let the (always) center patch interfere with windows that start fullscreen --- dwm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/dwm.c b/dwm.c index 794fab7..6907d94 100644 --- a/dwm.c +++ b/dwm.c @@ -2490,8 +2490,6 @@ manage(Window w, XWindowAttributes *wa) #endif // BAR_FLEXWINTITLE_PATCH configure(c); /* propagates border_width, if size doesn't change */ updatesizehints(c); - if (getatomprop(c, netatom[NetWMState], XA_ATOM) == netatom[NetWMFullscreen]) - setfullscreen(c, 1); updatewmhints(c); #if DECORATION_HINTS_PATCH updatemotifhints(c); @@ -2521,6 +2519,9 @@ manage(Window w, XWindowAttributes *wa) } #endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH + if (getatomprop(c, netatom[NetWMState], XA_ATOM) == netatom[NetWMFullscreen]) + setfullscreen(c, 1); + XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); grabbuttons(c, 0); #if MAXIMIZE_PATCH From 1ac17a493705d150cb4b92ca7e33fb98b51de4c7 Mon Sep 17 00:00:00 2001 From: monosans Date: Mon, 26 Sep 2022 08:03:12 +0000 Subject: [PATCH 2/6] Add dwm.desktop file (#301) --- Makefile | 6 +++++- dwm.desktop | 7 +++++++ 2 files changed, 12 insertions(+), 1 deletion(-) create mode 100644 dwm.desktop diff --git a/Makefile b/Makefile index c2ea8df..01ea136 100644 --- a/Makefile +++ b/Makefile @@ -65,9 +65,13 @@ endif mkdir -p ${DESTDIR}${MANPREFIX}/man1 sed "s/VERSION/${VERSION}/g" < dwm.1 > ${DESTDIR}${MANPREFIX}/man1/dwm.1 chmod 644 ${DESTDIR}${MANPREFIX}/man1/dwm.1 + mkdir -p ${DESTDIR}${PREFIX}/share/xsession + cp -n dwm.desktop ${DESTDIR}${PREFIX}/share/xsession + chmod 644 ${DESTDIR}${PREFIX}/share/xsession/dwm.desktop uninstall: rm -f ${DESTDIR}${PREFIX}/bin/dwm\ - ${DESTDIR}${MANPREFIX}/man1/dwm.1 + ${DESTDIR}${MANPREFIX}/man1/dwm.1\ + ${DESTDIR}${PREFIX}/share/xsession/dwm.desktop .PHONY: all options clean dist install uninstall diff --git a/dwm.desktop b/dwm.desktop new file mode 100644 index 0000000..b0c3354 --- /dev/null +++ b/dwm.desktop @@ -0,0 +1,7 @@ +[Desktop Entry] +Encoding=UTF-8 +Name=Dwm +Comment=Dynamic window manager +Exec=dwm +Icon=dwm +Type=XSession From 4912e3129aa8e1e9bb5f56d20377102575aca2b7 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Thu, 6 Oct 2022 14:44:11 +0200 Subject: [PATCH 3/6] Bump to 50ad171. remove workaround for a crash with color emojis on some systems, now fixed in libXft 2.3.5 https://gitlab.freedesktop.org/xorg/lib/libxft/-/blob/libXft-2.3.5/NEWS bump version to 6.4 Ref. https://git.suckless.org/dwm/commit/970f37697358574e127019eb0ee2f5725ec05ce0.html https://git.suckless.org/dwm/commit/50ad171eea9db5ccb36fce2592e047c3282975ff.html Consequently the color emoji patch has been inverted into no color emoji, keeping the workaround in the code base for those that are on systems with older versions of the Xft library. --- README.md | 12 ++++++------ config.mk | 2 +- drw.c | 6 ++++-- patches.def.h | 14 ++++++-------- 4 files changed, 17 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index 64956a5..981dd6d 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -This dwm 6.3 (c2b748e, 2022-08-26) side project has a different take on dwm patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. Due to the complexity of some of the patches dwm-flexipatch has diverged from mainstream dwm by making some core patches non-optional for maintenance reasons. For the classic dwm-flexipatch build refer to branch [dwm-flexipatch-1.0](https://github.com/bakkeby/dwm-flexipatch/tree/dwm-flexipatch-1.0). +This dwm 6.4 (50ad171, 2022-10-04) side project has a different take on dwm patching. It uses preprocessor directives to decide whether or not to include a patch during build time. Essentially this means that this build, for better or worse, contains both the patched _and_ the original code. The aim being that you can select which patches to include and the build will contain that code and nothing more. Due to the complexity of some of the patches dwm-flexipatch has diverged from mainstream dwm by making some core patches non-optional for maintenance reasons. For the classic dwm-flexipatch build refer to branch [dwm-flexipatch-1.0](https://github.com/bakkeby/dwm-flexipatch/tree/dwm-flexipatch-1.0). For example to include the `alpha` patch then you would only need to flip this setting from 0 to 1 in [patches.h](https://github.com/bakkeby/dwm-flexipatch/blob/master/patches.def.h): ```c @@ -310,11 +310,11 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6 - [colorbar](https://dwm.suckless.org/patches/colorbar/) - lets you change the foreground and background color of every statusbar element - - color_emoji - - enables color emoji in dmenu by removing a workaround for a BadLength error in the Xft - library when color glyphs are used - - enabling this will crash dwm on encountering such glyphs unless you also have an updated - Xft library that can handle them + - ~color_emoji~ + - ~enables color emoji in dmenu by removing a workaround for a BadLength error in the Xft~ + ~library when color glyphs are used~ + - ~enabling this will crash dwm on encountering such glyphs unless you also have an updated~ + ~Xft library that can handle them~ - [combo](https://dwm.suckless.org/patches/combo/) - allows you to select multiple tags by pressing all the right keys as a combo, e.g. hold MOD diff --git a/config.mk b/config.mk index eb1f2cf..b4a6ee5 100644 --- a/config.mk +++ b/config.mk @@ -1,5 +1,5 @@ # dwm version -VERSION = 6.3 +VERSION = 6.4 # Customize below to fit your system diff --git a/drw.c b/drw.c index 68dd015..2e74b20 100644 --- a/drw.c +++ b/drw.c @@ -237,7 +237,7 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) die("no font specified."); } - #if !BAR_COLOR_EMOJI_PATCH + #if BAR_NO_COLOR_EMOJI_PATCH /* Do not allow using color fonts. This is a workaround for a BadLength * error from Xft with color glyphs. Modelled on the Xterm workaround. See * https://bugzilla.redhat.com/show_bug.cgi?id=1498269 @@ -250,7 +250,7 @@ xfont_create(Drw *drw, const char *fontname, FcPattern *fontpattern) XftFontClose(drw->dpy, xfont); return NULL; } - #endif // BAR_COLOR_EMOJI_PATCH + #endif // BAR_NO_COLOR_EMOJI_PATCH font = ecalloc(1, sizeof(Fnt)); font->xfont = xfont; @@ -592,7 +592,9 @@ drw_text(Drw *drw, int x, int y, unsigned int w, unsigned int h, unsigned int lp fcpattern = FcPatternDuplicate(drw->fonts->pattern); FcPatternAddCharSet(fcpattern, FC_CHARSET, fccharset); FcPatternAddBool(fcpattern, FC_SCALABLE, FcTrue); + #if BAR_NO_COLOR_EMOJI_PATCH FcPatternAddBool(fcpattern, FC_COLOR, FcFalse); + #endif // BAR_NO_COLOR_EMOJI_PATCH FcConfigSubstitute(NULL, fcpattern, FcMatchPattern); FcDefaultSubstitute(fcpattern); diff --git a/patches.def.h b/patches.def.h index 784e324..deb6e3c 100644 --- a/patches.def.h +++ b/patches.def.h @@ -299,14 +299,6 @@ */ #define BAR_CLIENTINDICATOR_PATCH N/A -/* This patch enables color emoji in dwm by removing a workaround for a BadLength error - * in the Xft library when color glyphs are used. - * To enable this you will need an updated Xft library that can handle color glyphs otherwise - * dwm will crash on encountering such characters. Note that you will also need a font that - * provides color emojis for this to work. - */ -#define BAR_COLOR_EMOJI_PATCH 0 - /* Updates the position of dmenu to match that of the bar. I.e. if topbar is 0 then dmenu * will appear at the bottom and if 1 then dmenu will appear at the top. * https://dwm.suckless.org/patches/dmenumatchtop @@ -359,6 +351,12 @@ */ #define BAR_IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH 0 +/* This patch adds back in the workaround for a BadLength error in the Xft library when color + * glyphs are used. This is for systems that do not have an updated version of the Xft library + * (or generally prefer monochrome fonts). + */ +#define BAR_NO_COLOR_EMOJI_PATCH 0 + /* This patch adds vertical and horizontal space between the statusbar and the edge of the screen. * https://dwm.suckless.org/patches/barpadding/ */ From cc58ad2ef41bf0b9a298366fbdc5afbde31edb17 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sat, 8 Oct 2022 22:12:03 +0200 Subject: [PATCH 4/6] Adding alt-tab patch ref. #303 --- README.md | 5 ++ config.def.h | 14 +++ config.mk | 2 +- dwm.c | 4 + patch/alttab.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++++ patch/alttab.h | 5 ++ patch/include.c | 3 + patch/include.h | 3 + patches.def.h | 5 ++ 9 files changed, 262 insertions(+), 1 deletion(-) create mode 100644 patch/alttab.c create mode 100644 patch/alttab.h diff --git a/README.md b/README.md index 981dd6d..53faf27 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,8 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6 ### Changelog: +2022-10-08 - Added the alt-tab patch + 2022-08-12 - Added the nametag patch 2022-08-02 - Added the bidi patch @@ -230,6 +232,9 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6 - [alpha](https://dwm.suckless.org/patches/alpha/) - adds transparency for the status bar + - [alt-tab](https://dwm.suckless.org/patches/alt-tab/) + - adds a window task switcher toggled using alt-tab + - [alternativetags](https://dwm.suckless.org/patches/alternativetags/) - adds alternative tags which can be toggled on the fly for the sole purpose of providing visual aid diff --git a/config.def.h b/config.def.h index 1b06f0d..5d10181 100644 --- a/config.def.h +++ b/config.def.h @@ -122,6 +122,16 @@ static const int ulineall = 0; /* 1 to show underline on all ta #define NAMETAG_COMMAND "dmenu < /dev/null" #endif // NAMETAG_PATCH +#if ALT_TAB_PATCH +/* alt-tab configuration */ +static const unsigned int tabmodkey = 0x40; /* (Alt) when this key is held down the alt-tab functionality stays active. Must be the same modifier as used to run alttabstart */ +static const unsigned int tabcyclekey = 0x17; /* (Tab) when this key is hit the menu moves one position forward in client stack. Must be the same key as used to run alttabstart */ +static const unsigned int tabposy = 1; /* tab position on Y axis, 0 = top, 1 = center, 2 = bottom */ +static const unsigned int tabposx = 1; /* tab position on X axis, 0 = left, 1 = center, 2 = right */ +static const unsigned int maxwtab = 600; /* tab menu width */ +static const unsigned int maxhtab = 200; /* tab menu height */ +#endif // ALT_TAB_PATCH + /* Indicators: see patch/bar_indicators.h for options */ static int tagindicatortype = INDICATOR_TOP_LEFT_SQUARE; static int tiledindicatortype = INDICATOR_NONE; @@ -996,7 +1006,11 @@ static const Key keys[] = { { MODKEY|Mod4Mask, XK_0, togglegaps, {0} }, { MODKEY|Mod4Mask|ShiftMask, XK_0, defaultgaps, {0} }, #endif // VANITYGAPS_PATCH + #if ALT_TAB_PATCH + { Mod1Mask, XK_Tab, alttabstart, {0} }, + #else { MODKEY, XK_Tab, view, {0} }, + #endif // ALT_TAB_PATCH #if SHIFTTAG_PATCH { MODKEY|ShiftMask, XK_Left, shifttag, { .i = -1 } }, // note keybinding conflict with focusadjacenttag tagtoleft { MODKEY|ShiftMask, XK_Right, shifttag, { .i = +1 } }, // note keybinding conflict with focusadjacenttag tagtoright diff --git a/config.mk b/config.mk index b4a6ee5..7db6cba 100644 --- a/config.mk +++ b/config.mk @@ -29,7 +29,7 @@ FREETYPEINC = /usr/include/freetype2 #KVMLIB = -lkvm # Uncomment this for the alpha patch and the winicon patch (BAR_ALPHA_PATCH, BAR_WINICON_PATCH) -#XRENDER = -lXrender +XRENDER = -lXrender # Uncomment this for the mdpcontrol patch / MDPCONTROL_PATCH #MPDCLIENT = -lmpdclient diff --git a/dwm.c b/dwm.c index 6907d94..5652136 100644 --- a/dwm.c +++ b/dwm.c @@ -1245,6 +1245,10 @@ cleanup(void) Layout foo = { "", NULL }; size_t i; + #if ALT_TAB_PATCH + alttabend(); + #endif // ALT_TAB_PATCH + #if SEAMLESS_RESTART_PATCH for (m = mons; m; m = m->next) persistmonitorstate(m); diff --git a/patch/alttab.c b/patch/alttab.c new file mode 100644 index 0000000..861ab2f --- /dev/null +++ b/patch/alttab.c @@ -0,0 +1,222 @@ +int alttabn; /* move that many clients forward */ +int ntabs; /* number of active clients in tag */ +int isalt; +Client **altsnext; /* array of all clients in the tag */ +Window alttabwin; + +void +alttab() +{ + Monitor *m = selmon; + + /* move to next window */ + if (m->sel && m->sel->snext) { + alttabn++; + if (alttabn >= ntabs) + alttabn = 0; /* reset alttabn */ + + focus(altsnext[alttabn]); + restack(m); + } + + /* redraw tab */ + XRaiseWindow(dpy, alttabwin); + drawtab(ntabs, 0, m); +} + +void +alttabend() +{ + Monitor *m = selmon; + Client *buff; + int i; + + if (!isalt) + return; + + /* Move all clients between first and choosen position, + * one down in stack and put choosen client to the first position + * so they remain in right order for the next time that alt-tab is used + */ + if (ntabs > 1) { + if (alttabn != 0) { /* if user picked original client do nothing */ + buff = altsnext[alttabn]; + if (alttabn > 1) + for (i = alttabn; i > 0; i--) + altsnext[i] = altsnext[i - 1]; + else /* swap them if there are just 2 clients */ + altsnext[alttabn] = altsnext[0]; + altsnext[0] = buff; + } + + /* restack clients */ + for (i = ntabs - 1; i >= 0; i--) { + focus(altsnext[i]); + restack(m); + } + + free(altsnext); /* free list of clients */ + } + + /* destroy the window */ + isalt = 0; + ntabs = 0; + XUnmapWindow(dpy, alttabwin); + XDestroyWindow(dpy, alttabwin); +} + +void +drawtab(int nwins, int first, Monitor *m) +{ + Client *c; + int i, h; + int y = 0; + int px = m->mx; + int py = m->my; + + if (first) { + XSetWindowAttributes wa = { + .override_redirect = True, + #if BAR_ALPHA_PATCH + .background_pixel = 0, + .border_pixel = 0, + .colormap = cmap, + #else + .background_pixmap = ParentRelative, + #endif // BAR_ALPHA_PATCH + .event_mask = ButtonPressMask|ExposureMask + }; + + /* decide position of tabwin */ + if (tabposx == 1) + px = m->mx + (m->mw / 2) - (maxwtab / 2); + else if (tabposx == 2) + px = m->mx + m->mw - maxwtab; + + if (tabposy == 1) + py = m->my + (m->mh / 2) - (maxhtab / 2); + else if (tabposy == 2) + py = m->my + m->mh - maxhtab; + + h = maxhtab; + + #if BAR_ALPHA_PATCH + alttabwin = XCreateWindow(dpy, root, px, py, maxwtab, maxhtab, 2, depth, + InputOutput, visual, + CWOverrideRedirect|CWBackPixel|CWBorderPixel|CWColormap|CWEventMask, &wa); + #else + alttabwin = XCreateWindow(dpy, root, px, py, maxwtab, maxhtab, 2, DefaultDepth(dpy, screen), + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + #endif // BAR_ALPHA_PATCH + + XDefineCursor(dpy, alttabwin, cursor[CurNormal]->cursor); + XMapRaised(dpy, alttabwin); + } + + h = maxhtab / ntabs; + for (i = 0; i < ntabs; i++) { /* draw all clients into tabwin */ + c = altsnext[i]; + if (!ISVISIBLE(c)) + continue; + if (HIDDEN(c)) + continue; + + drw_setscheme(drw, scheme[c == m->sel ? SchemeSel : SchemeNorm]); + drw_text(drw, 0, y, maxwtab, h, 0, c->name, 0, 0); + y += h; + } + + drw_setscheme(drw, scheme[SchemeNorm]); + drw_map(drw, alttabwin, 0, 0, maxwtab, maxhtab); +} + +void +alttabstart(const Arg *arg) +{ + Client *c; + Monitor *m = selmon; + int grabbed; + int i; + + altsnext = NULL; + if (alttabwin) + alttabend(); + + if (isalt == 1) { + alttabend(); + return; + } + + isalt = 1; + alttabn = 0; + ntabs = 0; + + for (c = m->clients; c; c = c->next) { + if (!ISVISIBLE(c)) + continue; + if (HIDDEN(c)) + continue; + + ++ntabs; + } + + if (!ntabs) { + alttabend(); + return; + } + + altsnext = (Client **) malloc(ntabs * sizeof(Client *)); + + for (i = 0, c = m->stack; c; c = c->snext, i++) { + if (!ISVISIBLE(c)) + continue; + if (HIDDEN(c)) + continue; + + altsnext[i] = c; + } + + drawtab(ntabs, 1, m); + + struct timespec ts = { .tv_sec = 0, .tv_nsec = 1000000 }; + + /* grab keyboard (take all input from keyboard) */ + grabbed = 1; + for (i = 0; i < 1000; i++) { + if (XGrabKeyboard(dpy, root, True, GrabModeAsync, GrabModeAsync, CurrentTime) == GrabSuccess) + break; + nanosleep(&ts, NULL); + if (i == 1000 - 1) + grabbed = 0; + } + + XEvent event; + alttab(); + + if (grabbed == 0) { + alttabend(); + return; + } + + while (grabbed) { + XNextEvent(dpy, &event); + if (event.type == KeyPress || event.type == KeyRelease) { + if (event.type == KeyRelease && event.xkey.keycode == tabmodkey) /* if mod key is released break cycle */ + break; + + if (event.type == KeyPress) { + if (event.xkey.keycode == tabcyclekey) { /* if tab is pressed move to the next window */ + alttab(); + } + } + } + } + + c = m->sel; + alttabend(); + + XUngrabKeyboard(dpy, CurrentTime); + focus(c); + restack(m); +} diff --git a/patch/alttab.h b/patch/alttab.h new file mode 100644 index 0000000..2951d04 --- /dev/null +++ b/patch/alttab.h @@ -0,0 +1,5 @@ +#include + +static void drawtab(int nwins, int first, Monitor *m); +static void alttabstart(const Arg *arg); +static void alttabend(); diff --git a/patch/include.c b/patch/include.c index 4263f45..326323c 100644 --- a/patch/include.c +++ b/patch/include.c @@ -98,6 +98,9 @@ #endif /* Other patches */ +#if ALT_TAB_PATCH +#include "alttab.c" +#endif #if ASPECTRESIZE_PATCH #include "aspectresize.c" #endif diff --git a/patch/include.h b/patch/include.h index 65e0eda..9ab7527 100644 --- a/patch/include.h +++ b/patch/include.h @@ -98,6 +98,9 @@ #endif /* Other patches */ +#if ALT_TAB_PATCH +#include "alttab.h" +#endif #if ASPECTRESIZE_PATCH #include "aspectresize.h" #endif diff --git a/patches.def.h b/patches.def.h index deb6e3c..e787ada 100644 --- a/patches.def.h +++ b/patches.def.h @@ -438,6 +438,11 @@ * Other patches */ +/* Adds a window task switcher toggled using alt-tab. + * https://dwm.suckless.org/patches/alt-tab/ + */ +#define ALT_TAB_PATCH 0 + /* All floating windows are centered, like the center patch, but without a rule. * The center patch takes precedence over this patch. * This patch interferes with the center transient windows patches. From 9a5378440c57718e6d219418eee4fd4f90704e74 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Mon, 10 Oct 2022 22:58:35 +0200 Subject: [PATCH 5/6] rounded rectangles: fullscreen compatibility fix ref. #304 --- dwm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/dwm.c b/dwm.c index 5652136..d0df3d7 100644 --- a/dwm.c +++ b/dwm.c @@ -3482,6 +3482,10 @@ setfullscreen(Client *c, int fullscreen) c->bw = 0; c->isfloating = 1; resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + #if ROUNDED_CORNERS_PATCH + XRectangle rect = { .x = 0, .y = 0, .width = c->w, .height = c->h }; + XShapeCombineRectangles(dpy, c->win, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 1); + #endif // ROUNDED_CORNERS_PATCH XRaiseWindow(dpy, c->win); } else if (restorestate && (c->oldstate & (1 << 1))) { c->bw = c->oldbw; @@ -3516,6 +3520,10 @@ setfullscreen(Client *c, int fullscreen) c->bw = 0; c->isfloating = 1; resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); + #if ROUNDED_CORNERS_PATCH + XRectangle rect = { .x = 0, .y = 0, .width = c->w, .height = c->h }; + XShapeCombineRectangles(dpy, c->win, ShapeBounding, 0, 0, &rect, 1, ShapeSet, 1); + #endif // ROUNDED_CORNERS_PATCH XRaiseWindow(dpy, c->win); #endif // !FAKEFULLSCREEN_PATCH } else if (!fullscreen && c->isfullscreen){ From b732821f7b5458ae1bb2476da5441942ec8fa398 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Thu, 13 Oct 2022 12:34:09 +0200 Subject: [PATCH 6/6] alttab: fixing crash when clients are on other tags --- patch/alttab.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/patch/alttab.c b/patch/alttab.c index 861ab2f..f6775d8 100644 --- a/patch/alttab.c +++ b/patch/alttab.c @@ -168,13 +168,14 @@ alttabstart(const Arg *arg) altsnext = (Client **) malloc(ntabs * sizeof(Client *)); - for (i = 0, c = m->stack; c; c = c->snext, i++) { + for (i = 0, c = m->stack; c; c = c->snext) { if (!ISVISIBLE(c)) continue; if (HIDDEN(c)) continue; altsnext[i] = c; + i++; } drawtab(ntabs, 1, m);