implemented better fullscreen handling, please test
62d3caa9
1 file(s) · +75 −30
| 57 | 57 | /* enums */ |
|
| 58 | 58 | enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ |
|
| 59 | 59 | enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ |
|
| 60 | - | enum { NetSupported, NetWMName, NetWMState, NetLast }; /* EWMH atoms */ |
|
| 60 | + | enum { NetSupported, NetWMName, NetWMState, |
|
| 61 | + | NetWMFullscreen, NetLast }; /* EWMH atoms */ |
|
| 61 | 62 | enum { WMProtocols, WMDelete, WMState, WMLast }; /* default atoms */ |
|
| 62 | 63 | enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, |
|
| 63 | 64 | ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ |
|
| 83 | 84 | char name[256]; |
|
| 84 | 85 | float mina, maxa; |
|
| 85 | 86 | int x, y, w, h; |
|
| 87 | + | int oldx, oldy, oldw, oldh; |
|
| 86 | 88 | int basew, baseh, incw, inch, maxw, maxh, minw, minh; |
|
| 87 | 89 | int bw, oldbw; |
|
| 88 | 90 | unsigned int tags; |
|
| 89 | - | Bool isfixed, isfloating, isurgent; |
|
| 91 | + | Bool isfixed, isfloating, isurgent, oldstate; |
|
| 90 | 92 | Client *next; |
|
| 91 | 93 | Client *snext; |
|
| 92 | 94 | Monitor *mon; |
|
| 161 | 163 | static void cleanup(void); |
|
| 162 | 164 | static void cleanupmon(Monitor *mon); |
|
| 163 | 165 | static void clearurgent(Client *c); |
|
| 166 | + | static void clientmessage(XEvent *e); |
|
| 164 | 167 | static void configure(Client *c); |
|
| 165 | 168 | static void configurenotify(XEvent *e); |
|
| 166 | 169 | static void configurerequest(XEvent *e); |
|
| 200 | 203 | static void propertynotify(XEvent *e); |
|
| 201 | 204 | static void quit(const Arg *arg); |
|
| 202 | 205 | static void resize(Client *c, int x, int y, int w, int h, Bool interact); |
|
| 206 | + | static void resizeclient(Client *c, int x, int y, int w, int h); |
|
| 203 | 207 | static void resizemouse(const Arg *arg); |
|
| 204 | 208 | static void restack(Monitor *m); |
|
| 205 | 209 | static void run(void); |
|
| 220 | 224 | static void togglefloating(const Arg *arg); |
|
| 221 | 225 | static void toggletag(const Arg *arg); |
|
| 222 | 226 | static void toggleview(const Arg *arg); |
|
| 223 | - | static void unfocus(Client *c); |
|
| 227 | + | static void unfocus(Client *c, Bool setfocus); |
|
| 224 | 228 | static void unmanage(Client *c, Bool destroyed); |
|
| 225 | 229 | static void unmapnotify(XEvent *e); |
|
| 226 | 230 | static Bool updategeom(void); |
|
| 249 | 253 | static unsigned int numlockmask = 0; |
|
| 250 | 254 | static void (*handler[LASTEvent]) (XEvent *) = { |
|
| 251 | 255 | [ButtonPress] = buttonpress, |
|
| 256 | + | [ClientMessage] = clientmessage, |
|
| 252 | 257 | [ConfigureRequest] = configurerequest, |
|
| 253 | 258 | [ConfigureNotify] = configurenotify, |
|
| 254 | 259 | [DestroyNotify] = destroynotify, |
|
| 423 | 428 | click = ClkRootWin; |
|
| 424 | 429 | /* focus monitor if necessary */ |
|
| 425 | 430 | if((m = wintomon(ev->window)) && m != selmon) { |
|
| 426 | - | unfocus(selmon->sel); |
|
| 431 | + | unfocus(selmon->sel, True); |
|
| 427 | 432 | selmon = m; |
|
| 428 | 433 | focus(NULL); |
|
| 429 | 434 | } |
|
| 792 | 797 | if((ev->mode != NotifyNormal || ev->detail == NotifyInferior) && ev->window != root) |
|
| 793 | 798 | return; |
|
| 794 | 799 | if((m = wintomon(ev->window)) && m != selmon) { |
|
| 795 | - | unfocus(selmon->sel); |
|
| 800 | + | unfocus(selmon->sel, True); |
|
| 796 | 801 | selmon = m; |
|
| 797 | 802 | } |
|
| 798 | 803 | if((c = wintoclient(ev->window))) |
|
| 814 | 819 | focus(Client *c) { |
|
| 815 | 820 | if(!c || !ISVISIBLE(c)) |
|
| 816 | 821 | for(c = selmon->stack; c && !ISVISIBLE(c); c = c->snext); |
|
| 817 | - | if(selmon->sel) |
|
| 818 | - | unfocus(selmon->sel); |
|
| 822 | + | /* was if(selmon->sel) */ |
|
| 823 | + | if(selmon->sel && selmon->sel != c) |
|
| 824 | + | unfocus(selmon->sel, False); |
|
| 819 | 825 | if(c) { |
|
| 820 | 826 | if(c->mon != selmon) |
|
| 821 | 827 | selmon = c->mon; |
|
| 849 | 855 | return; |
|
| 850 | 856 | if((m = dirtomon(arg->i)) == selmon) |
|
| 851 | 857 | return; |
|
| 852 | - | unfocus(selmon->sel); |
|
| 858 | + | unfocus(selmon->sel, True); |
|
| 853 | 859 | selmon = m; |
|
| 854 | 860 | focus(NULL); |
|
| 855 | 861 | } |
|
| 901 | 907 | ||
| 902 | 908 | long |
|
| 903 | 909 | getstate(Window w) { |
|
| 904 | - | int format, status; |
|
| 910 | + | int format; |
|
| 905 | 911 | long result = -1; |
|
| 906 | 912 | unsigned char *p = NULL; |
|
| 907 | 913 | unsigned long n, extra; |
|
| 908 | 914 | Atom real; |
|
| 909 | 915 | ||
| 910 | - | status = XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], |
|
| 911 | - | &real, &format, &n, &extra, (unsigned char **)&p); |
|
| 912 | - | if(status != Success) |
|
| 916 | + | if(XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], |
|
| 917 | + | &real, &format, &n, &extra, (unsigned char **)&p) != Success) |
|
| 913 | 918 | return -1; |
|
| 914 | 919 | if(n != 0) |
|
| 915 | 920 | result = *p; |
|
| 1110 | 1115 | applyrules(c); |
|
| 1111 | 1116 | } |
|
| 1112 | 1117 | /* geometry */ |
|
| 1113 | - | c->x = wa->x + c->mon->wx; |
|
| 1114 | - | c->y = wa->y + c->mon->wy; |
|
| 1115 | - | c->w = wa->width; |
|
| 1116 | - | c->h = wa->height; |
|
| 1118 | + | c->x = c->oldx = wa->x + c->mon->wx; |
|
| 1119 | + | c->y = c->oldy = wa->y + c->mon->wy; |
|
| 1120 | + | c->w = c->oldw = wa->width; |
|
| 1121 | + | c->h = c->oldh = wa->height; |
|
| 1117 | 1122 | c->oldbw = wa->border_width; |
|
| 1118 | 1123 | if(c->w == c->mon->mw && c->h == c->mon->mh) { |
|
| 1124 | + | c->isfloating = 1; |
|
| 1119 | 1125 | c->x = c->mon->mx; |
|
| 1120 | 1126 | c->y = c->mon->my; |
|
| 1121 | 1127 | c->bw = 0; |
|
| 1139 | 1145 | XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); |
|
| 1140 | 1146 | grabbuttons(c, False); |
|
| 1141 | 1147 | if(!c->isfloating) |
|
| 1142 | - | c->isfloating = trans != None || c->isfixed; |
|
| 1148 | + | c->isfloating = c->oldstate = trans != None || c->isfixed; |
|
| 1143 | 1149 | if(c->isfloating) |
|
| 1144 | 1150 | XRaiseWindow(dpy, c->win); |
|
| 1145 | 1151 | attach(c); |
|
| 1292 | 1298 | } |
|
| 1293 | 1299 | ||
| 1294 | 1300 | void |
|
| 1301 | + | clientmessage(XEvent *e) { |
|
| 1302 | + | XClientMessageEvent *cme = &e->xclient; |
|
| 1303 | + | Client *c; |
|
| 1304 | + | ||
| 1305 | + | if((c = wintoclient(cme->window)) |
|
| 1306 | + | && (cme->message_type == netatom[NetWMState] && cme->data.l[1] == netatom[NetWMFullscreen])) |
|
| 1307 | + | { |
|
| 1308 | + | if(cme->data.l[0]) { |
|
| 1309 | + | XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, |
|
| 1310 | + | PropModeReplace, (unsigned char*)&netatom[NetWMFullscreen], 1); |
|
| 1311 | + | c->oldstate = c->isfloating; |
|
| 1312 | + | c->oldbw = c->bw; |
|
| 1313 | + | c->bw = 0; |
|
| 1314 | + | c->isfloating = 1; |
|
| 1315 | + | resizeclient(c, c->mon->mx, c->mon->my, c->mon->mw, c->mon->mh); |
|
| 1316 | + | XRaiseWindow(dpy, c->win); |
|
| 1317 | + | } |
|
| 1318 | + | else { |
|
| 1319 | + | XChangeProperty(dpy, cme->window, netatom[NetWMState], XA_ATOM, 32, |
|
| 1320 | + | PropModeReplace, (unsigned char*)0, 0); |
|
| 1321 | + | c->isfloating = c->oldstate; |
|
| 1322 | + | c->bw = c->oldbw; |
|
| 1323 | + | c->x = c->oldx; |
|
| 1324 | + | c->y = c->oldy; |
|
| 1325 | + | c->w = c->oldw; |
|
| 1326 | + | c->h = c->oldh; |
|
| 1327 | + | resizeclient(c, c->x, c->y, c->w, c->h); |
|
| 1328 | + | arrange(c->mon); |
|
| 1329 | + | } |
|
| 1330 | + | } |
|
| 1331 | + | } |
|
| 1332 | + | ||
| 1333 | + | void |
|
| 1295 | 1334 | quit(const Arg *arg) { |
|
| 1296 | 1335 | running = False; |
|
| 1297 | 1336 | } |
|
| 1298 | 1337 | ||
| 1299 | 1338 | void |
|
| 1300 | 1339 | resize(Client *c, int x, int y, int w, int h, Bool interact) { |
|
| 1340 | + | if(applysizehints(c, &x, &y, &w, &h, interact)) |
|
| 1341 | + | resizeclient(c, x, y, w, h); |
|
| 1342 | + | } |
|
| 1343 | + | ||
| 1344 | + | void |
|
| 1345 | + | resizeclient(Client *c, int x, int y, int w, int h) { |
|
| 1301 | 1346 | XWindowChanges wc; |
|
| 1302 | 1347 | ||
| 1303 | - | if(applysizehints(c, &x, &y, &w, &h, interact)) { |
|
| 1304 | - | c->x = wc.x = x; |
|
| 1305 | - | c->y = wc.y = y; |
|
| 1306 | - | c->w = wc.width = w; |
|
| 1307 | - | c->h = wc.height = h; |
|
| 1308 | - | wc.border_width = c->bw; |
|
| 1309 | - | XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); |
|
| 1310 | - | configure(c); |
|
| 1311 | - | XSync(dpy, False); |
|
| 1312 | - | } |
|
| 1348 | + | c->oldx = c->x; c->x = wc.x = x; |
|
| 1349 | + | c->oldy = c->y; c->y = wc.y = y; |
|
| 1350 | + | c->oldw = c->w; c->w = wc.width = w; |
|
| 1351 | + | c->oldh = c->h; c->h = wc.height = h; |
|
| 1352 | + | wc.border_width = c->bw; |
|
| 1353 | + | XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); |
|
| 1354 | + | configure(c); |
|
| 1355 | + | XSync(dpy, False); |
|
| 1313 | 1356 | } |
|
| 1314 | 1357 | ||
| 1315 | 1358 | void |
|
| 1427 | 1470 | sendmon(Client *c, Monitor *m) { |
|
| 1428 | 1471 | if(c->mon == m) |
|
| 1429 | 1472 | return; |
|
| 1430 | - | unfocus(c); |
|
| 1473 | + | unfocus(c, True); |
|
| 1431 | 1474 | detach(c); |
|
| 1432 | 1475 | detachstack(c); |
|
| 1433 | 1476 | c->mon = m; |
|
| 1495 | 1538 | netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); |
|
| 1496 | 1539 | netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); |
|
| 1497 | 1540 | netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); |
|
| 1541 | + | netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); |
|
| 1498 | 1542 | /* init cursors */ |
|
| 1499 | 1543 | cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); |
|
| 1500 | 1544 | cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); |
|
| 1663 | 1707 | } |
|
| 1664 | 1708 | ||
| 1665 | 1709 | void |
|
| 1666 | - | unfocus(Client *c) { |
|
| 1710 | + | unfocus(Client *c, Bool setfocus) { |
|
| 1667 | 1711 | if(!c) |
|
| 1668 | 1712 | return; |
|
| 1669 | 1713 | grabbuttons(c, False); |
|
| 1670 | 1714 | XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]); |
|
| 1671 | - | XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); |
|
| 1715 | + | if(setfocus) |
|
| 1716 | + | XSetInputFocus(dpy, root, RevertToPointerRoot, CurrentTime); |
|
| 1672 | 1717 | } |
|
| 1673 | 1718 | ||
| 1674 | 1719 | void |
|