X-Git-Url: https://git.danieliu.xyz/?p=dwm.git;a=blobdiff_plain;f=dwm.c;h=b0d99c05ffed432638a943610625fa5adbbfb400;hp=d27cb672baa9b841ae7b7589522e95928e99b2ff;hb=a9b6a312a77b9cc81ca8b08a95c09e9f7948d7a6;hpb=bb3bd6fec37174e8d4bb9457ca815c00609e5157 diff --git a/dwm.c b/dwm.c index d27cb67..b0d99c0 100644 --- a/dwm.c +++ b/dwm.c @@ -3,7 +3,7 @@ * dynamic window manager is designed like any other X client as well. It is * driven through handling X events. In contrast to other X clients, a window * manager selects for SubstructureRedirectMask on the root window, to receive - * events about window (dis-)appearance. Only one X connection at a time is + * events about window (dis-)appearance. Only one X connection at a time is * allowed to select for this event mask. * * The event handlers of dwm are organized in an array which is accessed @@ -11,7 +11,7 @@ * in O(1) time. * * Each child of the root window is called a client, except windows which have - * set the override_redirect flag. Clients are organized in a linked client + * set the override_redirect flag. Clients are organized in a linked client * list on each monitor, the focus history is remembered through a stack list * on each monitor. Each client contains a bit array to indicate the tags of a * client. @@ -446,6 +446,8 @@ buttonpress(XEvent *e) click = ClkWinTitle; } else if ((c = wintoclient(ev->window))) { focus(c); + restack(selmon); + XAllowEvents(dpy, ReplayPointer, CurrentTime); click = ClkClientWin; } for (i = 0; i < LENGTH(buttons); i++) @@ -517,9 +519,10 @@ clientmessage(XEvent *e) if (!c) return; if (cme->message_type == netatom[NetWMState]) { - if (cme->data.l[1] == netatom[NetWMFullscreen] || cme->data.l[2] == netatom[NetWMFullscreen]) + if (cme->data.l[1] == netatom[NetWMFullscreen] + || cme->data.l[2] == netatom[NetWMFullscreen]) setfullscreen(c, (cme->data.l[0] == 1 /* _NET_WM_STATE_ADD */ - || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); + || (cme->data.l[0] == 2 /* _NET_WM_STATE_TOGGLE */ && !c->isfullscreen))); } else if (cme->message_type == netatom[NetActiveWindow]) { if (c != selmon->sel && !c->isurgent) seturgent(c, 1); @@ -718,8 +721,8 @@ drawbar(Monitor *m) drw_text(drw, x, 0, w, bh, lrpad / 2, tags[i], urg & 1 << i); if (occ & 1 << i) drw_rect(drw, x + boxs, boxs, boxw, boxw, - m == selmon && selmon->sel && selmon->sel->tags & 1 << i, - urg & 1 << i); + m == selmon && selmon->sel && selmon->sel->tags & 1 << i, + urg & 1 << i); x += w; } w = blw = TEXTW(m->ltsymbol); @@ -783,7 +786,6 @@ focus(Client *c) { if (!c || !ISVISIBLE(c)) for (c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); - /* was if (selmon->sel) */ if (selmon->sel && selmon->sel != c) unfocus(selmon->sel, 0); if (c) { @@ -804,7 +806,7 @@ focus(Client *c) drawbars(); } -/* there are some broken focus acquiring clients */ +/* there are some broken focus acquiring clients needing extra handling */ void focusin(XEvent *e) { @@ -823,8 +825,7 @@ focusmon(const Arg *arg) return; if ((m = dirtomon(arg->i)) == selmon) return; - unfocus(selmon->sel, 0); /* s/1/0/ fixes input focus issues - in gedit and anjuta */ + unfocus(selmon->sel, 0); selmon = m; focus(NULL); } @@ -864,7 +865,7 @@ getatomprop(Client *c, Atom prop) Atom da, atom = None; if (XGetWindowProperty(dpy, c->win, prop, 0L, sizeof atom, False, XA_ATOM, - &da, &di, &dl, &dl, &p) == Success && p) { + &da, &di, &dl, &dl, &p) == Success && p) { atom = *(Atom *)p; XFree(p); } @@ -891,7 +892,7 @@ getstate(Window w) Atom real; if (XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], - &real, &format, &n, &extra, (unsigned char **)&p) != Success) + &real, &format, &n, &extra, (unsigned char **)&p) != Success) return -1; if (n != 0) result = *p; @@ -933,17 +934,16 @@ grabbuttons(Client *c, int focused) unsigned int i, j; unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask }; XUngrabButton(dpy, AnyButton, AnyModifier, c->win); - if (focused) { - for (i = 0; i < LENGTH(buttons); i++) - if (buttons[i].click == ClkClientWin) - for (j = 0; j < LENGTH(modifiers); j++) - XGrabButton(dpy, buttons[i].button, - buttons[i].mask | modifiers[j], - c->win, False, BUTTONMASK, - GrabModeAsync, GrabModeSync, None, None); - } else + if (!focused) XGrabButton(dpy, AnyButton, AnyModifier, c->win, False, - BUTTONMASK, GrabModeAsync, GrabModeSync, None, None); + BUTTONMASK, GrabModeSync, GrabModeSync, None, None); + for (i = 0; i < LENGTH(buttons); i++) + if (buttons[i].click == ClkClientWin) + for (j = 0; j < LENGTH(modifiers); j++) + XGrabButton(dpy, buttons[i].button, + buttons[i].mask | modifiers[j], + c->win, False, BUTTONMASK, + GrabModeAsync, GrabModeSync, None, None); } } @@ -961,7 +961,7 @@ grabkeys(void) if ((code = XKeysymToKeycode(dpy, keys[i].keysym))) for (j = 0; j < LENGTH(modifiers); j++) XGrabKey(dpy, code, keys[i].mod | modifiers[j], root, - True, GrabModeAsync, GrabModeAsync); + True, GrabModeAsync, GrabModeAsync); } } @@ -1048,7 +1048,7 @@ manage(Window w, XWindowAttributes *wa) c->x = MAX(c->x, c->mon->mx); /* only fix client y-offset, if the client center might cover the bar */ c->y = MAX(c->y, ((c->mon->by == c->mon->my) && (c->x + (c->w / 2) >= c->mon->wx) - && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); + && (c->x + (c->w / 2) < c->mon->wx + c->mon->ww)) ? bh : c->mon->my); c->bw = borderpx; wc.border_width = c->bw; @@ -1067,7 +1067,7 @@ manage(Window w, XWindowAttributes *wa) attach(c); attachstack(c); XChangeProperty(dpy, root, netatom[NetClientList], XA_WINDOW, 32, PropModeAppend, - (unsigned char *) &(c->win), 1); + (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) @@ -1151,7 +1151,7 @@ movemouse(const Arg *arg) ocx = c->x; ocy = c->y; if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) + None, cursor[CurMove]->cursor, CurrentTime) != GrabSuccess) return; if (!getrootptr(&x, &y)) return; @@ -1170,20 +1170,17 @@ movemouse(const Arg *arg) nx = ocx + (ev.xmotion.x - x); ny = ocy + (ev.xmotion.y - y); - if (nx >= selmon->wx && nx <= selmon->wx + selmon->ww - && ny >= selmon->wy && ny <= selmon->wy + selmon->wh) { - if (abs(selmon->wx - nx) < snap) - nx = selmon->wx; - else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) - nx = selmon->wx + selmon->ww - WIDTH(c); - if (abs(selmon->wy - ny) < snap) - ny = selmon->wy; - else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) - ny = selmon->wy + selmon->wh - HEIGHT(c); - if (!c->isfloating && selmon->lt[selmon->sellt]->arrange - && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) - togglefloating(NULL); - } + if (abs(selmon->wx - nx) < snap) + nx = selmon->wx; + else if (abs((selmon->wx + selmon->ww) - (nx + WIDTH(c))) < snap) + nx = selmon->wx + selmon->ww - WIDTH(c); + if (abs(selmon->wy - ny) < snap) + ny = selmon->wy; + else if (abs((selmon->wy + selmon->wh) - (ny + HEIGHT(c))) < snap) + ny = selmon->wy + selmon->wh - HEIGHT(c); + if (!c->isfloating && selmon->lt[selmon->sellt]->arrange + && (abs(nx - c->x) > snap || abs(ny - c->y) > snap)) + togglefloating(NULL); if (!selmon->lt[selmon->sellt]->arrange || c->isfloating) resize(c, nx, ny, c->w, c->h, 1); break; @@ -1229,7 +1226,7 @@ propertynotify(XEvent *e) default: break; case XA_WM_TRANSIENT_FOR: if (!c->isfloating && (XGetTransientForHint(dpy, c->win, &trans)) && - (c->isfloating = (wintoclient(trans)) != NULL)) + (c->isfloating = (wintoclient(trans)) != NULL)) arrange(c->mon); break; case XA_WM_NORMAL_HINTS: @@ -1309,7 +1306,7 @@ resizemouse(const Arg *arg) ocx = c->x; ocy = c->y; if (XGrabPointer(dpy, root, False, MOUSEMASK, GrabModeAsync, GrabModeAsync, - None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) + None, cursor[CurResize]->cursor, CurrentTime) != GrabSuccess) return; XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w + c->bw - 1, c->h + c->bw - 1); do { @@ -1434,7 +1431,7 @@ setclientstate(Client *c, long state) long data[] = { state, None }; XChangeProperty(dpy, c->win, wmatom[WMState], wmatom[WMState], 32, - PropModeReplace, (unsigned char *)data, 2); + PropModeReplace, (unsigned char *)data, 2); } int @@ -1468,8 +1465,8 @@ setfocus(Client *c) if (!c->neverfocus) { XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); XChangeProperty(dpy, root, netatom[NetActiveWindow], - XA_WINDOW, 32, PropModeReplace, - (unsigned char *) &(c->win), 1); + XA_WINDOW, 32, PropModeReplace, + (unsigned char *) &(c->win), 1); } sendevent(c, wmatom[WMTakeFocus]); } @@ -1479,7 +1476,7 @@ setfullscreen(Client *c, int fullscreen) { if (fullscreen && !c->isfullscreen) { XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); + PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); c->isfullscreen = 1; c->oldstate = c->isfloating; c->oldbw = c->bw; @@ -1489,7 +1486,7 @@ setfullscreen(Client *c, int fullscreen) XRaiseWindow(dpy, c->win); } else if (!fullscreen && c->isfullscreen){ XChangeProperty(dpy, c->win, netatom[NetWMState], XA_ATOM, 32, - PropModeReplace, (unsigned char*)0, 0); + PropModeReplace, (unsigned char*)0, 0); c->isfullscreen = 0; c->isfloating = c->oldstate; c->bw = c->oldbw; @@ -1516,7 +1513,7 @@ setlayout(const Arg *arg) drawbar(selmon); } -/* arg > 1.0 will set mfact absolutly */ +/* arg > 1.0 will set mfact absolutely */ void setmfact(const Arg *arg) { @@ -1588,12 +1585,13 @@ setup(void) PropModeReplace, (unsigned char *) &wmcheckwin, 1); /* EWMH support per view */ XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, - PropModeReplace, (unsigned char *) netatom, NetLast); + PropModeReplace, (unsigned char *) netatom, NetLast); XDeleteProperty(dpy, root, netatom[NetClientList]); - /* select for events */ + /* select events */ wa.cursor = cursor[CurNormal]->cursor; - wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask|ButtonPressMask|PointerMotionMask - |EnterWindowMask|LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; + wa.event_mask = SubstructureRedirectMask|SubstructureNotifyMask + |ButtonPressMask|PointerMotionMask|EnterWindowMask + |LeaveWindowMask|StructureNotifyMask|PropertyChangeMask; XChangeWindowAttributes(dpy, root, CWEventMask|CWCursor, &wa); XSelectInput(dpy, root, wa.event_mask); grabkeys(); @@ -1719,7 +1717,7 @@ togglefloating(const Arg *arg) selmon->sel->isfloating = !selmon->sel->isfloating || selmon->sel->isfixed; if (selmon->sel->isfloating) resize(selmon->sel, selmon->sel->x, selmon->sel->y, - selmon->sel->w, selmon->sel->h, 0); + selmon->sel->w, selmon->sel->h, 0); arrange(selmon); } @@ -1769,12 +1767,11 @@ unmanage(Client *c, int destroyed) Monitor *m = c->mon; XWindowChanges wc; - /* The server grab construct avoids race conditions. */ detach(c); detachstack(c); if (!destroyed) { wc.border_width = c->oldbw; - XGrabServer(dpy); + XGrabServer(dpy); /* avoid race conditions */ XSetErrorHandler(xerrordummy); XConfigureWindow(dpy, c->win, CWBorderWidth, &wc); /* restore border */ XUngrabButton(dpy, AnyButton, AnyModifier, c->win); @@ -1812,14 +1809,16 @@ updatebars(void) .background_pixmap = ParentRelative, .event_mask = ButtonPressMask|ExposureMask }; + XClassHint ch = {"dwm", "dwm"}; for (m = mons; m; m = m->next) { if (m->barwin) continue; m->barwin = XCreateWindow(dpy, root, m->wx, m->by, m->ww, bh, 0, DefaultDepth(dpy, screen), - CopyFromParent, DefaultVisual(dpy, screen), - CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); + CopyFromParent, DefaultVisual(dpy, screen), + CWOverrideRedirect|CWBackPixmap|CWEventMask, &wa); XDefineCursor(dpy, m->barwin, cursor[CurNormal]->cursor); XMapRaised(dpy, m->barwin); + XSetClassHint(dpy, m->barwin, &ch); } } @@ -1846,8 +1845,8 @@ updateclientlist() 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); + XA_WINDOW, 32, PropModeAppend, + (unsigned char *) &(c->win), 1); } int @@ -1871,8 +1870,8 @@ updategeom(void) memcpy(&unique[j++], &info[i], sizeof(XineramaScreenInfo)); XFree(info); nn = j; - if (n <= nn) { - for (i = 0; i < (nn - n); i++) { /* new monitors available */ + if (n <= nn) { /* new monitors available */ + for (i = 0; i < (nn - n); i++) { for (m = mons; m && m->next; m = m->next); if (m) m->next = createmon(); @@ -1881,8 +1880,8 @@ updategeom(void) } 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)) + || unique[i].x_org != m->mx || unique[i].y_org != m->my + || unique[i].width != m->mw || unique[i].height != m->mh) { dirty = 1; m->num = i; @@ -1892,13 +1891,11 @@ updategeom(void) m->mh = m->wh = unique[i].height; updatebarpos(m); } - } else { - /* less monitors available nn < n */ + } else { /* less monitors available nn < n */ for (i = nn; i < n; i++) { for (m = mons; m && m->next; m = m->next); - while (m->clients) { + while ((c = m->clients)) { dirty = 1; - c = m->clients; m->clients = c->next; detachstack(c); c->mon = mons; @@ -1913,8 +1910,7 @@ updategeom(void) free(unique); } else #endif /* XINERAMA */ - /* default monitor setup */ - { + { /* default monitor setup */ if (!mons) mons = createmon(); if (mons->mw != sw || mons->mh != sh) { @@ -1942,7 +1938,7 @@ updatenumlockmask(void) for (i = 0; i < 8; i++) for (j = 0; j < modmap->max_keypermod; j++) if (modmap->modifiermap[i * modmap->max_keypermod + j] - == XKeysymToKeycode(dpy, XK_Num_Lock)) + == XKeysymToKeycode(dpy, XK_Num_Lock)) numlockmask = (1 << i); XFreeModifiermap(modmap); } @@ -1987,8 +1983,7 @@ updatesizehints(Client *c) c->maxa = (float)size.max_aspect.x / size.max_aspect.y; } else c->maxa = c->mina = 0.0; - c->isfixed = (c->maxw && c->minw && c->maxh && c->minh - && c->maxw == c->minw && c->maxh == c->minh); + c->isfixed = (c->maxw && c->maxh && c->maxw == c->minw && c->maxh == c->minh); } void @@ -2082,8 +2077,8 @@ wintomon(Window w) } /* There's no way to check accesses to destroyed windows, thus those cases are - * ignored (especially on UnmapNotify's). Other types of errors call Xlibs - * default error handler, which may call exit. */ + * ignored (especially on UnmapNotify's). Other types of errors call Xlibs + * default error handler, which may call exit. */ int xerror(Display *dpy, XErrorEvent *ee) { @@ -2098,7 +2093,7 @@ xerror(Display *dpy, XErrorEvent *ee) || (ee->request_code == X_CopyArea && ee->error_code == BadDrawable)) return 0; fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n", - ee->request_code, ee->error_code); + ee->request_code, ee->error_code); return xerrorxlib(dpy, ee); /* may call exit */ }