X-Git-Url: https://jasonwoof.com/gitweb/?p=dwm.git;a=blobdiff_plain;f=dwm.c;h=7941bd1480baef87f175818d99ccc6fdecba918d;hp=6b3951924554747197ac258ff3c8077768dae7eb;hb=f2544a331845ad80655c1f79c9dc61922fe3441c;hpb=606b44179dfeec8d31930488aa91c8d4808235a7 diff --git a/dwm.c b/dwm.c index 6b39519..7941bd1 100644 --- a/dwm.c +++ b/dwm.c @@ -36,11 +36,13 @@ #include #include #include -#include #ifdef XINERAMA #include #endif /* XINERAMA */ +#include "drw.h" +#include "util.h" + /* macros */ #define BUTTONMASK (ButtonPressMask|ButtonReleaseMask) #define CLEANMASK(mask) (mask & ~(numlockmask|LockMask) & (ShiftMask|ControlMask|Mod1Mask|Mod2Mask|Mod3Mask|Mod4Mask|Mod5Mask)) @@ -48,8 +50,6 @@ * MAX(0, MIN((y)+(h),(m)->wy+(m)->wh) - MAX((y),(m)->wy))) #define ISVISIBLE(C) ((C->tags & C->mon->tagset[C->mon->seltags])) #define LENGTH(X) (sizeof X / sizeof X[0]) -#define MAX(A, B) ((A) > (B) ? (A) : (B)) -#define MIN(A, B) ((A) < (B) ? (A) : (B)) #define MOUSEMASK (BUTTONMASK|PointerMotionMask) #define WIDTH(X) ((X)->w + 2 * (X)->bw) #define HEIGHT(X) ((X)->h + 2 * (X)->bw) @@ -175,7 +175,6 @@ static Monitor *createmon(void); static void destroynotify(XEvent *e); static void detach(Client *c); static void detachstack(Client *c); -static void die(const char *errstr, ...); static Monitor *dirtomon(int dir); static void drawbar(Monitor *m); static void drawbars(void); @@ -236,7 +235,7 @@ static void toggleview(const Arg *arg); static void unfocus(Client *c, Bool setfocus); static void unmanage(Client *c, Bool destroyed); static void unmapnotify(XEvent *e); -static void updategeom(void); +static Bool updategeom(void); static void updatebarpos(Monitor *m); static void updatebars(void); static void updateclientlist(void); @@ -574,18 +573,23 @@ void configurenotify(XEvent *e) { Monitor *m; XConfigureEvent *ev = &e->xconfigure; + Bool dirty; + // TODO: updategeom handling sucks, needs to be simplified if(ev->window == root) { + dirty = (sw != ev->width || sh != ev->height); sw = ev->width; sh = ev->height; - if(dc.drawable != 0) - XFreePixmap(dpy, dc.drawable); - dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); - updatebars(); - for(m = mons; m; m = m->next) - XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); - focus(NULL); - arrange(NULL); + if(updategeom() || dirty) { + if(dc.drawable != 0) + XFreePixmap(dpy, dc.drawable); + dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); + updatebars(); + for(m = mons; m; m = m->next) + XMoveResizeWindow(dpy, m->barwin, m->wx, m->by, m->ww, bh); + focus(NULL); + arrange(NULL); + } } } @@ -689,16 +693,6 @@ detachstack(Client *c) { } } -void -die(const char *errstr, ...) { - va_list ap; - - va_start(ap, errstr); - vfprintf(stderr, errstr, ap); - va_end(ap); - exit(EXIT_FAILURE); -} - Monitor * dirtomon(int dir) { Monitor *m = NULL; @@ -1072,8 +1066,8 @@ initfont(const char *fontstr) { static Bool isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { while(n--) - /* treat origin (x, y) as fixpoint for uniqueness only, first screen wins */ - if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org) + if(unique[n].x_org == info->x_org && unique[n].y_org == info->y_org + && unique[n].width == info->width && unique[n].height == info->height) return False; return True; } @@ -1086,7 +1080,7 @@ keypress(XEvent *e) { XKeyEvent *ev; ev = &e->xkey; - keysym = XkbKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0, 0); + keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); for(i = 0; i < LENGTH(keys); i++) if(keysym == keys[i].keysym && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) @@ -1883,74 +1877,86 @@ updateclientlist() { (unsigned char *) &(c->win), 1); } -void +Bool updategeom(void) { - /* Starting with dwm 6.1 this function uses a new (simpler) strategy: - * whenever screen changes are reported, we destroy all monitors - * and recreate all unique origin monitors and add all clients to - * the first monitor, only. In several circumstances this may suck, - * but dealing with all corner-cases sucks even more.*/ + Bool dirty = False; #ifdef XINERAMA if(XineramaIsActive(dpy)) { - int i, j, n; + int i, j, n, nn; Client *c; - Monitor *m, *oldmons = mons; - XineramaScreenInfo *info = XineramaQueryScreens(dpy, &n); + Monitor *m; + XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); XineramaScreenInfo *unique = NULL; + for(n = 0, m = mons; m; m = m->next, n++); /* only consider unique geometries as separate screens */ - if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * n))) - die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * n); - for(i = 0, j = 0; i < n; i++) + if(!(unique = (XineramaScreenInfo *)malloc(sizeof(XineramaScreenInfo) * nn))) + die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * nn); + for(i = 0, j = 0; i < nn; i++) if(isuniquegeom(unique, j, &info[i])) memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); XFree(info); - /* create new monitor structure */ - n = j; - mons = m = createmon(); /* new first monitor */ - for(i = 1; i < n; i++) { - m->next = createmon(); - m = m->next; - } - for(i = 0, m = mons; i < n && m; m = m->next, i++) { - m->num = i; - m->mx = m->wx = unique[i].x_org; - m->my = m->wy = unique[i].y_org; - m->mw = m->ww = unique[i].width; - m->mh = m->wh = unique[i].height; - updatebarpos(m); + nn = j; + if(n <= nn) { + for(i = 0; i < (nn - n); i++) { /* new monitors available */ + for(m = mons; m && m->next; m = m->next); + if(m) + m->next = createmon(); + else + mons = createmon(); + } + for(i = 0, m = mons; i < nn && m; m = m->next, i++) + if(i >= n + || (unique[i].x_org != m->mx || unique[i].y_org != m->my + || unique[i].width != m->mw || unique[i].height != m->mh)) + { + dirty = True; + m->num = i; + m->mx = m->wx = unique[i].x_org; + m->my = m->wy = unique[i].y_org; + m->mw = m->ww = unique[i].width; + m->mh = m->wh = unique[i].height; + updatebarpos(m); + } } - free(unique); - /* re-attach old clients and cleanup old monitor structure */ - while(oldmons) { - m = oldmons; - while(m->clients) { - c = m->clients; - m->clients = c->next; - detachstack(c); - c->mon = mons; - attach(c); - attachstack(c); + else { /* less monitors available nn < n */ + for(i = nn; i < n; i++) { + for(m = mons; m && m->next; m = m->next); + while(m->clients) { + dirty = True; + c = m->clients; + m->clients = c->next; + detachstack(c); + c->mon = mons; + attach(c); + attachstack(c); + } + if(m == selmon) + selmon = mons; + cleanupmon(m); } - oldmons = m->next; - cleanupmon(m); } + free(unique); } else #endif /* XINERAMA */ /* default monitor setup */ { - if(!mons) /* only true if !XINERAMA compile flag */ + if(!mons) mons = createmon(); if(mons->mw != sw || mons->mh != sh) { + dirty = True; mons->mw = mons->ww = sw; mons->mh = mons->wh = sh; updatebarpos(mons); } } - selmon = mons; - selmon = wintomon(root); + if(dirty) { + selmon = mons; + selmon = wintomon(root); + } + return dirty; } void