diff --git a/Makefile b/Makefile index 348b9c5..581760f 100644 --- a/Makefile +++ b/Makefile @@ -67,9 +67,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/README.md b/README.md index 64956a5..53faf27 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 @@ -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 @@ -310,11 +315,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/README.org b/README.org index a7de099..4ece963 100644 --- a/README.org +++ b/README.org @@ -43,7 +43,6 @@ - [[#border][Border]] - [[#centered-window-name][Centered Window Name]] - [[#client-indicator][Client Indicator]] - - [[#color-emoji][Color Emoji]] - [[#dmenu-match-top][Dmenu Match Top]] - [[#extra-status][Extra Status]] - [[#ewmh-tags][EWMH Tags]] @@ -51,6 +50,7 @@ - [[#hide-vacant-tags][Hide Vacant Tags]] - [[#holdbar][Holdbar]] - [[#ignore-xft-errors-when-drawing-text][Ignore Xft Errors When Drawing Text]] + - [[#no-color-emoji][No Color Emoji]] - [[#padding][Padding]] - [[#pango][Pango]] - [[#static-status][Static Status]] @@ -60,6 +60,7 @@ - [[#vt-colors][VT Colors]] - [[#window-title-actions][Window Title Actions]] - [[#other][Other]] + - [[#alt-tab][Alt Tab]] - [[#always-center][Always Center]] - [[#aspect-resize][Aspect Resize]] - [[#attach-above][Attach Above]] @@ -277,7 +278,7 @@ exec dwm * dwm flexipatch -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 [[https://github.com/bakkeby/dwm-flexipatch/tree/dwm-flexipatch-1.0][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 [[https://github.com/bakkeby/dwm-flexipatch/tree/dwm-flexipatch-1.0][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 [[https://github.com/bakkeby/dwm-flexipatch/blob/master/patches.def.h][patches.h]]: @@ -297,6 +298,8 @@ Browsing patches? There is a [[https://coggle.it/diagram/X9IiSSM6PTWOM9Wz][map o ** Changelog +2022-10-08 - Added the alt-tab patch + 2022-08-12 - Added the nametag patch 2022-08-02 - Added the bidi patch @@ -507,6 +510,9 @@ Browsing patches? There is a [[https://coggle.it/diagram/X9IiSSM6PTWOM9Wz][map o - [[https://dwm.suckless.org/patches/alpha/][alpha]] - adds transparency for the status bar + - [[https://dwm.suckless.org/patches/alt-tab/][alt-tab]] + - adds a window task switcher toggled using alt-tab + - [[https://dwm.suckless.org/patches/alternativetags/][alternativetags]] - adds alternative tags which can be toggled on the fly for the sole purpose of providing visual aid @@ -581,9 +587,9 @@ Browsing patches? There is a [[https://coggle.it/diagram/X9IiSSM6PTWOM9Wz][map o - [[https://dwm.suckless.org/patches/colorbar/][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+ - [[https://dwm.suckless.org/patches/combo/][combo]] - allows you to select multiple tags by pressing all the right keys as a combo, e.g. hold MOD and press and hold 1 and 3 together to view those two tags @@ -1529,16 +1535,6 @@ https://dwm.suckless.org/patches/clientindicators/ #define BAR_CLIENTINDICATOR_PATCH N/A #+END_SRC -*** Color Emoji - -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. - -#+BEGIN_SRC c :tangle patches.def.h -#define BAR_COLOR_EMOJI_PATCH 0 -#+END_SRC - *** Dmenu Match Top 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. @@ -1621,6 +1617,14 @@ https://docs.google.com/viewer?a=v&pid=forums&srcid=MDAwODA2MTg0MDQyMjE0OTgzMzMB #define BAR_IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH 0 #+END_SRC +*** No Color Emoji + +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). + +#+BEGIN_SRC c :tangle patches.def.h +#define BAR_NO_COLOR_EMOJI_PATCH 0 +#+END_SRC + *** Padding This patch adds vertical and horizontal space between the statusbar and the edge of the screen. @@ -1727,6 +1731,16 @@ https://github.com/bakkeby/patches/blob/master/dwm/dwm-barmodules-wintitleaction ** Other +*** Alt Tab + +Adds a window task switcher toggled using alt-tab. + +https://dwm.suckless.org/patches/alt-tab/ + +#+BEGIN_SRC c :tangle patches.def.h +#define ALT_TAB_PATCH 0 +#+END_SRC + *** Always Center 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. @@ -3335,7 +3349,7 @@ This can be optionally disabled in favour of other layouts. #+BEGIN_SRC makefile :tangle config.mk # dwm version -VERSION = 6.3 +VERSION = 6.4 # Customize below to fit your system @@ -3365,7 +3379,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 @@ -3480,10 +3494,14 @@ 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 #+END_SRC @@ -3683,6 +3701,18 @@ static const int ulineall = 0; /* 1 to show underline on all ta #endif // NAMETAG_PATCH #+END_SRC +#+BEGIN_SRC c :tangle config.def.h +#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 +#+END_SRC + ** Indicators See patch/bar_indicators.h for options @@ -4773,7 +4803,11 @@ static const Key keys[] = { { MODKEY|Mod1Mask|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 diff --git a/config.def.h b/config.def.h index 3c35a4f..2e95641 100644 --- a/config.def.h +++ b/config.def.h @@ -141,6 +141,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 + static int tagindicatortype = INDICATOR_TOP_LEFT_SQUARE; static int tiledindicatortype = INDICATOR_NONE; static int floatindicatortype = INDICATOR_TOP_LEFT_SQUARE; @@ -1046,7 +1056,11 @@ static const Key keys[] = { { MODKEY|Mod1Mask|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 diff --git a/config.mk b/config.mk index 617fe27..983027d 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 @@ -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/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/dwm.c b/dwm.c index 794fab7..d0df3d7 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); @@ -2490,8 +2494,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 +2523,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 @@ -3477,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; @@ -3511,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){ 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 diff --git a/patch/alttab.c b/patch/alttab.c new file mode 100644 index 0000000..f6775d8 --- /dev/null +++ b/patch/alttab.c @@ -0,0 +1,223 @@ +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) { + if (!ISVISIBLE(c)) + continue; + if (HIDDEN(c)) + continue; + + altsnext[i] = c; + i++; + } + + 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 cbec2b1..58c7823 100644 --- a/patches.def.h +++ b/patches.def.h @@ -73,8 +73,6 @@ #define BAR_CLIENTINDICATOR_PATCH N/A -#define BAR_COLOR_EMOJI_PATCH 0 - #define BAR_DMENUMATCHTOP_PATCH 0 #define BAR_EXTRASTATUS_PATCH 0 @@ -89,6 +87,8 @@ #define BAR_IGNORE_XFT_ERRORS_WHEN_DRAWING_TEXT_PATCH 0 +#define BAR_NO_COLOR_EMOJI_PATCH 0 + #define BAR_PADDING_PATCH 0 #define BAR_PANGO_PATCH 0 @@ -105,6 +105,8 @@ #define BAR_WINTITLEACTIONS_PATCH BAR_AWESOMEBAR_PATCH || BAR_TABGROUPS_PATCH || BAR_FLEXWINTITLE_PATCH +#define ALT_TAB_PATCH 0 + #define ALWAYSCENTER_PATCH 1 #define ASPECTRESIZE_PATCH 1