Xinqi Bao's Git
1 /* See LICENSE file for copyright and license details. */
9 #include <sys/select.h>
10 #include <X11/cursorfont.h>
11 #include <X11/keysym.h>
12 #include <X11/Xatom.h>
13 #include <X11/Xproto.h>
14 #include <X11/Xutil.h>
19 int screen
, sx
, sy
, sw
, sh
, wax
, way
, waw
, wah
;
21 unsigned int numlockmask
= 0;
22 Atom wmatom
[WMLast
], netatom
[NetLast
];
24 Bool selscreen
= True
;
25 Client
*clients
= NULL
;
28 Cursor cursor
[CurLast
];
34 static int (*xerrorxlib
)(Display
*, XErrorEvent
*);
35 static Bool otherwm
, readin
;
36 static Bool running
= True
;
46 XFreeFontSet(dpy
, dc
.font
.set
);
48 XFreeFont(dpy
, dc
.font
.xfont
);
49 XUngrabKey(dpy
, AnyKey
, AnyModifier
, root
);
50 XFreePixmap(dpy
, dc
.drawable
);
52 XDestroyWindow(dpy
, barwin
);
53 XFreeCursor(dpy
, cursor
[CurNormal
]);
54 XFreeCursor(dpy
, cursor
[CurResize
]);
55 XFreeCursor(dpy
, cursor
[CurMove
]);
56 XSetInputFocus(dpy
, PointerRoot
, RevertToPointerRoot
, CurrentTime
);
65 unsigned char *p
= NULL
;
66 unsigned long n
, extra
;
69 status
= XGetWindowProperty(dpy
, w
, wmatom
[WMState
], 0L, 2L, False
, wmatom
[WMState
],
70 &real
, &format
, &n
, &extra
, (unsigned char **)&p
);
86 if(XQueryTree(dpy
, root
, &d1
, &d2
, &wins
, &num
)) {
87 for(i
= 0; i
< num
; i
++) {
88 if(!XGetWindowAttributes(dpy
, wins
[i
], &wa
)
89 || wa
.override_redirect
|| XGetTransientForHint(dpy
, wins
[i
], &d1
))
91 if(wa
.map_state
== IsViewable
|| getstate(wins
[i
]) == IconicState
)
94 for(i
= 0; i
< num
; i
++) { /* now the transients */
95 if(!XGetWindowAttributes(dpy
, wins
[i
], &wa
))
97 if(XGetTransientForHint(dpy
, wins
[i
], &d1
)
98 && (wa
.map_state
== IsViewable
|| getstate(wins
[i
]) == IconicState
))
111 XModifierKeymap
*modmap
;
112 XSetWindowAttributes wa
;
115 wmatom
[WMProtocols
] = XInternAtom(dpy
, "WM_PROTOCOLS", False
);
116 wmatom
[WMDelete
] = XInternAtom(dpy
, "WM_DELETE_WINDOW", False
);
117 wmatom
[WMName
] = XInternAtom(dpy
, "WM_NAME", False
);
118 wmatom
[WMState
] = XInternAtom(dpy
, "WM_STATE", False
);
119 netatom
[NetSupported
] = XInternAtom(dpy
, "_NET_SUPPORTED", False
);
120 netatom
[NetWMName
] = XInternAtom(dpy
, "_NET_WM_NAME", False
);
121 XChangeProperty(dpy
, root
, netatom
[NetSupported
], XA_ATOM
, 32,
122 PropModeReplace
, (unsigned char *) netatom
, NetLast
);
124 cursor
[CurNormal
] = XCreateFontCursor(dpy
, XC_left_ptr
);
125 cursor
[CurResize
] = XCreateFontCursor(dpy
, XC_sizing
);
126 cursor
[CurMove
] = XCreateFontCursor(dpy
, XC_fleur
);
127 /* init modifier map */
128 modmap
= XGetModifierMapping(dpy
);
129 for (i
= 0; i
< 8; i
++)
130 for (j
= 0; j
< modmap
->max_keypermod
; j
++) {
131 if(modmap
->modifiermap
[i
* modmap
->max_keypermod
+ j
]
132 == XKeysymToKeycode(dpy
, XK_Num_Lock
))
133 numlockmask
= (1 << i
);
135 XFreeModifiermap(modmap
);
136 /* select for events */
137 wa
.event_mask
= SubstructureRedirectMask
| SubstructureNotifyMask
138 | EnterWindowMask
| LeaveWindowMask
| StructureNotifyMask
;
139 wa
.cursor
= cursor
[CurNormal
];
140 XChangeWindowAttributes(dpy
, root
, CWEventMask
| CWCursor
, &wa
);
141 XSelectInput(dpy
, root
, wa
.event_mask
);
144 for(ntags
= 0; tags
[ntags
]; ntags
++);
145 seltags
= emallocz(sizeof(Bool
) * ntags
);
149 sw
= DisplayWidth(dpy
, screen
);
150 sh
= DisplayHeight(dpy
, screen
);
153 /* multihead support */
154 selscreen
= XQueryPointer(dpy
, root
, &w
, &w
, &i
, &i
, &i
, &i
, &mask
);
158 * Startup Error handler to check if another window manager
159 * is already running.
162 xerrorstart(Display
*dsply
, XErrorEvent
*ee
) {
170 gettextprop(Window w
, Atom atom
, char *text
, unsigned int size
) {
175 if(!text
|| size
== 0)
178 XGetTextProperty(dpy
, w
, &name
, atom
);
181 if(name
.encoding
== XA_STRING
)
182 strncpy(text
, (char *)name
.value
, size
- 1);
184 if(XmbTextPropertyToTextList(dpy
, &name
, &list
, &n
) >= Success
187 strncpy(text
, *list
, size
- 1);
188 XFreeStringList(list
);
191 text
[size
- 1] = '\0';
197 quit(const char *arg
) {
198 readin
= running
= False
;
201 /* There's no way to check accesses to destroyed windows, thus those cases are
202 * ignored (especially on UnmapNotify's). Other types of errors call Xlibs
203 * default error handler, which may call exit.
206 xerror(Display
*dpy
, XErrorEvent
*ee
) {
207 if(ee
->error_code
== BadWindow
208 || (ee
->request_code
== X_SetInputFocus
&& ee
->error_code
== BadMatch
)
209 || (ee
->request_code
== X_PolyText8
&& ee
->error_code
== BadDrawable
)
210 || (ee
->request_code
== X_PolyFillRectangle
&& ee
->error_code
== BadDrawable
)
211 || (ee
->request_code
== X_PolySegment
&& ee
->error_code
== BadDrawable
)
212 || (ee
->request_code
== X_ConfigureWindow
&& ee
->error_code
== BadMatch
)
213 || (ee
->request_code
== X_GrabKey
&& ee
->error_code
== BadAccess
)
214 || (ee
->request_code
== X_CopyArea
&& ee
->error_code
== BadDrawable
))
216 fprintf(stderr
, "dwm: fatal error: request code=%d, error code=%d\n",
217 ee
->request_code
, ee
->error_code
);
218 return xerrorxlib(dpy
, ee
); /* may call exit */
222 main(int argc
, char *argv
[]) {
228 if(argc
== 2 && !strcmp("-v", argv
[1]))
229 eprint("dwm-"VERSION
", © 2006-2007 A. R. Garbe, S. van Dijk, J. Salmi, P. Hruby, S. Nagy\n");
231 eprint("usage: dwm [-v]\n");
232 setlocale(LC_CTYPE
, "");
233 if(!(dpy
= XOpenDisplay(0)))
234 eprint("dwm: cannot open display\n");
235 xfd
= ConnectionNumber(dpy
);
236 screen
= DefaultScreen(dpy
);
237 root
= RootWindow(dpy
, screen
);
239 XSetErrorHandler(xerrorstart
);
240 /* this causes an error if some other window manager is running */
241 XSelectInput(dpy
, root
, SubstructureRedirectMask
);
244 eprint("dwm: another window manager is already running\n");
247 XSetErrorHandler(NULL
);
248 xerrorxlib
= XSetErrorHandler(xerror
);
254 /* main event loop, also reads status text from stdin */
260 FD_SET(STDIN_FILENO
, &rd
);
262 if(select(xfd
+ 1, &rd
, NULL
, NULL
, NULL
) == -1) {
265 eprint("select failed\n");
267 if(FD_ISSET(STDIN_FILENO
, &rd
)) {
268 switch(r
= read(STDIN_FILENO
, stext
, sizeof stext
- 1)) {
270 strncpy(stext
, strerror(errno
), sizeof stext
- 1);
271 stext
[sizeof stext
- 1] = '\0';
275 strncpy(stext
, "EOF", 4);
279 for(stext
[r
] = '\0', p
= stext
+ strlen(stext
) - 1; p
>= stext
&& *p
== '\n'; *p
-- = '\0');
280 for(; p
>= stext
&& *p
!= '\n'; --p
);
282 strncpy(stext
, p
+ 1, sizeof stext
);
286 while(XPending(dpy
)) {
287 XNextEvent(dpy
, &ev
);
289 (handler
[ev
.type
])(&ev
); /* call handler */