applied Brendan MacDonell's WM_TAKE_FOCUS patch, thanks Brendan!
1e20a0f7
1 file(s) · +42 −31
| 59 | 59 | enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ |
|
| 60 | 60 | enum { NetSupported, NetWMName, NetWMState, |
|
| 61 | 61 | NetWMFullscreen, NetLast }; /* EWMH atoms */ |
|
| 62 | - | enum { WMProtocols, WMDelete, WMState, WMLast }; /* default atoms */ |
|
| 62 | + | enum { WMProtocols, WMDelete, WMState, WMTakeFocus, WMLast }; /* default atoms */ |
|
| 63 | 63 | enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, |
|
| 64 | 64 | ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ |
|
| 65 | 65 | ||
| 88 | 88 | int basew, baseh, incw, inch, maxw, maxh, minw, minh; |
|
| 89 | 89 | int bw, oldbw; |
|
| 90 | 90 | unsigned int tags; |
|
| 91 | - | Bool isfixed, isfloating, isurgent, oldstate; |
|
| 91 | + | Bool isfixed, isfloating, isurgent, neverfocus, oldstate; |
|
| 92 | 92 | Client *next; |
|
| 93 | 93 | Client *snext; |
|
| 94 | 94 | Monitor *mon; |
|
| 190 | 190 | static void grabbuttons(Client *c, Bool focused); |
|
| 191 | 191 | static void grabkeys(void); |
|
| 192 | 192 | static void initfont(const char *fontstr); |
|
| 193 | - | static Bool isprotodel(Client *c); |
|
| 194 | 193 | static void keypress(XEvent *e); |
|
| 195 | 194 | static void killclient(const Arg *arg); |
|
| 196 | 195 | static void manage(Window w, XWindowAttributes *wa); |
|
| 208 | 207 | static void restack(Monitor *m); |
|
| 209 | 208 | static void run(void); |
|
| 210 | 209 | static void scan(void); |
|
| 210 | + | static Bool sendevent(Client *c, Atom proto); |
|
| 211 | 211 | static void sendmon(Client *c, Monitor *m); |
|
| 212 | 212 | static void setclientstate(Client *c, long state); |
|
| 213 | + | static void setfocus(Client *c); |
|
| 213 | 214 | static void setlayout(const Arg *arg); |
|
| 214 | 215 | static void setmfact(const Arg *arg); |
|
| 215 | 216 | static void setup(void); |
|
| 821 | 822 | attachstack(c); |
|
| 822 | 823 | grabbuttons(c, True); |
|
| 823 | 824 | XSetWindowBorder(dpy, c->win, dc.sel[ColBorder]); |
|
| 824 | - | XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
|
| 825 | + | setfocus(c); |
|
| 825 | 826 | } |
|
| 826 | 827 | else |
|
| 827 | 828 | XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); |
|
| 834 | 835 | XFocusChangeEvent *ev = &e->xfocus; |
|
| 835 | 836 | ||
| 836 | 837 | if(selmon->sel && ev->window != selmon->sel->win) |
|
| 837 | - | XSetInputFocus(dpy, selmon->sel->win, RevertToPointerRoot, CurrentTime); |
|
| 838 | + | setfocus(selmon->sel); |
|
| 838 | 839 | } |
|
| 839 | 840 | ||
| 840 | 841 | void |
|
| 1012 | 1013 | dc.font.height = dc.font.ascent + dc.font.descent; |
|
| 1013 | 1014 | } |
|
| 1014 | 1015 | ||
| 1015 | - | Bool |
|
| 1016 | - | isprotodel(Client *c) { |
|
| 1017 | - | int n; |
|
| 1018 | - | Atom *protocols; |
|
| 1019 | - | Bool ret = False; |
|
| 1020 | - | ||
| 1021 | - | if(XGetWMProtocols(dpy, c->win, &protocols, &n)) { |
|
| 1022 | - | while(!ret && n--) |
|
| 1023 | - | ret = protocols[n] == wmatom[WMDelete]; |
|
| 1024 | - | XFree(protocols); |
|
| 1025 | - | } |
|
| 1026 | - | return ret; |
|
| 1027 | - | } |
|
| 1028 | - | ||
| 1029 | 1016 | #ifdef XINERAMA |
|
| 1030 | 1017 | static Bool |
|
| 1031 | 1018 | isuniquegeom(XineramaScreenInfo *unique, size_t n, XineramaScreenInfo *info) { |
|
| 1054 | 1041 | ||
| 1055 | 1042 | void |
|
| 1056 | 1043 | killclient(const Arg *arg) { |
|
| 1057 | - | XEvent ev; |
|
| 1058 | - | ||
| 1059 | 1044 | if(!selmon->sel) |
|
| 1060 | 1045 | return; |
|
| 1061 | - | if(isprotodel(selmon->sel)) { |
|
| 1062 | - | ev.type = ClientMessage; |
|
| 1063 | - | ev.xclient.window = selmon->sel->win; |
|
| 1064 | - | ev.xclient.message_type = wmatom[WMProtocols]; |
|
| 1065 | - | ev.xclient.format = 32; |
|
| 1066 | - | ev.xclient.data.l[0] = wmatom[WMDelete]; |
|
| 1067 | - | ev.xclient.data.l[1] = CurrentTime; |
|
| 1068 | - | XSendEvent(dpy, selmon->sel->win, False, NoEventMask, &ev); |
|
| 1069 | - | } |
|
| 1070 | - | else { |
|
| 1046 | + | if(!sendevent(selmon->sel, wmatom[WMDelete])) { |
|
| 1071 | 1047 | XGrabServer(dpy); |
|
| 1072 | 1048 | XSetErrorHandler(xerrordummy); |
|
| 1073 | 1049 | XSetCloseDownMode(dpy, DestroyAll); |
|
| 1124 | 1100 | XSetWindowBorder(dpy, w, dc.norm[ColBorder]); |
|
| 1125 | 1101 | configure(c); /* propagates border_width, if size doesn't change */ |
|
| 1126 | 1102 | updatesizehints(c); |
|
| 1103 | + | updatewmhints(c); |
|
| 1127 | 1104 | XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); |
|
| 1128 | 1105 | grabbuttons(c, False); |
|
| 1129 | 1106 | if(!c->isfloating) |
|
| 1471 | 1448 | PropModeReplace, (unsigned char *)data, 2); |
|
| 1472 | 1449 | } |
|
| 1473 | 1450 | ||
| 1451 | + | Bool |
|
| 1452 | + | sendevent(Client *c, Atom proto) { |
|
| 1453 | + | int n; |
|
| 1454 | + | Atom *protocols; |
|
| 1455 | + | Bool exists = False; |
|
| 1456 | + | XEvent ev; |
|
| 1457 | + | ||
| 1458 | + | if(XGetWMProtocols(dpy, c->win, &protocols, &n)) { |
|
| 1459 | + | while(!exists && n--) |
|
| 1460 | + | exists = protocols[n] == proto; |
|
| 1461 | + | XFree(protocols); |
|
| 1462 | + | } |
|
| 1463 | + | if (exists) { |
|
| 1464 | + | ev.type = ClientMessage; |
|
| 1465 | + | ev.xclient.window = c->win; |
|
| 1466 | + | ev.xclient.message_type = wmatom[WMProtocols]; |
|
| 1467 | + | ev.xclient.format = 32; |
|
| 1468 | + | ev.xclient.data.l[0] = proto; |
|
| 1469 | + | ev.xclient.data.l[1] = CurrentTime; |
|
| 1470 | + | XSendEvent(dpy, c->win, False, NoEventMask, &ev); |
|
| 1471 | + | } |
|
| 1472 | + | return exists; |
|
| 1473 | + | } |
|
| 1474 | + | ||
| 1475 | + | void |
|
| 1476 | + | setfocus(Client *c) { |
|
| 1477 | + | if (!c->neverfocus) |
|
| 1478 | + | XSetInputFocus(dpy, c->win, RevertToPointerRoot, CurrentTime); |
|
| 1479 | + | sendevent(c, wmatom[WMTakeFocus]); |
|
| 1480 | + | } |
|
| 1481 | + | ||
| 1474 | 1482 | void |
|
| 1475 | 1483 | setlayout(const Arg *arg) { |
|
| 1476 | 1484 | if(!arg || !arg->v || arg->v != selmon->lt[selmon->sellt]) |
|
| 1517 | 1525 | wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); |
|
| 1518 | 1526 | wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); |
|
| 1519 | 1527 | wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); |
|
| 1528 | + | wmatom[WMTakeFocus] = XInternAtom(dpy, "WM_TAKE_FOCUS", False); |
|
| 1520 | 1529 | netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); |
|
| 1521 | 1530 | netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); |
|
| 1522 | 1531 | netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); |
|
| 1933 | 1942 | } |
|
| 1934 | 1943 | else |
|
| 1935 | 1944 | c->isurgent = (wmh->flags & XUrgencyHint) ? True : False; |
|
| 1945 | + | if (wmh->flags & InputHint) c->neverfocus = !wmh->input; |
|
| 1946 | + | else c->neverfocus = False; |
|
| 1936 | 1947 | XFree(wmh); |
|
| 1937 | 1948 | } |
|
| 1938 | 1949 | } |
|