aewl

view main.c @ 384:126e78129f1d

configurenotify remembers max geom now, and restores this if necessary, however it accepts to touch the max size on configurerequest, this shouldn't break fillscreen apps (tested with mplayer)
author Anselm R. Garbe <arg@10kloc.org>
date Tue, 29 Aug 2006 17:31:55 +0200
parents 175045ce7537
children 052657ff2e7b
line source
1 /*
2 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
3 * See LICENSE file for license details.
4 */
6 #include "dwm.h"
7 #include <errno.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <sys/select.h>
13 #include <X11/cursorfont.h>
14 #include <X11/keysym.h>
15 #include <X11/Xatom.h>
16 #include <X11/Xproto.h>
18 /* extern */
20 char stext[1024];
21 Bool *seltag;
22 int bx, by, bw, bh, bmw, mw, screen, sx, sy, sw, sh;
23 unsigned int ntags, numlockmask;
24 Atom wmatom[WMLast], netatom[NetLast];
25 Bool running = True;
26 Bool issel = True;
27 Client *clients = NULL;
28 Client *sel = NULL;
29 Cursor cursor[CurLast];
30 Display *dpy;
31 DC dc = {0};
32 Window root, barwin;
34 /* static */
36 static int (*xerrorxlib)(Display *, XErrorEvent *);
37 static Bool otherwm, readin;
39 static void
40 cleanup()
41 {
42 close(STDIN_FILENO);
43 while(sel) {
44 resize(sel, True, TopLeft);
45 unmanage(sel);
46 }
47 if(dc.font.set)
48 XFreeFontSet(dpy, dc.font.set);
49 else
50 XFreeFont(dpy, dc.font.xfont);
51 XUngrabKey(dpy, AnyKey, AnyModifier, root);
52 XFreePixmap(dpy, dc.drawable);
53 XFreeGC(dpy, dc.gc);
54 XDestroyWindow(dpy, barwin);
55 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime);
56 XSync(dpy, False);
57 }
59 static void
60 scan()
61 {
62 unsigned int i, num;
63 Window *wins, d1, d2;
64 XWindowAttributes wa;
66 wins = NULL;
67 if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) {
68 for(i = 0; i < num; i++) {
69 if(!XGetWindowAttributes(dpy, wins[i], &wa))
70 continue;
71 if(wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1))
72 continue;
73 if(wa.map_state == IsViewable)
74 manage(wins[i], &wa);
75 }
76 }
77 if(wins)
78 XFree(wins);
79 }
81 static void
82 setup()
83 {
84 int i, j;
85 unsigned int mask;
86 Window w;
87 XModifierKeymap *modmap;
88 XSetWindowAttributes wa;
90 /* init atoms */
91 wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False);
92 wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
93 netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False);
94 netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False);
95 XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32,
96 PropModeReplace, (unsigned char *) netatom, NetLast);
98 /* init cursors */
99 cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr);
100 cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing);
101 cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur);
103 modmap = XGetModifierMapping(dpy);
104 for (i = 0; i < 8; i++) {
105 for (j = 0; j < modmap->max_keypermod; j++) {
106 if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock))
107 numlockmask = (1 << i);
108 }
109 }
110 XFree(modmap);
112 wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask | EnterWindowMask | LeaveWindowMask;
113 wa.cursor = cursor[CurNormal];
114 XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa);
116 grabkeys();
117 initrregs();
119 for(ntags = 0; tags[ntags]; ntags++);
120 seltag = emallocz(sizeof(Bool) * ntags);
121 seltag[0] = True;
123 /* style */
124 dc.norm[ColBG] = getcolor(NORMBGCOLOR);
125 dc.norm[ColFG] = getcolor(NORMFGCOLOR);
126 dc.sel[ColBG] = getcolor(SELBGCOLOR);
127 dc.sel[ColFG] = getcolor(SELFGCOLOR);
128 dc.status[ColBG] = getcolor(STATUSBGCOLOR);
129 dc.status[ColFG] = getcolor(STATUSFGCOLOR);
130 setfont(FONT);
132 bmw = textw(FLOATSYMBOL) > textw(TILESYMBOL) ? textw(FLOATSYMBOL) : textw(TILESYMBOL);
133 sx = sy = 0;
134 sw = DisplayWidth(dpy, screen);
135 sh = DisplayHeight(dpy, screen);
136 mw = (sw * MASTERW) / 100;
138 bx = by = 0;
139 bw = sw;
140 dc.h = bh = dc.font.height + 2;
141 wa.override_redirect = 1;
142 wa.background_pixmap = ParentRelative;
143 wa.event_mask = ButtonPressMask | ExposureMask;
144 barwin = XCreateWindow(dpy, root, bx, by, bw, bh, 0, DefaultDepth(dpy, screen),
145 CopyFromParent, DefaultVisual(dpy, screen),
146 CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa);
147 XDefineCursor(dpy, barwin, cursor[CurNormal]);
148 XMapRaised(dpy, barwin);
150 dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen));
151 dc.gc = XCreateGC(dpy, root, 0, 0);
152 XSetLineAttributes(dpy, dc.gc, 1, LineSolid, CapButt, JoinMiter);
154 issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask);
155 strcpy(stext, "dwm-"VERSION);
156 }
158 /*
159 * Startup Error handler to check if another window manager
160 * is already running.
161 */
162 static int
163 xerrorstart(Display *dsply, XErrorEvent *ee)
164 {
165 otherwm = True;
166 return -1;
167 }
169 /* extern */
171 int
172 getproto(Window w)
173 {
174 int i, format, protos, status;
175 unsigned long extra, res;
176 Atom *protocols, real;
178 protos = 0;
179 status = XGetWindowProperty(dpy, w, wmatom[WMProtocols], 0L, 20L, False,
180 XA_ATOM, &real, &format, &res, &extra, (unsigned char **)&protocols);
181 if(status != Success || protocols == 0)
182 return protos;
183 for(i = 0; i < res; i++)
184 if(protocols[i] == wmatom[WMDelete])
185 protos |= PROTODELWIN;
186 free(protocols);
187 return protos;
188 }
190 void
191 sendevent(Window w, Atom a, long value)
192 {
193 XEvent e;
195 e.type = ClientMessage;
196 e.xclient.window = w;
197 e.xclient.message_type = a;
198 e.xclient.format = 32;
199 e.xclient.data.l[0] = value;
200 e.xclient.data.l[1] = CurrentTime;
201 XSendEvent(dpy, w, False, NoEventMask, &e);
202 XSync(dpy, False);
203 }
205 void
206 quit(Arg *arg)
207 {
208 readin = running = False;
209 }
211 /*
212 * There's no way to check accesses to destroyed windows, thus those cases are
213 * ignored (especially on UnmapNotify's). Other types of errors call Xlibs
214 * default error handler, which calls exit().
215 */
216 int
217 xerror(Display *dpy, XErrorEvent *ee)
218 {
219 if(ee->error_code == BadWindow
220 || (ee->request_code == X_SetInputFocus && ee->error_code == BadMatch)
221 || (ee->request_code == X_PolyText8 && ee->error_code == BadDrawable)
222 || (ee->request_code == X_PolyFillRectangle && ee->error_code == BadDrawable)
223 || (ee->request_code == X_PolySegment && ee->error_code == BadDrawable)
224 || (ee->request_code == X_ConfigureWindow && ee->error_code == BadMatch)
225 || (ee->request_code == X_GrabKey && ee->error_code == BadAccess))
226 return 0;
227 fprintf(stderr, "dwm: fatal error: request code=%d, error code=%d\n",
228 ee->request_code, ee->error_code);
229 return xerrorxlib(dpy, ee); /* may call exit() */
230 }
232 int
233 main(int argc, char *argv[])
234 {
235 int r, xfd;
236 fd_set rd;
238 if(argc == 2 && !strncmp("-v", argv[1], 3)) {
239 fputs("dwm-"VERSION", (C)opyright MMVI Anselm R. Garbe\n", stdout);
240 exit(EXIT_SUCCESS);
241 }
242 else if(argc != 1)
243 eprint("usage: dwm [-v]\n");
245 dpy = XOpenDisplay(0);
246 if(!dpy)
247 eprint("dwm: cannot open display\n");
249 xfd = ConnectionNumber(dpy);
250 screen = DefaultScreen(dpy);
251 root = RootWindow(dpy, screen);
253 otherwm = False;
254 XSetErrorHandler(xerrorstart);
255 /* this causes an error if some other window manager is running */
256 XSelectInput(dpy, root, SubstructureRedirectMask);
257 XSync(dpy, False);
259 if(otherwm)
260 eprint("dwm: another window manager is already running\n");
262 XSync(dpy, False);
263 XSetErrorHandler(NULL);
264 xerrorxlib = XSetErrorHandler(xerror);
265 XSync(dpy, False);
267 setup();
268 drawstatus();
269 scan();
271 /* main event loop, also reads status text from stdin */
272 XSync(dpy, False);
273 procevent();
274 readin = True;
275 while(running) {
276 FD_ZERO(&rd);
277 if(readin)
278 FD_SET(STDIN_FILENO, &rd);
279 FD_SET(xfd, &rd);
280 r = select(xfd + 1, &rd, NULL, NULL, NULL);
281 if((r == -1) && (errno == EINTR))
282 continue;
283 if(r > 0) {
284 if(readin && FD_ISSET(STDIN_FILENO, &rd)) {
285 readin = NULL != fgets(stext, sizeof(stext), stdin);
286 if(readin)
287 stext[strlen(stext) - 1] = 0;
288 else
289 strcpy(stext, "broken pipe");
290 drawstatus();
291 }
292 }
293 else if(r < 0)
294 eprint("select failed\n");
295 procevent();
296 }
297 cleanup();
298 XCloseDisplay(dpy);
300 return 0;
301 }