Compare commits

..
13 Commits
Author SHA1 Message Date
lupan 1a18d7ca48 apply dwm-xinerama-monitors-xorder-6.4.diff 2026-07-18 23:50:05 +02:00
lupan dbaf66abb3 agree: change dwm-autodarkmode signal to USR1 and leave restarsig signal to HUP 2026-07-18 23:50:05 +02:00
lupan e401821c15 apply patch dwm-autodarkmode-20250224-6.5.diff 2026-07-18 23:50:05 +02:00
lupan 3a8b2220db apply patch dwm-awesomebar-20230431-6.4.diff 2026-07-18 23:50:05 +02:00
lupan 14e59f1f91 apply patch dwm-exitmenu-6.3.diff 2026-07-18 23:50:05 +02:00
Arda Atci 0b15b3a2bf preserve clients on old tags when renewing dwm
By default, when dwm is recompiled-restarted all clients will
lose it's current tag and collapse to first tag. This patch preserves
clients on old tags, however note that layout order is not preserved.
2026-07-18 23:50:05 +02:00
Christopher Drelich 22b54433b8 Modifies quit to handle restarts and adds SIGHUP and SIGTERM handlers.
Modified quit() to restart if it receives arg .i = 1
MOD+CTRL+SHIFT+Q was added to confid.def.h to do just that.

Signal handlers were handled for SIGHUP and SIGTERM.
If dwm receives these signals it calls quit() with
arg .i = to 1 or 0, respectively.

To restart dwm:
MOD+CTRL+SHIFT+Q
or
kill -HUP dwmpid

To quit dwm cleanly:
MOD+SHIFT+Q
or
kill -TERM dwmpid
2026-07-18 23:40:30 +02:00
Ruben Gonzalez 44dbc6809d buttonpress: fix status text click area mismatch
The status bar in drawbar() calculates the text width as TEXTW(stext)
- lrpad + 2. However, the click detection in buttonpress() used
TEXTW(stext) without adjusting for that padding.

This created an "extra" clickable area of some pixels to the left of
the status text that would incorrectly trigger ClkStatusText actions
instead of ClkWinTitle.

Steps to reproduce:
1. Set a status text: xsetroot -name "HELLO"
2. Move the mouse to the empty space with some pixels close to the
left of the word "HELLO" but in the title area.
3. Middle-click (or any binding for ClkStatusText).
4. You can see that the status bar action is triggered (default a
terminal spawns), even though you clicked in the window title area.

This fix ensures that the clickable area matches the visual text.
2026-03-13 18:27:18 +01:00
Ruben Gonzalez 2bb919e634 sendmon: resize fullscreen windows to target monitor
When a fullscreen window is moved to another monitor (e.g. via
tagmon), its geometry does not always match the new monitor's
dimensions.

Steps to reproduce:
1. Start dwm with two monitors (A and B).
2. Open a window on Monitor A.
3. Make the window fullscreen (e.g. Firefox with F11).
4. Move the window to Monitor B using the tagmon shortcut (Mod+Shift+>).
5. Go to the other monitor (B), observe that the window is still
visible on Monitor A and its contents, even though the window's title
is seen on Monitor B bar.
6. Go to the monitor A where the window is still in fullscreen, remove
the fullscreen and the window automatically will go to monitor B.

This fix ensures that fullscreen windows are correctly resized to the
new monitor's geometry during the move.
2026-03-10 19:52:48 +01:00
NRK c3dd6a829b more overflow fix in getatomprop()
commit 244fa852 (and a9aa0d8) tried to fix overflow by checking
the number of items returned. however this is not sufficient
since the format may be lower than 32 bits.

to reproduce the crash, i used the reproducer given in commit
244fa85 but changed the XChangeProperty line to the following to
set the property to a 1 element 16 bit item:

	short si = 1;
	XChangeProperty(d, w, net_wm_state, XA_ATOM, 16,
		PropModeReplace, (unsigned char *)&si, 1);

this client reliably crashes dwm under ASAN since dwm is trying
to read a 32 bit value from a 16 bit one. fix it by checking for
format == 32 as well.

also change the access type from Atom to long, on my machine
Atom is typedef-ed to long already but that may not be true
everywere. the XGetWindowProperty manpage says format == 32 is
returned as `long` so use `long` directly.

(N.B: it also might be worth checking if the returned type is
 XA_ATOM as well, but i wasn't able to cause any crashes by
 setting different types so i'm leaving it out for now.)
2026-02-20 15:31:29 +01:00
NRK 5c9f30300b getstate: fix access type and remove redundant cast
WM_STATE is defined to be format == 32 which xlib returns as
`long` and so accessing it as `unsigned char` is incorrect.

and also &p is already an `unsigned char **` and so the cast was
completely redundant.

given the redundant cast, i assume `p` was `long *` at some time
but was changed to `unsigned char *` later, but the pointer
access (and the cast) wasn't updated.

also add a `format == 32` check as safety measure before
accessing, just in case.
2026-02-20 15:31:28 +01:00
NRK 397d618f1c fix not updating _NET_ACTIVE_WINDOW
currently clients that set the input field of WM_HINTS to true
(c->neverfocus) will never be updated as _NET_ACTIVE_WINDOW even
when they are focused. according to the ICCCM [0] the input
field of WM_HINTS tells the WM to either use or not use
XSetInputFocus(), it shouldn't have any relation to
_NET_ACTIVE_WINDOW. EWMH spec [1] also does not mention any
relationship between the two.

this issue was noticed when launching games via steam/proton and
noticing that _NET_ACTIVE_WINDOW was always wrong/stale (i.e not
updated to the game window).

for reference I've looked at bspwm [2] and it also seems to set
_NET_ACTIVE_WINDOW regardless of whether the client has WM_HINTS
input true or not.

[0]: https://x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html#input_focus
[1]: https://specifications.freedesktop.org/wm/1.5/ar01s03.html#id-1.4.10
[2]: https://github.com/baskerville/bspwm/blob/c5cf7d3943f9a34a5cb2bab36bf473fd77e7d4f6/src/tree.c#L659-L662
2026-02-13 10:16:08 +01:00
Hiltjo Posthuma f63cde9354 bump version to 6.8 2026-01-30 11:18:38 +01:00
8 changed files with 193 additions and 400 deletions

No files matched your search

-28
View File
@@ -1,9 +1,7 @@
/* See LICENSE file for copyright and license details. */
#include "gaplessgrid.c"
/* appearance */
static const unsigned int borderpx = 1; /* border pixel of windows */
static const unsigned int gappx = 6; /* gaps between windows */
static const unsigned int snap = 32; /* snap pixel */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
@@ -24,7 +22,6 @@ static const char *colorslight[][3] = {
/* fg bg border */
[SchemeNorm] = { col_gray1, col_gray3, col_gray2 },
[SchemeSel] = { col_cyan, col_gray4, col_cyan },
[SchemeHid] = { col_cyan, col_gray1, col_cyan },
};
/* tagging */
@@ -52,7 +49,6 @@ static const Layout layouts[] = {
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
{ "HHH", gaplessgrid },
};
/* key definitions */
@@ -71,17 +67,11 @@ static char dmenumon[2] = "0"; /* component of dmenu{dark,light}, manipulated in
static const char *dmenudark[] = { "dmenu_run", "-m", dmenumon, "-i", "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
static const char *dmenulight[] = { "dmenu_run", "-m", dmenumon, "-i", "-fn", dmenufont, "-nb", col_gray3, "-nf", col_gray1, "-sb", col_cyan, "-sf", col_gray4, NULL };
static const char *termcmd[] = { "st", NULL };
#include "shift-tools.c"
#include "exitdwm.c"
#include "movestack.c"
static const Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_p, spawndmenu, {0} },
{ MODKEY, XK_o, shiftviewclients, { .i = +1 } },
{ MODKEY|ShiftMask, XK_o, shiftview, { .i = +1 } },
{ MODKEY|ShiftMask, XK_i, shiftview, { .i = -1 } },
{ MODKEY, XK_i, shiftviewclients, { .i = -1 } },
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
{ MODKEY, XK_b, togglebar, {0} },
{ MODKEY, XK_j, focusstackvis, {.i = +1 } },
@@ -91,16 +81,9 @@ static const Key keys[] = {
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY|ShiftMask, XK_h, shiftboth, { .i = -1 } },
{ MODKEY|ControlMask, XK_h, shiftswaptags, { .i = -1 } },
{ MODKEY|ControlMask, XK_l, shiftswaptags, { .i = +1 } },
{ MODKEY|ShiftMask, XK_l, shiftboth, { .i = +1 } },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
{ MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
{ MODKEY, XK_Return, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY, XK_g, goback, {0} },
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
@@ -125,20 +108,9 @@ static const Key keys[] = {
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
{ MODKEY|ShiftMask, XK_j, focusbynum, {.i = 0} },
{ MODKEY|ShiftMask, XK_k, focusbynum, {.i = 1} },
{ MODKEY|ShiftMask, XK_l, focusbynum, {.i = 2} },
{ MODKEY|ShiftMask, XK_colon, focusbynum, {.i = 3} },
{ MODKEY|ShiftMask, XK_f, focusbynum, {.i = 4} },
{ MODKEY|ShiftMask, XK_d, focusbynum, {.i = 5} },
{ MODKEY|ShiftMask, XK_s, focusbynum, {.i = 6} },
{ MODKEY|ShiftMask, XK_a, focusbynum, {.i = 7} },
{ MODKEY|ShiftMask, XK_q, quit, {0} },
{ MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} },
{ MODKEY|ShiftMask, XK_e, exitdwm, {0} },
{ MODKEY, XK_o, winview, {0} },
{ MODKEY, XK_g, gridall, {} },
{ MODKEY, XK_r, winviewmono, {} },
};
/* button definitions */
+174
View File
@@ -0,0 +1,174 @@
/* See LICENSE file for copyright and license details. */
#include "gaplessgrid.c"
/* appearance */
static const unsigned int borderpx = 2; /* border pixel of windows */
static const unsigned int gappx = 2; /* gaps between windows */
static const unsigned int snap = 32; /* snap pixel */
static const int showbar = 1; /* 0 means no bar */
static const int topbar = 1; /* 0 means bottom bar */
static const char *fonts[] = { "monospace:size=11" };
static const char dmenufont[] = "monospace:size=11";
static const char col_gray1[] = "#222222";
static const char col_gray2[] = "#444444";
static const char col_gray3[] = "#bbbbbb";
static const char col_gray4[] = "#eeeeee";
static const char col_cyan[] = "#005577";
static const char col_border_focus_light[] = "#df8c20"; // hsl(34 75% 50%)
static const char col_border_focus_dark[] = "#b25e34"; // hsl(20 55% 45%)
static const char *colorsdark[][3] = {
/* fg bg border */
[SchemeNorm] = { col_gray3, col_gray1, col_gray2 },
[SchemeSel] = { col_gray4, col_cyan, col_border_focus_dark },
[SchemeHid] = { col_cyan, col_gray1, col_cyan },
};
static const char *colorslight[][3] = {
/* fg bg border */
[SchemeNorm] = { col_gray1, col_gray3, col_gray2 },
[SchemeSel] = { col_cyan, col_gray4, col_border_focus_light },
[SchemeHid] = { col_cyan, col_gray1, col_cyan },
};
/* tagging */
static const char *tags[] = { "1", "2", "3", "4", "5", "6", "7", "8", "9" };
static const Rule rules[] = {
/* xprop(1):
* WM_CLASS(STRING) = instance, class
* WM_NAME(STRING) = title
*/
/* class instance title tags mask isfloating monitor */
{ "Gimp", NULL, NULL, 0, 1, -1 },
{ "Firefox", NULL, NULL, 1 << 8, 0, -1 },
};
/* layout(s) */
static const float mfact = 0.55; /* factor of master area size [0.05..0.95] */
static const int nmaster = 1; /* number of clients in master area */
static const int resizehints = 1; /* 1 means respect size hints in tiled resizals */
static const int lockfullscreen = 1; /* 1 will force focus on the fullscreen window */
static const int refreshrate = 120; /* refresh rate (per second) for client move/resize */
static const Layout layouts[] = {
/* symbol arrange function */
{ "[]=", tile }, /* first entry is default */
{ "><>", NULL }, /* no layout function means floating behavior */
{ "[M]", monocle },
{ "HHH", gaplessgrid },
};
/* key definitions */
#define MODKEY Mod4Mask
#define TAGKEYS(KEY,TAG) \
{ MODKEY, KEY, view, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask, KEY, toggleview, {.ui = 1 << TAG} }, \
{ MODKEY|ShiftMask, KEY, tag, {.ui = 1 << TAG} }, \
{ MODKEY|ControlMask|ShiftMask, KEY, toggletag, {.ui = 1 << TAG} },
/* helper for spawning shell commands in the pre dwm-5.0 fashion */
#define SHCMD(cmd) { .v = (const char*[]){ "/bin/sh", "-c", cmd, NULL } }
/* commands */
static char dmenumon[2] = "0"; /* component of dmenu{dark,light}, manipulated in spawndmenu() */
static const char *dmenudark[] = { "dmenu_run", "-l", "10", "-m", dmenumon, "-i", "-fn", dmenufont, "-nb", col_gray1, "-nf", col_gray3, "-sb", col_cyan, "-sf", col_gray4, NULL };
static const char *dmenulight[] = { "dmenu_run", "-l", "10", "-m", dmenumon, "-i", "-fn", dmenufont, "-nb", col_gray3, "-nf", col_gray1, "-sb", col_cyan, "-sf", col_gray4, NULL };
static const char *termcmd[] = { "alacritty", NULL };
static const char *lockcmd[] = { "slock", NULL };
static const char *suspendcmd[] = { "systemctl", "suspend", NULL };
static const char *themecmd[] = { "lupan-set-theme", "toggle", NULL };
static const char *changeresulutioncmd[] = { "change-resolution", NULL };
#include "shift-tools.c"
#include "exitdwm.c"
#include "movestack.c"
static const Key keys[] = {
/* modifier key function argument */
{ MODKEY, XK_p, spawndmenu, {0} },
{ MODKEY, XK_u, shiftview, { .i = +1 } },
{ MODKEY|ShiftMask, XK_u, shifttag, { .i = +1 } },
{ MODKEY|ShiftMask, XK_y, shifttag, { .i = -1 } },
{ MODKEY, XK_y, shiftview, { .i = -1 } },
{ MODKEY|ShiftMask, XK_Return, spawn, {.v = termcmd } },
{ MODKEY, XK_b, togglebar, {0} },
{ MODKEY, XK_j, focusstackvis, {.i = +1 } },
{ MODKEY, XK_k, focusstackvis, {.i = -1 } },
{ MODKEY|ControlMask, XK_j, focusstackhid, {.i = +1 } },
{ MODKEY|ControlMask, XK_k, focusstackhid, {.i = -1 } },
{ MODKEY, XK_i, incnmaster, {.i = +1 } },
{ MODKEY, XK_d, incnmaster, {.i = -1 } },
{ MODKEY, XK_h, setmfact, {.f = -0.05} },
{ MODKEY|ShiftMask, XK_h, shiftboth, { .i = -1 } },
{ MODKEY|ControlMask, XK_h, shiftswaptags, { .i = -1 } },
{ MODKEY|ControlMask, XK_l, shiftswaptags, { .i = +1 } },
{ MODKEY|ShiftMask, XK_l, shiftboth, { .i = +1 } },
{ MODKEY, XK_l, setmfact, {.f = +0.05} },
{ MODKEY|ShiftMask, XK_j, movestack, {.i = +1 } },
{ MODKEY|ShiftMask, XK_k, movestack, {.i = -1 } },
{ MODKEY, XK_Return, zoom, {0} },
{ MODKEY, XK_Tab, view, {0} },
{ MODKEY, XK_w, goback, {0} },
{ MODKEY|ShiftMask, XK_c, killclient, {0} },
{ MODKEY, XK_t, setlayout, {.v = &layouts[0]} },
{ MODKEY, XK_f, setlayout, {.v = &layouts[1]} },
{ MODKEY, XK_m, setlayout, {.v = &layouts[2]} },
{ MODKEY, XK_g, setlayout, {.v = &layouts[3]} },
{ MODKEY, XK_space, setlayout, {0} },
{ MODKEY|ShiftMask, XK_space, togglefloating, {0} },
{ MODKEY, XK_0, view, {.ui = ~0 } },
{ MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } },
{ MODKEY, XK_comma, focusmon, {.i = -1 } },
{ MODKEY, XK_period, focusmon, {.i = +1 } },
{ MODKEY|ShiftMask, XK_comma, tagmon, {.i = -1 } },
{ MODKEY|ShiftMask, XK_period, tagmon, {.i = +1 } },
{ MODKEY, XK_s, show, {0} },
{ MODKEY|ShiftMask, XK_s, showall, {0} },
{ MODKEY|ControlMask, XK_s, hide, {0} },
TAGKEYS( XK_1, 0)
TAGKEYS( XK_2, 1)
TAGKEYS( XK_3, 2)
TAGKEYS( XK_4, 3)
TAGKEYS( XK_5, 4)
TAGKEYS( XK_6, 5)
TAGKEYS( XK_7, 6)
TAGKEYS( XK_8, 7)
TAGKEYS( XK_9, 8)
{ ControlMask, XK_1, focusbynum, {.i = 0} },
{ ControlMask, XK_2, focusbynum, {.i = 1} },
{ ControlMask, XK_3, focusbynum, {.i = 2} },
{ ControlMask, XK_4, focusbynum, {.i = 3} },
{ ControlMask, XK_5, focusbynum, {.i = 4} },
{ ControlMask, XK_6, focusbynum, {.i = 5} },
{ ControlMask, XK_7, focusbynum, {.i = 6} },
{ ControlMask, XK_8, focusbynum, {.i = 7} },
{ ControlMask, XK_9, focusbynum, {.i = 8} },
{ MODKEY|ShiftMask, XK_q, quit, {0} },
{ MODKEY|ControlMask|ShiftMask, XK_q, quit, {1} },
{ MODKEY|ShiftMask, XK_e, exitdwm, {0} },
{ MODKEY, XK_o, winview, {0} },
{ MODKEY, XK_a, gridall, {} },
{ MODKEY, XK_r, winviewmono, {} },
{ MODKEY, XK_n, spawn, {.v = changeresulutioncmd } },
{ MODKEY|ControlMask|ShiftMask, XK_s, spawn, {.v = suspendcmd } },
{ MODKEY|ControlMask|ShiftMask, XK_l, spawn, {.v = lockcmd } },
{ MODKEY|ControlMask|ShiftMask, XK_t, spawn, {.v = themecmd } },
};
/* button definitions */
/* click can be ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, or ClkRootWin */
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, Button2, zoom, {0} },
{ ClkStatusText, 0, Button2, spawn, {.v = termcmd } },
{ ClkClientWin, MODKEY, Button1, movemouse, {0} },
{ ClkClientWin, MODKEY, Button2, togglefloating, {0} },
{ ClkClientWin, MODKEY, Button3, resizemouse, {0} },
{ ClkTagBar, 0, Button1, view, {0} },
{ ClkTagBar, 0, Button3, toggleview, {0} },
{ ClkTagBar, MODKEY, Button1, tag, {0} },
{ ClkTagBar, MODKEY, Button3, toggletag, {0} },
};
+1 -1
View File
@@ -1,5 +1,5 @@
# dwm version
VERSION = 6.7
VERSION = 6.8
# Customize below to fit your system
-3
View File
@@ -110,9 +110,6 @@ Increase master area size.
.B Mod1\-h
Decrease master area size.
.TP
.B Mod1\-o
Select view of the window in focus. The list of tags to be displayed is matched to the window tag list.
.TP
.B Mod1\-Return
Zooms/cycles focused window to/from master area (tiled layouts only).
.TP
+18 -150
View File
@@ -52,8 +52,8 @@
#define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags]))
#define HIDDEN(C) ((getstate(C->win) == IconicState))
#define MOUSEMASK (BUTTONMASK|PointerMotionMask)
#define WIDTH(X) ((X)->w + 2 * (X)->bw + gappx)
#define HEIGHT(X) ((X)->h + 2 * (X)->bw + gappx)
#define WIDTH(X) ((X)->w + 2 * (X)->bw)
#define HEIGHT(X) ((X)->h + 2 * (X)->bw)
#define TAGMASK ((1 << LENGTH(tags)) - 1)
#define TEXTW(X) (drw_fontset_getwidth(drw, (X)) + lrpad)
@@ -179,7 +179,6 @@ static Atom getatomprop(Client *c, Atom prop);
static int getrootptr(int *x, int *y);
static long getstate(Window w);
static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
static void goback(const Arg *arg);
static void grabbuttons(Client *c, int focused);
static void grabkeys(void);
static void hide(const Arg *arg);
@@ -229,7 +228,6 @@ static void tagmon(const Arg *arg);
static void tile(Monitor *m);
static void togglebar(const Arg *arg);
static void togglefloating(const Arg *arg);
static void focusbynum(const Arg *arg);
static void toggletag(const Arg *arg);
static void toggleview(const Arg *arg);
static void togglewin(const Arg *arg);
@@ -247,16 +245,12 @@ static void updatetitle(Client *c);
static void updatewindowtype(Client *c);
static void updatewmhints(Client *c);
static void view(const Arg *arg);
static void warp(const Client *c);
static Client *wintoclient(Window w);
static Monitor *wintomon(Window w);
static void winview(const Arg* arg);
static int xerror(Display *dpy, XErrorEvent *ee);
static int xerrordummy(Display *dpy, XErrorEvent *ee);
static int xerrorstart(Display *dpy, XErrorEvent *ee);
static void zoom(const Arg *arg);
static void gridall(const Arg *arg);
static void winviewmono(const Arg *arg);
/* variables */
static const char broken[] = "broken";
@@ -290,7 +284,7 @@ static Cur *cursor[CurLast];
static Clr **scheme, **schemedark, **schemelight;
static Display *dpy;
static Drw *drw;
static Monitor *mons, *selmon, *prevmon;
static Monitor *mons, *selmon;
static Window root, wmcheckwin;
static const char **dmenucmd;
static int colormodechanged;
@@ -455,7 +449,6 @@ buttonpress(XEvent *e)
/* focus monitor if necessary */
if ((m = wintomon(ev->window)) && m != selmon) {
unfocus(selmon->sel, 1);
prevmon = selmon;
selmon = m;
focus(NULL);
}
@@ -844,7 +837,6 @@ enternotify(XEvent *e)
m = c ? c->mon : wintomon(ev->window);
if (m != selmon) {
unfocus(selmon->sel, 1);
prevmon = selmon;
selmon = m;
} else if (!c || c == selmon->sel)
return;
@@ -877,10 +869,8 @@ focus(Client *c)
}
}
if (c) {
if (c->mon != selmon) {
prevmon = selmon;
if (c->mon != selmon)
selmon = c->mon;
}
if (c->isurgent)
seturgent(c, 0);
detachstack(c);
@@ -916,10 +906,8 @@ focusmon(const Arg *arg)
if ((m = dirtomon(arg->i)) == selmon)
return;
unfocus(selmon->sel, 0);
prevmon = selmon;
selmon = m;
focus(NULL);
warp(selmon->sel);
}
void
@@ -975,15 +963,15 @@ focusstack(int inc, int hid)
Atom
getatomprop(Client *c, Atom prop)
{
int di;
int format;
unsigned long nitems, dl;
unsigned char *p = NULL;
Atom da, atom = None;
if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
&da, &di, &nitems, &dl, &p) == Success && p) {
if (nitems > 0)
atom = *(Atom *)p;
&da, &format, &nitems, &dl, &p) == Success && p) {
if (nitems > 0 && format == 32)
atom = *(long *)p;
XFree(p);
}
return atom;
@@ -1009,10 +997,10 @@ getstate(Window w)
Atom real;
if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState],
&real, &format, &n, &extra, (unsigned char **)&p) != Success)
&real, &format, &n, &extra, &p) != Success)
return -1;
if (n != 0)
result = *p;
if (n != 0 && format == 32)
result = *(long *)p;
XFree(p);
return result;
}
@@ -1040,22 +1028,6 @@ gettextprop(Window w, Atom atom, char *text, unsigned int size)
return 1;
}
void
goback(const Arg *arg)
{
if (prevmon == NULL) {
Arg a = {0};
view(&a);
} else if (prevmon != selmon) {
unfocus(selmon->sel, 0);
Monitor *p = selmon;
selmon = prevmon;
focus(NULL);
prevmon = p;
warp(selmon->sel);
}
}
void
grabbuttons(Client *c, int focused)
{
@@ -1316,8 +1288,6 @@ motionnotify(XEvent *e)
return;
if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) {
unfocus(selmon->sel, 1);
if (m != selmon)
prevmon = selmon;
selmon = m;
focus(NULL);
}
@@ -1379,7 +1349,6 @@ movemouse(const Arg *arg)
XUngrabPointer(dpy, CurrentTime);
if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
sendmon(c, m);
prevmon = selmon;
selmon = m;
focus(NULL);
}
@@ -1484,36 +1453,12 @@ void
resizeclient(Client *c, int x, int y, int w, int h)
{
XWindowChanges wc;
unsigned int n;
unsigned int gapoffset;
unsigned int gapincr;
Client *nbc;
c->oldx = c->x; c->x = wc.x = x;
c->oldy = c->y; c->y = wc.y = y;
c->oldw = c->w; c->w = wc.width = w;
c->oldh = c->h; c->h = wc.height = h;
wc.border_width = c->bw;
/* Get number of clients for the selected monitor */
for (n = 0, nbc = nexttiled(selmon->clients); nbc; nbc = nexttiled(nbc->next), n++);
/* Do nothing if layout is floating */
if (c->isfloating || selmon->lt[selmon->sellt]->arrange == NULL) {
gapincr = gapoffset = 0;
} else {
/* Remove border and gap if layout is monocle or only one client */
if (selmon->lt[selmon->sellt]->arrange == monocle || n == 1) {
gapoffset = 0;
gapincr = -2 * borderpx;
wc.border_width = 0;
} else {
gapoffset = gappx;
gapincr = 2 * gappx;
}
}
c->oldx = c->x; c->x = wc.x = x + gapoffset;
c->oldy = c->y; c->y = wc.y = y + gapoffset;
c->oldw = c->w; c->w = wc.width = w - gapincr;
c->oldh = c->h; c->h = wc.height = h - gapincr;
XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc);
configure(c);
XSync(dpy, False);
@@ -1571,7 +1516,6 @@ resizemouse(const Arg *arg)
while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
sendmon(c, m);
prevmon = selmon;
selmon = m;
focus(NULL);
}
@@ -1598,8 +1542,6 @@ restack(Monitor *m)
wc.sibling = c->win;
}
}
if (m == selmon && (m->tagset[m->seltags] & m->sel->tags) && m->lt[m->sellt]->arrange != &monocle)
warp(m->sel);
XSync(dpy, False);
while (XCheckMaskEvent(dpy, EnterWindowMask, &ev));
}
@@ -1722,12 +1664,10 @@ sendevent(Client *c, Atom proto)
void
setfocus(Client *c)
{
if (!c->neverfocus) {
if (!c->neverfocus)
XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime);
XChangeProperty(dpy, root, netatom[NetActiveWindow],
XA_WINDOW, 32, PropModeReplace,
(unsigned char *) &(c->win), 1);
}
XChangeProperty(dpy, root, netatom[NetActiveWindow], XA_WINDOW, 32,
PropModeReplace, (unsigned char *)&c->win, 1);
sendevent(c, wmatom[WMTakeFocus]);
}
@@ -2075,19 +2015,6 @@ togglefloating(const Arg *arg)
arrange(selmon);
}
void
focusbynum(const Arg *arg)
{
int i;
Client *c;
i = 0;
c = nexttiled(selmon->clients);
for (; c && i < arg->i; c = nexttiled(c->next), i++);
focus(c);
}
void
toggletag(const Arg *arg)
{
@@ -2110,7 +2037,6 @@ toggleview(const Arg *arg)
unsigned int newtagset = selmon->tagset[selmon->seltags] ^ (arg->ui & TAGMASK);
if (newtagset) {
prevmon = NULL;
selmon->tagset[selmon->seltags] = newtagset;
focus(NULL);
arrange(selmon);
@@ -2439,7 +2365,6 @@ view(const Arg *arg)
{
if ((arg->ui & TAGMASK) == selmon->tagset[selmon->seltags])
return;
prevmon = NULL;
selmon->seltags ^= 1; /* toggle sel tagset */
if (arg->ui & TAGMASK)
selmon->tagset[selmon->seltags] = arg->ui & TAGMASK;
@@ -2447,28 +2372,6 @@ view(const Arg *arg)
arrange(selmon);
}
void
warp(const Client *c)
{
int x, y;
if (!c) {
XWarpPointer(dpy, None, root, 0, 0, 0, 0, selmon->wx + selmon->ww / 2, selmon->wy + selmon->wh / 2);
return;
}
if (!getrootptr(&x, &y) ||
(x > c->x - c->bw &&
y > c->y - c->bw &&
x < c->x + c->w + c->bw*2 &&
y < c->y + c->h + c->bw*2) ||
(y > c->mon->by && y < c->mon->by + bh) ||
(c->mon->topbar && !y))
return;
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w / 2, c->h / 2);
}
Client *
wintoclient(Window w)
{
@@ -2499,41 +2402,6 @@ wintomon(Window w)
return selmon;
}
/* Selects for the view of the focused window. The list of tags */
/* to be displayed is matched to the focused window tag list. */
void
winview(const Arg* arg){
Window win, win_r, win_p, *win_c;
unsigned nc;
int unused;
Client* c;
Arg a;
if (!XGetInputFocus(dpy, &win, &unused)) return;
while(XQueryTree(dpy, win, &win_r, &win_p, &win_c, &nc)
&& win_p != win_r) win = win_p;
if (!(c = wintoclient(win))) return;
a.ui = c->tags;
view(&a);
}
/* by desgua */
void
gridall(const Arg *arg)
{
setlayout(&(Arg){.v = &layouts[3]});
view(&(Arg){.ui = ~0});
}
void
winviewmono(const Arg *arg)
{
winview(&(Arg){0});
setlayout(&(Arg){.v = &layouts[2]});
}
/* There's no way to check accesses to destroyed windows, thus those cases are
* ignored (especially on UnmapNotify's). Other types of errors call Xlibs
* default error handler, which may call exit. */
-35
View File
@@ -1,35 +0,0 @@
void
gaplessgrid(Monitor *m) {
unsigned int n, cols, rows, cn, rn, i, cx, cy, cw, ch;
Client *c;
for(n = 0, c = nexttiled(m->clients); c; c = nexttiled(c->next), n++) ;
if(n == 0)
return;
/* grid dimensions */
for(cols = 0; cols <= n/2; cols++)
if(cols*cols >= n)
break;
if(n == 5) /* set layout against the general calculation: not 1:2:2, but 2:3 */
cols = 2;
rows = n/cols;
/* window geometries */
cw = cols ? m->ww / cols : m->ww;
cn = 0; /* current column number */
rn = 0; /* current row number */
for(i = 0, c = nexttiled(m->clients); c; i++, c = nexttiled(c->next)) {
if(i/rows + 1 > cols - n%cols)
rows = n/cols + 1;
ch = rows ? m->wh / rows : m->wh;
cx = m->wx + cn*cw;
cy = m->wy + rn*ch;
resize(c, cx, cy, cw - 2 * c->bw, ch - 2 * c->bw, False);
rn++;
if(rn >= rows) {
rn = 0;
cn++;
}
}
}
-48
View File
@@ -1,48 +0,0 @@
void
movestack(const Arg *arg) {
Client *c = NULL, *p = NULL, *pc = NULL, *i;
if(arg->i > 0) {
/* find the client after selmon->sel */
for(c = selmon->sel->next; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
if(!c)
for(c = selmon->clients; c && (!ISVISIBLE(c) || c->isfloating); c = c->next);
}
else {
/* find the client before selmon->sel */
for(i = selmon->clients; i != selmon->sel; i = i->next)
if(ISVISIBLE(i) && !i->isfloating)
c = i;
if(!c)
for(; i; i = i->next)
if(ISVISIBLE(i) && !i->isfloating)
c = i;
}
/* find the client before selmon->sel and c */
for(i = selmon->clients; i && (!p || !pc); i = i->next) {
if(i->next == selmon->sel)
p = i;
if(i->next == c)
pc = i;
}
/* swap c and selmon->sel selmon->clients in the selmon->clients list */
if(c && c != selmon->sel) {
Client *temp = selmon->sel->next==c?selmon->sel:selmon->sel->next;
selmon->sel->next = c->next==selmon->sel?c:c->next;
c->next = temp;
if(p && p != c)
p->next = c;
if(pc && pc != selmon->sel)
pc->next = selmon->sel;
if(selmon->sel == selmon->clients)
selmon->clients = c;
else if(c == selmon->clients)
selmon->clients = selmon->sel;
arrange(selmon);
}
}
-135
View File
@@ -1,135 +0,0 @@
/* Sends a window to the next/prev tag */
void
shifttag(const Arg *arg)
{
Arg shifted;
shifted.ui = selmon->tagset[selmon->seltags];
if (arg->i > 0) /* left circular shift */
shifted.ui = ((shifted.ui << arg->i) | (shifted.ui >> (LENGTH(tags) - arg->i)));
else /* right circular shift */
shifted.ui = (shifted.ui >> (- arg->i) | shifted.ui << (LENGTH(tags) + arg->i));
tag(&shifted);
}
/* Sends a window to the next/prev tag that has a client, else it moves it to the next/prev one. */
void
shifttagclients(const Arg *arg)
{
Arg shifted;
Client *c;
unsigned int tagmask = 0;
shifted.ui = selmon->tagset[selmon->seltags];
for (c = selmon->clients; c; c = c->next)
if (!(c->tags))
tagmask = tagmask | c->tags;
if (arg->i > 0) /* left circular shift */
do {
shifted.ui = (shifted.ui << arg->i)
| (shifted.ui >> (LENGTH(tags) - arg->i));
} while (tagmask && !(shifted.ui & tagmask));
else /* right circular shift */
do {
shifted.ui = (shifted.ui >> (- arg->i)
| shifted.ui << (LENGTH(tags) + arg->i));
} while (tagmask && !(shifted.ui & tagmask));
tag(&shifted);
}
/* Navigate to the next/prev tag */
void
shiftview(const Arg *arg)
{
Arg shifted;
shifted.ui = selmon->tagset[selmon->seltags];
if (arg->i > 0) /* left circular shift */
shifted.ui = (shifted.ui << arg->i) | (shifted.ui >> (LENGTH(tags) - arg->i));
else /* right circular shift */
shifted.ui = (shifted.ui >> (- arg->i) | shifted.ui << (LENGTH(tags) + arg->i));
view(&shifted);
}
/* Navigate to the next/prev tag that has a client, else moves it to the next/prev tag */
void
shiftviewclients(const Arg *arg)
{
Arg shifted;
Client *c;
unsigned int tagmask = 0;
shifted.ui = selmon->tagset[selmon->seltags];
for (c = selmon->clients; c; c = c->next)
if (!(c->tags))
tagmask = tagmask | c->tags;
if (arg->i > 0) /* left circular shift */
do {
shifted.ui = (shifted.ui << arg->i)
| (shifted.ui >> (LENGTH(tags) - arg->i));
} while (tagmask && !(shifted.ui & tagmask));
else /* right circular shift */
do {
shifted.ui = (shifted.ui >> (- arg->i)
| shifted.ui << (LENGTH(tags) + arg->i));
} while (tagmask && !(shifted.ui & tagmask));
view(&shifted);
}
/* move the current active window to the next/prev tag and view it. More like following the window */
void
shiftboth(const Arg *arg)
{
Arg shifted;
shifted.ui = selmon->tagset[selmon->seltags];
if (arg->i > 0) /* left circular shift */
shifted.ui = ((shifted.ui << arg->i) | (shifted.ui >> (LENGTH(tags) - arg->i)));
else /* right circular shift */
shifted.ui = ((shifted.ui >> (- arg->i) | shifted.ui << (LENGTH(tags) + arg->i)));
tag(&shifted);
view(&shifted);
}
//helper function for shiftswaptags.
//see: https://github.com/moizifty/DWM-Build/blob/65379c62640788881486401a0d8c79333751b02f/config.h#L48
void
swaptags(const Arg *arg)
{
Client *c;
unsigned int newtag = arg->ui & TAGMASK;
unsigned int curtag = selmon->tagset[selmon->seltags];
if (newtag == curtag || !curtag || (curtag & (curtag-1)))
return;
for (c = selmon->clients; c != NULL; c = c->next) {
if ((c->tags & newtag) || (c->tags & curtag))
c->tags ^= curtag ^ newtag;
if (!c->tags)
c->tags = newtag;
}
//move to the swaped tag
//selmon->tagset[selmon->seltags] = newtag;
focus(NULL);
arrange(selmon);
}
/* swaps "tags" (all the clients) with the next/prev tag. */
void
shiftswaptags(const Arg *arg)
{
Arg shifted;
shifted.ui = selmon->tagset[selmon->seltags];
if (arg->i > 0) /* left circular shift */
shifted.ui = ((shifted.ui << arg->i) | (shifted.ui >> (LENGTH(tags) - arg->i)));
else /* right circular shift */
shifted.ui = ((shifted.ui >> (- arg->i) | shifted.ui << (LENGTH(tags) + arg->i)));
swaptags(&shifted);
// uncomment if you also want to "go" (view) the tag where the the clients are going
//view(&shifted);
}