Merge remote-tracking branch 'upstream/master'

- Seamless restart patch
This commit is contained in:
Sravan Balaji
2022-06-17 14:07:10 -04:00
11 changed files with 674 additions and 74 deletions

View File

@ -19,6 +19,8 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6
### Changelog: ### Changelog:
2022-06-17 - Ported the seamless restart feature from dusk into dwm-flexipatch
2022-02-11 - Added the isfreesize version of the sizehints patch and the [tagsync](https://github.com/bakkeby/dwm-flexipatch/pull/219) patch (contributed by [Bagelli](https://github.com/Bagellll)) 2022-02-11 - Added the isfreesize version of the sizehints patch and the [tagsync](https://github.com/bakkeby/dwm-flexipatch/pull/219) patch (contributed by [Bagelli](https://github.com/Bagellll))
2021-11-23 - Added the taglabels and underlinetags patches 2021-11-23 - Added the taglabels and underlinetags patches
@ -602,6 +604,9 @@ Browsing patches? There is a [map of patches](https://coggle.it/diagram/X9IiSSM6
- this alternative patch enables a scratchpad feature in dwm similar to the scratchpad - this alternative patch enables a scratchpad feature in dwm similar to the scratchpad
feature in i3wm feature in i3wm
- seamless_restart
- allows for selected layout, assigned tags, etc. to be persisted across restarts
- [selfrestart](https://dwm.suckless.org/patches/selfrestart/) - [selfrestart](https://dwm.suckless.org/patches/selfrestart/)
- restart dwm without the unnecessary dependency of an external script - restart dwm without the unnecessary dependency of an external script

View File

@ -127,6 +127,7 @@
- [[#rounded-corners][Rounded Corners]] - [[#rounded-corners][Rounded Corners]]
- [[#save-floats][Save Floats]] - [[#save-floats][Save Floats]]
- [[#scratch-pads][Scratch Pads]] - [[#scratch-pads][Scratch Pads]]
- [[#seamless-restart][Seamless Restart]]
- [[#selective-fake-fullscreen][Selective Fake Fullscreen]] - [[#selective-fake-fullscreen][Selective Fake Fullscreen]]
- [[#self-restart][Self Restart]] - [[#self-restart][Self Restart]]
- [[#send-monitor-keep-focus][Send Monitor Keep Focus]] - [[#send-monitor-keep-focus][Send Monitor Keep Focus]]
@ -288,6 +289,8 @@ Browsing patches? There is a [[https://coggle.it/diagram/X9IiSSM6PTWOM9Wz][map o
** Changelog ** Changelog
2022-06-17 - Ported the seamless restart feature from dusk into dwm-flexipatch
2022-02-11 - Added the isfreesize version of the sizehints patch and the [[https://github.com/bakkeby/dwm-flexipatch/pull/219][tagsync]] patch (contributed by [[https://github.com/Bagellll][Bagelli]]) 2022-02-11 - Added the isfreesize version of the sizehints patch and the [[https://github.com/bakkeby/dwm-flexipatch/pull/219][tagsync]] patch (contributed by [[https://github.com/Bagellll][Bagelli]])
2021-11-23 - Added the taglabels and underlinetags patches 2021-11-23 - Added the taglabels and underlinetags patches
@ -870,6 +873,9 @@ Browsing patches? There is a [[https://coggle.it/diagram/X9IiSSM6PTWOM9Wz][map o
- this alternative patch enables a scratchpad feature in dwm similar to the scratchpad - this alternative patch enables a scratchpad feature in dwm similar to the scratchpad
feature in i3wm feature in i3wm
- seamless_restart
- allows for selected layout, assigned tags, etc. to be persisted across restarts
- [[https://dwm.suckless.org/patches/selfrestart/][selfrestart]] - [[https://dwm.suckless.org/patches/selfrestart/][selfrestart]]
- restart dwm without the unnecessary dependency of an external script - restart dwm without the unnecessary dependency of an external script
@ -2588,6 +2594,21 @@ https://github.com/GasparVardanyan/dwm-scratchpad
#define SCRATCHPAD_ALT_1_PATCH 0 #define SCRATCHPAD_ALT_1_PATCH 0
#+END_SRC #+END_SRC
*** Seamless Restart
This patch persists some settings across window manager restarts. These include but are not limited to:
- client's assigned tag(s) on which monitor
- the order of clients
- nmaster
- selected layout
- plus various additions depending on what other patches are used
The above is not persisted across reboots, however.
#+BEGIN_SRC c :tangle patches.def.h
#define SEAMLESS_RESTART_PATCH 0
#+END_SRC
*** Selective Fake Fullscreen *** Selective Fake Fullscreen
As opposed to the original patch this only adds a rule option allowing fake fullscreen to be enabled for applications when they start. This is intended to be used in combination with the fakefullscreenclient patch and offers no practical functionality without it. As opposed to the original patch this only adds a rule option allowing fake fullscreen to be enabled for applications when they start. This is intended to be used in combination with the fakefullscreenclient patch and offers no practical functionality without it.

189
dwm.c
View File

@ -212,6 +212,14 @@ enum {
WMLast WMLast
}; /* default atoms */ }; /* default atoms */
#if SEAMLESS_RESTART_PATCH
enum {
ClientFields,
ClientTags,
ClientLast
}; /* dwm client atoms */
#endif // SEAMLESS_RESTART_PATCH
enum { enum {
#if BAR_STATUSBUTTON_PATCH #if BAR_STATUSBUTTON_PATCH
ClkButton, ClkButton,
@ -335,6 +343,9 @@ struct Client {
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH #if SAVEFLOATS_PATCH || EXRESIZE_PATCH
int sfx, sfy, sfw, sfh; /* stored float geometry, used on mode revert */ int sfx, sfy, sfw, sfh; /* stored float geometry, used on mode revert */
#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH #endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
#if SEAMLESS_RESTART_PATCH
unsigned int idx;
#endif // SEAMLESS_RESTART_PATCH
int oldx, oldy, oldw, oldh; int oldx, oldy, oldw, oldh;
int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid; int basew, baseh, incw, inch, maxw, maxh, minw, minh, hintsvalid;
int bw, oldbw; int bw, oldbw;
@ -620,7 +631,7 @@ static void focusmon(const Arg *arg);
#if !STACKER_PATCH #if !STACKER_PATCH
static void focusstack(const Arg *arg); static void focusstack(const Arg *arg);
#endif // STACKER_PATCH #endif // STACKER_PATCH
static Atom getatomprop(Client *c, Atom prop); static Atom getatomprop(Client *c, Atom prop, Atom req);
static int getrootptr(int *x, int *y); static int getrootptr(int *x, int *y);
static long getstate(Window w); static long getstate(Window w);
static int gettextprop(Window w, Atom atom, char *text, unsigned int size); static int gettextprop(Window w, Atom atom, char *text, unsigned int size);
@ -782,11 +793,13 @@ static void (*handler[LASTEvent]) (XEvent *) = {
#endif // BAR_SYSTRAY_PATCH #endif // BAR_SYSTRAY_PATCH
[UnmapNotify] = unmapnotify [UnmapNotify] = unmapnotify
}; };
#if BAR_SYSTRAY_PATCH
static Atom wmatom[WMLast], netatom[NetLast], xatom[XLast];
#else
static Atom wmatom[WMLast], netatom[NetLast]; static Atom wmatom[WMLast], netatom[NetLast];
#if BAR_SYSTRAY_PATCH
static Atom xatom[XLast];
#endif // BAR_SYSTRAY_PATCH #endif // BAR_SYSTRAY_PATCH
#if SEAMLESS_RESTART_PATCH
static Atom clientatom[ClientLast];
#endif // SEAMLESS_RESTART_PATCH
#if ON_EMPTY_KEYS_PATCH #if ON_EMPTY_KEYS_PATCH
static int isempty = 0; static int isempty = 0;
#endif // ON_EMPTY_KEYS_PATCH #endif // ON_EMPTY_KEYS_PATCH
@ -839,7 +852,7 @@ applyrules(Client *c)
XGetClassHint(dpy, c->win, &ch); XGetClassHint(dpy, c->win, &ch);
class = ch.res_class ? ch.res_class : broken; class = ch.res_class ? ch.res_class : broken;
instance = ch.res_name ? ch.res_name : broken; instance = ch.res_name ? ch.res_name : broken;
wintype = getatomprop(c, netatom[NetWMWindowType]); wintype = getatomprop(c, netatom[NetWMWindowType], XA_ATOM);
#if WINDOWROLERULE_PATCH #if WINDOWROLERULE_PATCH
gettextprop(c->win, wmatom[WMWindowRole], role, sizeof(role)); gettextprop(c->win, wmatom[WMWindowRole], role, sizeof(role));
#endif // WINDOWROLERULE_PATCH #endif // WINDOWROLERULE_PATCH
@ -1199,11 +1212,15 @@ checkotherwm(void)
void void
cleanup(void) cleanup(void)
{ {
#if !SEAMLESS_RESTART_PATCH
Arg a = {.ui = ~0}; Arg a = {.ui = ~0};
#endif // SEAMLESS_RESTART_PATCH
Layout foo = { "", NULL }; Layout foo = { "", NULL };
Monitor *m; Monitor *m;
size_t i; size_t i;
#if !SEAMLESS_RESTART_PATCH
view(&a); view(&a);
#endif // SEAMLESS_RESTART_PATCH
selmon->lt[selmon->sellt] = &foo; selmon->lt[selmon->sellt] = &foo;
for (m = mons; m; m = m->next) for (m = mons; m; m = m->next)
while (m->stack) while (m->stack)
@ -1690,6 +1707,11 @@ createmon(void)
#endif // PERTAG_VANITYGAPS_PATCH | VANITYGAPS_PATCH #endif // PERTAG_VANITYGAPS_PATCH | VANITYGAPS_PATCH
} }
#endif // PERTAG_PATCH #endif // PERTAG_PATCH
#if SEAMLESS_RESTART_PATCH
restoremonitorstate(m);
#endif // SEAMLESS_RESTART_PATCH
#if INSETS_PATCH #if INSETS_PATCH
m->inset = default_inset; m->inset = default_inset;
#endif // INSETS_PATCH #endif // INSETS_PATCH
@ -1735,9 +1757,13 @@ void
detach(Client *c) detach(Client *c)
{ {
Client **tc; Client **tc;
#if SEAMLESS_RESTART_PATCH
c->idx = 0;
#endif // SEAMLESS_RESTART_PATCH
for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next); for (tc = &c->mon->clients; *tc && *tc != c; tc = &(*tc)->next);
*tc = c->next; *tc = c->next;
c->next = NULL;
} }
void void
@ -1752,6 +1778,7 @@ detachstack(Client *c)
for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext); for (t = c->mon->stack; t && !ISVISIBLE(t); t = t->snext);
c->mon->sel = t; c->mon->sel = t;
} }
c->snext = NULL;
} }
Monitor * Monitor *
@ -2080,7 +2107,7 @@ focusstack(const Arg *arg)
#endif // STACKER_PATCH #endif // STACKER_PATCH
Atom Atom
getatomprop(Client *c, Atom prop) getatomprop(Client *c, Atom prop, Atom req)
{ {
int di; int di;
unsigned long dl; unsigned long dl;
@ -2088,26 +2115,21 @@ getatomprop(Client *c, Atom prop)
Atom da, atom = None; Atom da, atom = None;
#if BAR_SYSTRAY_PATCH #if BAR_SYSTRAY_PATCH
/* FIXME getatomprop should return the number of items and a pointer to
* the stored data instead of this workaround */
Atom req = XA_ATOM;
if (prop == xatom[XembedInfo]) if (prop == xatom[XembedInfo])
req = xatom[XembedInfo]; req = xatom[XembedInfo];
#endif // BAR_SYSTRAY_PATCH
/* FIXME getatomprop should return the number of items and a pointer to
* the stored data instead of this workaround */
if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req, if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, req,
&da, &di, &dl, &dl, &p) == Success && p) { &da, &di, &dl, &dl, &p) == Success && p) {
atom = *(Atom *)p; atom = *(Atom *)p;
#if BAR_SYSTRAY_PATCH
if (da == xatom[XembedInfo] && dl == 2) if (da == xatom[XembedInfo] && dl == 2)
atom = ((Atom *)p)[1]; atom = ((Atom *)p)[1];
XFree(p);
}
#else
if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM,
&da, &di, &dl, &dl, &p) == Success && p) {
atom = *(Atom *)p;
XFree(p);
}
#endif // BAR_SYSTRAY_PATCH #endif // BAR_SYSTRAY_PATCH
XFree(p);
}
return atom; return atom;
} }
@ -2310,6 +2332,9 @@ manage(Window w, XWindowAttributes *wa)
#if SWALLOW_PATCH #if SWALLOW_PATCH
Client *term = NULL; Client *term = NULL;
#endif // SWALLOW_PATCH #endif // SWALLOW_PATCH
#if SEAMLESS_RESTART_PATCH
int settings_restored;
#endif // SEAMLESS_RESTART_PATCH
Window trans = None; Window trans = None;
XWindowChanges wc; XWindowChanges wc;
@ -2319,6 +2344,9 @@ manage(Window w, XWindowAttributes *wa)
c->pid = winpid(w); c->pid = winpid(w);
#endif // SWALLOW_PATCH #endif // SWALLOW_PATCH
/* geometry */ /* geometry */
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
c->sfx = c->sfy = c->sfw = c->sfh = -9999;
#endif // SAVEFLOATS_PATCH | EXRESIZE_PATCH
c->x = c->oldx = wa->x; c->x = c->oldx = wa->x;
c->y = c->oldy = wa->y; c->y = c->oldy = wa->y;
c->w = c->oldw = wa->width; c->w = c->oldw = wa->width;
@ -2327,6 +2355,9 @@ manage(Window w, XWindowAttributes *wa)
#if CFACTS_PATCH #if CFACTS_PATCH
c->cfact = 1.0; c->cfact = 1.0;
#endif // CFACTS_PATCH #endif // CFACTS_PATCH
#if SEAMLESS_RESTART_PATCH
settings_restored = restoreclientstate(c);
#endif // SEAMLESS_RESTART_PATCH
#if BAR_WINICON_PATCH #if BAR_WINICON_PATCH
updateicon(c); updateicon(c);
#endif // BAR_WINICON_PATCH #endif // BAR_WINICON_PATCH
@ -2359,7 +2390,12 @@ manage(Window w, XWindowAttributes *wa)
c->iscentered = 1; c->iscentered = 1;
#endif // CENTER_TRANSIENT_WINDOWS_PATCH | CENTER_TRANSIENT_WINDOWS_BY_PARENT_PATCH | CENTER_PATCH #endif // CENTER_TRANSIENT_WINDOWS_PATCH | CENTER_TRANSIENT_WINDOWS_BY_PARENT_PATCH | CENTER_PATCH
} else { } else {
#if SEAMLESS_RESTART_PATCH
if (!settings_restored)
c->mon = selmon; c->mon = selmon;
#else
c->mon = selmon;
#endif // SEAMLESS_RESTART_PATCH
#if CENTER_PATCH #if CENTER_PATCH
if (c->x == c->mon->wx && c->y == c->mon->wy) if (c->x == c->mon->wx && c->y == c->mon->wy)
c->iscentered = 1; c->iscentered = 1;
@ -2369,7 +2405,12 @@ manage(Window w, XWindowAttributes *wa)
#else #else
c->bw = borderpx; c->bw = borderpx;
#endif // SETBORDERPX_PATCH #endif // SETBORDERPX_PATCH
#if SEAMLESS_RESTART_PATCH
if (!settings_restored)
applyrules(c); applyrules(c);
#else
applyrules(c);
#endif // SEAMLESS_RESTART_PATCH
#if SWALLOW_PATCH #if SWALLOW_PATCH
term = termforwin(c); term = termforwin(c);
if (term) if (term)
@ -2396,7 +2437,7 @@ manage(Window w, XWindowAttributes *wa)
#endif // BAR_FLEXWINTITLE_PATCH #endif // BAR_FLEXWINTITLE_PATCH
configure(c); /* propagates border_width, if size doesn't change */ configure(c); /* propagates border_width, if size doesn't change */
updatesizehints(c); updatesizehints(c);
if (getatomprop(c, netatom[NetWMState]) == netatom[NetWMFullscreen]) if (getatomprop(c, netatom[NetWMState], XA_ATOM) == netatom[NetWMFullscreen])
setfullscreen(c, 1); setfullscreen(c, 1);
updatewmhints(c); updatewmhints(c);
#if DECORATION_HINTS_PATCH #if DECORATION_HINTS_PATCH
@ -2404,8 +2445,6 @@ manage(Window w, XWindowAttributes *wa)
#endif // DECORATION_HINTS_PATCH #endif // DECORATION_HINTS_PATCH
#if CENTER_PATCH && SAVEFLOATS_PATCH || CENTER_PATCH && EXRESIZE_PATCH #if CENTER_PATCH && SAVEFLOATS_PATCH || CENTER_PATCH && EXRESIZE_PATCH
c->sfx = -9999;
c->sfy = -9999;
if (c->iscentered) { if (c->iscentered) {
c->sfx = c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2; c->sfx = c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2;
c->sfy = c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2; c->sfy = c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2;
@ -2421,13 +2460,12 @@ manage(Window w, XWindowAttributes *wa)
#elif ALWAYSCENTER_PATCH #elif ALWAYSCENTER_PATCH
c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2; c->x = c->mon->wx + (c->mon->ww - WIDTH(c)) / 2;
c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2; c->y = c->mon->wy + (c->mon->wh - HEIGHT(c)) / 2;
#elif SAVEFLOATS_PATCH || EXRESIZE_PATCH
c->sfx = -9999;
c->sfy = -9999;
#endif // CENTER_PATCH / ALWAYSCENTER_PATCH / SAVEFLOATS_PATCH #endif // CENTER_PATCH / ALWAYSCENTER_PATCH / SAVEFLOATS_PATCH
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH #if SAVEFLOATS_PATCH || EXRESIZE_PATCH
if (c->sfw == -9999) {
c->sfw = c->w; c->sfw = c->w;
c->sfh = c->h; c->sfh = c->h;
}
#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH #endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask);
@ -2445,7 +2483,7 @@ manage(Window w, XWindowAttributes *wa)
XRaiseWindow(dpy, c->win); XRaiseWindow(dpy, c->win);
XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel); XSetWindowBorder(dpy, w, scheme[SchemeNorm][ColFloat].pixel);
} }
#if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBELOW_PATCH || ATTACHBOTTOM_PATCH #if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBELOW_PATCH || ATTACHBOTTOM_PATCH || SEAMLESS_RESTART_PATCH
attachx(c); attachx(c);
#else #else
attach(c); attach(c);
@ -2600,8 +2638,8 @@ movemouse(const Arg *arg)
#endif // FAKEFULLSCREEN_CLIENT_PATCH #endif // FAKEFULLSCREEN_CLIENT_PATCH
#endif // FAKEFULLSCREEN_PATCH #endif // FAKEFULLSCREEN_PATCH
restack(selmon); restack(selmon);
ocx = c->x; nx = ocx = c->x;
ocy = c->y; ny = ocy = c->y;
if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync,
None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess)
return; return;
@ -2639,14 +2677,7 @@ movemouse(const Arg *arg)
togglefloating(NULL); togglefloating(NULL);
} }
if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) { if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
resize(c, nx, ny, c->w, c->h, 1); resize(c, nx, ny, c->w, c->h, 1);
/* save last known float coordinates */
c->sfx = nx;
c->sfy = ny;
#else
resize(c, nx, ny, c->w, c->h, 1);
#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
} }
#if ROUNDED_CORNERS_PATCH #if ROUNDED_CORNERS_PATCH
drawroundedcorners(c); drawroundedcorners(c);
@ -2654,6 +2685,7 @@ movemouse(const Arg *arg)
break; break;
} }
} while (ev.type != ButtonRelease); } while (ev.type != ButtonRelease);
XUngrabPointer(dpy, CurrentTime); XUngrabPointer(dpy, CurrentTime);
if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) { if ((m = recttomon(c->x, c->y, c->w, c->h)) != selmon) {
#if SCRATCHPADS_PATCH #if SCRATCHPADS_PATCH
@ -2666,6 +2698,13 @@ movemouse(const Arg *arg)
selmon = m; selmon = m;
focus(NULL); focus(NULL);
} }
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
/* save last known float coordinates */
if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
c->sfx = nx;
c->sfy = ny;
}
#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
#if ROUNDED_CORNERS_PATCH #if ROUNDED_CORNERS_PATCH
drawroundedcorners(c); drawroundedcorners(c);
#endif // ROUNDED_CORNERS_PATCH #endif // ROUNDED_CORNERS_PATCH
@ -2773,8 +2812,13 @@ quit(const Arg *arg)
#if RESTARTSIG_PATCH #if RESTARTSIG_PATCH
restart = arg->i; restart = arg->i;
#endif // RESTARTSIG_PATCH #endif // RESTARTSIG_PATCH
#if ONLYQUITONEMPTY_PATCH #if SEAMLESS_RESTART_PATCH
Monitor *m; Monitor *m;
#endif // SEAMLESS_RESTART_PATCH
#if ONLYQUITONEMPTY_PATCH
#if !SEAMLESS_RESTART_PATCH
Monitor *m;
#endif // SEAMLESS_RESTART_PATCH
Client *c; Client *c;
unsigned int n = 0; unsigned int n = 0;
@ -2794,6 +2838,11 @@ quit(const Arg *arg)
running = 0; running = 0;
#endif // ONLYQUITONEMPTY_PATCH #endif // ONLYQUITONEMPTY_PATCH
#if SEAMLESS_RESTART_PATCH
for (m = mons; m && !running; m = m->next)
persistmonitorstate(m);
#endif // SEAMLESS_RESTART_PATCH
#if COOL_AUTOSTART_PATCH #if COOL_AUTOSTART_PATCH
/* kill child processes */ /* kill child processes */
for (i = 0; i < autostart_len && !running; i++) { for (i = 0; i < autostart_len && !running; i++) {
@ -2876,9 +2925,9 @@ resizeclient(Client *c, int x, int y, int w, int h)
void void
resizemouse(const Arg *arg) resizemouse(const Arg *arg)
{ {
int ocx, ocy, nw, nh; int ocx, ocy, nw, nh, nx, ny;
#if RESIZEPOINT_PATCH || RESIZECORNERS_PATCH #if RESIZEPOINT_PATCH || RESIZECORNERS_PATCH
int opx, opy, och, ocw, nx, ny; int opx, opy, och, ocw;
int horizcorner, vertcorner; int horizcorner, vertcorner;
unsigned int dui; unsigned int dui;
Window dummy; Window dummy;
@ -2900,8 +2949,10 @@ resizemouse(const Arg *arg)
#endif // FAKEFULLSCREEN_CLIENT_PATCH #endif // FAKEFULLSCREEN_CLIENT_PATCH
#endif // !FAKEFULLSCREEN_PATCH #endif // !FAKEFULLSCREEN_PATCH
restack(selmon); restack(selmon);
ocx = c->x; nx = ocx = c->x;
ocy = c->y; ny = ocy = c->y;
nh = c->h;
nw = c->w;
#if RESIZEPOINT_PATCH #if RESIZEPOINT_PATCH
och = c->h; och = c->h;
ocw = c->w; ocw = c->w;
@ -2968,24 +3019,7 @@ resizemouse(const Arg *arg)
} }
} }
if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) { if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
#if RESIZECORNERS_PATCH || RESIZEPOINT_PATCH resize(c, nx, ny, nw, nh, 1);
resizeclient(c, nx, ny, nw, nh);
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
/* save last known float dimensions */
c->sfx = nx;
c->sfy = ny;
c->sfw = nw;
c->sfh = nh;
#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
#else
resize(c, c->x, c->y, nw, nh, 1);
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
c->sfx = c->x;
c->sfy = c->y;
c->sfw = nw;
c->sfh = nh;
#endif // SAVEFLOATS_PATCH / EXRESIZE_PATCH
#endif // RESIZECORNERS_PATCH
#if ROUNDED_CORNERS_PATCH #if ROUNDED_CORNERS_PATCH
drawroundedcorners(c); drawroundedcorners(c);
#endif // ROUNDED_CORNERS_PATCH #endif // ROUNDED_CORNERS_PATCH
@ -2993,6 +3027,7 @@ resizemouse(const Arg *arg)
break; break;
} }
} while (ev.type != ButtonRelease); } while (ev.type != ButtonRelease);
#if !RESIZEPOINT_PATCH #if !RESIZEPOINT_PATCH
#if RESIZECORNERS_PATCH #if RESIZECORNERS_PATCH
XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
@ -3015,6 +3050,15 @@ resizemouse(const Arg *arg)
selmon = m; selmon = m;
focus(NULL); focus(NULL);
} }
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH
/* save last known float dimensions */
if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) {
c->sfx = nx;
c->sfy = ny;
c->sfw = nw;
c->sfh = nh;
}
#endif // SAVEFLOATS_PATCH | EXRESIZE_PATCH
ignoreconfigurerequests = 0; ignoreconfigurerequests = 0;
} }
@ -3568,6 +3612,10 @@ setup(void)
#if WINDOWROLERULE_PATCH #if WINDOWROLERULE_PATCH
wmatom[WMWindowRole] = XInternAtom(dpy, "WM_WINDOW_ROLE", False); wmatom[WMWindowRole] = XInternAtom(dpy, "WM_WINDOW_ROLE", False);
#endif // WINDOWROLERULE_PATCH #endif // WINDOWROLERULE_PATCH
#if SEAMLESS_RESTART_PATCH
clientatom[ClientFields] = XInternAtom(dpy, "_DWM_CLIENT_FIELDS", False);
clientatom[ClientTags] = XInternAtom(dpy, "_DWM_CLIENT_TAGS", False);
#endif // SEAMLESS_RESTART_PATCH
netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False); netatom[NetActiveWindow] = XInternAtom(dpy, "_NET_ACTIVE_WINDOW", False);
netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
#if BAR_SYSTRAY_PATCH #if BAR_SYSTRAY_PATCH
@ -3757,7 +3805,7 @@ showhide(Client *c)
/* show clients top down */ /* show clients top down */
#if SAVEFLOATS_PATCH || EXRESIZE_PATCH #if SAVEFLOATS_PATCH || EXRESIZE_PATCH
if (!c->mon->lt[c->mon->sellt]->arrange && c->sfx != -9999 && !c->isfullscreen) { if (!c->mon->lt[c->mon->sellt]->arrange && c->sfx != -9999 && !c->isfullscreen) {
XMoveWindow(dpy, c->win, c->sfx, c->sfy); XMoveResizeWindow(dpy, c->win, c->sfx, c->sfy, c->sfw, c->sfh);
resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 0); resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 0);
showhide(c->snext); showhide(c->snext);
return; return;
@ -3935,13 +3983,26 @@ tag(const Arg *arg)
void void
tagmon(const Arg *arg) tagmon(const Arg *arg)
{ {
#if TAGMONFIXFS_PATCH
Client *c = selmon->sel; Client *c = selmon->sel;
Monitor *dest;
#if SEAMLESS_RESTART_PATCH && SAVEFLOATS_PATCH
int restored;
#endif // SEAMLESS_RESTART_PATCH | SAVEFLOATS_PATCH
if (!c || !mons->next) if (!c || !mons->next)
return; return;
dest = dirtomon(arg->i);
#if SEAMLESS_RESTART_PATCH && SAVEFLOATS_PATCH
savewindowfloatposition(c, c->mon);
restored = restorewindowfloatposition(c, dest);
if (restored && (!dest->lt[dest->sellt]->arrange || c->isfloating)) {
XMoveResizeWindow(dpy, c->win, c->sfx, c->sfy, c->sfw, c->sfh);
resize(c, c->sfx, c->sfy, c->sfw, c->sfh, 1);
}
#endif // SEAMLESS_RESTART_PATCH | SAVEFLOATS_PATCH
#if TAGMONFIXFS_PATCH
if (c->isfullscreen) { if (c->isfullscreen) {
c->isfullscreen = 0; c->isfullscreen = 0;
sendmon(c, dirtomon(arg->i)); sendmon(c, dest);
c->isfullscreen = 1; c->isfullscreen = 1;
#if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH #if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH
if (c->fakefullscreen != 1) { if (c->fakefullscreen != 1) {
@ -3953,11 +4014,9 @@ tagmon(const Arg *arg)
XRaiseWindow(dpy, c->win); XRaiseWindow(dpy, c->win);
#endif // FAKEFULLSCREEN_CLIENT_PATCH #endif // FAKEFULLSCREEN_CLIENT_PATCH
} else } else
sendmon(c, dirtomon(arg->i)); sendmon(c, dest);
#else #else
if (!selmon->sel || !mons->next) sendmon(c, dest);
return;
sendmon(selmon->sel, dirtomon(arg->i));
#endif // TAGMONFIXFS_PATCH #endif // TAGMONFIXFS_PATCH
} }
@ -4991,12 +5050,12 @@ main(int argc, char *argv[])
runautostart(); runautostart();
#endif #endif
run(); run();
cleanup();
XCloseDisplay(dpy);
#if RESTARTSIG_PATCH #if RESTARTSIG_PATCH
if (restart) if (restart)
execvp(argv[0], argv); execvp(argv[0], argv);
#endif // RESTARTSIG_PATCH #endif // RESTARTSIG_PATCH
cleanup();
XCloseDisplay(dpy);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

View File

@ -1,8 +1,27 @@
void void
attachx(Client *c) attachx(Client *c)
{ {
#if ATTACHABOVE_PATCH #if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBOTTOM_PATCH || SEAMLESS_RESTART_PATCH
Client *at; Client *at;
#endif // ATTACHABOVE_PATCH | ATTACHASIDE_PATCH | ATTACHBOTTOM_PATCH | SEAMLESS_RESTART_PATCH
#if SEAMLESS_RESTART_PATCH
if (c->idx > 0) { /* then the client has a designated position in the client list */
for (at = c->mon->clients; at; at = at->next) {
if (c->idx < at->idx) {
c->next = at;
c->mon->clients = c;
return;
} else if (at->idx <= c->idx && (!at->next || c->idx <= at->next->idx)) {
c->next = at->next;
at->next = c;
return;
}
}
}
#endif // SEAMLESS_RESTART_PATCH
#if ATTACHABOVE_PATCH
if (!(c->mon->sel == NULL || c->mon->sel == c->mon->clients || c->mon->sel->isfloating)) { if (!(c->mon->sel == NULL || c->mon->sel == c->mon->clients || c->mon->sel->isfloating)) {
for (at = c->mon->clients; at->next != c->mon->sel; at = at->next); for (at = c->mon->clients; at->next != c->mon->sel; at = at->next);
c->next = at->next; c->next = at->next;
@ -10,9 +29,7 @@ attachx(Client *c)
return; return;
} }
#elif ATTACHASIDE_PATCH #elif ATTACHASIDE_PATCH
Client *at;
unsigned int n; unsigned int n;
for (at = c->mon->clients, n = 0; at; at = at->next) for (at = c->mon->clients, n = 0; at; at = at->next)
if (!at->isfloating && ISVISIBLEONTAG(at, c->tags)) if (!at->isfloating && ISVISIBLEONTAG(at, c->tags))
if (++n >= c->mon->nmaster) if (++n >= c->mon->nmaster)
@ -30,7 +47,6 @@ attachx(Client *c)
return; return;
} }
#elif ATTACHBOTTOM_PATCH #elif ATTACHBOTTOM_PATCH
Client *at;
for (at = c->mon->clients; at && at->next; at = at->next); for (at = c->mon->clients; at && at->next; at = at->next);
if (at) { if (at) {
at->next = c; at->next = c;

View File

@ -111,6 +111,7 @@ removesystrayicon(Client *i)
for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next); for (ii = &systray->icons; *ii && *ii != i; ii = &(*ii)->next);
if (ii) if (ii)
*ii = i->next; *ii = i->next;
XReparentWindow(dpy, i->win, root, 0, 0);
free(i); free(i);
drawbarwin(systray->bar); drawbarwin(systray->bar);
} }
@ -163,7 +164,7 @@ updatesystrayiconstate(Client *i, XPropertyEvent *ev)
int code = 0; int code = 0;
if (!showsystray || !systray || !i || ev->atom != xatom[XembedInfo] || if (!showsystray || !systray || !i || ev->atom != xatom[XembedInfo] ||
!(flags = getatomprop(i, xatom[XembedInfo]))) !(flags = getatomprop(i, xatom[XembedInfo], xatom[XembedInfo])))
return; return;
if (flags & XEMBED_MAPPED && !i->tags) { if (flags & XEMBED_MAPPED && !i->tags) {

View File

@ -97,7 +97,7 @@
#if ASPECTRESIZE_PATCH #if ASPECTRESIZE_PATCH
#include "aspectresize.c" #include "aspectresize.c"
#endif #endif
#if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBELOW_PATCH || ATTACHBOTTOM_PATCH #if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBELOW_PATCH || ATTACHBOTTOM_PATCH || SEAMLESS_RESTART_PATCH
#include "attachx.c" #include "attachx.c"
#endif #endif
#if AUTOSTART_PATCH #if AUTOSTART_PATCH
@ -313,6 +313,9 @@
#if DRAGMFACT_PATCH #if DRAGMFACT_PATCH
#include "dragmfact.c" #include "dragmfact.c"
#endif #endif
#if SEAMLESS_RESTART_PATCH
#include "seamless_restart.c"
#endif
/* Layouts */ /* Layouts */
#if BSTACK_LAYOUT || BSTACKHORIZ_LAYOUT || CENTEREDMASTER_LAYOUT || CENTEREDFLOATINGMASTER_LAYOUT || COLUMNS_LAYOUT || DECK_LAYOUT || TILE_LAYOUT #if BSTACK_LAYOUT || BSTACKHORIZ_LAYOUT || CENTEREDMASTER_LAYOUT || CENTEREDFLOATINGMASTER_LAYOUT || COLUMNS_LAYOUT || DECK_LAYOUT || TILE_LAYOUT
#include "layout_facts.c" #include "layout_facts.c"

View File

@ -97,7 +97,7 @@
#if ASPECTRESIZE_PATCH #if ASPECTRESIZE_PATCH
#include "aspectresize.h" #include "aspectresize.h"
#endif #endif
#if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBELOW_PATCH || ATTACHBOTTOM_PATCH #if ATTACHABOVE_PATCH || ATTACHASIDE_PATCH || ATTACHBELOW_PATCH || ATTACHBOTTOM_PATCH || SEAMLESS_RESTART_PATCH
#include "attachx.h" #include "attachx.h"
#endif #endif
#if AUTOSTART_PATCH #if AUTOSTART_PATCH
@ -223,6 +223,9 @@
#if SCRATCHPAD_ALT_1_PATCH #if SCRATCHPAD_ALT_1_PATCH
#include "scratchpad_alt_1.h" #include "scratchpad_alt_1.h"
#endif #endif
#if SEAMLESS_RESTART_PATCH
#include "seamless_restart.h"
#endif
#if SELFRESTART_PATCH #if SELFRESTART_PATCH
#include "selfrestart.h" #include "selfrestart.h"
#endif #endif

471
patch/seamless_restart.c Normal file
View File

@ -0,0 +1,471 @@
void
persistmonitorstate(Monitor *m)
{
Client *c;
unsigned int i;
setmonitortags(m);
setmonitorfields(m);
/* Set client atoms */
for (i = 1, c = m->clients; c; c = c->next, ++i) {
c->idx = i;
persistclientstate(c);
#if SWALLOW_PATCH
if (c->swallowing) {
c->swallowing->idx = i;
persistclientstate(c->swallowing);
}
#endif // SWALLOW_PATCH
}
}
int
restoremonitorstate(Monitor *m)
{
return getmonitortags(m) | getmonitorfields(m);
}
void
persistclientstate(Client *c)
{
setclienttags(c);
setclientfields(c);
#if SAVEFLOATS_PATCH
savewindowfloatposition(c, c->mon);
#endif // SAVEFLOATS_PATCH
}
int
restoreclientstate(Client *c)
{
return getclienttags(c)
| getclientfields(c)
#if SAVEFLOATS_PATCH
| restorewindowfloatposition(c, c->mon ? c->mon : selmon)
#endif // SAVEFLOATS_PATCH
;
}
void setmonitorfields(Monitor *m)
{
#if PERTAG_PATCH
unsigned int i;
#endif // PERTAG_PATCH
char atom[22] = {0};
Atom monitor_fields;
#if FLEXTILE_DELUXE_LAYOUT
unsigned int flextile_deluxe_bitmask;
#endif // FLEXTILE_DELUXE_LAYOUT
sprintf(atom, "_DWM_MONITOR_FIELDS_%u", m->num);
monitor_fields = XInternAtom(dpy, atom, False);
/* Perists workspace information in 32 bits laid out like this:
*
* |0|0000|0|0000|0000|0000|0000|0000|000|000
* | | | | | | | | | |-- nmaster
* | | | | | | | | |-- nstack
* | | | | | | | |-- layout
* | | | | | | |-- flextile LAYOUT (split)
* | | | | | |-- flextile MASTER
* | | | | |-- flextile STACK1
* | | | |-- flextile STACK2
* | | |-- flextile mirror layout (indicated by negative layout)
* | |
* | |-- reserved
* |-- showbar
*/
#if PERTAG_PATCH
for (i = 0; i <= NUMTAGS; i++) {
#if FLEXTILE_DELUXE_LAYOUT
flextile_deluxe_bitmask = (m->pertag->nstacks[i] & 0x7) << 3;
if (m->pertag->ltidxs[i][m->pertag->sellts[i]]->arrange == flextile) {
flextile_deluxe_bitmask |=
(abs(m->pertag->ltaxis[i][LAYOUT]) & 0xF) << 10 |
(m->pertag->ltaxis[i][MASTER] & 0xF) << 14 |
(m->pertag->ltaxis[i][STACK] & 0xF) << 18 |
(m->pertag->ltaxis[i][STACK2] & 0xF) << 22 |
(m->pertag->ltaxis[i][LAYOUT] < 0 ? 1 : 0) << 24;
}
#endif // FLEXTILE_DELUXE_L1AYOUT
uint32_t data[] = {
#if FLEXTILE_DELUXE_LAYOUT
flextile_deluxe_bitmask |
#endif // FLEXTILE_DELUXE_LAYOUT
(m->pertag->nmasters[i] & 0x7) |
(getlayoutindex(m->pertag->ltidxs[i][m->pertag->sellts[i]]) & 0xF) << 6 |
#if PERTAGBAR_PATCH
m->pertag->showbars[i] << 31
#else
m->showbar << 31
#endif // PERTAGBAR_PATCH
};
XChangeProperty(dpy, root, monitor_fields, XA_CARDINAL, 32,
i ? PropModeAppend : PropModeReplace, (unsigned char *)data, 1);
}
#else // !PERTAG_PATCH
#if FLEXTILE_DELUXE_LAYOUT
flextile_deluxe_bitmask = (m->nstack & 0x7) << 3;
if (m->lt[m->sellt]->arrange == flextile) {
flextile_deluxe_bitmask |=
(abs(m->ltaxis[LAYOUT]) & 0xF) << 10 |
(m->ltaxis[MASTER] & 0xF) << 14 |
(m->ltaxis[STACK] & 0xF) << 18 |
(m->ltaxis[STACK2] & 0xF) << 22 |
(m->ltaxis[LAYOUT] < 0 ? 1 : 0) << 24;
}
#endif // FLEXTILE_DELUXE_L1AYOUT
uint32_t data[] = {
#if FLEXTILE_DELUXE_LAYOUT
flextile_deluxe_bitmask |
#endif // FLEXTILE_DELUXE_LAYOUT
(m->nmaster & 0x7) |
(getlayoutindex(m->lt[m->sellt]) & 0xF) << 6 |
m->showbar << 31
};
XChangeProperty(dpy, root, monitor_fields, XA_CARDINAL, 32, PropModeReplace,
(unsigned char *)data, 1);
#endif // PERTAG_PATCH
}
int
getlayoutindex(const Layout *layout)
{
int i;
for (i = 0; i < LENGTH(layouts) && &layouts[i] != layout; i++);
if (i == LENGTH(layouts))
i = 0;
return i;
}
int
getmonitorfields(Monitor *m)
{
int di, layout_index;
#if PERTAG_PATCH
unsigned int i, restored = 0;
unsigned int tags = m->tagset[m->seltags] << 1;
#endif // PERTAG_PATCH
unsigned long dl, nitems;
unsigned char *p = NULL;
char atom[22] = {0};
Atom da, state = None;
sprintf(atom, "_DWM_MONITOR_FIELDS_%u", m->num);
Atom dwm_monitor = XInternAtom(dpy, atom, False);
if (!dwm_monitor)
return 0;
#if PERTAG_PATCH
for (i = 0; i <= NUMTAGS; i++) {
if (!(XGetWindowProperty(dpy, root, dwm_monitor, i, (NUMTAGS + 1) * sizeof dl,
False, AnyPropertyType, &da, &di, &nitems, &dl, &p) == Success && p)) {
break;
}
if (!nitems) {
XFree(p);
break;
}
/* See bit layout in the persistmonitorstate function */
state = *(Atom *)p;
m->pertag->nmasters[i] = state & 0x7;
layout_index = (state >> 6) & 0xF;
if (layout_index < LENGTH(layouts))
m->pertag->ltidxs[i][m->pertag->sellts[i]] = &layouts[layout_index];
#if FLEXTILE_DELUXE_LAYOUT
m->pertag->nstacks[i] = (state >> 3) & 0x7;
if (m->pertag->ltidxs[i][m->pertag->sellts[i]]->arrange == flextile) {
m->pertag->ltaxis[i][LAYOUT] = (state >> 10) & 0xF;
m->pertag->ltaxis[i][MASTER] = (state >> 14) & 0xF;
m->pertag->ltaxis[i][STACK] = (state >> 18) & 0xF;
m->pertag->ltaxis[i][STACK2] = (state >> 22) & 0xF;
if (state >> 24 & 0x1) {
m->pertag->ltaxis[i][LAYOUT] *= -1;
}
}
#endif // FLEXTILE_DELUXE_LAYOUT
#if PERTAGBAR_PATCH
m->pertag->showbars[i] = (state >> 31) & 0x1;
#endif // PERTAGBAR_PATCH
if (!restored && i && (tags & (1 << i))) {
m->nmaster = m->pertag->nmasters[i];
m->sellt = m->pertag->sellts[i];
m->lt[m->sellt] = m->pertag->ltidxs[i][m->sellt];
#if FLEXTILE_DELUXE_LAYOUT
m->nstack = m->pertag->nstacks[i];
if (m->lt[m->sellt]->arrange == flextile) {
m->ltaxis[LAYOUT] = m->pertag->ltaxis[i][LAYOUT];
m->ltaxis[MASTER] = m->pertag->ltaxis[i][MASTER];
m->ltaxis[STACK] = m->pertag->ltaxis[i][STACK];
m->ltaxis[STACK2] = m->pertag->ltaxis[i][STACK2];
}
#endif // FLEXTILE_DELUXE_LAYOUT
#if PERTAGBAR_PATCH
m->showbar = m->pertag->showbars[i];
#else
m->showbar = (state >> 31) & 0x1;
#endif // PERTAGBAR_PATCH
restored = 1;
}
XFree(p);
}
return restored;
#else // !PERTAG_PATCH
if (!(XGetWindowProperty(dpy, root, dwm_monitor, 0L, sizeof dl,
False, AnyPropertyType, &da, &di, &nitems, &dl, &p) == Success && p)) {
return 0;
}
if (nitems) {
state = *(Atom *)p;
/* See bit layout in the persistmonitorstate function */
m->nmaster = state & 0x7;
#if FLEXTILE_DELUXE_LAYOUT
m->nstack = (state >> 3) & 0x7;
#endif // FLEXTILE_DELUXE_LAYOUT
layout_index = (state >> 6) & 0xF;
if (layout_index < LENGTH(layouts))
m->lt[m->sellt] = &layouts[layout_index];
#if FLEXTILE_DELUXE_LAYOUT
if (m->lt[m->sellt]->arrange == flextile) {
m->ltaxis[LAYOUT] = (state >> 10) & 0xF;
m->ltaxis[MASTER] = (state >> 14) & 0xF;
m->ltaxis[STACK] = (state >> 18) & 0xF;
m->ltaxis[STACK2] = (state >> 22) & 0xF;
}
#endif // FLEXTILE_DELUXE_LAYOUT
m->showbar = (state >> 31) & 0x1;
}
XFree(p);
return 1;
#endif // PERTAG_PATCH
}
void
setmonitortags(Monitor *m)
{
char atom[22] = {0};
Atom monitor_tags;
sprintf(atom, "_DWM_MONITOR_TAGS_%u", m->num);
monitor_tags = XInternAtom(dpy, atom, False);
uint32_t data[] = { m->tagset[m->seltags] };
XChangeProperty(dpy, root, monitor_tags, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
}
int
getmonitortags(Monitor *m)
{
int di;
unsigned long dl, nitems;
unsigned char *p = NULL;
char atom[22] = {0};
Atom da, monitor_tags = None, tags;
sprintf(atom, "_DWM_MONITOR_TAGS_%u", m->num);
monitor_tags = XInternAtom(dpy, atom, False);
if (!(XGetWindowProperty(dpy, root, monitor_tags, 0L, sizeof dl,
False, AnyPropertyType, &da, &di, &nitems, &dl, &p) == Success && p)) {
return 0;
}
if (nitems) {
tags = *(Atom *)p;
m->tagset[m->seltags] = tags & TAGMASK;
}
XFree(p);
return 1;
}
void
setclientfields(Client *c)
{
/* Perists client information in 32 bits laid out like this:
*
* |00000000|00000|0|0|0|0|0|0|0|0|00000000|000
* | | | | | | | | | | | |-- monitor index
* | | | | | | | | | | |-- client index
* | | | | | | | | | |-- isfloating
* | | | | | | | | |-- ispermanent
* | | | | | | | |-- isterminal
* | | | | | | |-- noswallow
* | | | | | |-- issteam
* | | | | |-- issticky
* | | | |-- fakefullscreen
* | | |-- isfreesize
* | |
* | |-- reserved
* |-- scratchkey (for scratchpads)
*/
uint32_t data[] = {
(c->mon->num & 0x7)
| (c->idx & 0xFF) << 3
| (c->isfloating & 0x1) << 11
#if ISPERMANENT_PATCH
| (c->ispermanent & 0x1) << 12
#endif // ISPERMANENT_PATCH
#if SWALLOW_PATCH
| (c->isterminal & 0x1) << 13
| (c->noswallow & 0x1) << 14
#endif // SWALLOW_PATCH
#if STEAM_PATCH
| (c->issteam & 0x1) << 15
#endif // STEAM_PATCH
#if STICKY_PATCH
| (c->issticky & 0x1) << 16
#endif // STICKY_PATCH
#if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH
| (c->fakefullscreen & 0x1) << 17
#endif // FAKEFULLSCREEN_CLIENT_PATCH
#if SIZEHINTS_ISFREESIZE_PATCH
| (c->isfreesize & 0x1) << 18
#endif // SIZEHINTS_ISFREESIZE_PATCH
#if RENAMED_SCRATCHPADS_PATCH
| (c->scratchkey & 0xFF) << 24
#endif // RENAMED_SCRATCHPADS_PATCH
};
XChangeProperty(dpy, c->win, clientatom[ClientFields], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
}
int
getclientfields(Client *c)
{
Monitor *m;
Atom fields = getatomprop(c, clientatom[ClientFields], AnyPropertyType);
if (fields == None)
return 0;
/* See bit layout in the setclientfields function */
for (m = mons; m; m = m->next)
if (m->num == (fields & 0x7)) {
c->mon = m;
break;
}
c->idx = (fields >> 3) & 0xFF;
c->isfloating = (fields >> 11) & 0x1;
#if ISPERMANENT_PATCH
c->ispermanent = (fields >> 12) & 0x1;
#endif // ISPERMANENT_PATCH
#if SWALLOW_PATCH
c->isterminal = (fields >> 13) & 0x1;
c->noswallow = (fields >> 14) & 0x1;
#endif // SWALLOW_PATCH
#if STEAM_PATCH
c->issteam = (fields >> 15) & 0x1;
#endif // STEAM_PATCH
#if STICKY_PATCH
c->issticky = (fields >> 16) & 0x1;
#endif // STICKY_PATCH
#if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH
c->fakefullscreen = (fields >> 17) & 0x1;
#endif // FAKEFULLSCREEN_CLIENT_PATCH
#if SIZEHINTS_ISFREESIZE_PATCH
c->isfreesize = (fields >> 18) & 0x1;
#endif // SIZEHINTS_ISFREESIZE_PATCH
#if RENAMED_SCRATCHPADS_PATCH
c->scratchkey = (fields >> 24) & 0xFF;
#endif // RENAMED_SCRATCHPADS_PATCH
return 1;
}
void
setclienttags(Client *c)
{
uint32_t data[] = { c->tags };
XChangeProperty(dpy, c->win, clientatom[ClientTags], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1);
}
int
getclienttags(Client *c)
{
Atom tags = getatomprop(c, clientatom[ClientTags], AnyPropertyType);
if (tags == None)
return 0;
c->tags = tags & TAGMASK;
return 1;
}
#if SAVEFLOATS_PATCH
void
savewindowfloatposition(Client *c, Monitor *m)
{
char atom[22] = {0};
if (c->sfx == -9999)
return;
sprintf(atom, "_DWM_FLOATPOS_%u", m->num);
uint32_t pos[] = { (MAX(c->sfx - m->mx, 0) & 0xffff) | ((MAX(c->sfy - m->my, 0) & 0xffff) << 16) };
XChangeProperty(dpy, c->win, XInternAtom(dpy, atom, False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)pos, 1);
sprintf(atom, "_DWM_FLOATSIZE_%u", m->num);
uint32_t size[] = { (c->sfw & 0xffff) | ((c->sfh & 0xffff) << 16) };
XChangeProperty(dpy, c->win, XInternAtom(dpy, atom, False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)size, 1);
XSync(dpy, False);
}
int
restorewindowfloatposition(Client *c, Monitor *m)
{
char atom[22] = {0};
Atom key, value;
int x, y, w, h;
if (m == NULL)
return 0;
sprintf(atom, "_DWM_FLOATPOS_%u", m->num);
key = XInternAtom(dpy, atom, False);
if (!key)
return 0;
value = getatomprop(c, key, AnyPropertyType);
if (!value)
return 0;
x = value & 0xffff;
y = value >> 16;
sprintf(atom, "_DWM_FLOATSIZE_%u", m->num);
key = XInternAtom(dpy, atom, False);
if (!key)
return 0;
value = getatomprop(c, key, AnyPropertyType);
if (!value)
return 0;
w = value & 0xffff;
h = value >> 16;
if (w <= 0 || h <= 0) {
fprintf(stderr, "restorewindowfloatposition: bad float values x = %d, y = %d, w = %d, h = %d for client = %s\n", x, y, w, h, c->name);
return 0;
}
c->sfx = m->mx + x;
c->sfy = m->my + y;
c->sfw = w;
c->sfh = h;
return 1;
}
#endif // SAVEFLOATS_PATCH

19
patch/seamless_restart.h Normal file
View File

@ -0,0 +1,19 @@
#include <stdint.h>
static void persistmonitorstate(Monitor *m);
static int restoremonitorstate(Monitor *m);
static void persistclientstate(Client *c);
static int restoreclientstate(Client *c);
static void setmonitorfields(Monitor *m);
static int getmonitorfields(Monitor *m);
static void setmonitortags(Monitor *m);
static int getmonitortags(Monitor *m);
static void setclientfields(Client *c);
static int getclientfields(Client *c);
static void setclienttags(Client *c);
static int getclienttags(Client *c);
static int getlayoutindex(const Layout *layout);
#if SAVEFLOATS_PATCH
static void savewindowfloatposition(Client *c, Monitor *m);
static int restorewindowfloatposition(Client *c, Monitor *m);
#endif // SAVEFLOATS_PATCH

View File

@ -13,7 +13,7 @@ checkfloatingrules(Client *c)
XGetClassHint(dpy, c->win, &ch); XGetClassHint(dpy, c->win, &ch);
class = ch.res_class ? ch.res_class : broken; class = ch.res_class ? ch.res_class : broken;
instance = ch.res_name ? ch.res_name : broken; instance = ch.res_name ? ch.res_name : broken;
wintype = getatomprop(c, netatom[NetWMWindowType]); wintype = getatomprop(c, netatom[NetWMWindowType], XA_ATOM);
#if WINDOWROLERULE_PATCH #if WINDOWROLERULE_PATCH
gettextprop(c->win, wmatom[WMWindowRole], role, sizeof(role)); gettextprop(c->win, wmatom[WMWindowRole], role, sizeof(role));
#endif // WINDOWROLERULE_PATCH #endif // WINDOWROLERULE_PATCH

View File

@ -253,6 +253,8 @@
#define SCRATCHPAD_ALT_1_PATCH 0 #define SCRATCHPAD_ALT_1_PATCH 0
#define SEAMLESS_RESTART_PATCH 0
#define SELECTIVEFAKEFULLSCREEN_PATCH 0 #define SELECTIVEFAKEFULLSCREEN_PATCH 0
#define SELFRESTART_PATCH 0 #define SELFRESTART_PATCH 0