X-Git-Url: https://jasonwoof.com/gitweb/?p=dwm.git;a=blobdiff_plain;f=dwm.c;h=6b3951924554747197ac258ff3c8077768dae7eb;hp=2d444424b1347b12a6f764f5ff701ac249600c33;hb=606b44179dfeec8d31930488aa91c8d4808235a7;hpb=54c3044decc9848ba18c137dd3558dc8bdf71f34 diff --git a/dwm.c b/dwm.c index 2d44442..6b39519 100644 --- a/dwm.c +++ b/dwm.c @@ -36,6 +36,7 @@ #include #include #include +#include #ifdef XINERAMA #include #endif /* XINERAMA */ @@ -60,7 +61,7 @@ enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ enum { NetSupported, NetWMName, NetWMState, NetWMFullscreen, NetActiveWindow, NetWMWindowType, - NetWMWindowTypeDialog, NetLast }; /* EWMH atoms */ + NetWMWindowTypeDialog, NetClientList, NetLast }; /* EWMH atoms */ enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ @@ -235,9 +236,10 @@ 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 Bool updategeom(void); +static void updategeom(void); static void updatebarpos(Monitor *m); static void updatebars(void); +static void updateclientlist(void); static void updatenumlockmask(void); static void updatesizehints(Client *c); static void updatestatus(void); @@ -499,6 +501,7 @@ cleanup(void) { cleanupmon(mons); XSync(dpy, False); XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); } void @@ -571,22 +574,18 @@ void configurenotify(XEvent *e) { Monitor *m; XConfigureEvent *ev = &e->xconfigure; - Bool dirty; if(ev->window == root) { - dirty = (sw != ev->width); sw = ev->width; sh = ev->height; - 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); - } + 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); } } @@ -858,8 +857,10 @@ focus(Client *c) { XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); setfocus(c); } - else + else { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } selmon->sel = c; drawbars(); } @@ -880,7 +881,8 @@ focusmon(const Arg *arg) { return; if((m = dirtomon(arg->i)) == selmon) return; - unfocus(selmon->sel, True); + unfocus(selmon->sel, False); /* s/True/False/ fixes input focus issues + in gedit and anjuta */ selmon = m; focus(NULL); } @@ -1070,8 +1072,8 @@ initfont(const char *fontstr) { static Bool isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { while(n--) - 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) + /* 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) return False; return True; } @@ -1084,7 +1086,7 @@ keypress(XEvent *e) { XKeyEvent *ev; ev = &e->xkey; - keysym = XKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0); + keysym = XkbKeycodeToKeysym(dpy, (KeyCode)ev->keycode, 0, 0); for(i = 0; i < LENGTH(keys); i++) if(keysym == keys[i].keysym && CLEANMASK(keys[i].mod) == CLEANMASK(ev->state) @@ -1157,6 +1159,8 @@ manage(Window w, XWindowAttributes *wa) { XRaiseWindow(dpy, c->win); attach(c); attachstack(c); + XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ setclientstate(c, NormalState); if (c->mon == selmon) @@ -1228,6 +1232,8 @@ movemouse(const Arg *arg) { if(!(c = selmon->sel)) return; + if(c->isfullscreen) /* no support moving fullscreen windows by mouse */ + return; restack(selmon); ocx = c->x; ocy = c->y; @@ -1372,6 +1378,8 @@ resizemouse(const Arg *arg) { if(!(c = selmon->sel)) return; + if(c->isfullscreen) /* no support resizing fullscreen windows by mouse */ + return; restack(selmon); ocx = c->x; ocy = c->y; @@ -1521,8 +1529,12 @@ sendevent(Client *c, Atom proto) { void setfocus(Client *c) { - if(!c->neverfocus) + if(!c->neverfocus) { XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); + XChangeProperty(dpy, root, netatom[NetActiveWindow], + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(c->win), 1); + } sendevent(c, wmatom[WMTakeFocus]); } @@ -1608,6 +1620,7 @@ setup(void) { netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); 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); /* init cursors */ cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); @@ -1630,6 +1643,7 @@ setup(void) { /* EWMH support per view */ XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, PropModeReplace, (unsigned char *) netatom, NetLast); + XDeleteProperty(dpy, root, netatom[NetClientList]); /* select for events */ wa.cursor = cursor[CurNormal]; wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask|PointerMotionMask @@ -1740,6 +1754,8 @@ void togglefloating(const Arg *arg) { if(!selmon->sel) return; + if(selmon->sel->isfullscreen) /* no support for fullscreen windows */ + return; selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; if(selmon->sel->isfloating) resize(selmon->sel, selmon->sel->x, selmon->sel->y, @@ -1778,8 +1794,10 @@ unfocus(Client *c, Bool setfocus) { return; grabbuttons(c, False); XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]); - if(setfocus) + if(setfocus) { XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); + XDeleteProperty(dpy, root, netatom[NetActiveWindow]); + } } void @@ -1803,6 +1821,7 @@ unmanage(Client *c, Bool destroyed) { } free(c); focus(NULL); + updateclientlist(); arrange(m); } @@ -1851,86 +1870,87 @@ updatebarpos(Monitor *m) { m->by = -bh; } -Bool +void +updateclientlist() { + Client *c; + Monitor *m; + + XDeleteProperty(dpy, root, netatom[NetClientList]); + for(m = mons; m; m = m->next) + for(c = m->clients; c; c = c->next) + XChangeProperty(dpy, root, netatom[NetClientList], + XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); +} + +void updategeom(void) { - Bool dirty = False; + /* 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.*/ #ifdef XINERAMA if(XineramaIsActive(dpy)) { - int i, j, n, nn; + int i, j, n; Client *c; - Monitor *m; - XineramaScreenInfo *info = XineramaQueryScreens(dpy, &nn); + Monitor *m, *oldmons = mons; + XineramaScreenInfo *info = XineramaQueryScreens(dpy, &n); 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) * nn))) - die("fatal: could not malloc() %u bytes\n", sizeof(XineramaScreenInfo) * nn); - for(i = 0, j = 0; i < nn; i++) + 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(isuniquegeom(unique, j, &info[i])) memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); XFree(info); - 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); - } + /* create new monitor structure */ + n = j; + mons = m = createmon(); /* new first monitor */ + for(i = 1; i < n; i++) { + m->next = createmon(); + m = m->next; } - 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); - } + 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); } 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); + } + oldmons = m->next; + cleanupmon(m); + } } else #endif /* XINERAMA */ /* default monitor setup */ { - if(!mons) + if(!mons) /* only true if !XINERAMA compile flag */ mons = createmon(); if(mons->mw != sw || mons->mh != sh) { - dirty = True; mons->mw = mons->ww = sw; mons->mh = mons->wh = sh; updatebarpos(mons); } } - if(dirty) { - selmon = mons; - selmon = wintomon(root); - } - return dirty; + selmon = mons; + selmon = wintomon(root); } void @@ -2020,7 +2040,6 @@ updatewindowtype(Client *c) { if(state == netatom[NetWMFullscreen]) setfullscreen(c, True); - if(wtype == netatom[NetWMWindowTypeDialog]) c->isfloating = True; }