seamless_restart.c (12367B)
1 void 2 persistmonitorstate(Monitor *m) 3 { 4 Client *c; 5 unsigned int i; 6 7 setmonitortags(m); 8 setmonitorfields(m); 9 10 /* Set client atoms */ 11 for (i = 1, c = m->clients; c; c = c->next, ++i) { 12 c->idx = i; 13 persistclientstate(c); 14 #if SWALLOW_PATCH 15 if (c->swallowing) { 16 c->swallowing->idx = i; 17 persistclientstate(c->swallowing); 18 } 19 #endif // SWALLOW_PATCH 20 } 21 } 22 23 int 24 restoremonitorstate(Monitor *m) 25 { 26 return getmonitortags(m) | getmonitorfields(m); 27 } 28 29 void 30 persistclientstate(Client *c) 31 { 32 setclienttags(c); 33 setclientfields(c); 34 #if SAVEFLOATS_PATCH 35 savewindowfloatposition(c, c->mon); 36 #endif // SAVEFLOATS_PATCH 37 } 38 39 int 40 restoreclientstate(Client *c) 41 { 42 int restored = getclientfields(c); 43 getclienttags(c); 44 #if SAVEFLOATS_PATCH 45 restorewindowfloatposition(c, c->mon ? c->mon : selmon); 46 #endif // SAVEFLOATS_PATCH 47 return restored; 48 } 49 50 void setmonitorfields(Monitor *m) 51 { 52 #if PERTAG_PATCH 53 unsigned int i; 54 #endif // PERTAG_PATCH 55 char atom[22] = {0}; 56 Atom monitor_fields; 57 #if FLEXTILE_DELUXE_LAYOUT 58 unsigned int flextile_deluxe_bitmask; 59 #endif // FLEXTILE_DELUXE_LAYOUT 60 61 sprintf(atom, "_DWM_MONITOR_FIELDS_%u", m->num); 62 monitor_fields = XInternAtom(dpy, atom, False); 63 64 /* Perists workspace information in 32 bits laid out like this: 65 * 66 * |0|0000|0|0000|0000|0000|0000|0000|000|000 67 * | | | | | | | | | |-- nmaster 68 * | | | | | | | | |-- nstack 69 * | | | | | | | |-- layout 70 * | | | | | | |-- flextile LAYOUT (split) 71 * | | | | | |-- flextile MASTER 72 * | | | | |-- flextile STACK1 73 * | | | |-- flextile STACK2 74 * | | |-- flextile mirror layout (indicated by negative layout) 75 * | | 76 * | |-- reserved 77 * |-- showbar 78 */ 79 #if PERTAG_PATCH 80 for (i = 0; i <= NUMTAGS; i++) { 81 #if FLEXTILE_DELUXE_LAYOUT 82 flextile_deluxe_bitmask = (m->pertag->nstacks[i] & 0x7) << 3; 83 if (m->pertag->ltidxs[i][m->pertag->sellts[i]]->arrange == flextile) { 84 flextile_deluxe_bitmask |= 85 (abs(m->pertag->ltaxis[i][LAYOUT]) & 0xF) << 10 | 86 (m->pertag->ltaxis[i][MASTER] & 0xF) << 14 | 87 (m->pertag->ltaxis[i][STACK] & 0xF) << 18 | 88 (m->pertag->ltaxis[i][STACK2] & 0xF) << 22 | 89 (m->pertag->ltaxis[i][LAYOUT] < 0 ? 1 : 0) << 24; 90 } 91 #endif // FLEXTILE_DELUXE_L1AYOUT 92 uint32_t data[] = { 93 #if FLEXTILE_DELUXE_LAYOUT 94 flextile_deluxe_bitmask | 95 #endif // FLEXTILE_DELUXE_LAYOUT 96 (m->pertag->nmasters[i] & 0x7) | 97 (getlayoutindex(m->pertag->ltidxs[i][m->pertag->sellts[i]]) & 0xF) << 6 | 98 #if PERTAGBAR_PATCH 99 m->pertag->showbars[i] << 31 100 #else 101 m->showbar << 31 102 #endif // PERTAGBAR_PATCH 103 }; 104 105 XChangeProperty(dpy, root, monitor_fields, XA_CARDINAL, 32, 106 i ? PropModeAppend : PropModeReplace, (unsigned char *)data, 1); 107 } 108 #else // !PERTAG_PATCH 109 #if FLEXTILE_DELUXE_LAYOUT 110 flextile_deluxe_bitmask = (m->nstack & 0x7) << 3; 111 if (m->lt[m->sellt]->arrange == flextile) { 112 flextile_deluxe_bitmask |= 113 (abs(m->ltaxis[LAYOUT]) & 0xF) << 10 | 114 (m->ltaxis[MASTER] & 0xF) << 14 | 115 (m->ltaxis[STACK] & 0xF) << 18 | 116 (m->ltaxis[STACK2] & 0xF) << 22 | 117 (m->ltaxis[LAYOUT] < 0 ? 1 : 0) << 24; 118 } 119 #endif // FLEXTILE_DELUXE_L1AYOUT 120 uint32_t data[] = { 121 #if FLEXTILE_DELUXE_LAYOUT 122 flextile_deluxe_bitmask | 123 #endif // FLEXTILE_DELUXE_LAYOUT 124 (m->nmaster & 0x7) | 125 (getlayoutindex(m->lt[m->sellt]) & 0xF) << 6 | 126 m->showbar << 31 127 }; 128 129 XChangeProperty(dpy, root, monitor_fields, XA_CARDINAL, 32, PropModeReplace, 130 (unsigned char *)data, 1); 131 #endif // PERTAG_PATCH 132 } 133 134 int 135 getlayoutindex(const Layout *layout) 136 { 137 int i; 138 139 for (i = 0; i < LENGTH(layouts) && &layouts[i] != layout; i++); 140 if (i == LENGTH(layouts)) 141 i = 0; 142 return i; 143 } 144 145 int 146 getmonitorfields(Monitor *m) 147 { 148 int di, layout_index; 149 #if PERTAG_PATCH 150 unsigned int i, restored = 0; 151 unsigned int tags = m->tagset[m->seltags] << 1; 152 #endif // PERTAG_PATCH 153 unsigned long dl, nitems; 154 unsigned char *p = NULL; 155 char atom[22] = {0}; 156 Atom da, state = None; 157 158 sprintf(atom, "_DWM_MONITOR_FIELDS_%u", m->num); 159 Atom dwm_monitor = XInternAtom(dpy, atom, False); 160 if (!dwm_monitor) 161 return 0; 162 163 #if PERTAG_PATCH 164 for (i = 0; i <= NUMTAGS; i++) { 165 if (!(XGetWindowProperty(dpy, root, dwm_monitor, i, (NUMTAGS + 1) * sizeof dl, 166 False, AnyPropertyType, &da, &di, &nitems, &dl, &p) == Success && p)) { 167 break; 168 } 169 170 if (!nitems) { 171 XFree(p); 172 break; 173 } 174 175 /* See bit layout in the persistmonitorstate function */ 176 state = *(Atom *)p; 177 178 m->pertag->nmasters[i] = state & 0x7; 179 layout_index = (state >> 6) & 0xF; 180 if (layout_index < LENGTH(layouts)) 181 m->pertag->ltidxs[i][m->pertag->sellts[i]] = &layouts[layout_index]; 182 #if FLEXTILE_DELUXE_LAYOUT 183 m->pertag->nstacks[i] = (state >> 3) & 0x7; 184 if (m->pertag->ltidxs[i][m->pertag->sellts[i]]->arrange == flextile) { 185 m->pertag->ltaxis[i][LAYOUT] = (state >> 10) & 0xF; 186 m->pertag->ltaxis[i][MASTER] = (state >> 14) & 0xF; 187 m->pertag->ltaxis[i][STACK] = (state >> 18) & 0xF; 188 m->pertag->ltaxis[i][STACK2] = (state >> 22) & 0xF; 189 if (state >> 24 & 0x1) { 190 m->pertag->ltaxis[i][LAYOUT] *= -1; 191 } 192 } 193 #endif // FLEXTILE_DELUXE_LAYOUT 194 #if PERTAGBAR_PATCH 195 m->pertag->showbars[i] = (state >> 31) & 0x1; 196 #endif // PERTAGBAR_PATCH 197 198 if (!restored && i && (tags & (1 << i))) { 199 m->nmaster = m->pertag->nmasters[i]; 200 m->sellt = m->pertag->sellts[i]; 201 m->lt[m->sellt] = m->pertag->ltidxs[i][m->sellt]; 202 #if FLEXTILE_DELUXE_LAYOUT 203 m->nstack = m->pertag->nstacks[i]; 204 if (m->lt[m->sellt]->arrange == flextile) { 205 m->ltaxis[LAYOUT] = m->pertag->ltaxis[i][LAYOUT]; 206 m->ltaxis[MASTER] = m->pertag->ltaxis[i][MASTER]; 207 m->ltaxis[STACK] = m->pertag->ltaxis[i][STACK]; 208 m->ltaxis[STACK2] = m->pertag->ltaxis[i][STACK2]; 209 } 210 #endif // FLEXTILE_DELUXE_LAYOUT 211 #if PERTAGBAR_PATCH 212 m->showbar = m->pertag->showbars[i]; 213 #else 214 m->showbar = (state >> 31) & 0x1; 215 #endif // PERTAGBAR_PATCH 216 restored = 1; 217 } 218 219 XFree(p); 220 } 221 222 return restored; 223 #else // !PERTAG_PATCH 224 if (!(XGetWindowProperty(dpy, root, dwm_monitor, 0L, sizeof dl, 225 False, AnyPropertyType, &da, &di, &nitems, &dl, &p) == Success && p)) { 226 return 0; 227 } 228 229 if (nitems) { 230 state = *(Atom *)p; 231 232 /* See bit layout in the persistmonitorstate function */ 233 m->nmaster = state & 0x7; 234 #if FLEXTILE_DELUXE_LAYOUT 235 m->nstack = (state >> 3) & 0x7; 236 #endif // FLEXTILE_DELUXE_LAYOUT 237 layout_index = (state >> 6) & 0xF; 238 if (layout_index < LENGTH(layouts)) 239 m->lt[m->sellt] = &layouts[layout_index]; 240 #if FLEXTILE_DELUXE_LAYOUT 241 if (m->lt[m->sellt]->arrange == flextile) { 242 m->ltaxis[LAYOUT] = (state >> 10) & 0xF; 243 m->ltaxis[MASTER] = (state >> 14) & 0xF; 244 m->ltaxis[STACK] = (state >> 18) & 0xF; 245 m->ltaxis[STACK2] = (state >> 22) & 0xF; 246 } 247 #endif // FLEXTILE_DELUXE_LAYOUT 248 m->showbar = (state >> 31) & 0x1; 249 } 250 251 XFree(p); 252 return 1; 253 #endif // PERTAG_PATCH 254 } 255 256 void 257 setmonitortags(Monitor *m) 258 { 259 char atom[22] = {0}; 260 Atom monitor_tags; 261 262 sprintf(atom, "_DWM_MONITOR_TAGS_%u", m->num); 263 monitor_tags = XInternAtom(dpy, atom, False); 264 265 uint32_t data[] = { m->tagset[m->seltags] }; 266 XChangeProperty(dpy, root, monitor_tags, XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); 267 } 268 269 int 270 getmonitortags(Monitor *m) 271 { 272 int di; 273 unsigned long dl, nitems; 274 unsigned char *p = NULL; 275 char atom[22] = {0}; 276 Atom da, monitor_tags = None, tags; 277 278 sprintf(atom, "_DWM_MONITOR_TAGS_%u", m->num); 279 monitor_tags = XInternAtom(dpy, atom, False); 280 281 if (!(XGetWindowProperty(dpy, root, monitor_tags, 0L, sizeof dl, 282 False, AnyPropertyType, &da, &di, &nitems, &dl, &p) == Success && p)) { 283 return 0; 284 } 285 286 if (nitems) { 287 tags = *(Atom *)p; 288 m->tagset[m->seltags] = tags & TAGMASK; 289 } 290 291 XFree(p); 292 return 1; 293 } 294 295 void 296 setclientfields(Client *c) 297 { 298 /* Perists client information in 32 bits laid out like this: 299 * 300 * |00000000|00000|0|0|0|0|0|0|0|0|00000000|000 301 * | | | | | | | | | | | |-- monitor index 302 * | | | | | | | | | | |-- client index 303 * | | | | | | | | | |-- isfloating 304 * | | | | | | | | |-- ispermanent 305 * | | | | | | | |-- isterminal 306 * | | | | | | |-- noswallow 307 * | | | | | |-- issteam 308 * | | | | |-- issticky 309 * | | | |-- fakefullscreen 310 * | | |-- isfreesize 311 * | | 312 * | |-- reserved 313 * |-- scratchkey (for scratchpads) 314 */ 315 uint32_t data[] = { 316 (c->mon->num & 0x7) 317 | (c->idx & 0xFF) << 3 318 | (c->isfloating & 0x1) << 11 319 #if ISPERMANENT_PATCH 320 | (c->ispermanent & 0x1) << 12 321 #endif // ISPERMANENT_PATCH 322 #if SWALLOW_PATCH 323 | (c->isterminal & 0x1) << 13 324 | (c->noswallow & 0x1) << 14 325 #endif // SWALLOW_PATCH 326 #if STEAM_PATCH 327 | (c->issteam & 0x1) << 15 328 #endif // STEAM_PATCH 329 #if STICKY_PATCH 330 | (c->issticky & 0x1) << 16 331 #endif // STICKY_PATCH 332 #if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH 333 | (c->fakefullscreen & 0x1) << 17 334 #endif // FAKEFULLSCREEN_CLIENT_PATCH 335 #if SIZEHINTS_ISFREESIZE_PATCH 336 | (c->isfreesize & 0x1) << 18 337 #endif // SIZEHINTS_ISFREESIZE_PATCH 338 #if RENAMED_SCRATCHPADS_PATCH 339 | (c->scratchkey & 0xFF) << 24 340 #endif // RENAMED_SCRATCHPADS_PATCH 341 }; 342 XChangeProperty(dpy, c->win, clientatom[ClientFields], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); 343 } 344 345 int 346 getclientfields(Client *c) 347 { 348 Monitor *m; 349 Atom fields = getatomprop(c, clientatom[ClientFields], AnyPropertyType); 350 if (fields == None) 351 return 0; 352 353 /* See bit layout in the setclientfields function */ 354 for (m = mons; m; m = m->next) 355 if (m->num == (fields & 0x7)) { 356 c->mon = m; 357 break; 358 } 359 c->idx = (fields >> 3) & 0xFF; 360 c->isfloating = (fields >> 11) & 0x1; 361 #if ISPERMANENT_PATCH 362 c->ispermanent = (fields >> 12) & 0x1; 363 #endif // ISPERMANENT_PATCH 364 #if SWALLOW_PATCH 365 c->isterminal = (fields >> 13) & 0x1; 366 c->noswallow = (fields >> 14) & 0x1; 367 #endif // SWALLOW_PATCH 368 #if STEAM_PATCH 369 c->issteam = (fields >> 15) & 0x1; 370 #endif // STEAM_PATCH 371 #if STICKY_PATCH 372 c->issticky = (fields >> 16) & 0x1; 373 #endif // STICKY_PATCH 374 #if !FAKEFULLSCREEN_PATCH && FAKEFULLSCREEN_CLIENT_PATCH 375 c->fakefullscreen = (fields >> 17) & 0x1; 376 #endif // FAKEFULLSCREEN_CLIENT_PATCH 377 #if SIZEHINTS_ISFREESIZE_PATCH 378 c->isfreesize = (fields >> 18) & 0x1; 379 #endif // SIZEHINTS_ISFREESIZE_PATCH 380 #if RENAMED_SCRATCHPADS_PATCH 381 c->scratchkey = (fields >> 24) & 0xFF; 382 #endif // RENAMED_SCRATCHPADS_PATCH 383 return 1; 384 } 385 386 void 387 setclienttags(Client *c) 388 { 389 uint32_t data[] = { c->tags }; 390 XChangeProperty(dpy, c->win, clientatom[ClientTags], XA_CARDINAL, 32, PropModeReplace, (unsigned char *)data, 1); 391 } 392 393 int 394 getclienttags(Client *c) 395 { 396 Atom tags = getatomprop(c, clientatom[ClientTags], AnyPropertyType); 397 if (tags == None) 398 return 0; 399 400 c->tags = tags & TAGMASK; 401 return 1; 402 } 403 404 #if SAVEFLOATS_PATCH 405 void 406 savewindowfloatposition(Client *c, Monitor *m) 407 { 408 char atom[22] = {0}; 409 if (c->sfx == -9999) 410 return; 411 412 sprintf(atom, "_DWM_FLOATPOS_%u", m->num); 413 uint32_t pos[] = { (MAX(c->sfx - m->mx, 0) & 0xffff) | ((MAX(c->sfy - m->my, 0) & 0xffff) << 16) }; 414 XChangeProperty(dpy, c->win, XInternAtom(dpy, atom, False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)pos, 1); 415 416 sprintf(atom, "_DWM_FLOATSIZE_%u", m->num); 417 uint32_t size[] = { (c->sfw & 0xffff) | ((c->sfh & 0xffff) << 16) }; 418 XChangeProperty(dpy, c->win, XInternAtom(dpy, atom, False), XA_CARDINAL, 32, PropModeReplace, (unsigned char *)size, 1); 419 420 XSync(dpy, False); 421 } 422 423 int 424 restorewindowfloatposition(Client *c, Monitor *m) 425 { 426 char atom[22] = {0}; 427 Atom key, value; 428 int x, y, w, h; 429 430 if (m == NULL) 431 return 0; 432 433 sprintf(atom, "_DWM_FLOATPOS_%u", m->num); 434 435 key = XInternAtom(dpy, atom, False); 436 if (!key) 437 return 0; 438 439 value = getatomprop(c, key, AnyPropertyType); 440 if (!value) 441 return 0; 442 443 x = value & 0xffff; 444 y = value >> 16; 445 446 sprintf(atom, "_DWM_FLOATSIZE_%u", m->num); 447 448 key = XInternAtom(dpy, atom, False); 449 if (!key) 450 return 0; 451 452 value = getatomprop(c, key, AnyPropertyType); 453 if (!value) 454 return 0; 455 456 w = value & 0xffff; 457 h = value >> 16; 458 459 if (w <= 0 || h <= 0) { 460 fprintf(stderr, "restorewindowfloatposition: bad float values x = %d, y = %d, w = %d, h = %d for client = %s\n", x, y, w, h, c->name); 461 return 0; 462 } 463 464 c->sfx = m->mx + x; 465 c->sfy = m->my + y; 466 c->sfw = w; 467 c->sfh = h; 468 469 if (c->isfloating) { 470 c->x = c->sfx; 471 c->y = c->sfy; 472 c->w = c->sfw; 473 c->h = c->sfh; 474 } 475 476 return 1; 477 } 478 #endif // SAVEFLOATS_PATCH