5 /* Copyright (c) 1994-1996 David Hogan, see README for licence details */
12 #include <X11/Xutil.h>
13 #include <X11/Xatom.h>
14 #include <X11/extensions/shape.h>
21 manage(Client *c, int mapped)
23 int fixsize, dohide, doreshape, state;
27 XSetWindowAttributes attrs;
29 trace("manage", c, 0);
30 XSelectInput(dpy, c->window, ColormapChangeMask | EnterWindowMask | PropertyChangeMask | FocusChangeMask | KeyPressMask);
32 /* Get loads of hints */
34 if(XGetClassHint(dpy, c->window, &class) != 0){ /* ``Success'' */
35 c->instance = class.res_name;
36 c->class = class.res_class;
39 c->is9term = strstr(c->class, "term") || strstr(c->class, "Term");
48 c->iconname = getprop(c->window, XA_WM_ICON_NAME);
49 c->name = getprop(c->window, XA_WM_NAME);
52 hints = XGetWMHints(dpy, c->window);
53 if(XGetWMNormalHints(dpy, c->window, &c->size, &msize) == 0 || c->size.flags == 0)
54 c->size.flags = PSize; /* not specified - punt */
60 c->hold = getiprop(c->window, _rio_hold_mode);
62 /* Figure out what to do with the window from hints */
64 if(!getstate(c->window, &state))
65 state = hints ? hints->initial_state : NormalState;
66 dohide = (state == IconicState);
69 if((c->size.flags & (USSize|PSize)))
71 if((c->size.flags & (PMinSize|PMaxSize)) == (PMinSize|PMaxSize) && c->size.min_width == c->size.max_width && c->size.min_height == c->size.max_height)
75 if(c->size.flags & USPosition)
77 if(dohide && (c->size.flags & PPosition))
84 if(c->size.flags & PBaseSize){
85 c->min_dx = c->size.base_width;
86 c->min_dy = c->size.base_height;
88 else if(c->size.flags & PMinSize){
89 c->min_dx = c->size.min_width;
90 c->min_dy = c->size.min_height;
97 c->min_dx = c->min_dy = 0;
105 if(0) fprintf(stderr, "in doreshape is9term=%d fixsize=%d, x=%d, y=%d, min_dx=%d, min_dy=%d, dx=%d, dy=%d\n",
106 c->is9term, fixsize, c->x, c->y, c->min_dx, c->min_dy, c->dx, c->dy);
107 if(current && current->screen == c->screen)
108 cmapnofocus(c->screen);
109 if(!c->is9term && c->x==0 && c->y==0){
112 c->x = 20*nwin+BORDER;
113 c->y = 20*nwin+BORDER;
118 if(c->is9term && !(fixsize ? drag(c, Button3) : sweep(c, Button3))){
119 ScreenInfo *screen = c->screen;
120 XKillClient(dpy, c->window);
122 if(current && current->screen == screen)
128 attrs.border_pixel = c->screen->black;
129 attrs.background_pixel = c->screen->white;
130 attrs.colormap = c->screen->def_cmap;
131 c->parent = XCreateWindow(dpy, c->screen->root,
132 c->x - BORDER, c->y - BORDER,
133 c->dx + 2*BORDER, c->dy + 2*BORDER,
138 CWBackPixel | CWBorderPixel | CWColormap,
141 XSelectInput(dpy, c->parent, SubstructureRedirectMask | SubstructureNotifyMask|ButtonPressMask| PointerMotionMask|LeaveWindowMask|KeyPressMask);
144 if(doreshape && !fixsize)
145 XResizeWindow(dpy, c->window, c->dx, c->dy);
146 XSetWindowBorderWidth(dpy, c->window, 0);
149 * To have something more than only a big white or black border
150 * XXX should replace this by a pattern in the white or black
151 * such that we can see the border also if all our
152 * windows are black and/or white
153 * (black (or white) border around black (or white) window
154 * is not very helpful.
156 if(c->screen->depth <= 8){
157 XSetWindowBorderWidth(dpy, c->parent, 1);
160 XReparentWindow(dpy, c->window, c->parent, BORDER, BORDER);
163 XShapeSelectInput(dpy, c->window, ShapeNotifyMask);
164 ignore_badwindow = 1; /* magic */
166 ignore_badwindow = 0;
169 XAddToSaveSet(dpy, c->window);
173 XMapWindow(dpy, c->window);
174 XMapWindow(dpy, c->parent);
175 XUnmapWindow(dpy, c->screen->sweepwin);
176 if(nostalgia || doreshape)
178 else if(c->trans != None && current && current->window == c->trans)
182 setstate(c, NormalState);
184 if(current && (current != c))
189 * If we swept the window, let's send a resize event to the
190 * guy who just got resized. It's not clear whether the apps
191 * should notice their new size via other means. Try as I might,
192 * I can't find a way to have them notice during initdraw, so
193 * I solve the problem this way instead. -rsc
201 scanwins(ScreenInfo *s)
203 unsigned int i, nwins;
205 Window dw1, dw2, *wins;
206 XWindowAttributes attr;
208 XQueryTree(dpy, s->root, &dw1, &dw2, &wins, &nwins);
209 for(i = 0; i < nwins; i++){
210 XGetWindowAttributes(dpy, wins[i], &attr);
211 if(attr.override_redirect || wins[i] == s->menuwin)
213 c = getclient(wins[i], 1);
214 if(c != 0 && c->window == wins[i] && !c->init){
219 c->border = attr.border_width;
222 if(attr.map_state == IsViewable)
226 XFree((void *) wins); /* cast is to shut stoopid compiler up */
235 if(XGetTransientForHint(dpy, c->window, &trans) != 0)
244 XUnmapWindow(dpy, c->parent);
245 XReparentWindow(dpy, c->window, c->screen->root, c->x, c->y);
246 XRemoveFromSaveSet(dpy, c->window);
247 setstate(c, WithdrawnState);
249 /* flush any errors */
250 ignore_badwindow = 1;
252 ignore_badwindow = 0;
256 installcmap(ScreenInfo *s, Colormap cmap)
259 XInstallColormap(dpy, s->def_cmap);
261 XInstallColormap(dpy, cmap);
272 else if(c->ncmapwins != 0){
274 for(i = c->ncmapwins-1; i >= 0; i--){
275 installcmap(c->screen, c->wmcmaps[i]);
276 if(c->cmapwins[i] == c->window)
280 installcmap(c->screen, c->cmap);
282 else if(c->trans != None && (cc = getclient(c->trans, 0)) != 0 && cc->ncmapwins != 0)
285 installcmap(c->screen, c->cmap);
289 cmapnofocus(ScreenInfo *s)
291 installcmap(s, None);
299 XWindowAttributes attr;
302 ignore_badwindow = 1;
303 XGetWindowAttributes(dpy, c->window, &attr);
304 c->cmap = attr.colormap;
306 ignore_badwindow = 0;
309 n = _getprop(c->window, wm_colormaps, XA_WINDOW, 100L, (void*)&cw);
310 if(c->ncmapwins != 0){
311 XFree((char *)c->cmapwins);
312 free((char *)c->wmcmaps);
322 c->wmcmaps = (Colormap*)malloc(n*sizeof(Colormap));
323 for(i = 0; i < n; i++){
324 if(cw[i] == c->window)
325 c->wmcmaps[i] = c->cmap;
327 /* flush any errors (e.g., caused by mozilla tabs) */
328 ignore_badwindow = 1;
329 XSelectInput(dpy, cw[i], ColormapChangeMask);
330 XGetWindowAttributes(dpy, cw[i], &attr);
331 c->wmcmaps[i] = attr.colormap;
333 ignore_badwindow = 0;
345 else if(c->name != 0)
347 else if(c->instance != 0)
349 else if(c->class != 0)
353 if((p = index(label, ':')) != 0)
365 /* don't try to add a border if the window is non-rectangular */
366 rect = XShapeGetRectangles(dpy, c->window, ShapeBounding, &n, &order);
368 XShapeCombineShape(dpy, c->parent, ShapeBounding, BORDER, BORDER,
369 c->window, ShapeBounding, ShapeSet);
375 _getprop(Window w, Atom a, Atom type, long len, unsigned char **p)
379 unsigned long n, extra;
382 status = XGetWindowProperty(dpy, w, a, 0L, len, False, type, &real_type, &format, &n, &extra, p);
383 if(status != Success || *p == 0)
387 /* could check real_type, format, extra here... */
392 getprop(Window w, Atom a)
396 if(_getprop(w, a, XA_STRING, 100L, &p) <= 0)
402 get1prop(Window w, Atom a, Atom type)
406 if(_getprop(w, a, type, 1L, (void*)&p) <= 0)
410 return (int)(uintptr_t)x;
414 getwprop(Window w, Atom a)
416 return get1prop(w, a, XA_WINDOW);
420 getiprop(Window w, Atom a)
422 return get1prop(w, a, XA_INTEGER);
426 setstate(Client *c, int state)
430 data[0] = (long) state;
431 data[1] = (long) None;
434 XChangeProperty(dpy, c->window, wm_state, wm_state, 32,
435 PropModeReplace, (unsigned char *)data, 2);
439 getstate(Window w, int *state)
443 if(_getprop(w, wm_state, wm_state, 2L, (void*)&p) <= 0)
461 if((n = _getprop(w, wm_protocols, XA_ATOM, 20L, (void*)&p)) <= 0)
464 for(i = 0; i < n; i++)
465 if(p[i] == wm_delete)
467 else if(p[i] == wm_take_focus)
468 c->proto |= Ptakefocus;
469 else if(p[i] == wm_lose_focus)
470 c->proto |= Plosefocus;