55 #define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height) |
55 #define TEXTW(X) (textnw(X, strlen(X)) + dc.font.height) |
56 |
56 |
57 /* enums */ |
57 /* enums */ |
58 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ |
58 enum { CurNormal, CurResize, CurMove, CurLast }; /* cursor */ |
59 enum { ColBorder, ColFG, ColBG, ColLast }; /* color */ |
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 enum { WMProtocols, WMDelete, WMState, WMLast }; /* default atoms */ |
62 enum { WMProtocols, WMDelete, WMState, WMLast }; /* default atoms */ |
62 enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, |
63 enum { ClkTagBar, ClkLtSymbol, ClkStatusText, ClkWinTitle, |
63 ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ |
64 ClkClientWin, ClkRootWin, ClkLast }; /* clicks */ |
64 |
65 |
65 typedef union { |
66 typedef union { |
81 typedef struct Client Client; |
82 typedef struct Client Client; |
82 struct Client { |
83 struct Client { |
83 char name[256]; |
84 char name[256]; |
84 float mina, maxa; |
85 float mina, maxa; |
85 int x, y, w, h; |
86 int x, y, w, h; |
|
87 int oldx, oldy, oldw, oldh; |
86 int basew, baseh, incw, inch, maxw, maxh, minw, minh; |
88 int basew, baseh, incw, inch, maxw, maxh, minw, minh; |
87 int bw, oldbw; |
89 int bw, oldbw; |
88 unsigned int tags; |
90 unsigned int tags; |
89 Bool isfixed, isfloating, isurgent; |
91 Bool isfixed, isfloating, isurgent, oldstate; |
90 Client *next; |
92 Client *next; |
91 Client *snext; |
93 Client *snext; |
92 Monitor *mon; |
94 Monitor *mon; |
93 Window win; |
95 Window win; |
94 }; |
96 }; |
159 static void buttonpress(XEvent *e); |
161 static void buttonpress(XEvent *e); |
160 static void checkotherwm(void); |
162 static void checkotherwm(void); |
161 static void cleanup(void); |
163 static void cleanup(void); |
162 static void cleanupmon(Monitor *mon); |
164 static void cleanupmon(Monitor *mon); |
163 static void clearurgent(Client *c); |
165 static void clearurgent(Client *c); |
|
166 static void clientmessage(XEvent *e); |
164 static void configure(Client *c); |
167 static void configure(Client *c); |
165 static void configurenotify(XEvent *e); |
168 static void configurenotify(XEvent *e); |
166 static void configurerequest(XEvent *e); |
169 static void configurerequest(XEvent *e); |
167 static Monitor *createmon(void); |
170 static Monitor *createmon(void); |
168 static void destroynotify(XEvent *e); |
171 static void destroynotify(XEvent *e); |
198 static Client *nexttiled(Client *c); |
201 static Client *nexttiled(Client *c); |
199 static Monitor *ptrtomon(int x, int y); |
202 static Monitor *ptrtomon(int x, int y); |
200 static void propertynotify(XEvent *e); |
203 static void propertynotify(XEvent *e); |
201 static void quit(const Arg *arg); |
204 static void quit(const Arg *arg); |
202 static void resize(Client *c, int x, int y, int w, int h, Bool interact); |
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 static void resizemouse(const Arg *arg); |
207 static void resizemouse(const Arg *arg); |
204 static void restack(Monitor *m); |
208 static void restack(Monitor *m); |
205 static void run(void); |
209 static void run(void); |
206 static void scan(void); |
210 static void scan(void); |
207 static void sendmon(Client *c, Monitor *m); |
211 static void sendmon(Client *c, Monitor *m); |
218 static void tile(Monitor *); |
222 static void tile(Monitor *); |
219 static void togglebar(const Arg *arg); |
223 static void togglebar(const Arg *arg); |
220 static void togglefloating(const Arg *arg); |
224 static void togglefloating(const Arg *arg); |
221 static void toggletag(const Arg *arg); |
225 static void toggletag(const Arg *arg); |
222 static void toggleview(const Arg *arg); |
226 static void toggleview(const Arg *arg); |
223 static void unfocus(Client *c); |
227 static void unfocus(Client *c, Bool setfocus); |
224 static void unmanage(Client *c, Bool destroyed); |
228 static void unmanage(Client *c, Bool destroyed); |
225 static void unmapnotify(XEvent *e); |
229 static void unmapnotify(XEvent *e); |
226 static Bool updategeom(void); |
230 static Bool updategeom(void); |
227 static void updatebarpos(Monitor *m); |
231 static void updatebarpos(Monitor *m); |
228 static void updatebars(void); |
232 static void updatebars(void); |
247 static int bh, blw = 0; /* bar geometry */ |
251 static int bh, blw = 0; /* bar geometry */ |
248 static int (*xerrorxlib)(Display *, XErrorEvent *); |
252 static int (*xerrorxlib)(Display *, XErrorEvent *); |
249 static unsigned int numlockmask = 0; |
253 static unsigned int numlockmask = 0; |
250 static void (*handler[LASTEvent]) (XEvent *) = { |
254 static void (*handler[LASTEvent]) (XEvent *) = { |
251 [ButtonPress] = buttonpress, |
255 [ButtonPress] = buttonpress, |
|
256 [ClientMessage] = clientmessage, |
252 [ConfigureRequest] = configurerequest, |
257 [ConfigureRequest] = configurerequest, |
253 [ConfigureNotify] = configurenotify, |
258 [ConfigureNotify] = configurenotify, |
254 [DestroyNotify] = destroynotify, |
259 [DestroyNotify] = destroynotify, |
255 [EnterNotify] = enternotify, |
260 [EnterNotify] = enternotify, |
256 [Expose] = expose, |
261 [Expose] = expose, |
899 return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); |
905 return XQueryPointer(dpy, root, &dummy, &dummy, x, y, &di, &di, &dui); |
900 } |
906 } |
901 |
907 |
902 long |
908 long |
903 getstate(Window w) { |
909 getstate(Window w) { |
904 int format, status; |
910 int format; |
905 long result = -1; |
911 long result = -1; |
906 unsigned char *p = NULL; |
912 unsigned char *p = NULL; |
907 unsigned long n, extra; |
913 unsigned long n, extra; |
908 Atom real; |
914 Atom real; |
909 |
915 |
910 status = XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], |
916 if(XGetWindowProperty(dpy, w, wmatom[WMState], 0L, 2L, False, wmatom[WMState], |
911 &real, &format, &n, &extra, (unsigned char **)&p); |
917 &real, &format, &n, &extra, (unsigned char **)&p) != Success) |
912 if(status != Success) |
|
913 return -1; |
918 return -1; |
914 if(n != 0) |
919 if(n != 0) |
915 result = *p; |
920 result = *p; |
916 XFree(p); |
921 XFree(p); |
917 return result; |
922 return result; |
1137 configure(c); /* propagates border_width, if size doesn't change */ |
1143 configure(c); /* propagates border_width, if size doesn't change */ |
1138 updatesizehints(c); |
1144 updatesizehints(c); |
1139 XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); |
1145 XSelectInput(dpy, w, EnterWindowMask|FocusChangeMask|PropertyChangeMask|StructureNotifyMask); |
1140 grabbuttons(c, False); |
1146 grabbuttons(c, False); |
1141 if(!c->isfloating) |
1147 if(!c->isfloating) |
1142 c->isfloating = trans != None || c->isfixed; |
1148 c->isfloating = c->oldstate = trans != None || c->isfixed; |
1143 if(c->isfloating) |
1149 if(c->isfloating) |
1144 XRaiseWindow(dpy, c->win); |
1150 XRaiseWindow(dpy, c->win); |
1145 attach(c); |
1151 attach(c); |
1146 attachstack(c); |
1152 attachstack(c); |
1147 XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ |
1153 XMoveResizeWindow(dpy, c->win, c->x + 2 * sw, c->y, c->w, c->h); /* some windows require this */ |
1290 } |
1296 } |
1291 } |
1297 } |
1292 } |
1298 } |
1293 |
1299 |
1294 void |
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 quit(const Arg *arg) { |
1334 quit(const Arg *arg) { |
1296 running = False; |
1335 running = False; |
1297 } |
1336 } |
1298 |
1337 |
1299 void |
1338 void |
1300 resize(Client *c, int x, int y, int w, int h, Bool interact) { |
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 XWindowChanges wc; |
1346 XWindowChanges wc; |
1302 |
1347 |
1303 if(applysizehints(c, &x, &y, &w, &h, interact)) { |
1348 c->oldx = c->x; c->x = wc.x = x; |
1304 c->x = wc.x = x; |
1349 c->oldy = c->y; c->y = wc.y = y; |
1305 c->y = wc.y = y; |
1350 c->oldw = c->w; c->w = wc.width = w; |
1306 c->w = wc.width = w; |
1351 c->oldh = c->h; c->h = wc.height = h; |
1307 c->h = wc.height = h; |
1352 wc.border_width = c->bw; |
1308 wc.border_width = c->bw; |
1353 XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); |
1309 XConfigureWindow(dpy, c->win, CWX|CWY|CWWidth|CWHeight|CWBorderWidth, &wc); |
1354 configure(c); |
1310 configure(c); |
1355 XSync(dpy, False); |
1311 XSync(dpy, False); |
|
1312 } |
|
1313 } |
1356 } |
1314 |
1357 |
1315 void |
1358 void |
1316 resizemouse(const Arg *arg) { |
1359 resizemouse(const Arg *arg) { |
1317 int ocx, ocy; |
1360 int ocx, ocy; |
1493 wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); |
1536 wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); |
1494 wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); |
1537 wmatom[WMState] = XInternAtom(dpy, "WM_STATE", False); |
1495 netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); |
1538 netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); |
1496 netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); |
1539 netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); |
1497 netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); |
1540 netatom[NetWMState] = XInternAtom(dpy, "_NET_WM_STATE", False); |
|
1541 netatom[NetWMFullscreen] = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN", False); |
1498 /* init cursors */ |
1542 /* init cursors */ |
1499 cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); |
1543 cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); |
1500 cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); |
1544 cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); |
1501 cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); |
1545 cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); |
1502 /* init appearance */ |
1546 /* init appearance */ |
1661 arrange(selmon); |
1705 arrange(selmon); |
1662 } |
1706 } |
1663 } |
1707 } |
1664 |
1708 |
1665 void |
1709 void |
1666 unfocus(Client *c) { |
1710 unfocus(Client *c, Bool setfocus) { |
1667 if(!c) |
1711 if(!c) |
1668 return; |
1712 return; |
1669 grabbuttons(c, False); |
1713 grabbuttons(c, False); |
1670 XSetWindowBorder(dpy, c->win, dc.norm[ColBorder]); |
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 void |
1719 void |
1675 unmanage(Client *c, Bool destroyed) { |
1720 unmanage(Client *c, Bool destroyed) { |
1676 Monitor *m = c->mon; |
1721 Monitor *m = c->mon; |