From 312d2c5d61d1e0fbfd8a77e0aeaba0dd3dfa7791 Mon Sep 17 00:00:00 2001 From: bakkeby Date: Sat, 5 Sep 2020 14:58:44 +0200 Subject: [PATCH] Assortment of fullscreen improvements --- dwm/dwm-fullscreen-compilation-6.2.diff | 350 ++++++++++++++++++++++++ dwm/dwm-tagallmon-6.2.diff | 32 ++- dwm/dwm-tagswapmon-6.2.diff | 12 +- 3 files changed, 377 insertions(+), 17 deletions(-) create mode 100644 dwm/dwm-fullscreen-compilation-6.2.diff diff --git a/dwm/dwm-fullscreen-compilation-6.2.diff b/dwm/dwm-fullscreen-compilation-6.2.diff new file mode 100644 index 0000000..1c96c7d --- /dev/null +++ b/dwm/dwm-fullscreen-compilation-6.2.diff @@ -0,0 +1,350 @@ +From 35ff963bc8038b3fd935aa1db0d42cad819e5aa4 Mon Sep 17 00:00:00 2001 +From: bakkeby +Date: Sat, 5 Sep 2020 14:32:26 +0200 +Subject: [PATCH] Compilation of fullscreen patches for dwm. + +This aims to provide a comprehensive fullscreen solution with the following features: + - toggle fullscreen for any window using a single keybinding rather than having + to rely on per-application keybindings + - the ability to have windows go fullscreen within the size and position the + window is currently in (fake fullscreen) + - allow a fullscreen window to be moved to an adjacent monitor while remaining + fullscreen + - make fullscreen windows lose fullscreen if another (e.g. new) window on the + same monitor receives focus, while still allowing dialog boxes to show while + in fullscreen + - allow seamless transition between the two fullscreen modes + +The default keybindings are: + - MOD+f to make a window fullscreen + - MOD+Shift+f to make a window fake fullscreen + +This incorporates, and expands on, the following patches: + - fakefullscreenclient + - togglefullscreen (a.k.a. actualfullscreen) + - tagmonfixfs + - losefullscreen +--- + config.def.h | 4 +- + dwm.c | 135 ++++++++++++++++++++++++++++++++++++++++++--------- + 2 files changed, 114 insertions(+), 25 deletions(-) + +diff --git a/config.def.h b/config.def.h +index 1c0b587..5f28f2c 100644 +--- a/config.def.h ++++ b/config.def.h +@@ -74,10 +74,12 @@ static Key keys[] = { + { MODKEY, XK_Tab, view, {0} }, + { MODKEY|ShiftMask, XK_c, killclient, {0} }, + { MODKEY, XK_t, setlayout, {.v = &layouts[0]} }, +- { MODKEY, XK_f, setlayout, {.v = &layouts[1]} }, ++ { MODKEY, XK_e, setlayout, {.v = &layouts[1]} }, + { MODKEY, XK_m, setlayout, {.v = &layouts[2]} }, + { MODKEY, XK_space, setlayout, {0} }, + { MODKEY|ShiftMask, XK_space, togglefloating, {0} }, ++ { MODKEY, XK_f, togglefullscreen, {0} }, ++ { MODKEY|ShiftMask, XK_f, togglefakefullscreen, {0} }, + { MODKEY, XK_0, view, {.ui = ~0 } }, + { MODKEY|ShiftMask, XK_0, tag, {.ui = ~0 } }, + { MODKEY, XK_comma, focusmon, {.i = -1 } }, +diff --git a/dwm.c b/dwm.c +index 4465af1..ac03fbb 100644 +--- a/dwm.c ++++ b/dwm.c +@@ -93,6 +93,7 @@ struct Client { + int bw, oldbw; + unsigned int tags; + int isfixed, isfloating, isurgent, neverfocus, oldstate, isfullscreen; ++ int fakefullscreen; + Client *next; + Client *snext; + Monitor *mon; +@@ -210,10 +211,12 @@ static void tag(const Arg *arg); + static void tagmon(const Arg *arg); + static void tile(Monitor *); + static void togglebar(const Arg *arg); ++static void togglefakefullscreen(const Arg *arg); + static void togglefloating(const Arg *arg); ++static void togglefullscreen(const Arg *arg); + static void toggletag(const Arg *arg); + static void toggleview(const Arg *arg); +-static void unfocus(Client *c, int setfocus); ++static void unfocus(Client *c, int setfocus, Client *nextfocus); + static void unmanage(Client *c, int destroyed); + static void unmapnotify(XEvent *e); + static void updatebarpos(Monitor *m); +@@ -425,7 +428,7 @@ buttonpress(XEvent *e) + click = ClkRootWin; + /* focus monitor if necessary */ + if ((m = wintomon(ev->window)) && m != selmon) { +- unfocus(selmon->sel, 1); ++ unfocus(selmon->sel, 1, NULL); + selmon = m; + focus(NULL); + } +@@ -519,9 +522,13 @@ clientmessage(XEvent *e) + return; + if (cme->message_type == netatom[NetWMState]) { + if (cme->data.l[1] == netatom[NetWMFullscreen] +- || cme->data.l[2] == netatom[NetWMFullscreen]) +- setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ +- || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); ++ || cme->data.l[2] == netatom[NetWMFullscreen]) { ++ if (c->fakefullscreen == 1) ++ resizeclient(c, c->x, c->y, c->w, c->h); ++ else ++ setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ ++ || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); ++ } + } else if (cme->message_type == netatom[NetActiveWindow]) { + if (c != selmon->sel && !c->isurgent) + seturgent(c, 1); +@@ -565,7 +572,7 @@ configurenotify(XEvent *e) + updatebars(); + for (m = mons; m; m = m->next) { + for (c = m->clients; c; c = c->next) +- if (c->isfullscreen) ++ if (c->isfullscreen && c->fakefullscreen != 1) + resizeclient(c, m->mx, m->my, m->mw, m->mh); + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + } +@@ -754,7 +761,7 @@ drawbars(void) + void + enternotify(XEvent *e) + { +- Client *c; ++ Client *c, *sel; + Monitor *m; + XCrossingEvent *ev = &e->xcrossing; + +@@ -763,8 +770,9 @@ enternotify(XEvent *e) + c = wintoclient(ev->window); + m = c ? c->mon : wintomon(ev->window); + if (m != selmon) { +- unfocus(selmon->sel, 1); ++ sel = selmon->sel; + selmon = m; ++ unfocus(sel, 1, c); + } else if (!c || c == selmon->sel) + return; + focus(c); +@@ -786,7 +794,7 @@ focus(Client *c) + if (!c || !ISVISIBLE(c)) + for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); + if (selmon->sel && selmon->sel != c) +- unfocus(selmon->sel, 0); ++ unfocus(selmon->sel, 0, c); + if (c) { + if (c->mon != selmon) + selmon = c->mon; +@@ -819,13 +827,15 @@ void + focusmon(const Arg *arg) + { + Monitor *m; ++ Client *sel; + + if (!mons->next) + return; + if ((m = dirtomon(arg->i)) == selmon) + return; +- unfocus(selmon->sel, 0); ++ sel = selmon->sel; + selmon = m; ++ unfocus(sel, 0, NULL); + focus(NULL); + } + +@@ -1069,7 +1079,7 @@ manage(Window w, XWindowAttributes *wa) + XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ + setclientstate(c, NormalState); + if (c->mon == selmon) +- unfocus(selmon->sel, 0); ++ unfocus(selmon->sel, 0, c); + c->mon->sel = c; + arrange(c->mon); + XMapWindow(dpy, c->win); +@@ -1120,13 +1130,15 @@ motionnotify(XEvent *e) + { + static Monitor *mon = NULL; + Monitor *m; ++ Client *sel; + XMotionEvent *ev = &e->xmotion; + + if (ev->window != root) + return; + if ((m = recttomon(ev->x_root, ev->y_root, 1, 1)) != mon && mon) { +- unfocus(selmon->sel, 1); ++ sel = selmon->sel; + selmon = m; ++ unfocus(sel, 1, NULL); + focus(NULL); + } + mon = m; +@@ -1143,7 +1155,7 @@ movemouse(const Arg *arg) + + if (!(c = selmon->sel)) + return; +- if (c->isfullscreen) /* no support moving fullscreen windows by mouse */ ++ if (c->isfullscreen && c->fakefullscreen != 1) /* no support moving fullscreen windows by mouse */ + return; + restack(selmon); + ocx = c->x; +@@ -1298,7 +1310,7 @@ resizemouse(const Arg *arg) + + if (!(c = selmon->sel)) + return; +- if (c->isfullscreen) /* no support resizing fullscreen windows by mouse */ ++ if (c->isfullscreen && c->fakefullscreen != 1) /* no support resizing fullscreen windows by mouse */ + return; + restack(selmon); + ocx = c->x; +@@ -1412,7 +1424,7 @@ sendmon(Client *c, Monitor *m) + { + if (c->mon == m) + return; +- unfocus(c, 1); ++ unfocus(c, 1, NULL); + detach(c); + detachstack(c); + c->mon = m; +@@ -1476,6 +1488,8 @@ setfullscreen(Client *c, int fullscreen) + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + c->isfullscreen = 1; ++ if (c->fakefullscreen == 1) ++ return; + c->oldstate = c->isfloating; + c->oldbw = c->bw; + c->bw = 0; +@@ -1486,6 +1500,10 @@ setfullscreen(Client *c, int fullscreen) + XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, + PropModeReplace, (unsigned char*)0, 0); + c->isfullscreen = 0; ++ if (c->fakefullscreen == 1) ++ return; ++ if (c->fakefullscreen == 2) ++ c->fakefullscreen = 1; + c->isfloating = c->oldstate; + c->bw = c->oldbw; + c->x = c->oldx; +@@ -1665,9 +1683,19 @@ tag(const Arg *arg) + void + tagmon(const Arg *arg) + { +- if (!selmon->sel || !mons->next) ++ Client *c = selmon->sel; ++ if (!c || !mons->next) + return; +- sendmon(selmon->sel, dirtomon(arg->i)); ++ if (c->isfullscreen) { ++ c->isfullscreen = 0; ++ sendmon(c, dirtomon(arg->i)); ++ c->isfullscreen = 1; ++ if (c->fakefullscreen != 1) { ++ resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); ++ XRaiseWindow(dpy, c->win); ++ } ++ } else ++ sendmon(c, dirtomon(arg->i)); + } + + void +@@ -1705,18 +1733,69 @@ togglebar(const Arg *arg) + arrange(selmon); + } + ++void ++togglefakefullscreen(const Arg *arg) ++{ ++ Client *c = selmon->sel; ++ if (!c) ++ return; ++ ++ if (c->fakefullscreen) { ++ if (c->isfullscreen) ++ c->fakefullscreen = 0; ++ else ++ c->isfullscreen = 0; ++ } else { ++ if (c->isfullscreen) { ++ c->isfloating = c->oldstate; ++ c->bw = c->oldbw; ++ c->x = c->oldx; ++ c->y = c->oldy; ++ c->w = c->oldw; ++ c->h = c->oldh; ++ resizeclient(c, c->x, c->y, c->w, c->h); ++ } ++ c->fakefullscreen = 1; ++ c->isfullscreen = 0; ++ } ++ setfullscreen(c, !c->isfullscreen); ++} ++ + void + togglefloating(const Arg *arg) + { +- if (!selmon->sel) ++ Client *c = selmon->sel; ++ if (!c) + return; +- if (selmon->sel->isfullscreen) /* no support for fullscreen windows */ ++ if (c->isfullscreen && c->fakefullscreen != 1) /* no support for fullscreen windows */ + return; +- selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; ++ c->isfloating = !c->isfloating || c->isfixed; + if (selmon->sel->isfloating) +- resize(selmon->sel, selmon->sel->x, selmon->sel->y, +- selmon->sel->w, selmon->sel->h, 0); +- arrange(selmon); ++ resize(c, c->x, c->y, c->w, c->h, 0); ++ arrange(c->mon); ++} ++ ++void ++togglefullscreen(const Arg *arg) ++{ ++ Client *c = selmon->sel; ++ if (!c) ++ return; ++ ++ if (c->fakefullscreen == 1) { ++ c->fakefullscreen = 2; ++ if (c->isfullscreen) ++ c->isfullscreen = 0; ++ } else if (c->fakefullscreen == 2) { ++ c->fakefullscreen = 0; ++ togglefakefullscreen(NULL); ++ arrange(selmon); ++ return; ++ } ++ ++ setfullscreen(c, !c->isfullscreen); ++ if (!c->isfullscreen) ++ arrange(c->mon); + } + + void +@@ -1747,10 +1826,18 @@ toggleview(const Arg *arg) + } + + void +-unfocus(Client *c, int setfocus) ++unfocus(Client *c, int setfocus, Client *nextfocus) + { + if (!c) + return; ++ if (c->isfullscreen && ISVISIBLE(c) && c->mon == selmon && nextfocus && !nextfocus->isfloating) { ++ if (!c->fakefullscreen) ++ setfullscreen(c, 0); ++ else if (c->fakefullscreen == 2) { ++ c->fakefullscreen = 0; ++ togglefakefullscreen(NULL); ++ } ++ } + grabbuttons(c, 0); + XSetWindowBorder(dpy, c->win, scheme[SchemeNorm][ColBorder].pixel); + if (setfocus) { +-- +2.19.1 + diff --git a/dwm/dwm-tagallmon-6.2.diff b/dwm/dwm-tagallmon-6.2.diff index 0bc2bc7..77d6911 100644 --- a/dwm/dwm-tagallmon-6.2.diff +++ b/dwm/dwm-tagallmon-6.2.diff @@ -1,12 +1,12 @@ -From 24b096ef83d05de74b3d91c25e799f2906a0bac1 Mon Sep 17 00:00:00 2001 +From 6ef2e352d9288b06daca4c13fe833cdea269981e Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 7 Apr 2020 12:02:43 +0200 Subject: [PATCH] tagallmon, move all visible windows to an adjacent monitor --- config.def.h | 2 ++ - dwm.c | 33 +++++++++++++++++++++++++++++++++ - 2 files changed, 35 insertions(+) + dwm.c | 43 +++++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 45 insertions(+) diff --git a/config.def.h b/config.def.h index 1c0b587..4852ae2 100644 @@ -22,7 +22,7 @@ index 1c0b587..4852ae2 100644 TAGKEYS( XK_2, 1) TAGKEYS( XK_3, 2) diff --git a/dwm.c b/dwm.c -index 4465af1..5048970 100644 +index 4465af1..9fd5b03 100644 --- a/dwm.c +++ b/dwm.c @@ -208,6 +208,7 @@ static void sigchld(int unused); @@ -33,7 +33,7 @@ index 4465af1..5048970 100644 static void tile(Monitor *); static void togglebar(const Arg *arg); static void togglefloating(const Arg *arg); -@@ -1670,6 +1671,38 @@ tagmon(const Arg *arg) +@@ -1670,6 +1671,48 @@ tagmon(const Arg *arg) sendmon(selmon->sel, dirtomon(arg->i)); } @@ -41,13 +41,15 @@ index 4465af1..5048970 100644 +tagallmon(const Arg *arg) +{ + Monitor *m; -+ Client *c; -+ Client *next; ++ Client *c, *last, *slast, *next; + + if (!mons->next) + return; + + m = dirtomon(arg->i); ++ for (last = m->clients; last && last->next; last = last->next); ++ for (slast = m->stack; slast && slast->snext; slast = slast->snext); ++ + for (c = selmon->clients; c; c = next) { + next = c->next; + if (!ISVISIBLE(c)) @@ -57,11 +59,19 @@ index 4465af1..5048970 100644 + detachstack(c); + c->mon = m; + c->tags = m->tagset[m->seltags]; /* assign tags of target monitor */ -+ attach(c); -+ attachstack(c); ++ c->next = NULL; ++ c->snext = NULL; ++ if (last) ++ last = last->next = c; ++ else ++ m->clients = last = c; ++ if (slast) ++ slast = slast->snext = c; ++ else ++ m->stack = slast = c; + if (c->isfullscreen) { -+ setfullscreen(c, 0); -+ setfullscreen(c, 1); ++ resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); ++ XRaiseWindow(dpy, c->win); + } + } + diff --git a/dwm/dwm-tagswapmon-6.2.diff b/dwm/dwm-tagswapmon-6.2.diff index 97463c0..ede62bf 100644 --- a/dwm/dwm-tagswapmon-6.2.diff +++ b/dwm/dwm-tagswapmon-6.2.diff @@ -1,4 +1,4 @@ -From 8a7910595e9aa93e9af8ff6e433683f26f8cde4a Mon Sep 17 00:00:00 2001 +From ef0816393e3e6d019bdbd12c02427fddf15fa27d Mon Sep 17 00:00:00 2001 From: bakkeby Date: Tue, 7 Apr 2020 12:41:35 +0200 Subject: [PATCH] tagswapmon, swap all visible windows with those of one of the @@ -23,7 +23,7 @@ index 1c0b587..09331fb 100644 TAGKEYS( XK_2, 1) TAGKEYS( XK_3, 2) diff --git a/dwm.c b/dwm.c -index 4465af1..862eaf7 100644 +index 4465af1..53a3bf5 100644 --- a/dwm.c +++ b/dwm.c @@ -209,6 +209,7 @@ static void spawn(const Arg *arg); @@ -78,8 +78,8 @@ index 4465af1..862eaf7 100644 + attach(c); + attachstack(c); + if (c->isfullscreen) { -+ setfullscreen(c, 0); -+ setfullscreen(c, 1); ++ resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); ++ XRaiseWindow(dpy, c->win); + } + } + @@ -90,8 +90,8 @@ index 4465af1..862eaf7 100644 + attach(c); + attachstack(c); + if (c->isfullscreen) { -+ setfullscreen(c, 0); -+ setfullscreen(c, 1); ++ resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); ++ XRaiseWindow(dpy, c->win); + } + } +