myvxwm

[fork] my vxwm config (optimised for my T480)
git clone https://git.lukeonline.net/repos/myvxwm
Log | Files | Refs | README | LICENSE

commit 79c26e4baa0a7521e8cbc8d5cfa12e68040bc4db
parent fff50797065bbc6281dbac122c1f3b63e5e5e7eb
Author: wh1tepearl <wh1tepearl@gmail.com>
Date:   Mon, 16 Feb 2026 17:13:32 +0000

2.0 RELEASE

Diffstat:
MREADME.md | 18++++++++++++++++++
Mconfig.def.h | 31+++++++++++++++++++++++++++++++
Mconfig.mk | 4++--
Mmodules.def.h | 38++++++++++++++++++++++++++++++++++----
Mmodules/betterresize/betterresize.c | 3++-
Mmodules/etf/etf.h | 2+-
Mmodules/gaps/gaps.h | 1-
Amodules/infinitetags/infinitetags.c | 204+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/infinitetags/infinitetags.h | 7+++++++
Amodules/moveresizekbd/moveresizekbd.c | 74++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Amodules/moveresizekbd/moveresizekbd.h | 1+
Mmodules/vxwm_includes.c | 8++++++++
Mmodules/vxwm_includes.h | 8++++++++
Mmodules/warptoclient/warptoclient.h | 2+-
Mvxwm.c | 166++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
15 files changed, 531 insertions(+), 36 deletions(-)

diff --git a/README.md b/README.md @@ -6,6 +6,23 @@ It has some patches for dwm pre installed that can be enabled/disabled by switch It also has some unique features like 8 sided resize, enhanced toggle floating, warp cursor and more! (They also can be toggled) Check modules.def.h for full list of features. +But the main feature of vxwm, is infinite tags. + +Most tiling window managers (like the default dwm) treat your screen like a slide-projector. You click a button, and the current "slide" is swapped for another. If an window is off-screen, it doesn't exist. + +With infinite tags enabled, vxwm treats your screen like a magnifying glass over a giant wooden desk. + +The Canvas is Infinite +Your windows aren't "on" tags. They are placed on a massive, invisible surface. Your monitor is just a small window through which you look at that surface. + +Move the View, Not Just the Windows +Instead of managing "layers" or "hidden states," you manage position. + +Want more space? Slide the view over. +Can't find a window? Swicth your focus to it, and the world slides until that window is right under your nose. +Lost? Hit the "homecanvas" keybind to snap your view back to the start. +Even though this sounds complex, it is actually pretty lightweight ~250 l.o.c, and is very easy to use. + ## Requirements In order to build vxwm you need the Xlib header files. @@ -72,3 +89,4 @@ match your preferences and (re)compiling the source code. ## Acknowledgements vxwm was made in solo by a linux enthusiast wh1tepearl, many thanks to suckless.org and the [dwm] developers for making dwm in first place. +Thanks hevel wayland compositor developers for insipiration of infinite tags. diff --git a/config.def.h b/config.def.h @@ -59,6 +59,15 @@ static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; static const char *occupiedtags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" }; #endif +#if INFINITE_TAGS +#define MOVE_CANVAS_STEP 120 /* Defines how many pixel will be jumped when using movecanvas function */ +#endif + +#if MOVE_RESIZE_WITH_KEYBOARD +#define MOVE_WITH_KEYBOARD_STEP 50 /* Defines by how many pixels windows will be resized with keyboard */ +#define RESIZE_WITH_KEYBOARD_STEP 50 /* Defines by how many pixels windows will be resized with keyboard */ +#endif + static const Rule rules[] = { /* xprop(1): * WM_CLASS(STRING) = instance, class @@ -155,12 +164,34 @@ static const Key keys[] = { { MODKEY, XK_equal, setgaps, {.i = +1 } }, { MODKEY|ShiftMask, XK_equal, setgaps, {.i = 0 } }, #endif +#if MOVE_RESIZE_WITH_KEYBOARD +{ MODKEY, XK_Down, moveresize, {.v = (int []){ 0, MOVE_WITH_KEYBOARD_STEP, 0, 0 }}}, +{ MODKEY, XK_Up, moveresize, {.v = (int []){ 0, -MOVE_WITH_KEYBOARD_STEP, 0, 0 }}}, +{ MODKEY, XK_Right, moveresize, {.v = (int []){ MOVE_WITH_KEYBOARD_STEP, 0, 0, 0 }}}, +{ MODKEY, XK_Left, moveresize, {.v = (int []){ -MOVE_WITH_KEYBOARD_STEP, 0, 0, 0 }}}, +{ MODKEY|ControlMask, XK_Down, moveresize, {.v = (int []){ 0, 0, 0, RESIZE_WITH_KEYBOARD_STEP }}}, +{ MODKEY|ControlMask, XK_Up, moveresize, {.v = (int []){ 0, 0, 0, -RESIZE_WITH_KEYBOARD_STEP }}}, +{ MODKEY|ControlMask, XK_Right, moveresize, {.v = (int []){ 0, 0, RESIZE_WITH_KEYBOARD_STEP, 0 }}}, +{ MODKEY|ControlMask, XK_Left, moveresize, {.v = (int []){ 0, 0, -RESIZE_WITH_KEYBOARD_STEP, 0 }}}, +#endif +#if INFINITE_TAGS + { MODKEY|ShiftMask, XK_Left, movecanvas, {.i = 0} }, // Move your position to left + { MODKEY|ShiftMask, XK_Right, movecanvas, {.i = 1} }, // Move your position to right + { MODKEY|ShiftMask, XK_Up, movecanvas, {.i = 2} }, // Move your position up + { MODKEY|ShiftMask, XK_Down, movecanvas, {.i = 3} }, // Move your position down + { MODKEY, XK_r, homecanvas, {0} }, + { MODKEY|ShiftMask, XK_d, centerwindow, {0} }, +#endif }; /* button definitions */ /* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */ static const Button buttons[] = { /* click event mask button function argument */ +#if INFINITE_TAGS + { ClkRootWin, MODKEY|ShiftMask, Button1, manuallymovecanvas, {0} }, + { ClkClientWin, MODKEY|ShiftMask, Button1, manuallymovecanvas, {0} }, +#endif { ClkLtSymbol, 0, Button1, setlayout, {0} }, { ClkLtSymbol, 0, Button3, setlayout, {.v = &layouts[2]} }, { ClkWinTitle, 0, Button2, zoom, {0} }, diff --git a/config.mk b/config.mk @@ -1,5 +1,5 @@ # vxwm version -VERSION = 1.5 +VERSION = 2.0 # Customize below to fit your system @@ -36,4 +36,4 @@ LDFLAGS = ${LIBS} #LDFLAGS = ${LIBS} # compiler and linker -CC = gcc +CC = cc diff --git a/modules.def.h b/modules.def.h @@ -2,13 +2,36 @@ /* vxwm compile-time options */ +/* KILLER FEATURES */ +#define INFINITE_TAGS 1 +/* +Most tiling window managers (like the default dwm) treat your screen like a slide-projector. You click a button, and the current "slide" is swapped for another. If an window is off-screen, it doesn't exist. + +With infinite tags enabled, vxwm treats your screen like a magnifying glass over a giant wooden desk. + +1. The Canvas is Infinite +Your windows aren't "on" tags. They are placed on a massive, invisible surface. Your monitor is just a small window through which you look at that surface. + +2. Move the View, Not Just the Windows +Instead of managing "layers" or "hidden states," you manage position. + +Want more space? Slide the view over. +Can't find a window? Swicth your focus to it, and the world slides until that window is right under your nose. +Lost? Hit the "homecanvas" keybind to snap your view back to the start. +Even though this sounds complex, it is actually pretty lightweight ~250 l.o.c, and is very easy to use. + + */ +#define IT_SHOW_COORDINATES_IN_BAR 1 // Shows your coordinates in the bar. + + + /* Move/Resize */ #define BETTER_RESIZE 1 // Enables 8 sided window resize. #define BR_CHANGE_CURSOR 1 // When resizing windows while having BETTER_RESIZE set to 1, the cursor will change depending on from which side you are resizing. #define LOCK_MOVE_RESIZE_REFRESH_RATE 1 // Recomended to use on every pc, because cpu (software) rendered apps like ST will lagg when resizing even if you have a good pc. #define USE_RESIZECLIENT_FUNC 0 // Use resizeclient function of instead of resize function which ignores window's resize hints, not recommended. #define RESIZINIG_WINDOWS_IN_ALL_LAYOUTS_FLOATS_THEM 0 // yeah. - +#define MOVE_RESIZE_WITH_KEYBOARD 1 // Allows to move and resize windows with keyboard. /* Kind of eye candy */ #define GAPS 0 // Gaps support. @@ -54,21 +77,28 @@ #define FULLSCREEN 0 // Support for toggling fullscreen. #define MOVE_IN_TILED 0 // Support for moving windows in tiled mode. #define EWMH_TAGS 0 // Support for EWMH tags, recommended if you want to use external bars with less pain -#define ALWAYS_CENTER_NEW_FLOATING_WINDOWS 0 //so, basically, it does what it says. /* Floating */ /* Recomended to use with ALWAYS_CENTER_NEW_FLOATING_WINDOWS set to 1. */ +#define ALWAYS_CENTER_NEW_FLOATING_WINDOWS 0 // so, basically, it does what it says. + #define FLOATING_LAYOUT_FLOATS_WINDOWS 0 /* By default, in floating layout, windows appear to be floating, but, for dwm, they are not. Because of this, when switching to tiled layout after floating layout, windows will be tiled, enable this if you don't want that behaviour. */ -#define ENHANCED_TOGGLE_FLOATING 0 +#define ENHANCED_TOGGLE_FLOATING 0 /* Support for enhanced toggle floating, when toggling floating window will resize to its natural size, and in floating layout, window will be tiled. - REQUIRES "FLOATING_LAYOUT_FLOATS_WINDOWS" AND "RESIZINIG_WINDOWS_IN_ALL_LAYOUTS_FLOATS_THEM" SET TO 1 TO WORK PROPERLY. */ + REQUIRES "FLOATING_LAYOUT_FLOATS_WINDOWS" SET TO 1 TO WORK PROPERLY. */ #define RESTORE_SIZE_AND_POS_ETF 0 // Restore previous size and position of window when toggling floating + + + +/* Dependency list */ +/* INFINITE_TAGS requires WINDOWMAP, please set WINDOWMAP to 1, if not, it will be automatically enabled. + * ENHANCED_TOGGLE_FLOATING requires FLOATING_LAYOUT_FLOATS_WINDOWS, please set FLOATING_LAYOUT_FLOATS_WINDOWS to 1, if not, it will be automatically enabled. */ diff --git a/modules/betterresize/betterresize.c b/modules/betterresize/betterresize.c @@ -4,8 +4,9 @@ resizemouse(const Arg *arg) Client *c; Monitor *m; XEvent ev; +#if LOCK_MOVE_RESIZE_REFRESH_RATE Time lasttime = 0; - +#endif if (!(c = selmon->sel) || c->isfullscreen) return; diff --git a/modules/etf/etf.h b/modules/etf/etf.h @@ -1 +1 @@ -void enhancedtogglefloating(const Arg *arg); +static void enhancedtogglefloating(const Arg *arg); diff --git a/modules/gaps/gaps.h b/modules/gaps/gaps.h @@ -1,2 +1 @@ static void setgaps(const Arg *arg); - diff --git a/modules/infinitetags/infinitetags.c b/modules/infinitetags/infinitetags.c @@ -0,0 +1,204 @@ +int +getcurrenttag(Monitor *m) { + unsigned int i; + for (i = 0; i < LENGTH(tags) && !(m->tagset[m->seltags] & (1 << i)); i++); + return i < LENGTH(tags) ? i : 0; +} + +void +homecanvas(const Arg *arg) { + Client *c; + int tagidx = getcurrenttag(selmon); + int cx = selmon->canvas[tagidx].cx; + int cy = selmon->canvas[tagidx].cy; + + for (c = selmon->clients; c; c = c->next) { + if (c->tags & (1 << tagidx)) { + c->x -= cx; + c->y -= cy; + XMoveWindow(dpy, c->win, c->x, c->y); + } + } + + selmon->canvas[tagidx].cx = 0; + selmon->canvas[tagidx].cy = 0; + drawbar(selmon); + XFlush(dpy); +} + +void +movecanvas(const Arg *arg) +{ + if (selmon->lt[selmon->sellt]->arrange != NULL) + return; + + int tagidx = getcurrenttag(selmon); + int dx = 0, dy = 0; + +#ifndef MOVE_CANVAS_STEP +#define MOVE_CANVAS_STEP 120 +#endif + + switch(arg->i) { + case 0: dx = MOVE_CANVAS_STEP; break; + case 1: dx = -MOVE_CANVAS_STEP; break; + case 2: dy = MOVE_CANVAS_STEP; break; + case 3: dy = -MOVE_CANVAS_STEP; break; + } + + selmon->canvas[tagidx].cx -= dx; + selmon->canvas[tagidx].cy -= dy; + + Client *c; + for (c = selmon->clients; c; c = c->next) { + if (ISVISIBLE(c)) { + c->x += dx; + c->y += dy; + XMoveWindow(dpy, c->win, c->x, c->y); + } + } + + drawbar(selmon); +} + +void +manuallymovecanvas(const Arg *arg) { + if (selmon->lt[selmon->sellt]->arrange != NULL) + return; + int start_x, start_y; + Window dummy; + int di; + unsigned int dui; + int tagidx = getcurrenttag(selmon); +#if LOCK_MOVE_RESIZE_REFRESH_RATE + Time lasttime = 0; +#endif + if (selmon->sel && selmon->sel->isfullscreen) + return; + + if (!XQueryPointer(dpy, root, &dummy, &dummy, &start_x, &start_y, &di, &di, &dui)) + return; + + if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + return; + + XEvent ev; + do { + XMaskEvent(dpy, MOUSEMASK|ExposureMask|SubstructureRedirectMask, &ev); + + switch (ev.type) { + case MotionNotify: + { +#if LOCK_MOVE_RESIZE_REFRESH_RATE + if ((ev.xmotion.time - lasttime) <= (1000 / refreshrate)) + continue; + lasttime = ev.xmotion.time; +#endif + int nx = ev.xmotion.x - start_x; + int ny = ev.xmotion.y - start_y; + + for (Client *c = selmon->clients; c; c = c->next) { + if (c->tags & (1 << tagidx)) { + c->x += nx; + c->y += ny; + XMoveWindow(dpy, c->win, c->x, c->y); + } + } + + selmon->canvas[tagidx].cx += nx; + selmon->canvas[tagidx].cy += ny; + drawbar(selmon); + start_x = ev.xmotion.x; + start_y = ev.xmotion.y; + } break; + } + } while (ev.type != ButtonRelease); + + XUngrabPointer(dpy, CurrentTime); +} + +void +save_canvas_positions(Monitor *m) { + Client *c; + int tagidx = getcurrenttag(m); + + m->canvas[tagidx].saved_cx = m->canvas[tagidx].cx; + m->canvas[tagidx].saved_cy = m->canvas[tagidx].cy; + + for (c = m->clients; c; c = c->next) { + if (ISVISIBLE(c)) { + c->saved_cx = c->x + m->canvas[tagidx].cx; + c->saved_cy = c->y + m->canvas[tagidx].cy; + c->saved_cw = c->w; + c->saved_ch = c->h; + c->was_on_canvas = 1; + } + } +} + +void +restore_canvas_positions(Monitor *m) { + Client *c; + int tagidx = getcurrenttag(m); + + m->canvas[tagidx].cx = m->canvas[tagidx].saved_cx; + m->canvas[tagidx].cy = m->canvas[tagidx].saved_cy; + + for (c = m->clients; c; c = c->next) { + if (ISVISIBLE(c) && c->was_on_canvas) { + c->isfloating = 1; + + int target_x = c->saved_cx - m->canvas[tagidx].cx; + int target_y = c->saved_cy - m->canvas[tagidx].cy; + + c->x = target_x; + c->y = target_y; + c->w = c->saved_cw; + c->h = c->saved_ch; + + XMoveResizeWindow(dpy, c->win, target_x, target_y, c->w, c->h); + + configure(c); + } + } + XSync(dpy, False); +} + +void +centerwindow(const Arg *arg) +{ + Client *c = (arg && arg->v) ? (Client *)arg->v : selmon->sel; + + if (!c || !c->mon || c->mon->lt[c->mon->sellt]->arrange != NULL) + return; + + Monitor *m = c->mon; + int tagidx = getcurrenttag(m); + + int screen_center_x = m->wx + (m->ww / 2); + int screen_center_y = m->wy + (m->wh / 2); + + int win_center_x = c->x + (c->w + 2 * c->bw) / 2; + int win_center_y = c->y + (c->h + 2 * c->bw) / 2; + + int dx = screen_center_x - win_center_x; + int dy = screen_center_y - win_center_y; + + if (dx == 0 && dy == 0) + return; + + Client *tmp; + for (tmp = m->clients; tmp; tmp = tmp->next) { + if (ISVISIBLE(tmp)) { + tmp->x += dx; + tmp->y += dy; + XMoveWindow(dpy, tmp->win, tmp->x, tmp->y); + } + } + + m->canvas[tagidx].cx += dx; + m->canvas[tagidx].cy += dy; + + drawbar(m); +} diff --git a/modules/infinitetags/infinitetags.h b/modules/infinitetags/infinitetags.h @@ -0,0 +1,7 @@ +static void movecanvas(const Arg *arg); +static void manuallymovecanvas(const Arg *arg); +static void homecanvas(const Arg *arg); +static int getcurrenttag(Monitor *m); +static void save_canvas_positions(Monitor *m); +static void restore_canvas_positions(Monitor *m); +static void centerwindow(const Arg *arg); diff --git a/modules/moveresizekbd/moveresizekbd.c b/modules/moveresizekbd/moveresizekbd.c @@ -0,0 +1,74 @@ +void +moveresize(const Arg *arg) +{ + if (selmon->lt[selmon->sellt]->arrange != NULL) + return; + + Monitor *m = selmon; + Client *c = m->sel; +#if INFINITE_TAGS + int tagidx = getcurrenttag(m); +#endif + if (!(c && arg && arg->v && c->isfloating)) + return; + + int dx = ((int *)arg->v)[0]; + int dy = ((int *)arg->v)[1]; + int dw = ((int *)arg->v)[2]; + int dh = ((int *)arg->v)[3]; + + if (dw != 0 || dh != 0) { + if (c->x + c->w + dw > m->mw) + return; + + if (c->y + c->h + dh > m->mh) + return; + + resize(c, c->x, c->y, c->w + dw, c->h + dh, True); + + XEvent ev; + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); + return; + } + + if (dx != 0 || dy != 0) { + resize(c, c->x + dx, c->y + dy, c->w, c->h, True); + +#if INFINITE_TAGS + int canvas_dx = 0; + int canvas_dy = 0; + + if (c->x < 0) { + canvas_dx = c->x; + } + else if (c->x + WIDTH(c) > m->mw) { + canvas_dx = (c->x + WIDTH(c)) - m->mw; + } + + if (c->y < 0) { + canvas_dy = c->y; + } + else if (c->y + HEIGHT(c) > m->mh) { + canvas_dy = (c->y + HEIGHT(c)) - m->mh; + } + + if (canvas_dx != 0 || canvas_dy != 0) { + m->canvas[tagidx].cx += canvas_dx; + m->canvas[tagidx].cy += canvas_dy; + + Client *tmp; + for (tmp = m->clients; tmp; tmp = tmp->next) { + if (ISVISIBLE(tmp)) { + tmp->x -= canvas_dx; + tmp->y -= canvas_dy; + XMoveWindow(dpy, tmp->win, tmp->x, tmp->y); + } + } + drawbar(m); + } +#endif + } + + XEvent ev; + while (XCheckMaskEvent(dpy, EnterWindowMask, &ev)); +} diff --git a/modules/moveresizekbd/moveresizekbd.h b/modules/moveresizekbd/moveresizekbd.h @@ -0,0 +1 @@ +static void moveresize(const Arg *arg); diff --git a/modules/vxwm_includes.c b/modules/vxwm_includes.c @@ -31,3 +31,11 @@ #if WINDOWMAP #include "windowmap/windowmap.c" #endif + +#if INFINITE_TAGS +#include "infinitetags/infinitetags.c" +#endif + +#if MOVE_RESIZE_WITH_KEYBOARD +#include "moveresizekbd/moveresizekbd.c" +#endif diff --git a/modules/vxwm_includes.h b/modules/vxwm_includes.h @@ -27,3 +27,11 @@ #if WINDOWMAP #include "windowmap/windowmap.h" #endif + +#if INFINITE_TAGS +#include "infinitetags/infinitetags.h" +#endif + +#if MOVE_RESIZE_WITH_KEYBOARD +#include "moveresizekbd/moveresizekbd.h" +#endif diff --git a/modules/warptoclient/warptoclient.h b/modules/warptoclient/warptoclient.h @@ -1 +1 @@ -void warptoclient(Client *c); +static void warptoclient(Client *c); diff --git a/vxwm.c b/vxwm.c @@ -1,7 +1,7 @@ /* See LICENSE file for copyright and license details. This wm is forked from dwm 6.7 (but keep up with all dwm's updates), thanks suckless for their incredible work on dwm! -vxwm 1.5 // by wh1tepearl +vxwm 2.0 // by wh1tepearl Known issues: @@ -14,7 +14,7 @@ Solved issues: 4. When using BETTER_RESIZE window is not becaming floating when resizing */ -//Modules configuration is in modules.h +// Modules configuration is in modules.h #include <errno.h> #include <locale.h> @@ -41,6 +41,16 @@ Solved issues: #include "drw.h" #include "util.h" +#if INFINITE_TAGS && !WINDOWMAP + #undef WINDOWMAP + #define WINDOWMAP 1 +#endif + +#if ENHANCED_TOGGLE_FLOATING && !FLOATING_LAYOUT_FLOATS_WINDOWS + #undef FLOATING_LAYOUT_FLOATS_WINDOWS + #define FLOATING_LAYOUT_FLOATS_WINDOWS 1 +#endif + /* macros */ #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) @@ -124,6 +134,11 @@ struct Client { Client *snext; Monitor *mon; Window win; +#if INFINITE_TAGS + int saved_cx, saved_cy; + int saved_cw, saved_ch; + int was_on_canvas; +#endif #if WINDOWMAP int ismapped; #endif @@ -147,6 +162,13 @@ typedef struct { void (*arrange)(Monitor *); } Layout; +#if INFINITE_TAGS +typedef struct { + int cx, cy; + int saved_cx, saved_cy; +} CanvasOffset; +#endif + struct Monitor { char ltsymbol[16]; float mfact; @@ -169,6 +191,9 @@ struct Monitor { Monitor *next; Window barwin; const Layout *lt[2]; +#if INFINITE_TAGS + CanvasOffset *canvas; +#endif }; typedef struct { @@ -715,6 +740,14 @@ createmon(void) m->lt[0] = &layouts[0]; m->lt[1] = &layouts[1 % LENGTH(layouts)]; strncpy(m->ltsymbol, layouts[0].symbol, sizeof m->ltsymbol); +#if INFINITE_TAGS + m->canvas = ecalloc(LENGTH(tags), sizeof(CanvasOffset)); + unsigned int i; + for (i = 0; i < LENGTH(tags); i++) { + m->canvas[i].cx = 0; + m->canvas[i].cy = 0; + } +#endif return m; } @@ -815,6 +848,18 @@ drawbar(Monitor *m) #endif x += w; } +#if INFINITE_TAGS && IT_SHOW_COORDINATES_IN_BAR + int tagidx = getcurrenttag(m); + char coords[64]; + snprintf(coords, sizeof(coords), "x:%d y:%d", + m->canvas[tagidx].cx / 10, + m->canvas[tagidx].cy / 10); // Delete 10 if you want to get the most accurate values + w = TEXTW(coords); + drw_setscheme(drw, scheme[SchemeNorm]); + drw_text(drw, x, 0, w, bh, lrpad / 2, coords, 0); + x += w; +#endif + w = TEXTW(m->ltsymbol); drw_setscheme(drw, scheme[SchemeNorm]); x = drw_text(drw, x, 0, w, bh, lrpad / 2, m->ltsymbol, 0); @@ -954,6 +999,9 @@ focusstack(const Arg *arg) } if (c) { focus(c); +#if INFINITE_TAGS + centerwindow(NULL); +#endif #if WARP_TO_CLIENT && WARP_TO_CENTER_OF_WINDOW_AFFECTED_BY_FOCUSSTACK warptoclient(c); #endif @@ -1236,7 +1284,7 @@ manage(Window w, XWindowAttributes *wa) XMapWindow(dpy, c->win); focus(NULL); #if WARP_TO_CLIENT && WARP_TO_CENTER_OF_NEW_WINDOW - warptoclient(c); + warptoclient(c); #endif } @@ -1752,18 +1800,38 @@ setfullscreen(Client *c, int fullscreen) void setlayout(const Arg *arg) { - if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) - selmon->sellt ^= 1; - if (arg && arg->v) - selmon->lt[selmon->sellt] = (Layout *)arg->v; - strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol - 1); - selmon->ltsymbol[sizeof selmon->ltsymbol - 1] = '\0'; - if (selmon->sel) - arrange(selmon); - else - drawbar(selmon); -} +#if INFINITE_TAGS + const Layout *old_layout = selmon->lt[selmon->sellt]; +#endif + if (!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) + selmon->sellt ^= 1; + if (arg && arg->v) + selmon->lt[selmon->sellt] = (Layout *)arg->v; +#if INFINITE_TAGS + const Layout *new_layout = selmon->lt[selmon->sellt]; +#endif +#if INFINITE_TAGS + if (old_layout->arrange == NULL && new_layout->arrange != NULL) { + save_canvas_positions(selmon); + homecanvas(NULL); + Client *c; + for (c = selmon->clients; c; c = c->next) + if (!c->isfixed) c->isfloating = 0; + } + + if (new_layout->arrange == NULL) { + restore_canvas_positions(selmon); + + Client *c; + for (c = selmon->clients; c; c = c->next) + c->isfloating = 1; + } +#endif + strncpy(selmon->ltsymbol, selmon->lt[selmon->sellt]->symbol, sizeof selmon->ltsymbol - 1); + selmon->ltsymbol[sizeof selmon->ltsymbol - 1] = '\0'; + arrange(selmon); +} /* arg > 1.0 will set mfact absolutely */ void setmfact(const Arg *arg) @@ -2400,36 +2468,82 @@ updatewmhints(Client *c) void view(const Arg *arg) { - if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) - selmon->seltags ^= 1; /* toggle sel tagset */ - else { - selmon->seltags ^= 1; /* toggle sel tagset */ - if (arg->ui & TAGMASK) - selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; - } - focus(NULL); - arrange(selmon); -#if EWMH_TAGS - updatecurrentdesktop(); +#if INFINITE_TAGS + if (selmon->lt[selmon->sellt]->arrange == NULL) { + save_canvas_positions(selmon); + } #endif + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) + selmon->seltags ^= 1; + else { + selmon->seltags ^= 1; + if (arg->ui & TAGMASK) + selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + } + +#if INFINITE_TAGS + int newtag = getcurrenttag(selmon); + + if (selmon->lt[selmon->sellt]->arrange == NULL) { + restore_canvas_positions(selmon); + + Client *c; + for (c = selmon->clients; c; c = c->next) + if (c->tags & (1 << newtag)) + c->isfloating = 1; + } else { + selmon->canvas[newtag].cx = 0; + selmon->canvas[newtag].cy = 0; + } +#endif + + focus(NULL); + arrange(selmon); +#if EWMH_TAGS + updatecurrentdesktop(); +#endif } + #else void view(const Arg *arg) { +#if INFINITE_TAGS + if (selmon->lt[selmon->sellt]->arrange == NULL) + save_canvas_positions(selmon); +#endif + if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags]) return; - selmon->seltags ^= 1; /* toggle sel tagset */ + selmon->seltags ^= 1; if (arg->ui & TAGMASK) selmon->tagset[selmon->seltags] = arg->ui & TAGMASK; + +#if INFINITE_TAGS + int newtag = getcurrenttag(selmon); + + if (selmon->lt[selmon->sellt]->arrange != NULL) { + selmon->canvas[newtag].cx = 0; + selmon->canvas[newtag].cy = 0; + } else { + restore_canvas_positions(selmon); + + Client *c; + for (c = selmon->clients; c; c = c->next) + if (ISVISIBLE(c)) + c->isfloating = 1; + } +#endif + focus(NULL); arrange(selmon); #if EWMH_TAGS updatecurrentdesktop(); #endif } + #endif Client *