diff options
| author | bakkeby <[email protected]> | 2022-06-17 14:36:20 +0200 |
|---|---|---|
| committer | bakkeby <[email protected]> | 2022-06-17 14:36:20 +0200 |
| commit | 440c4a6efa789f41213d78ea564087ffdb65bafd (patch) | |
| tree | be43cead3b46cf77d45e875a75b16ad26d9bf55e /patch/seamless_restart.c | |
| parent | 6f7d9b1bdf2dd5a19a712ee739d8fe328d198c6d (diff) | |
| download | dwm-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.c | 471 |
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 |
