aewl

view main.c @ 541:08d3d329270a

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