summaryrefslogtreecommitdiffhomepage
path: root/patch/seamless_restart.c
diff options
context:
space:
mode:
authorbakkeby <[email protected]>2022-06-17 14:36:20 +0200
committerbakkeby <[email protected]>2022-06-17 14:36:20 +0200
commit440c4a6efa789f41213d78ea564087ffdb65bafd (patch)
treebe43cead3b46cf77d45e875a75b16ad26d9bf55e /patch/seamless_restart.c
parent6f7d9b1bdf2dd5a19a712ee739d8fe328d198c6d (diff)
downloaddwm-flexipatch-440c4a6efa789f41213d78ea564087ffdb65bafd.tar.gz
dwm-flexipatch-440c4a6efa789f41213d78ea564087ffdb65bafd.zip
Porting the seamless restart feature from dusk into dwm-flexipatch
Diffstat (limited to 'patch/seamless_restart.c')
-rw-r--r--patch/seamless_restart.c471
1 files changed, 471 insertions, 0 deletions
diff --git a/patch/seamless_restart.c b/patch/seamless_restart.c
new file mode 100644
index 0000000..7241eea
--- /dev/null
+++ b/patch/seamless_restart.c
@@ -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