12 #include <sys/select.h> |
12 #include <sys/select.h> |
13 #include <X11/cursorfont.h> |
13 #include <X11/cursorfont.h> |
14 #include <X11/keysym.h> |
14 #include <X11/keysym.h> |
15 #include <X11/Xatom.h> |
15 #include <X11/Xatom.h> |
16 #include <X11/Xproto.h> |
16 #include <X11/Xproto.h> |
17 |
|
18 /* static */ |
|
19 |
|
20 static int (*xerrorxlib)(Display *, XErrorEvent *); |
|
21 static Bool otherwm, readin; |
|
22 |
|
23 static void |
|
24 cleanup() |
|
25 { |
|
26 close(STDIN_FILENO); |
|
27 while(sel) { |
|
28 resize(sel, True, TopLeft); |
|
29 unmanage(sel); |
|
30 } |
|
31 if(dc.font.set) |
|
32 XFreeFontSet(dpy, dc.font.set); |
|
33 else |
|
34 XFreeFont(dpy, dc.font.xfont); |
|
35 XUngrabKey(dpy, AnyKey, AnyModifier, root); |
|
36 XFreePixmap(dpy, dc.drawable); |
|
37 XFreeGC(dpy, dc.gc); |
|
38 XDestroyWindow(dpy, barwin); |
|
39 XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); |
|
40 XSync(dpy, False); |
|
41 } |
|
42 |
|
43 static void |
|
44 scan() |
|
45 { |
|
46 unsigned int i, num; |
|
47 Window *wins, d1, d2; |
|
48 XWindowAttributes wa; |
|
49 |
|
50 wins = NULL; |
|
51 if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { |
|
52 for(i = 0; i < num; i++) { |
|
53 if(!XGetWindowAttributes(dpy, wins[i], &wa)) |
|
54 continue; |
|
55 if(wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) |
|
56 continue; |
|
57 if(wa.map_state == IsViewable) |
|
58 manage(wins[i], &wa); |
|
59 } |
|
60 } |
|
61 if(wins) |
|
62 XFree(wins); |
|
63 } |
|
64 |
|
65 /* |
|
66 * Startup Error handler to check if another window manager |
|
67 * is already running. |
|
68 */ |
|
69 static int |
|
70 xerrorstart(Display *dsply, XErrorEvent *ee) |
|
71 { |
|
72 otherwm = True; |
|
73 return -1; |
|
74 } |
|
75 |
17 |
76 /* extern */ |
18 /* extern */ |
77 |
19 |
78 char stext[1024]; |
20 char stext[1024]; |
79 Bool *seltag; |
21 Bool *seltag; |
87 Cursor cursor[CurLast]; |
29 Cursor cursor[CurLast]; |
88 Display *dpy; |
30 Display *dpy; |
89 DC dc = {0}; |
31 DC dc = {0}; |
90 Window root, barwin; |
32 Window root, barwin; |
91 |
33 |
|
34 /* static */ |
|
35 |
|
36 static int (*xerrorxlib)(Display *, XErrorEvent *); |
|
37 static Bool otherwm, readin; |
|
38 |
|
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 } |
|
58 |
|
59 static void |
|
60 scan() |
|
61 { |
|
62 unsigned int i, num; |
|
63 Window *wins, d1, d2; |
|
64 XWindowAttributes wa; |
|
65 |
|
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 } |
|
80 |
|
81 static void |
|
82 setup() |
|
83 { |
|
84 int i, j; |
|
85 unsigned int mask; |
|
86 Window w; |
|
87 XModifierKeymap *modmap; |
|
88 XSetWindowAttributes wa; |
|
89 |
|
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); |
|
97 |
|
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); |
|
102 |
|
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); |
|
111 |
|
112 wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask | EnterWindowMask | LeaveWindowMask; |
|
113 wa.cursor = cursor[CurNormal]; |
|
114 XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); |
|
115 |
|
116 grabkeys(); |
|
117 initrregs(); |
|
118 |
|
119 for(ntags = 0; tags[ntags]; ntags++); |
|
120 seltag = emallocz(sizeof(Bool) * ntags); |
|
121 seltag[0] = True; |
|
122 |
|
123 /* style */ |
|
124 dc.bg = getcolor(BGCOLOR); |
|
125 dc.fg = getcolor(FGCOLOR); |
|
126 dc.border = getcolor(BORDERCOLOR); |
|
127 setfont(FONT); |
|
128 |
|
129 sx = sy = 0; |
|
130 sw = DisplayWidth(dpy, screen); |
|
131 sh = DisplayHeight(dpy, screen); |
|
132 mw = (sw * MASTERW) / 100; |
|
133 |
|
134 bx = by = 0; |
|
135 bw = sw; |
|
136 dc.h = bh = dc.font.height + 4; |
|
137 wa.override_redirect = 1; |
|
138 wa.background_pixmap = ParentRelative; |
|
139 wa.event_mask = ButtonPressMask | ExposureMask; |
|
140 barwin = XCreateWindow(dpy, root, bx, by, bw, bh, 0, DefaultDepth(dpy, screen), |
|
141 CopyFromParent, DefaultVisual(dpy, screen), |
|
142 CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); |
|
143 XDefineCursor(dpy, barwin, cursor[CurNormal]); |
|
144 XMapRaised(dpy, barwin); |
|
145 |
|
146 dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); |
|
147 dc.gc = XCreateGC(dpy, root, 0, 0); |
|
148 |
|
149 issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); |
|
150 |
|
151 strcpy(stext, "dwm-"VERSION); |
|
152 } |
|
153 |
|
154 /* |
|
155 * Startup Error handler to check if another window manager |
|
156 * is already running. |
|
157 */ |
|
158 static int |
|
159 xerrorstart(Display *dsply, XErrorEvent *ee) |
|
160 { |
|
161 otherwm = True; |
|
162 return -1; |
|
163 } |
|
164 |
|
165 /* extern */ |
|
166 |
92 int |
167 int |
93 getproto(Window w) |
168 getproto(Window w) |
94 { |
169 { |
95 int i, format, protos, status; |
170 int i, format, protos, status; |
96 unsigned long extra, res; |
171 unsigned long extra, res; |
187 XSync(dpy, False); |
258 XSync(dpy, False); |
188 XSetErrorHandler(NULL); |
259 XSetErrorHandler(NULL); |
189 xerrorxlib = XSetErrorHandler(xerror); |
260 xerrorxlib = XSetErrorHandler(xerror); |
190 XSync(dpy, False); |
261 XSync(dpy, False); |
191 |
262 |
192 /* init atoms */ |
263 setup(); |
193 wmatom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); |
|
194 wmatom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); |
|
195 netatom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); |
|
196 netatom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); |
|
197 XChangeProperty(dpy, root, netatom[NetSupported], XA_ATOM, 32, |
|
198 PropModeReplace, (unsigned char *) netatom, NetLast); |
|
199 |
|
200 /* init cursors */ |
|
201 cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); |
|
202 cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); |
|
203 cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); |
|
204 |
|
205 modmap = XGetModifierMapping(dpy); |
|
206 for (i = 0; i < 8; i++) { |
|
207 for (j = 0; j < modmap->max_keypermod; j++) { |
|
208 if(modmap->modifiermap[i * modmap->max_keypermod + j] == XKeysymToKeycode(dpy, XK_Num_Lock)) |
|
209 numlockmask = (1 << i); |
|
210 } |
|
211 } |
|
212 XFree(modmap); |
|
213 |
|
214 wa.event_mask = SubstructureRedirectMask | SubstructureNotifyMask | EnterWindowMask | LeaveWindowMask; |
|
215 wa.cursor = cursor[CurNormal]; |
|
216 XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); |
|
217 |
|
218 grabkeys(); |
|
219 initrregs(); |
|
220 |
|
221 for(ntags = 0; tags[ntags]; ntags++); |
|
222 seltag = emallocz(sizeof(Bool) * ntags); |
|
223 seltag[0] = True; |
|
224 |
|
225 /* style */ |
|
226 dc.bg = getcolor(BGCOLOR); |
|
227 dc.fg = getcolor(FGCOLOR); |
|
228 dc.border = getcolor(BORDERCOLOR); |
|
229 setfont(FONT); |
|
230 |
|
231 sx = sy = 0; |
|
232 sw = DisplayWidth(dpy, screen); |
|
233 sh = DisplayHeight(dpy, screen); |
|
234 mw = (sw * MASTERW) / 100; |
|
235 |
|
236 bx = by = 0; |
|
237 bw = sw; |
|
238 dc.h = bh = dc.font.height + 4; |
|
239 wa.override_redirect = 1; |
|
240 wa.background_pixmap = ParentRelative; |
|
241 wa.event_mask = ButtonPressMask | ExposureMask; |
|
242 barwin = XCreateWindow(dpy, root, bx, by, bw, bh, 0, DefaultDepth(dpy, screen), |
|
243 CopyFromParent, DefaultVisual(dpy, screen), |
|
244 CWOverrideRedirect | CWBackPixmap | CWEventMask, &wa); |
|
245 XDefineCursor(dpy, barwin, cursor[CurNormal]); |
|
246 XMapRaised(dpy, barwin); |
|
247 |
|
248 dc.drawable = XCreatePixmap(dpy, root, sw, bh, DefaultDepth(dpy, screen)); |
|
249 dc.gc = XCreateGC(dpy, root, 0, 0); |
|
250 |
|
251 strcpy(stext, "dwm-"VERSION); |
|
252 drawstatus(); |
264 drawstatus(); |
253 |
|
254 issel = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); |
|
255 |
|
256 scan(); |
265 scan(); |
257 |
266 |
258 /* main event loop, also reads status text from stdin */ |
267 /* main event loop, also reads status text from stdin */ |
259 XSync(dpy, False); |
268 XSync(dpy, False); |
260 procevent(); |
269 procevent(); |
262 while(running) { |
271 while(running) { |
263 FD_ZERO(&rd); |
272 FD_ZERO(&rd); |
264 if(readin) |
273 if(readin) |
265 FD_SET(STDIN_FILENO, &rd); |
274 FD_SET(STDIN_FILENO, &rd); |
266 FD_SET(xfd, &rd); |
275 FD_SET(xfd, &rd); |
267 i = select(xfd + 1, &rd, NULL, NULL, NULL); |
276 r = select(xfd + 1, &rd, NULL, NULL, NULL); |
268 if((i == -1) && (errno == EINTR)) |
277 if((r == -1) && (errno == EINTR)) |
269 continue; |
278 continue; |
270 if(i > 0) { |
279 if(r > 0) { |
271 if(readin && FD_ISSET(STDIN_FILENO, &rd)) { |
280 if(readin && FD_ISSET(STDIN_FILENO, &rd)) { |
272 readin = NULL != fgets(stext, sizeof(stext), stdin); |
281 readin = NULL != fgets(stext, sizeof(stext), stdin); |
273 if(readin) |
282 if(readin) |
274 stext[strlen(stext) - 1] = 0; |
283 stext[strlen(stext) - 1] = 0; |
275 else |
284 else |
276 strcpy(stext, "broken pipe"); |
285 strcpy(stext, "broken pipe"); |
277 drawstatus(); |
286 drawstatus(); |
278 } |
287 } |
279 } |
288 } |
280 else if(i < 0) |
289 else if(r < 0) |
281 eprint("select failed\n"); |
290 eprint("select failed\n"); |
282 procevent(); |
291 procevent(); |
283 } |
292 } |
284 cleanup(); |
293 cleanup(); |
285 XCloseDisplay(dpy); |
294 XCloseDisplay(dpy); |