4 #include <X11/extensions/Xcomposite.h>
5 #include <X11/extensions/Xdamage.h>
6 #include <X11/extensions/Xrender.h>
16 XserverRegion borderSize;
18 /* for drawing translucent windows */
19 XserverRegion borderClip;
20 struct _win *prev_trans;
30 XserverRegion allDamage;
32 #define WINDOW_PLAIN 0
34 #define WINDOW_TRANS 2
37 find_win (Display *dpy, Window id)
41 for (w = list; w; w = w->next)
48 paint_root (Display *dpy)
52 c.red = c.green = c.blue = 0x8080;
54 XRenderFillRectangle (dpy, PictOpSrc, rootPicture, &c,
59 border_size (Display *dpy, win *w)
62 border = XFixesCreateRegionFromWindow (dpy, w->id, WindowRegionBounding);
64 XFixesUnionRegion (dpy, border, border, w->a.x, w->a.y, None, 0, 0);
69 paint_all (Display *dpy, XserverRegion region)
74 for (w = list; w; w = w->next)
78 if (w->a.map_state != IsViewable)
80 if (w->mode == WINDOW_TRANS)
82 w->borderClip = XFixesCreateRegion (dpy, 0, 0);
83 XFixesUnionRegion (dpy, w->borderClip, region, 0, 0, None, 0, 0);
89 XFixesSetPictureClipRegion (dpy, rootPicture, 0, 0, region);
91 XFixesDestroyRegion (dpy, w->borderSize);
92 w->borderSize = border_size (dpy, w);
93 XFixesSubtractRegion (dpy, region, region, 0, 0, w->borderSize, 0, 0);
94 XRenderComposite (dpy, PictOpSrc, w->picture, None, rootPicture,
96 w->a.x + w->a.border_width,
97 w->a.y + w->a.border_width,
102 XFixesSetPictureClipRegion (dpy, rootPicture, 0, 0, region);
104 for (w = t; w; w = w->prev_trans)
106 XFixesSetPictureClipRegion (dpy, rootPicture, 0, 0, w->borderClip);
107 XRenderComposite (dpy, PictOpOver, w->picture, transPicture, rootPicture,
109 w->a.x + w->a.border_width,
110 w->a.y + w->a.border_width,
113 XFixesDestroyRegion (dpy, w->borderClip);
114 w->borderClip = None;
116 XFixesDestroyRegion (dpy, region);
120 add_damage (Display *dpy, XserverRegion damage)
124 XFixesUnionRegion (dpy, allDamage, allDamage, 0, 0, damage, 0, 0);
125 XFixesDestroyRegion (dpy, damage);
132 repair_win (Display *dpy, Window id)
134 win *w = find_win (dpy, id);
139 /* printf ("repair 0x%x\n", w->id); */
140 parts = XFixesCreateRegion (dpy, 0, 0);
141 /* translate region */
142 XDamageSubtract (dpy, w->damage, None, parts);
143 XFixesUnionRegion (dpy, parts, parts, w->a.x, w->a.y, None, 0, 0);
144 add_damage (dpy, parts);
148 map_win (Display *dpy, Window id)
150 win *w = find_win (dpy, id);
151 XserverRegion region;
155 w->a.map_state = IsViewable;
156 w->damage = XDamageCreate (dpy, id, XDamageReportNonEmpty);
157 region = border_size (dpy, w);
158 add_damage (dpy, region);
162 unmap_win (Display *dpy, Window id)
164 win *w = find_win (dpy, id);
168 w->a.map_state = IsUnmapped;
169 if (w->damage != None)
171 XDamageDestroy (dpy, w->damage);
174 if (w->borderSize != None)
176 add_damage (dpy, w->borderSize); /* destroys region */
177 w->borderSize = None;
182 add_win (Display *dpy, Window id, Window prev)
184 win *new = malloc (sizeof (win));
187 XRenderPictureAttributes pa;
193 for (p = &list; *p; p = &(*p)->next)
194 if ((*p)->id == prev)
200 if (!XGetWindowAttributes (dpy, id, &new->a))
207 pa.subwindow_mode = IncludeInferiors;
208 new->picture = XRenderCreatePicture (dpy, id,
209 XRenderFindVisualFormat (dpy,
214 new->borderSize = None;
215 if (new->a.override_redirect)
216 new->mode = WINDOW_TRANS;
218 new->mode = WINDOW_DROP;
221 if (new->a.map_state == IsViewable)
226 configure_win (Display *dpy, XConfigureEvent *ce)
228 win *w = find_win (dpy, ce->window);
230 XserverRegion damage = None;
234 if (w->a.map_state == IsViewable)
236 damage = XFixesCreateRegion (dpy, 0, 0);
237 if (w->borderSize != None)
238 XFixesUnionRegion (dpy, damage, w->borderSize, 0, 0, None, 0, 0);
242 w->a.width = ce->width;
243 w->a.height = ce->height;
244 w->a.border_width = ce->border_width;
245 w->a.override_redirect = ce->override_redirect;
250 if (above != ce->above)
255 for (prev = &list; *prev; prev = &(*prev)->next)
261 for (prev = &list; *prev; prev = &(*prev)->next)
263 if ((*prev)->id == ce->above)
271 XserverRegion border = border_size (dpy, w);
272 XFixesUnionRegion (dpy, damage, damage, 0, 0, border, 0, 0);
273 add_damage (dpy, damage);
278 destroy_win (Display *dpy, Window id, Bool gone)
282 for (prev = &list; w = *prev; prev = &w->next)
288 XRenderFreePicture (dpy, w->picture);
299 printf ("\t%08x: %d x %d + %d + %d (%d)\n", w->id,
300 w->a.width, w->a.height, w->a.x, w->a.y, w->a.border_width);
308 printf ("windows:\n");
309 for (w = list; w; w = w->next)
314 damage_win (Display *dpy, XDamageNotifyEvent *de)
316 repair_win (dpy, de->drawable);
320 error (Display *dpy, XErrorEvent *ev)
322 printf ("error %d request %d minor %d\n",
323 ev->error_code, ev->request_code, ev->minor_code);
327 expose_root (Display *dpy, Window root, XRectangle *rects, int nrects)
329 XserverRegion region = XFixesCreateRegion (dpy, rects, nrects);
331 add_damage (dpy, region);
337 int event_base, error_base;
338 Window root_return, parent_return;
341 unsigned int nchildren;
343 int damage_event, damage_error;
344 int xfixes_event, xfixes_error;
345 XRenderPictureAttributes pa;
347 XRectangle *expose_rects = 0;
351 dpy = XOpenDisplay (0);
354 fprintf (stderr, "Can't open display\n");
357 XSetErrorHandler (error);
358 scr = DefaultScreen (dpy);
359 root = RootWindow (dpy, scr);
360 pa.subwindow_mode = IncludeInferiors;
361 transPixmap = XCreatePixmap (dpy, root, 1, 1, 8);
363 transPicture = XRenderCreatePicture (dpy, transPixmap,
364 XRenderFindStandardFormat (dpy, PictStandardA8),
367 c.red = c.green = c.blue = 0;
369 XRenderFillRectangle (dpy, PictOpSrc, transPicture, &c, 0, 0, 1, 1);
371 rootPicture = XRenderCreatePicture (dpy, root,
372 XRenderFindVisualFormat (dpy,
373 DefaultVisual (dpy, scr)),
376 if (!XCompositeQueryExtension (dpy, &event_base, &error_base))
378 fprintf (stderr, "No composite extension\n");
381 if (!XDamageQueryExtension (dpy, &damage_event, &damage_error))
383 fprintf (stderr, "No damage extension\n");
386 if (!XFixesQueryExtension (dpy, &xfixes_event, &xfixes_error))
388 fprintf (stderr, "No XFixes extension\n");
393 XCompositeRedirectSubwindows (dpy, root, CompositeRedirectManual);
395 XSelectInput (dpy, root, SubstructureNotifyMask|ExposureMask);
396 XQueryTree (dpy, root, &root_return, &parent_return, &children, &nchildren);
397 for (i = 0; i < nchildren; i++)
398 add_win (dpy, children[i], i ? children[i-1] : None);
405 XNextEvent (dpy, &ev);
406 /* printf ("event %d\n", ev.type); */
409 add_win (dpy, ev.xcreatewindow.window, 0);
411 case ConfigureNotify:
412 configure_win (dpy, &ev.xconfigure);
415 destroy_win (dpy, ev.xdestroywindow.window, True);
418 map_win (dpy, ev.xmap.window);
421 unmap_win (dpy, ev.xunmap.window);
424 if (ev.xreparent.parent == root)
425 add_win (dpy, ev.xreparent.window, 0);
427 destroy_win (dpy, ev.xreparent.window, False);
430 if (ev.xexpose.window == root)
432 int more = ev.xexpose.count + 1;
433 if (n_expose == size_expose)
437 expose_rects = realloc (expose_rects,
438 (size_expose + more) *
439 sizeof (XRectangle));
444 expose_rects = malloc (more * sizeof (XRectangle));
448 expose_rects[n_expose].x = ev.xexpose.x;
449 expose_rects[n_expose].y = ev.xexpose.y;
450 expose_rects[n_expose].width = ev.xexpose.width;
451 expose_rects[n_expose].height = ev.xexpose.height;
453 if (ev.xexpose.count == 0)
455 expose_root (dpy, root, expose_rects, n_expose);
461 if (ev.type == damage_event + XDamageNotify)
462 damage_win (dpy, (XDamageNotifyEvent *) &ev);
465 } while (XEventsQueued (dpy, QueuedAfterReading));
468 paint_all (dpy, allDamage);