diff --git a/config.def.h b/config.def.h index 27f5251..c4625fa 100644 --- a/config.def.h +++ b/config.def.h @@ -1,20 +1,16 @@ /* See LICENSE file for copyright and license details. */ -/* Header file for XF86 keys */ -#include - /* Helper macros for spawning commands */ #define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } } #define CMD(...) { .v = (const char*[]){ __VA_ARGS__, NULL } } +#include + /* appearance */ static const unsigned int borderpx = 1; /* border pixel of windows */ -static const unsigned int snap = 16; /* snap pixel */ -static const int swallowfloating = 1; /* 1 means swallow floating windows by default */ +static const unsigned int snap = 8; /* snap pixel */ +static const int swallowfloating = 0; /* 1 means swallow floating windows by default */ static const int scalepreview = 4; /* Tag preview scaling */ -static const int usealtbar = 1; /* 1 means use non-dwm status bar */ -static const char *altbarclass = "Polybar"; /* Alternate bar class name */ -static const char *altbarcmd = "$HOME/bar.sh"; /* Alternate bar launch command */ static const int showbar = 1; /* 0 means no bar */ static const int topbar = 1; /* 0 means bottom bar */ /* Status is to be shown on: -1 (all monitors), 0 (a specific monitor by index), 'A' (active monitor) */ @@ -34,6 +30,7 @@ static const unsigned int maxhtab = 200; /* tab menu height */ static int tagindicatortype = INDICATOR_TOP_LEFT_SQUARE; static int tiledindicatortype = INDICATOR_NONE; static int floatindicatortype = INDICATOR_TOP_LEFT_SQUARE; +static void (*bartabmonfns[])(Monitor *) = { monocle /* , customlayoutfn */ }; static const char *fonts[] = { "monospace:size=13" }; // static const char dmenufont[] = "monospace:size=10"; @@ -105,13 +102,12 @@ static char *colors[][ColCount] = { }; static const char *const autostart[] = { - // "st", NULL, - "arrpc", NULL, - "dunst", NULL, - "/home/ganome/.local/bin/dwmbar", NULL, - "xrdb", "/home/ganome/.Xresources", NULL, - "sh", "/home/ganome/.local/bin/wallsetter.dwm", NULL, - "parcellite", NULL, +"arrpc", NULL, +"dunst", NULL, +"/home/ganome/.local/bin/dwmbar", NULL, +"xrdb", "/home/ganome/.Xresources", NULL, +"sh", "/home/ganome/.local/bin/wallsetter.dwm", NULL, +"parcellite", NULL, NULL /* terminate */ }; @@ -146,7 +142,7 @@ static const char *scratchpadcmd[] = {"s", "ghostty", "--x11-instance-name=spter */ static char *tagicons[][NUMTAGS] = { - [DEFAULT_TAGS] = { "", "", "", "", "", "", "", " ", "" }, + [DEFAULT_TAGS] = { "", "", "", "", "", "", "", " ", "" }, [ALTERNATIVE_TAGS] = { "A", "B", "C", "D", "E", "F", "G", "H", "I" }, [ALT_TAGS_DECORATION] = { "<1>", "<2>", "<3>", "<4>", "<5>", "<6>", "<7>", "<8>", "<9>" }, }; @@ -180,10 +176,10 @@ static const Rule rules[] = { RULE(.wintype = WTYPE "UTILITY", .isfloating = 1) RULE(.wintype = WTYPE "TOOLBAR", .isfloating = 1) RULE(.wintype = WTYPE "SPLASH", .isfloating = 1) - RULE(.class = "Gimp", .tags = 1 << 3) - RULE(.class = "Vivaldi-stable", .tags = 1 << 2) - RULE(.class = "Nemo", .tags = 1 << 6) - RULE(.class = "quassel", .tags = 1 << 8) + RULE(.class = "Gimp", .tags = 1 << 3) + RULE(.class = "Vivaldi-stable", .tags = 1 << 2) + RULE(.class = "Nemo", .tags = 1 << 6) + RULE(.class = "quassel", .tags = 1 << 8) RULE(.class = "vesktop", .tags = 1 << 3, .monitor = 1) RULE(.instance = "spterm", .scratchkey = 's', .isfloating = 1) }; @@ -212,7 +208,7 @@ static const BarRule barrules[] = { { 0, 0, BAR_ALIGN_RIGHT, width_systray, draw_systray, click_systray, NULL, "systray" }, { -1, 0, BAR_ALIGN_LEFT, width_ltsymbol, draw_ltsymbol, click_ltsymbol, NULL, "layout" }, { statusmon, 0, BAR_ALIGN_RIGHT, width_status, draw_status, click_status, NULL, "status" }, - { -1, 0, BAR_ALIGN_NONE, width_wintitle, draw_wintitle, click_wintitle, NULL, "wintitle" }, + { -1, 0, BAR_ALIGN_NONE, width_bartabgroups, draw_bartabgroups, click_bartabgroups, NULL, "bartabgroups" }, }; /* layout(s) */ @@ -224,7 +220,7 @@ static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen win static const Layout layouts[] = { /* symbol arrange function */ { "[\\]", dwindle }, - { "[]=", tile }, /* first entry is default */ + { "[]=", tile }, /* first entry is default */ { "><>", NULL }, /* no layout function means floating behavior */ { "[M]", monocle }, { "HHH", grid }, @@ -240,39 +236,40 @@ static const Layout layouts[] = { /* commands */ static char dmenumon[2] = "0"; /* component of dmenucmd, manipulated in spawn() */ -// static const char *dmenucmd[] = { - // "dmenu_run", - // "-m", dmenumon, - // "-fn", dmenufont, - // "-nb", normbgcolor, - // "-nf", normfgcolor, - // "-sb", selbgcolor, - // "-sf", selfgcolor, - // NULL -// }; -static const char *dmenucmd[] = { -"rofi", +/* static const char *dmenucmd[] = { + "dmenu_run", + "-m", dmenumon, + "-fn", dmenufont, + "-nb", normbgcolor, + "-nf", normfgcolor, + "-sb", selbgcolor, + "-sf", selfgcolor, + NULL +}; */ + +static const char *termcmd[] = { "ghostty", NULL }; +static const char *term2cmd[] = { "kitty", NULL }; +static const char *wallpapercmd[]= { "/home/ganome/.local/bin/wallsetter.dwm", NULL }; + +static const char *roficmd[] = { + "rofi", "-show", "drun", "--with-images", NULL }; -// static const char *vesktop[] = { "vesktop", NULL }; -static const char *wallpapercmd[]= { "/home/ganome/.local/bin/wallsetter.dwm", NULL }; -static const char *termcmd[] = { "ghostty", NULL }; -static const char *term2cmd[] = { "kitty", NULL }; static const Key keys[] = { /* modifier key function argument */ - { MODKEY, XK_p, spawn, {.v = dmenucmd } }, + { MODKEY, XK_p, spawn, {.v = roficmd } }, { MODKEY, XK_Return, spawn, {.v = termcmd } }, - { MODKEY|ShiftMask, XK_Return, spawn, {.v = term2cmd } }, + { MODKEY|ShiftMask, XK_Return, spawn, {.v = term2cmd } }, { MODKEY, XK_b, togglebar, {0} }, + { MODKEY|ShiftMask, XK_d, spawn, CMD("vesktop-bin")}, { MODKEY, XK_j, focusstack, {.i = +1 } }, { MODKEY, XK_k, focusstack, {.i = -1 } }, { MODKEY, XK_i, incnmaster, {.i = +1 } }, { MODKEY, XK_d, incnmaster, {.i = -1 } }, - { MODKEY|ShiftMask, XK_d, spawn, CMD("vesktop-bin")}, { MODKEY, XK_h, setmfact, {.f = -0.05} }, { MODKEY, XK_l, setmfact, {.f = +0.05} }, { MODKEY|ShiftMask, XK_h, setcfact, {.f = +0.25} }, @@ -280,15 +277,26 @@ static const Key keys[] = { { MODKEY|ShiftMask, XK_o, setcfact, {0} }, { MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } }, { MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } }, - { MODKEY|ControlMask, XK_Return, zoom, {0} }, + { MODKEY|ControlMask, XK_Return, zoom, {0} }, { Mod1Mask, XK_Tab, alttabstart, {0} }, + { MODKEY|ControlMask, XK_z, showhideclient, {0} }, + { MODKEY|ControlMask, XK_s, unhideall, {0} }, { MODKEY|ShiftMask, XK_q, killclient, {0} }, { MODKEY|ShiftMask, XK_e, quit, {0} }, { MODKEY|ControlMask, XK_e, quit, {1} }, { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, - { MODKEY|ShiftMask, XK_n, spawn, {.v = wallpapercmd } }, + { MODKEY|ControlMask, XK_z, showhideclient, {0} }, + { MODKEY|ControlMask, XK_s, unhideall, {0} }, + { MODKEY|ShiftMask, XK_n, spawn, {.v = wallpapercmd } }, + { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("exec pactl set-sink-volume @DEFAULT_SINK@ +5%")}, + { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("exec pactl set-sink-volume @DEFAULT_SINK@ -5%")}, + { 0, XF86XK_AudioMute, spawn, SHCMD("exec pactl set-sink-mute @DEFAULT_SINK@ toggle")}, + { 0, XF86XK_AudioPlay, spawn, SHCMD("exec playerctl play-pause")}, + { 0, XF86XK_AudioPause, spawn, SHCMD("exec playerctl play-pause")}, + { 0, XF86XK_AudioNext, spawn, SHCMD("exec playerctl next")}, + { 0, XF86XK_AudioPrev, spawn, SHCMD("exec playerctl previous")}, { MODKEY, XK_space, setlayout, {0} }, { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, { MODKEY, XK_grave, togglescratch, {.v = scratchpadcmd } }, @@ -302,13 +310,6 @@ static const Key keys[] = { { MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } }, { MODKEY|ControlMask, XK_comma, cyclelayout, {.i = -1 } }, { MODKEY|ControlMask, XK_period, cyclelayout, {.i = +1 } }, - { 0, XF86XK_AudioRaiseVolume, spawn, SHCMD("exec pactl set-sink-volume @DEFAULT_SINK@ +5%")}, - { 0, XF86XK_AudioLowerVolume, spawn, SHCMD("exec pactl set-sink-volume @DEFAULT_SINK@ -5%")}, - { 0, XF86XK_AudioMute, spawn, SHCMD("exec pactl set-sink-mute @DEFAULT_SINK@ toggle")}, - { 0, XF86XK_AudioPlay, spawn, SHCMD("exec playerctl play-pause")}, - { 0, XF86XK_AudioPause, spawn, SHCMD("exec playerctl play-pause")}, - { 0, XF86XK_AudioNext, spawn, SHCMD("exec playerctl next")}, - { 0, XF86XK_AudioPrev, spawn, SHCMD("exec playerctl previous")}, TAGKEYS( XK_1, 0) TAGKEYS( XK_2, 1) TAGKEYS( XK_3, 2) @@ -326,6 +327,8 @@ static const Button buttons[] = { /* click event mask button function argument */ { ClkLtSymbol, 0, Button1, setlayout, {0} }, { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, + { ClkWinTitle, 0, Button1, togglewin, {0} }, + { ClkWinTitle, 0, Button3, showhideclient, {0} }, { ClkWinTitle, 0, Button2, zoom, {0} }, { ClkStatusText, 0, Button2, spawn, {.v = termcmd } }, { ClkClientWin, MODKEY, Button1, movemouse, {0} }, @@ -359,4 +362,5 @@ static IPCCommand ipccommands[] = { IPCCOMMAND( zoom, 1, {ARG_TYPE_NONE} ), IPCCOMMAND( setcfact, 1, {ARG_TYPE_FLOAT} ), IPCCOMMAND( cyclelayout, 1, {ARG_TYPE_SINT} ), + IPCCOMMAND( showhideclient, 1, {ARG_TYPE_NONE} ), }; diff --git a/dwm.c b/dwm.c index f864936..66d4f50 100644 --- a/dwm.c +++ b/dwm.c @@ -56,8 +56,8 @@ #define BARRULES 20 #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) #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)->mx+(m)->mw) - MAX((x),(m)->mx)) \ - * MAX(0, MIN((y)+(h),(m)->my+(m)->mh) - MAX((y),(m)->my))) +#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))) #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) #define MOUSEMASK (BUTTONMASK|PointerMotionMask) #define WIDTH(X) ((X)->w + 2 * (X)->bw) @@ -648,6 +648,7 @@ buttonpress(XEvent *e) buttons[i].func( ( click == ClkTagBar + || click == ClkWinTitle ) && buttons[i].arg.i == 0 ? &arg : &buttons[i].arg ); } @@ -859,7 +860,6 @@ configurerequest(XEvent *e) { Client *c; Monitor *m; - Bar *bar; XConfigureRequestEvent *ev = &e->xconfigurerequest; XWindowChanges wc; @@ -900,13 +900,6 @@ configurerequest(XEvent *e) } else { wc.x = ev->x; wc.y = ev->y; - m = wintomon(ev->window); - for (bar = m->bar; bar; bar = bar->next) { - if (bar->win == ev->window) { - wc.y = bar->by; - wc.x = bar->bx; - } - } wc.width = ev->width; wc.height = ev->height; wc.border_width = ev->border_width; @@ -1011,8 +1004,6 @@ void destroynotify(XEvent *e) { Client *c; - Monitor *m; - Bar *bar; XDestroyWindowEvent *ev = &e->xdestroywindow; if ((c = wintoclient(ev->window))) @@ -1023,15 +1014,6 @@ destroynotify(XEvent *e) removesystrayicon(c); drawbarwin(systray->bar); } - else { - m = wintomon(ev->window); - for (bar = m->bar; bar; bar = bar->next) { - if (bar->win == ev->window) { - unmanagealtbar(ev->window); - break; - } - } - } } void @@ -1308,16 +1290,16 @@ focusstack(const Arg *arg) if (!selmon->sel || (selmon->sel->isfullscreen && lockfullscreen)) return; if (arg->i > 0) { - for (c = selmon->sel->next; c && !ISVISIBLE(c); c = c->next); + for (c = selmon->sel->next; c && (!ISVISIBLE(c) || (arg->i == 1 && HIDDEN(c))); c = c->next); if (!c) - for (c = selmon->clients; c && !ISVISIBLE(c); c = c->next); + for (c = selmon->clients; c && (!ISVISIBLE(c) || (arg->i == 1 && HIDDEN(c))); c = c->next); } else { for (i = selmon->clients; i != selmon->sel; i = i->next) - if (ISVISIBLE(i)) + if (ISVISIBLE(i) && !(arg->i == -1 && HIDDEN(i))) c = i; if (!c) for (; i; i = i->next) - if (ISVISIBLE(i)) + if (ISVISIBLE(i) && !(arg->i == -1 && HIDDEN(i))) c = i; } if (c) { @@ -1577,13 +1559,15 @@ manage(Window w, XWindowAttributes *wa) (unsigned char *) &(c->win), 1); XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ - setclientstate(c, NormalState); + if (!HIDDEN(c)) + setclientstate(c, NormalState); if (c->mon == selmon) unfocus(selmon->sel, 0, c); c->mon->sel = c; if (!(term && swallow(term, c))) { arrange(c->mon); - XMapWindow(dpy, c->win); + if (!HIDDEN(c)) + XMapWindow(dpy, c->win); } focus(NULL); @@ -1614,9 +1598,6 @@ maprequest(XEvent *e) if (!XGetWindowAttributes(dpy, ev->window, &wa) || wa.override_redirect) return; - if (wmclasscontains(ev->window, altbarclass, "")) - managealtbar(ev->window, &wa); - else if (!wintoclient(ev->window)) manage(ev->window, &wa); } @@ -1713,7 +1694,7 @@ movemouse(const Arg *arg) Client * nexttiled(Client *c) { - for (; c && (c->isfloating || !ISVISIBLE(c)); c = c->next); + for (; c && (c->isfloating || !ISVISIBLE(c) || HIDDEN(c)); c = c->next); return c; } @@ -1960,9 +1941,6 @@ scan(void) if (!XGetWindowAttributes(dpy, wins[i], &wa) || wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) continue; - if (wmclasscontains(wins[i], altbarclass, "")) - managealtbar(wins[i], &wa); - else if (wa.map_state == IsViewable || getstate(wins[i]) == IconicState) manage(wins[i], &wa); else if (gettextprop(wins[i], netatom[NetClientList], swin, sizeof swin)) @@ -2198,8 +2176,6 @@ setup(void) grabkeys(); focus(NULL); setupepoll(); - if (usealtbar) - spawnbar(); } void @@ -2263,7 +2239,7 @@ spawn(const Arg *arg) { struct sigaction sa; - if (arg->v == dmenucmd) + if (arg->v == roficmd) dmenumon[0] = '0' + selmon->num; if (fork() == 0) @@ -2461,8 +2437,6 @@ void unmapnotify(XEvent *e) { Client *c; - Monitor *m; - Bar *bar; XUnmapEvent *ev = &e->xunmap; if ((c = wintoclient(ev->window))) { @@ -2477,15 +2451,6 @@ unmapnotify(XEvent *e) removesystrayicon(c); drawbarwin(systray->bar); } - else { - m = wintomon(ev->window); - for (bar = m->bar; bar; bar = bar->next) { - if (bar->win == ev->window) { - unmanagealtbar(ev->window); - break; - } - } - } } void @@ -2529,8 +2494,6 @@ updatebarpos(Monitor *m) for (bar = m->bar; bar; bar = bar->next) { bar->bx = m->wx + x_pad; - if (bar->external) - continue; bar->bw = m->ww - 2 * x_pad; } diff --git a/patch/bar_tabgroups.c b/patch/bar_tabgroups.c new file mode 100644 index 0000000..5b678ff --- /dev/null +++ b/patch/bar_tabgroups.c @@ -0,0 +1,231 @@ +/* Bartabgroups properties, you can override these in your config.h if you want. */ +#ifndef BARTAB_BORDERS +#define BARTAB_BORDERS 1 // 0 = off, 1 = on +#endif +#ifndef BARTAB_SHOWFLOATING +#define BARTAB_SHOWFLOATING 0 // whether to show titles for floating windows, hidden clients are always shown +#endif +#ifndef BARTAB_STACKWEIGHT +#define BARTAB_STACKWEIGHT 1 // stack weight compared to hidden and floating window titles +#endif +#ifndef BARTAB_HIDDENWEIGHT +#define BARTAB_HIDDENWEIGHT 1 // hidden window title weight +#endif +#ifndef BARTAB_FLOATWEIGHT +#define BARTAB_FLOATWEIGHT 1 // floating window title weight, set to 0 to not show floating windows +#endif + +int +width_bartabgroups(Bar *bar, BarArg *a) +{ + return a->w; +} + +int +draw_bartabgroups(Bar *bar, BarArg *a) +{ + drw_rect(drw, a->x, a->y, a->w, a->h, 1, 1); + return bartabcalculate(bar->mon, a->x, a->w, -1, bartabdraw, NULL, a); +} + +int +click_bartabgroups(Bar *bar, Arg *arg, BarArg *a) +{ + bartabcalculate(bar->mon, 0, a->w, a->x, bartabclick, arg, a); + return ClkWinTitle; +} + +void +bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg *arg, BarArg *a) +{ + if (!c) + return; + int i, nclienttags = 0, nviewtags = 0; + int tpad = lrpad / 2; + int tx = x; + int tw = w; + + drw_setscheme(drw, scheme[ + m->sel == c + #ifdef HIDDEN + && HIDDEN(c) + ? SchemeHidSel + : HIDDEN(c) + ? SchemeHidNorm + : m->sel == c + #endif + ? SchemeSel + : groupactive + ? SchemeTitleSel + : SchemeTitleNorm + ]); + if (w <= TEXTW("A") - lrpad + tpad) // reduce text padding if wintitle is too small + tpad = (w - TEXTW("A") + lrpad < 0 ? 0 : (w - TEXTW("A") + lrpad) / 2); + + XSetForeground(drw->dpy, drw->gc, drw->scheme[ColBg].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, w, a->h); + + tx += tpad; + tw -= lrpad; + + drw_text(drw, tx, a->y, tw, a->h, 0, c->name, 0, False); + + drawstateindicator(m, c, 1, x, a->y, w, a->h, 0, 0, c->isfixed); + + if (BARTAB_BORDERS) { + XSetForeground(drw->dpy, drw->gc, scheme[SchemeSel][ColBorder].pixel); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x, a->y, 1, a->h); + XFillRectangle(drw->dpy, drw->drawable, drw->gc, x + w - (x + w >= a->w ? 1 : 0), a->y, 1, a->h); + } + /* Optional tags icons */ + for (i = 0; i < NUMTAGS; i++) { + if ((m->tagset[m->seltags] >> i) & 1) + nviewtags++; + if ((c->tags >> i) & 1) + nclienttags++; + } + + if (TAGSINDICATOR == 2 || nclienttags > 1 || nviewtags > 1) + drawindicator(m, c, 1, x, a->y, w, a->h, 0, 0, 0, INDICATOR_RIGHT_TAGS); +} + +#ifndef HIDDEN +#define HIDDEN(C) 0 +#endif + +void +bartabclick(Monitor *m, Client *c, int passx, int x, int w, int unused, Arg *arg, BarArg *barg) +{ + if (passx >= x && passx <= x + w) + arg->v = c; +} + +int +bartabcalculate( + Monitor *m, int offx, int tabw, int passx, + void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), + Arg *arg, BarArg *barg +) { + Client *c; + int + i, clientsnmaster = 0, clientsnstack = 0, clientsnfloating = 0, clientsnhidden = 0, + masteractive = 0, fulllayout = 0, + x = offx, w, r, num = 0, den, tgactive; + + for (i = 0; i < LENGTH(bartabmonfns); i++) + if (m ->lt[m->sellt]->arrange == bartabmonfns[i]) { + fulllayout = 1; + break; + } + + for (i = 0, c = m->clients; c; c = c->next) { + if (!ISVISIBLE(c)) + continue; + if (HIDDEN(c)) { + clientsnhidden++; + continue; + } + if (c->isfloating) { + clientsnfloating++; + continue; + } + if (m->sel == c) + masteractive = i < m->nmaster; + if (i < m->nmaster) + clientsnmaster++; + else + clientsnstack++; + i++; + } + + if (clientsnmaster + clientsnstack + clientsnfloating + clientsnhidden == 0) + return 0; + + tgactive = 1; + num = tabw; + /* floating mode */ + if ((fulllayout && BARTAB_FLOATWEIGHT) || clientsnmaster + clientsnstack == 0 || !m->lt[m->sellt]->arrange) { + den = clientsnmaster + clientsnstack + clientsnfloating + clientsnhidden; + r = num % den; + w = num / den; + for (c = m->clients, i = 0; c; c = c->next) { + if (!ISVISIBLE(c)) + continue; + tabfn(m, c, passx, x, w + (i < r ? 1 : 0), tgactive, arg, barg); + x += w + (i < r ? 1 : 0); + i++; + } + /* no master and stack mode, e.g. monocole, grid layouts, fibonacci */ + } else if (fulllayout) { + den = clientsnmaster + clientsnstack + clientsnhidden; + r = num % den; + w = num / den; + for (c = m->clients, i = 0; c; c = c->next) { + if (!ISVISIBLE(c) || (c->isfloating && !HIDDEN(c))) + continue; + tabfn(m, c, passx, x, w + (i < r ? 1 : 0), tgactive, arg, barg); + x += w + (i < r ? 1 : 0); + i++; + } + /* tiled mode */ + } else { + den = clientsnmaster; + c = m->clients; + i = 0; + if (den) { + if (clientsnstack + clientsnfloating * BARTAB_FLOATWEIGHT + clientsnhidden) { + tgactive = masteractive; + num = tabw * m->mfact; + } + r = num % den; + w = num / den; + for (; c && i < m->nmaster; c = c->next) { // tiled master + if (!ISVISIBLE(c) || c->isfloating || HIDDEN(c)) + continue; + tabfn(m, c, passx, x, w + (i < r ? 1 : 0), tgactive, arg, barg); + x += w + (i < r ? 1 : 0); + i++; + } + tgactive = !tgactive; + num = tabw - num; + } + + den = clientsnstack * BARTAB_STACKWEIGHT + clientsnfloating * BARTAB_FLOATWEIGHT + clientsnhidden * BARTAB_HIDDENWEIGHT; + if (!den) + return 1; + + r = num % den; + w = num / den; + #if BARTAB_STACKWEIGHT + for (; c; c = c->next) { // tiled stack + if (!ISVISIBLE(c) || HIDDEN(c) || c->isfloating) + continue; + tabfn(m, c, passx, x, w * BARTAB_STACKWEIGHT + (i - m->nmaster < r ? 1 : 0), tgactive, arg, barg); + x += w * BARTAB_STACKWEIGHT + (i - m->nmaster < r ? 1 : 0); + i++; + } + #endif // BARTAB_STACKWEIGHT + + #if BARTAB_HIDDENWEIGHT + for (c = m->clients; c; c = c->next) { // hidden windows + if (!ISVISIBLE(c) || !HIDDEN(c)) + continue; + tabfn(m, c, passx, x, w * BARTAB_HIDDENWEIGHT + (i - m->nmaster < r ? 1 : 0), tgactive, arg, barg); + x += w * BARTAB_HIDDENWEIGHT + (i - m->nmaster < r ? 1 : 0); + i++; + } + #endif // BARTAB_HIDDENWEIGHT + + #if BARTAB_FLOATWEIGHT + for (c = m->clients; c; c = c->next) { // floating windows + if (!ISVISIBLE(c) || HIDDEN(c) || !c->isfloating) + continue; + tabfn(m, c, passx, x, w * BARTAB_FLOATWEIGHT + (i - m->nmaster < r ? 1 : 0), tgactive, arg, barg); + x += w * BARTAB_FLOATWEIGHT + (i - m->nmaster < r ? 1 : 0); + i++; + } + #endif // BARTAB_FLOATWEIGHT + } + return 1; +} + diff --git a/patch/bar_tabgroups.h b/patch/bar_tabgroups.h new file mode 100644 index 0000000..5ea8993 --- /dev/null +++ b/patch/bar_tabgroups.h @@ -0,0 +1,8 @@ +static int width_bartabgroups(Bar *bar, BarArg *a); +static int draw_bartabgroups(Bar *bar, BarArg *a); +static int click_bartabgroups(Bar *bar, Arg *arg, BarArg *a); + +static void bartabdraw(Monitor *m, Client *c, int unused, int x, int w, int groupactive, Arg *arg, BarArg *barg); +static void bartabclick(Monitor *m, Client *c, int passx, int x, int w, int unused, Arg *arg, BarArg *barg); +static int bartabcalculate(Monitor *m, int offx, int w, int passx, void(*tabfn)(Monitor *, Client *, int, int, int, int, Arg *arg, BarArg *barg), Arg *arg, BarArg *barg); + diff --git a/patch/bar_wintitleactions.c b/patch/bar_wintitleactions.c new file mode 100644 index 0000000..3ee57dd --- /dev/null +++ b/patch/bar_wintitleactions.c @@ -0,0 +1,103 @@ +void +hide(Client *c) { + + Client *n; + if (!c || HIDDEN(c)) + return; + + Window w = c->win; + static XWindowAttributes ra, ca; + + // more or less taken directly from blackbox's hide() function + XGrabServer(dpy); + XGetWindowAttributes(dpy, root, &ra); + XGetWindowAttributes(dpy, w, &ca); + // prevent UnmapNotify events + XSelectInput(dpy, root, ra.your_event_mask & ~SubstructureNotifyMask); + XSelectInput(dpy, w, ca.your_event_mask & ~StructureNotifyMask); + XUnmapWindow(dpy, w); + setclientstate(c, IconicState); + XSelectInput(dpy, root, ra.your_event_mask); + XSelectInput(dpy, w, ca.your_event_mask); + XUngrabServer(dpy); + + if (c->isfloating || !c->mon->lt[c->mon->sellt]->arrange) { + for (n = c->snext; n && (!ISVISIBLE(n) || HIDDEN(n)); n = n->snext); + if (!n) + for (n = c->mon->stack; n && (!ISVISIBLE(n) || HIDDEN(n)); n = n->snext); + } else { + n = nexttiled(c); + if (!n) + n = prevtiled(c); + } + focus(n); + arrange(c->mon); +} + +void +show(Client *c) +{ + if (!c || !HIDDEN(c)) + return; + + XMapWindow(dpy, c->win); + setclientstate(c, NormalState); + arrange(c->mon); +} + +void +togglewin(const Arg *arg) +{ + Client *c = (Client*)arg->v; + if (!c) + return; + if (!HIDDEN(c) && c == selmon->sel) + hide(c); + else { + if (HIDDEN(c)) + show(c); + focus(c); + restack(c->mon); + } +} + +Client * +prevtiled(Client *c) +{ + Client *p, *i; + for (p = NULL, i = c->mon->clients; c && i != c; i = i->next) + if (ISVISIBLE(i) && !HIDDEN(i)) + p = i; + return p; +} + +void +showhideclient(const Arg *arg) +{ + Client *c = (Client*)arg->v; + if (!c) + c = selmon->sel; + if (!c) + return; + + if (HIDDEN(c)) { + show(c); + focus(c); + restack(c->mon); + } else { + hide(c); + } +} + +void +unhideall(const Arg *arg) +{ + Client *c = NULL; + for (c = selmon->clients; c; c = c->next) { + if (ISVISIBLE(c)) { + XMapWindow(dpy, c->win); + setclientstate(c, NormalState); + } + } + arrange(selmon); +} diff --git a/patch/bar_wintitleactions.h b/patch/bar_wintitleactions.h new file mode 100644 index 0000000..053e565 --- /dev/null +++ b/patch/bar_wintitleactions.h @@ -0,0 +1,7 @@ +static void hide(Client *c); +static void show(Client *c); +static void togglewin(const Arg *arg); +static Client * prevtiled(Client *c); +static void showhideclient(const Arg *arg); +static void unhideall(const Arg *arg); + diff --git a/patch/include.c b/patch/include.c index 7753e69..4234358 100644 --- a/patch/include.c +++ b/patch/include.c @@ -3,14 +3,15 @@ #include "bar_tagicons.c" #include "bar.c" -#include "bar_anybar.c" #include "bar_ewmhtags.c" #include "bar_ltsymbol.c" #include "bar_status.c" +#include "bar_tabgroups.c" #include "bar_tagpreview.c" #include "bar_tags.c" #include "bar_wintitle.c" #include "bar_systray.c" +#include "bar_wintitleactions.c" /* Other patches */ #include "alttab.c" diff --git a/patch/include.h b/patch/include.h index fe90bbf..21abafa 100644 --- a/patch/include.h +++ b/patch/include.h @@ -3,14 +3,15 @@ #include "bar_tagicons.h" #include "bar.h" -#include "bar_anybar.h" #include "bar_ewmhtags.h" #include "bar_ltsymbol.h" #include "bar_status.h" +#include "bar_tabgroups.h" #include "bar_tags.h" #include "bar_tagpreview.h" #include "bar_wintitle.h" #include "bar_systray.h" +#include "bar_wintitleactions.h" /* Other patches */ #include "alttab.h" diff --git a/patch/renamed_scratchpads.c b/patch/renamed_scratchpads.c index bca536f..d91d2c1 100644 --- a/patch/renamed_scratchpads.c +++ b/patch/renamed_scratchpads.c @@ -66,6 +66,12 @@ togglescratch(const Arg *arg) if (c->scratchkey != ((char**)arg->v)[0][0]) continue; + /* unhide scratchpad if hidden */ + if (HIDDEN(c)) { + XMapWindow(dpy, c->win); + setclientstate(c, NormalState); + } + /* Record the first found scratchpad client for focus purposes, but prioritise the scratchpad on the current monitor if one exists */ if (!found || (mon == selmon && found->mon != selmon))