diff --git a/dwm.c b/dwm.c index 71bd8b9..97485d6 100644 --- a/dwm.c +++ b/dwm.c @@ -199,6 +199,7 @@ static Client *nexttiled(Client *c); static void pop(Client *c); static void propertynotify(XEvent *e); static void quit(const Arg *arg); +static void restoresession(void); static Monitor *recttomon(int x, int y, int w, int h); static void resize(Client *c, int x, int y, int w, int h, int interact); static void resizeclient(Client *c, int x, int y, int w, int h); @@ -278,6 +279,7 @@ static void (*handler[LASTEvent]) (XEvent *) = { [UnmapNotify] = unmapnotify }; static Atom wmatom[WMLast], netatom[NetLast]; +static Atom dwmatom_tags, dwmatom_mon, dwmatom_index; static int running = 1; static Cur *cursor[CurLast]; static Clr **scheme; @@ -1275,6 +1277,35 @@ manage(Window w, XWindowAttributes *wa) applyrules(c); } + /* restore tags and monitor from previous dwm session */ + { + Atom da; + int di; + unsigned long nitems, dl; + unsigned char *p = NULL; + + if (XGetWindowProperty(dpy, w, dwmatom_tags, 0L, 1L, True, XA_CARDINAL, + &da, &di, &nitems, &dl, &p) == Success && p) { + if (nitems == 1) + c->tags = (unsigned int)(*(long *)p); + XFree(p); + } + p = NULL; + if (XGetWindowProperty(dpy, w, dwmatom_mon, 0L, 1L, True, XA_CARDINAL, + &da, &di, &nitems, &dl, &p) == Success && p) { + if (nitems == 1) { + Monitor *m; + int mon = (int)(*(long *)p); + for (m = mons; m; m = m->next) + if (m->num == mon) { + c->mon = m; + break; + } + } + XFree(p); + } + } + if (c->x + WIDTH(c) > c->mon->wx + c->mon->ww) c->x = c->mon->wx + c->mon->ww - WIDTH(c); if (c->y + HEIGHT(c) > c->mon->wy + c->mon->wh) @@ -1483,9 +1514,121 @@ propertynotify(XEvent *e) } } +void +restoresession(void) +{ + Monitor *m; + Client *c, **list; + int *indices; + int i, n, di; + Atom da; + unsigned long nitems, dl; + unsigned char *p = NULL; + + /* restore client order per monitor */ + for (m = mons; m; m = m->next) { + /* count clients */ + for (n = 0, c = m->clients; c; c = c->next, n++); + if (n == 0) + continue; + + list = ecalloc(n, sizeof(Client *)); + indices = ecalloc(n, sizeof(int)); + for (i = 0, c = m->clients; c; c = c->next, i++) + list[i] = c; + + /* read saved index for each client */ + for (i = 0; i < n; i++) { + p = NULL; + indices[i] = n; /* default: high value = end of list */ + if (XGetWindowProperty(dpy, list[i]->win, dwmatom_index, 0L, 1L, True, XA_CARDINAL, + &da, &di, &nitems, &dl, &p) == Success && p) { + if (nitems == 1) + indices[i] = (int)(*(long *)p); + XFree(p); + } + } + + /* simple insertion sort by saved index */ + for (i = 1; i < n; i++) { + Client *tmp = list[i]; + int tmpidx = indices[i]; + int j = i - 1; + while (j >= 0 && indices[j] > tmpidx) { + list[j + 1] = list[j]; + indices[j + 1] = indices[j]; + j--; + } + list[j + 1] = tmp; + indices[j + 1] = tmpidx; + } + + /* rebuild the client list */ + m->clients = list[0]; + for (i = 0; i < n - 1; i++) + list[i]->next = list[i + 1]; + list[n - 1]->next = NULL; + + free(indices); + free(list); + } + + /* restore active tagset per monitor */ + for (m = mons; m; m = m->next) { + char atom_name[32]; + Atom a; + + snprintf(atom_name, sizeof(atom_name), "_DWM_TAGSET_%d", m->num); + a = XInternAtom(dpy, atom_name, False); + p = NULL; + if (XGetWindowProperty(dpy, root, a, 0L, 1L, True, XA_CARDINAL, + &da, &di, &nitems, &dl, &p) == Success && p) { + if (nitems == 1) + m->tagset[m->seltags] = (unsigned int)(*(long *)p); + XFree(p); + } + } + + /* rearrange all monitors */ + for (m = mons; m; m = m->next) + arrange(m); + + focus(NULL); + drawbars(); +} + void quit(const Arg *arg) { + Monitor *m; + Client *c; + int i; + + for (m = mons; m; m = m->next) { + i = 0; + for (c = m->clients; c; c = c->next, i++) { + long tags = (long)c->tags; + long mon = (long)m->num; + long idx = (long)i; + XChangeProperty(dpy, c->win, dwmatom_tags, XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)&tags, 1); + XChangeProperty(dpy, c->win, dwmatom_mon, XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)&mon, 1); + XChangeProperty(dpy, c->win, dwmatom_index, XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)&idx, 1); + } + /* save active tagset per monitor on root window */ + { + char atom_name[32]; + Atom a; + long tagset = (long)m->tagset[m->seltags]; + snprintf(atom_name, sizeof(atom_name), "_DWM_TAGSET_%d", m->num); + a = XInternAtom(dpy, atom_name, False); + XChangeProperty(dpy, root, a, XA_CARDINAL, 32, + PropModeReplace, (unsigned char *)&tagset, 1); + } + } + XSync(dpy, False); running = 0; } @@ -1851,6 +1994,9 @@ setup(void) netatom[NetWMWindowType] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE", False); netatom[NetWMWindowTypeDialog] = XInternAtom(dpy, "_NET_WM_WINDOW_TYPE_DIALOG", False); netatom[NetClientList] = XInternAtom(dpy, "_NET_CLIENT_LIST", False); + dwmatom_tags = XInternAtom(dpy, "_DWM_TAGS", False); + dwmatom_mon = XInternAtom(dpy, "_DWM_MON", False); + dwmatom_index = XInternAtom(dpy, "_DWM_INDEX", False); /* init cursors */ cursor[CurNormal] = drw_cur_create(drw, XC_left_ptr); cursor[CurResize] = drw_cur_create(drw, XC_sizing); @@ -2531,6 +2677,7 @@ main(int argc, char *argv[]) die("pledge"); #endif /* __OpenBSD__ */ scan(); + restoresession(); run(); cleanup(); XCloseDisplay(dpy);