1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2
3 /*
4 * Copyright (C) 2007 Iain Holmes
5 * Based on xcompmgr - (c) 2003 Keith Packard
6 * xfwm4 - (c) 2005-2007 Olivier Fourdan
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation; either version 2 of the
11 * License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21 * 02110-1301, USA.
22 */
23
24 #define _GNU_SOURCE
25 #define _XOPEN_SOURCE 500 /* for usleep() */
26
27 #include <config.h>
28
29 #ifdef HAVE_COMPOSITE_EXTENSIONS
30
31 #include <stdlib.h>
32 #include <string.h>
33 #include <limits.h>
34 #include <math.h>
35 #include <unistd.h>
36
37 #include <gdk/gdk.h>
38 #include <gdk/gdkx.h>
39 #include <gtk/gtk.h>
40
41 #include <cairo/cairo-xlib.h>
42
43 #include "display.h"
44 #include "../core/display-private.h"
45 #include "../core/screen-private.h"
46 #include "../core/workspace.h"
47 #include "screen.h"
48 #include "frame.h"
49 #include "errors.h"
50 #include "window.h"
51 #include "compositor-private.h"
52 #include "compositor-xrender.h"
53 #include "xprops.h"
54 #include "core.h"
55 #include <X11/Xatom.h>
56 #include <X11/extensions/shape.h>
57 #include <X11/extensions/Xcomposite.h>
58 #include <X11/extensions/Xdamage.h>
59 #include <X11/extensions/Xfixes.h>
60 #include <X11/extensions/Xrender.h>
61
62 #ifdef HAVE_PRESENT
63 #include <X11/extensions/Xpresent.h>
64 #endif
65
66 #define USE_IDLE_REPAINT 1
67
68 typedef enum _MetaCompWindowType
69 {
70 META_COMP_WINDOW_NORMAL,
71 META_COMP_WINDOW_DND,
72 META_COMP_WINDOW_DESKTOP,
73 META_COMP_WINDOW_DOCK,
74 META_COMP_WINDOW_MENU,
75 META_COMP_WINDOW_DROP_DOWN_MENU,
76 META_COMP_WINDOW_TOOLTIP,
77 } MetaCompWindowType;
78
79 typedef enum _MetaShadowType
80 {
81 META_SHADOW_SMALL,
82 META_SHADOW_MEDIUM,
83 META_SHADOW_LARGE,
84 LAST_SHADOW_TYPE
85 } MetaShadowType;
86
87 typedef struct _MetaCompositorXRender
88 {
89 MetaCompositor compositor;
90
91 MetaDisplay *display;
92
93 Atom atom_x_root_pixmap;
94 Atom atom_x_set_root;
95 Atom atom_net_wm_window_opacity;
96 Atom atom_net_wm_window_type_dnd;
97
98 Atom atom_net_wm_window_type;
99 Atom atom_net_wm_window_type_desktop;
100 Atom atom_net_wm_window_type_dock;
101 Atom atom_net_wm_window_type_menu;
102 Atom atom_net_wm_window_type_dialog;
103 Atom atom_net_wm_window_type_normal;
104 Atom atom_net_wm_window_type_utility;
105 Atom atom_net_wm_window_type_splash;
106 Atom atom_net_wm_window_type_toolbar;
107 Atom atom_net_wm_window_type_dropdown_menu;
108 Atom atom_net_wm_window_type_tooltip;
109
110 #ifdef USE_IDLE_REPAINT
111 guint repaint_id;
112 #endif
113 guint enabled : 1;
114 guint show_redraw : 1;
115 guint debug : 1;
116
117 #ifdef HAVE_PRESENT
118 guint has_present : 1;
119 int present_major;
120 #endif /* HAVE_PRESENT */
121 } MetaCompositorXRender;
122
123 typedef struct _conv
124 {
125 int size;
126 double *data;
127 } conv;
128
129 typedef struct _shadow
130 {
131 conv *gaussian_map;
132 guchar *shadow_corner;
133 guchar *shadow_top;
134 } shadow;
135
136 #define NUM_BUFFER 2
137 typedef struct _MetaCompScreen
138 {
139 MetaScreen *screen;
140 GList *windows;
141 GHashTable *windows_by_xid;
142
143 MetaWindow *focus_window;
144
145 Window output;
146
147 gboolean have_shadows;
148 shadow *shadows[LAST_SHADOW_TYPE];
149
150 Picture root_picture;
151 Picture root_buffers[NUM_BUFFER];
152 Pixmap root_pixmaps[NUM_BUFFER];
153 int root_current;
154 Picture black_picture;
155 Picture trans_black_picture;
156 Picture root_tile;
157 XserverRegion all_damage;
158 #ifdef HAVE_PRESENT
159 XserverRegion prev_damage;
160
161 XID present_eid;
162 gboolean use_present;
163 gboolean present_pending;
164 #endif /* HAVE_PRESENT */
165
166 guint overlays;
167 gboolean compositor_active;
168 gboolean clip_changed;
169
170 GSList *dock_windows;
171 } MetaCompScreen;
172
173 typedef struct _MetaCompWindow
174 {
175 MetaScreen *screen;
176 MetaWindow *window; /* May be NULL if this window isn't managed by Marco */
177 Window id;
178 XWindowAttributes attrs;
179
180 Pixmap back_pixmap;
181
182 /* When the window is shaded back_pixmap will be replaced with the pixmap
183 for the shaded window. This is a copy of the original unshaded window
184 so that we can still see what the window looked like when it is needed
185 for the _get_window_pixmap function */
186 Pixmap shaded_back_pixmap;
187
188 int mode;
189
190 gboolean damaged;
191 gboolean shaped;
192
193 XRectangle shape_bounds;
194
195 MetaCompWindowType type;
196
197 Damage damage;
198 Picture picture;
199 Picture alpha_pict;
200
201 gboolean needs_shadow;
202 MetaShadowType shadow_type;
203 Picture shadow_pict;
204
205 XserverRegion border_size;
206 XserverRegion extents;
207
208 Picture shadow;
209 int shadow_dx;
210 int shadow_dy;
211 int shadow_width;
212 int shadow_height;
213
214 guint opacity;
215
216 XserverRegion border_clip;
217
218 gboolean updates_frozen;
219 gboolean update_pending;
220 } MetaCompWindow;
221
222 #define OPAQUE 0xffffffff
223
224 #define WINDOW_SOLID 0
225 #define WINDOW_ARGB 1
226
227 #define SHADOW_SMALL_RADIUS 3.0
228 #define SHADOW_MEDIUM_RADIUS 6.0
229 #define SHADOW_LARGE_RADIUS 12.0
230
231 #define SHADOW_SMALL_OFFSET_X (SHADOW_SMALL_RADIUS * -3 / 2)
232 #define SHADOW_SMALL_OFFSET_Y (SHADOW_SMALL_RADIUS * -3 / 2)
233 #define SHADOW_MEDIUM_OFFSET_X (SHADOW_MEDIUM_RADIUS * -3 / 2)
234 #define SHADOW_MEDIUM_OFFSET_Y (SHADOW_MEDIUM_RADIUS * -5 / 4)
235 #define SHADOW_LARGE_OFFSET_X -15
236 #define SHADOW_LARGE_OFFSET_Y -15
237
238 #define SHADOW_OPACITY 0.66
239
240 #define TRANS_OPACITY 0.75
241
242 #define DISPLAY_COMPOSITOR(display) ((MetaCompositorXRender *) meta_display_get_compositor (display))
243
244 /* Gaussian stuff for creating the shadows */
245 static double
gaussian(double r,double x,double y)246 gaussian (double r,
247 double x,
248 double y)
249 {
250 return ((1 / (sqrt (2 * G_PI * r))) *
251 exp ((- (x * x + y * y)) / (2 * r * r)));
252 }
253
254 static conv *
make_gaussian_map(double r)255 make_gaussian_map (double r)
256 {
257 conv *c;
258 int size, centre;
259 int x, y;
260 double t, g;
261
262 size = ((int) ceil ((r * 3)) + 1) & ~1;
263 centre = size / 2;
264 c = g_malloc (sizeof (conv) + size * size * sizeof (double));
265 c->size = size;
266 c->data = (double *) (c + 1);
267 t = 0.0;
268
269 for (y = 0; y < size; y++)
270 {
271 for (x = 0; x < size; x++)
272 {
273 g = gaussian (r, (double) (x - centre), (double) (y - centre));
274 t += g;
275 c->data[y * size + x] = g;
276 }
277 }
278
279 for (y = 0; y < size; y++)
280 {
281 for (x = 0; x < size; x++)
282 {
283 c->data[y * size + x] /= t;
284 }
285 }
286
287 return c;
288 }
289
290 static void
dump_xserver_region(const char * location,MetaDisplay * display,XserverRegion region)291 dump_xserver_region (const char *location,
292 MetaDisplay *display,
293 XserverRegion region)
294 {
295 MetaCompositorXRender *compositor = DISPLAY_COMPOSITOR (display);
296 Display *xdisplay = meta_display_get_xdisplay (display);
297 int nrects;
298 XRectangle *rects;
299 XRectangle bounds;
300
301 if (!compositor->debug)
302 return;
303
304 if (region)
305 {
306 rects = XFixesFetchRegionAndBounds (xdisplay, region, &nrects, &bounds);
307 if (nrects > 0)
308 {
309 int i;
310 fprintf (stderr, "%s (XSR): %d rects, bounds: %d,%d (%d,%d)\n",
311 location, nrects, bounds.x, bounds.y, bounds.width, bounds.height);
312 for (i = 1; i < nrects; i++)
313 fprintf (stderr, "\t%d,%d (%d,%d)\n",
314 rects[i].x, rects[i].y, rects[i].width, rects[i].height);
315 }
316 else
317 fprintf (stderr, "%s (XSR): empty\n", location);
318 XFree (rects);
319 }
320 else
321 fprintf (stderr, "%s (XSR): null\n", location);
322 }
323
324 /*
325 * A picture will help
326 *
327 * -center 0 width width+center
328 * -center +-----+-------------------+-----+
329 * | | | |
330 * | | | |
331 * 0 +-----+-------------------+-----+
332 * | | | |
333 * | | | |
334 * | | | |
335 * height +-----+-------------------+-----+
336 * | | | |
337 * height+ | | | |
338 * center +-----+-------------------+-----+
339 */
340 static guchar
sum_gaussian(conv * map,double opacity,int x,int y,int width,int height)341 sum_gaussian (conv *map,
342 double opacity,
343 int x,
344 int y,
345 int width,
346 int height)
347 {
348 double *g_data, *g_line;
349 double v;
350 int fx, fy;
351 int fx_start, fx_end;
352 int fy_start, fy_end;
353 int g_size, centre;
354
355 g_line = map->data;
356 g_size = map->size;
357 centre = g_size / 2;
358 fx_start = centre - x;
359 if (fx_start < 0)
360 fx_start = 0;
361
362 fx_end = width + centre - x;
363 if (fx_end > g_size)
364 fx_end = g_size;
365
366 fy_start = centre - y;
367 if (fy_start < 0)
368 fy_start = 0;
369
370 fy_end = height + centre - y;
371 if (fy_end > g_size)
372 fy_end = g_size;
373
374 g_line = g_line + fy_start * g_size + fx_start;
375
376 v = 0.0;
377 for (fy = fy_start; fy < fy_end; fy++)
378 {
379 g_data = g_line;
380 g_line += g_size;
381
382 for (fx = fx_start; fx < fx_end; fx++)
383 v += *g_data++;
384 }
385
386 if (v > 1.0)
387 v = 1.0;
388
389 return ((guchar) (v * opacity * 255.0));
390 }
391
392 /* precompute shadow corners and sides to save time for large windows */
393 static void
presum_gaussian(shadow * shad)394 presum_gaussian (shadow *shad)
395 {
396 int centre;
397 int opacity, x, y;
398 int msize;
399 conv *map;
400
401 map = shad->gaussian_map;
402 msize = map->size;
403 centre = map->size / 2;
404
405 if (shad->shadow_corner)
406 g_free (shad->shadow_corner);
407 if (shad->shadow_top)
408 g_free (shad->shadow_top);
409
410 shad->shadow_corner = (guchar *)(g_malloc ((msize + 1) * (msize + 1) * 26));
411 shad->shadow_top = (guchar *) (g_malloc ((msize + 1) * 26));
412
413 for (x = 0; x <= msize; x++)
414 {
415
416 shad->shadow_top[25 * (msize + 1) + x] =
417 sum_gaussian (map, 1, x - centre, centre, msize * 2, msize * 2);
418 for (opacity = 0; opacity < 25; opacity++)
419 {
420 shad->shadow_top[opacity * (msize + 1) + x] =
421 shad->shadow_top[25 * (msize + 1) + x] * opacity / 25;
422 }
423
424 for (y = 0; y <= x; y++)
425 {
426 shad->shadow_corner[25 * (msize + 1) * (msize + 1)
427 + y * (msize + 1)
428 + x]
429 = sum_gaussian (map, 1, x - centre, y - centre,
430 msize * 2, msize * 2);
431
432 shad->shadow_corner[25 * (msize + 1) * (msize + 1)
433 + x * (msize + 1) + y] =
434 shad->shadow_corner[25 * (msize + 1) * (msize + 1)
435 + y * (msize + 1) + x];
436
437 for (opacity = 0; opacity < 25; opacity++)
438 {
439 shad->shadow_corner[opacity * (msize + 1) * (msize + 1)
440 + y * (msize + 1) + x]
441 = shad->shadow_corner[opacity * (msize + 1) * (msize + 1)
442 + x * (msize + 1) + y]
443 = shad->shadow_corner[25 * (msize + 1) * (msize + 1)
444 + y * (msize + 1) + x] * opacity / 25;
445 }
446 }
447 }
448 }
449
450 static void
generate_shadows(MetaCompScreen * info)451 generate_shadows (MetaCompScreen *info)
452 {
453 double radii[LAST_SHADOW_TYPE] = {SHADOW_SMALL_RADIUS,
454 SHADOW_MEDIUM_RADIUS,
455 SHADOW_LARGE_RADIUS};
456 int i;
457
458 for (i = 0; i < LAST_SHADOW_TYPE; i++) {
459 shadow *shad = g_new0 (shadow, 1);
460
461 shad->gaussian_map = make_gaussian_map (radii[i]);
462 presum_gaussian (shad);
463
464 info->shadows[i] = shad;
465 }
466 }
467
468 static XImage *
make_shadow(MetaDisplay * display,MetaScreen * screen,MetaShadowType shadow_type,double opacity,int width,int height)469 make_shadow (MetaDisplay *display,
470 MetaScreen *screen,
471 MetaShadowType shadow_type,
472 double opacity,
473 int width,
474 int height)
475 {
476 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
477 Display *xdisplay = meta_display_get_xdisplay (display);
478 XImage *ximage;
479 guchar *data;
480 shadow *shad;
481 int msize;
482 int ylimit, xlimit;
483 int swidth, sheight;
484 int centre;
485 int x, y;
486 guchar d;
487 int x_diff;
488 int opacity_int = (int)(opacity * 25);
489 int screen_number = meta_screen_get_screen_number (screen);
490
491 if (info==NULL)
492 {
493 return NULL;
494 }
495
496 shad = info->shadows[shadow_type];
497 msize = shad->gaussian_map->size;
498 swidth = width + msize;
499 sheight = height + msize;
500 centre = msize / 2;
501
502 data = g_malloc (swidth * sheight * sizeof (guchar));
503
504 ximage = XCreateImage (xdisplay, DefaultVisual (xdisplay, screen_number),
505 8, ZPixmap, 0, (char *) data,
506 swidth, sheight, 8, swidth * sizeof (guchar));
507 if (!ximage)
508 {
509 g_free (data);
510 return NULL;
511 }
512
513 /*
514 * Build the gaussian in sections
515 */
516
517 /*
518 * centre (fill the complete data array
519 */
520 if (msize > 0)
521 d = shad->shadow_top[opacity_int * (msize + 1) + msize];
522 else
523 d = sum_gaussian (shad->gaussian_map, opacity, centre,
524 centre, width, height);
525 memset (data, d, sheight * swidth);
526
527 /*
528 * corners
529 */
530 ylimit = msize;
531 if (ylimit > sheight / 2)
532 ylimit = (sheight + 1) / 2;
533
534 xlimit = msize;
535 if (xlimit > swidth / 2)
536 xlimit = (swidth + 1) / 2;
537
538 for (y = 0; y < ylimit; y++)
539 {
540 for (x = 0; x < xlimit; x++)
541 {
542
543 if (xlimit == msize && ylimit == msize)
544 d = shad->shadow_corner[opacity_int * (msize + 1) * (msize + 1) + y * (msize + 1) + x];
545 else
546 d = sum_gaussian (shad->gaussian_map, opacity, x - centre,
547 y - centre, width, height);
548
549 data[y * swidth + x] = d;
550 data[(sheight - y - 1) * swidth + x] = d;
551 data[(sheight - y - 1) * swidth + (swidth - x - 1)] = d;
552 data[y * swidth + (swidth - x - 1)] = d;
553 }
554 }
555
556 /* top/bottom */
557 x_diff = swidth - (msize * 2);
558 if (x_diff > 0 && ylimit > 0)
559 {
560 for (y = 0; y < ylimit; y++)
561 {
562 if (ylimit == msize)
563 d = shad->shadow_top[opacity_int * (msize + 1) + y];
564 else
565 d = sum_gaussian (shad->gaussian_map, opacity, centre,
566 y - centre, width, height);
567
568 memset (&data[y * swidth + msize], d, x_diff);
569 memset (&data[(sheight - y - 1) * swidth + msize], d, x_diff);
570 }
571 }
572
573 /*
574 * sides
575 */
576 for (x = 0; x < xlimit; x++)
577 {
578 if (xlimit == msize)
579 d = shad->shadow_top[opacity_int * (msize + 1) + x];
580 else
581 d = sum_gaussian (shad->gaussian_map, opacity, x - centre,
582 centre, width, height);
583
584 for (y = msize; y < sheight - msize; y++)
585 {
586 data[y * swidth + x] = d;
587 data[y * swidth + (swidth - x - 1)] = d;
588 }
589 }
590
591 ximage->data = (char *) data;
592
593 return ximage;
594 }
595
596 double shadow_offsets_x[LAST_SHADOW_TYPE] = {SHADOW_SMALL_OFFSET_X,
597 SHADOW_MEDIUM_OFFSET_X,
598 SHADOW_LARGE_OFFSET_X};
599 double shadow_offsets_y[LAST_SHADOW_TYPE] = {SHADOW_SMALL_OFFSET_Y,
600 SHADOW_MEDIUM_OFFSET_Y,
601 SHADOW_LARGE_OFFSET_Y};
602
603 static XserverRegion
cairo_region_to_xserver_region(Display * xdisplay,cairo_region_t * region)604 cairo_region_to_xserver_region (Display *xdisplay,
605 cairo_region_t *region)
606 {
607 int n_rects, i;
608 XRectangle *rects;
609 XserverRegion xregion;
610
611 n_rects = cairo_region_num_rectangles (region);
612 rects = g_new (XRectangle, n_rects);
613
614 for (i = 0; i < n_rects; i++)
615 {
616 cairo_rectangle_int_t rect;
617
618 cairo_region_get_rectangle (region, i, &rect);
619
620 rects[i].x = rect.x;
621 rects[i].y = rect.y;
622 rects[i].width = rect.width;
623 rects[i].height = rect.height;
624 }
625
626 xregion = XFixesCreateRegion (xdisplay, rects, n_rects);
627 g_free (rects);
628
629 return xregion;
630 }
631
632 static void
shadow_picture_clip(Display * xdisplay,Picture shadow_picture,MetaCompWindow * cw,MetaFrameBorders borders,int width,int height)633 shadow_picture_clip (Display *xdisplay,
634 Picture shadow_picture,
635 MetaCompWindow *cw,
636 MetaFrameBorders borders,
637 int width,
638 int height)
639 {
640 int shadow_dx;
641 int shadow_dy;
642 cairo_region_t *visible_region;
643 XRectangle rect;
644 XserverRegion region1;
645 XserverRegion region2;
646
647 if (!cw->window)
648 return;
649
650 visible_region = meta_window_get_frame_bounds (cw->window);
651
652 if (visible_region == NULL)
653 return;
654
655 shadow_dx = -1 * (int) shadow_offsets_x [cw->shadow_type] - borders.invisible.left;
656 shadow_dy = -1 * (int) shadow_offsets_y [cw->shadow_type] - borders.invisible.top;
657
658 rect.x = 0;
659 rect.y = 0;
660 rect.width = width;
661 rect.height = height;
662
663 region1 = XFixesCreateRegion (xdisplay, &rect, 1);
664 region2 = cairo_region_to_xserver_region (xdisplay, visible_region);
665
666 XFixesTranslateRegion (xdisplay, region2,
667 shadow_dx, shadow_dy);
668
669 XFixesSubtractRegion (xdisplay, region1, region1, region2);
670 XFixesSetPictureClipRegion (xdisplay, shadow_picture, 0, 0, region1);
671
672 XFixesDestroyRegion (xdisplay, region1);
673 XFixesDestroyRegion (xdisplay, region2);
674 }
675
676 static Picture
shadow_picture(MetaDisplay * display,MetaScreen * screen,MetaCompWindow * cw,double opacity,MetaFrameBorders borders,int width,int height,int * wp,int * hp)677 shadow_picture (MetaDisplay *display,
678 MetaScreen *screen,
679 MetaCompWindow *cw,
680 double opacity,
681 MetaFrameBorders borders,
682 int width,
683 int height,
684 int *wp,
685 int *hp)
686 {
687 Display *xdisplay = meta_display_get_xdisplay (display);
688 XImage *shadow_image;
689 Pixmap shadow_pixmap;
690 Picture shadow_picture;
691 Window xroot = meta_screen_get_xroot (screen);
692 GC gc;
693
694 shadow_image = make_shadow (display, screen, cw->shadow_type,
695 opacity, width, height);
696 if (!shadow_image)
697 return None;
698
699 shadow_pixmap = XCreatePixmap (xdisplay, xroot,
700 shadow_image->width, shadow_image->height, 8);
701 if (!shadow_pixmap)
702 {
703 XDestroyImage (shadow_image);
704 return None;
705 }
706
707 shadow_picture = XRenderCreatePicture (xdisplay, shadow_pixmap,
708 XRenderFindStandardFormat (xdisplay, PictStandardA8),
709 0, 0);
710 if (!shadow_picture)
711 {
712 XDestroyImage (shadow_image);
713 XFreePixmap (xdisplay, shadow_pixmap);
714 return None;
715 }
716
717 shadow_picture_clip (xdisplay, shadow_picture, cw, borders,
718 shadow_image->width, shadow_image->height);
719
720 gc = XCreateGC (xdisplay, shadow_pixmap, 0, 0);
721 if (!gc)
722 {
723 XDestroyImage (shadow_image);
724 XFreePixmap (xdisplay, shadow_pixmap);
725 XRenderFreePicture (xdisplay, shadow_picture);
726 return None;
727 }
728
729 XPutImage (xdisplay, shadow_pixmap, gc, shadow_image, 0, 0, 0, 0,
730 shadow_image->width, shadow_image->height);
731 *wp = shadow_image->width;
732 *hp = shadow_image->height;
733
734 XFreeGC (xdisplay, gc);
735 XDestroyImage (shadow_image);
736 XFreePixmap (xdisplay, shadow_pixmap);
737
738 return shadow_picture;
739 }
740
741 static MetaCompWindow *
find_window_for_screen(MetaScreen * screen,Window xwindow)742 find_window_for_screen (MetaScreen *screen,
743 Window xwindow)
744 {
745 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
746
747 if (info == NULL)
748 return NULL;
749
750 return g_hash_table_lookup (info->windows_by_xid, (gpointer) xwindow);
751 }
752
753 static MetaCompWindow *
find_window_in_display(MetaDisplay * display,Window xwindow)754 find_window_in_display (MetaDisplay *display,
755 Window xwindow)
756 {
757 GSList *index;
758
759 for (index = meta_display_get_screens (display); index; index = index->next)
760 {
761 MetaCompWindow *cw = find_window_for_screen (index->data, xwindow);
762
763 if (cw != NULL)
764 return cw;
765 }
766
767 return NULL;
768 }
769
770 static MetaCompWindow *
find_window_for_child_window_in_display(MetaDisplay * display,Window xwindow)771 find_window_for_child_window_in_display (MetaDisplay *display,
772 Window xwindow)
773 {
774 Window ignored1, *ignored2;
775 Window parent;
776 guint ignored_children;
777
778 XQueryTree (meta_display_get_xdisplay (display), xwindow, &ignored1,
779 &parent, &ignored2, &ignored_children);
780
781 if (parent != None)
782 return find_window_in_display (display, parent);
783
784 return NULL;
785 }
786
787 #ifdef HAVE_PRESENT
788 static MetaScreen *
find_screen_from_output(MetaDisplay * display,Window output)789 find_screen_from_output(MetaDisplay *display, Window output)
790 {
791 int i;
792 Display *xdisplay = meta_display_get_xdisplay(display);
793
794 for (i = 0; i < ScreenCount(xdisplay); i++)
795 {
796 MetaScreen *screen = meta_display_screen_for_x_screen(display,
797 ScreenOfDisplay(xdisplay, i));
798 MetaCompScreen *info = meta_screen_get_compositor_data(screen);
799
800 if (info->output == output)
801 return screen;
802 }
803 return NULL;
804 }
805 #endif /* HAVE_PRESENT */
806
807 static Picture
solid_picture(MetaDisplay * display,MetaScreen * screen,gboolean argb,double a,double r,double g,double b)808 solid_picture (MetaDisplay *display,
809 MetaScreen *screen,
810 gboolean argb,
811 double a,
812 double r,
813 double g,
814 double b)
815 {
816 Display *xdisplay = meta_display_get_xdisplay (display);
817 Pixmap pixmap;
818 Picture picture;
819 XRenderPictureAttributes pa;
820 XRenderPictFormat *render_format;
821 XRenderColor c;
822 Window xroot = meta_screen_get_xroot (screen);
823
824 render_format = XRenderFindStandardFormat (xdisplay,
825 argb ? PictStandardARGB32 : PictStandardA8);
826
827 pixmap = XCreatePixmap (xdisplay, xroot, 1, 1, argb ? 32 : 8);
828 g_return_val_if_fail (pixmap != None, None);
829
830 pa.repeat = TRUE;
831 picture = XRenderCreatePicture (xdisplay, pixmap, render_format,
832 CPRepeat, &pa);
833 if (picture == None)
834 {
835 XFreePixmap (xdisplay, pixmap);
836 g_warning ("(picture != None) failed");
837 return None;
838 }
839
840 c.alpha = (unsigned short)(a * USHRT_MAX);
841 c.red = (unsigned short)(r * USHRT_MAX);
842 c.green = (unsigned short)(g * USHRT_MAX);
843 c.blue = (unsigned short)(b * USHRT_MAX);
844
845 XRenderFillRectangle (xdisplay, PictOpSrc, picture, &c, 0, 0, 1, 1);
846 XFreePixmap (xdisplay, pixmap);
847
848 return picture;
849 }
850
851 static Picture
root_tile(MetaScreen * screen)852 root_tile (MetaScreen *screen)
853 {
854 MetaDisplay *display = meta_screen_get_display (screen);
855 Display *xdisplay = meta_display_get_xdisplay (display);
856 Picture picture;
857 Pixmap pixmap;
858 gboolean fill = FALSE;
859 XRenderPictureAttributes pa;
860 XRenderPictFormat *format;
861 int p;
862 Atom background_atoms[2];
863 Atom pixmap_atom;
864 int screen_number = meta_screen_get_screen_number (screen);
865 Window xroot = meta_screen_get_xroot (screen);
866
867 pixmap = None;
868 background_atoms[0] = DISPLAY_COMPOSITOR (display)->atom_x_root_pixmap;
869 background_atoms[1] = DISPLAY_COMPOSITOR (display)->atom_x_set_root;
870
871 pixmap_atom = XInternAtom (xdisplay, "PIXMAP", False);
872 for (p = 0; p < 2; p++)
873 {
874 Atom actual_type;
875 int actual_format;
876 gulong nitems, bytes_after;
877 guchar *prop;
878
879 if (XGetWindowProperty (xdisplay, xroot,
880 background_atoms[p],
881 0, 4, FALSE, AnyPropertyType,
882 &actual_type, &actual_format,
883 &nitems, &bytes_after, &prop) == Success)
884 {
885 if (actual_type == pixmap_atom &&
886 actual_format == 32 &&
887 nitems == 1)
888 {
889 memcpy (&pixmap, prop, 4);
890 XFree (prop);
891 fill = FALSE;
892 break;
893 }
894 }
895 }
896
897 if (!pixmap)
898 {
899 pixmap = XCreatePixmap (xdisplay, xroot, 1, 1,
900 DefaultDepth (xdisplay, screen_number));
901 g_return_val_if_fail (pixmap != None, None);
902 fill = TRUE;
903 }
904
905 pa.repeat = TRUE;
906 format = XRenderFindVisualFormat (xdisplay, DefaultVisual (xdisplay,
907 screen_number));
908 g_return_val_if_fail (format != NULL, None);
909
910 picture = XRenderCreatePicture (xdisplay, pixmap, format, CPRepeat, &pa);
911 if ((picture != None) && (fill))
912 {
913 XRenderColor c;
914
915 /* Background default to just plain black */
916 c.red = 0x0000;
917 c.green = 0x0000;
918 c.blue = 0x0000;
919 c.alpha = USHRT_MAX;
920
921 XRenderFillRectangle (xdisplay, PictOpSrc, picture, &c, 0, 0, 1, 1);
922 XFreePixmap (xdisplay, pixmap);
923 }
924
925 return picture;
926 }
927
928 static Pixmap
create_root_pixmap(MetaScreen * screen)929 create_root_pixmap (MetaScreen *screen)
930 {
931 MetaDisplay *display = meta_screen_get_display (screen);
932 Display *xdisplay = meta_display_get_xdisplay (display);
933 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
934 Window xroot = meta_screen_get_xroot (screen);
935 Pixmap pixmap;
936 int depth, screen_width, screen_height, screen_number;
937
938 if (info == NULL)
939 {
940 return None;
941 }
942
943 meta_screen_get_size (screen, &screen_width, &screen_height);
944 screen_number = meta_screen_get_screen_number (screen);
945
946 depth = DefaultDepth (xdisplay, screen_number);
947 pixmap = XCreatePixmap (xdisplay, xroot,
948 screen_width, screen_height,
949 depth);
950
951 return pixmap;
952 }
953
954 static Picture
create_root_buffer(MetaScreen * screen,Pixmap root_pixmap)955 create_root_buffer (MetaScreen *screen, Pixmap root_pixmap)
956 {
957 MetaDisplay *display = meta_screen_get_display (screen);
958 Display *xdisplay = meta_display_get_xdisplay (display);
959 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
960 Picture pict;
961 XRenderPictFormat *format;
962 Visual *visual;
963 int screen_number;
964
965 if (info == NULL)
966 {
967 return None;
968 }
969 g_return_val_if_fail (root_pixmap != None, None);
970
971 screen_number = meta_screen_get_screen_number (screen);
972 visual = DefaultVisual (xdisplay, screen_number);
973
974 format = XRenderFindVisualFormat (xdisplay, visual);
975 g_return_val_if_fail (format != NULL, None);
976
977 pict = XRenderCreatePicture (xdisplay, root_pixmap, format, 0, NULL);
978 return pict;
979 }
980
981 static void
paint_root(MetaScreen * screen,Picture root_buffer)982 paint_root (MetaScreen *screen,
983 Picture root_buffer)
984 {
985 MetaDisplay *display = meta_screen_get_display (screen);
986 Display *xdisplay = meta_display_get_xdisplay (display);
987 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
988 int width, height;
989
990 if (info == NULL)
991 {
992 return;
993 }
994
995 g_return_if_fail (root_buffer != None);
996
997 if (info->root_tile == None)
998 {
999 info->root_tile = root_tile (screen);
1000 g_return_if_fail (info->root_tile != None);
1001 }
1002
1003 meta_screen_get_size (screen, &width, &height);
1004 XRenderComposite (xdisplay, PictOpSrc, info->root_tile, None, root_buffer,
1005 0, 0, 0, 0, 0, 0, width, height);
1006 }
1007
1008 static gboolean
window_has_shadow(MetaCompWindow * cw)1009 window_has_shadow (MetaCompWindow *cw)
1010 {
1011 MetaCompScreen *info = meta_screen_get_compositor_data (cw->screen);
1012
1013 if (info == NULL || info->have_shadows == FALSE)
1014 return FALSE;
1015
1016 /* Always put a shadow around windows with a frame - This should override
1017 the restriction about not putting a shadow around shaped windows
1018 as the frame might be the reason the window is shaped */
1019 if (cw->window)
1020 {
1021 /* Do not add shadows for maximized windows */
1022 if (meta_window_is_maximized (cw->window))
1023 {
1024 meta_verbose ("Window has no shadow because it is maximized\n");
1025 return FALSE;
1026 }
1027
1028 /* Do not add shadows for left/right tiled windows */
1029 if (meta_window_is_tiled_left (cw->window))
1030 {
1031 meta_verbose ("Window has no shadow because it is tiled left\n");
1032 return FALSE;
1033 }
1034
1035 if (meta_window_is_tiled_right (cw->window))
1036 {
1037 meta_verbose ("Window has no shadow because it is tiled right\n");
1038 return FALSE;
1039 }
1040
1041 if (meta_window_get_frame (cw->window)) {
1042 meta_verbose ("Window has shadow because it has a frame\n");
1043 return TRUE;
1044 }
1045 }
1046
1047 /* Do not add shadows to ARGB windows */
1048 if (cw->mode == WINDOW_ARGB) {
1049 meta_verbose ("Window has no shadow as it is ARGB\n");
1050 return FALSE;
1051 }
1052
1053 /* Never put a shadow around shaped windows */
1054 if (cw->shaped) {
1055 meta_verbose ("Window has no shadow as it is shaped\n");
1056 return FALSE;
1057 }
1058
1059 /* Don't put shadow around DND icon windows */
1060 if (cw->type == META_COMP_WINDOW_DND ||
1061 cw->type == META_COMP_WINDOW_DESKTOP) {
1062 meta_verbose ("Window has no shadow as it is DND or Desktop\n");
1063 return FALSE;
1064 }
1065
1066 if (cw->mode != WINDOW_ARGB) {
1067 meta_verbose ("Window has shadow as it is not ARGB\n");
1068 return TRUE;
1069 }
1070
1071 if (cw->type == META_COMP_WINDOW_MENU ||
1072 cw->type == META_COMP_WINDOW_DROP_DOWN_MENU) {
1073 meta_verbose ("Window has shadow as it is a menu\n");
1074 return TRUE;
1075 }
1076
1077 if (cw->type == META_COMP_WINDOW_TOOLTIP) {
1078 meta_verbose ("Window has shadow as it is a tooltip\n");
1079 return TRUE;
1080 }
1081
1082 meta_verbose ("Window has no shadow as it fell through\n");
1083 return FALSE;
1084 }
1085
1086 static XserverRegion
win_extents(MetaCompWindow * cw)1087 win_extents (MetaCompWindow *cw)
1088 {
1089 MetaScreen *screen = cw->screen;
1090 MetaDisplay *display = meta_screen_get_display (screen);
1091 Display *xdisplay = meta_display_get_xdisplay (display);
1092 XRectangle r;
1093
1094 r.x = cw->attrs.x;
1095 r.y = cw->attrs.y;
1096 r.width = cw->attrs.width + cw->attrs.border_width * 2;
1097 r.height = cw->attrs.height + cw->attrs.border_width * 2;
1098
1099 if (cw->needs_shadow)
1100 {
1101 MetaFrameBorders borders;
1102 XRectangle sr;
1103
1104 meta_frame_borders_clear (&borders);
1105
1106 if (cw->window)
1107 {
1108 MetaFrame *frame = meta_window_get_frame (cw->window);
1109
1110 if (frame)
1111 meta_frame_calc_borders (frame, &borders);
1112 }
1113
1114 cw->shadow_dx = (int) shadow_offsets_x [cw->shadow_type] + borders.invisible.left;
1115 cw->shadow_dy = (int) shadow_offsets_y [cw->shadow_type] + borders.invisible.top;
1116
1117 if (!cw->shadow)
1118 {
1119 double opacity = SHADOW_OPACITY;
1120 int invisible_width = borders.invisible.left + borders.invisible.right;
1121 int invisible_height = borders.invisible.top + borders.invisible.bottom;
1122
1123 if (cw->opacity != (guint) OPAQUE)
1124 opacity = opacity * ((double) cw->opacity) / ((double) OPAQUE);
1125
1126 cw->shadow = shadow_picture (display, screen, cw, opacity, borders,
1127 cw->attrs.width - invisible_width + cw->attrs.border_width * 2,
1128 cw->attrs.height - invisible_height + cw->attrs.border_width * 2,
1129 &cw->shadow_width, &cw->shadow_height);
1130 }
1131
1132 sr.x = cw->attrs.x + cw->shadow_dx;
1133 sr.y = cw->attrs.y + cw->shadow_dy;
1134 sr.width = cw->shadow_width;
1135 sr.height = cw->shadow_height;
1136
1137 if (sr.x < r.x)
1138 {
1139 r.width = (r.x + r.width) - sr.x;
1140 r.x = sr.x;
1141 }
1142
1143 if (sr.y < r.y)
1144 {
1145 r.height = (r.y + r.height) - sr.y;
1146 r.y = sr.y;
1147 }
1148
1149 if (sr.x + sr.width > r.x + r.width)
1150 r.width = sr.x + sr.width - r.x;
1151
1152 if (sr.y + sr.height > r.y + r.height)
1153 r.height = sr.y + sr.height - r.y;
1154 }
1155
1156 return XFixesCreateRegion (xdisplay, &r, 1);
1157 }
1158
1159 static XserverRegion
border_size(MetaCompWindow * cw)1160 border_size (MetaCompWindow *cw)
1161 {
1162 MetaScreen *screen = cw->screen;
1163 MetaDisplay *display = meta_screen_get_display (screen);
1164 Display *xdisplay = meta_display_get_xdisplay (display);
1165 cairo_region_t *visible_region;
1166 XserverRegion visible = None;
1167 XserverRegion border;
1168
1169 if (cw->window)
1170 {
1171 visible_region = meta_window_get_frame_bounds (cw->window);
1172
1173 if (visible_region != NULL)
1174 visible = cairo_region_to_xserver_region (xdisplay, visible_region);
1175 }
1176
1177 meta_error_trap_push (display);
1178 border = XFixesCreateRegionFromWindow (xdisplay, cw->id,
1179 WindowRegionBounding);
1180 meta_error_trap_pop (display, FALSE);
1181
1182 g_return_val_if_fail (border != None, None);
1183 XFixesTranslateRegion (xdisplay, border,
1184 cw->attrs.x + cw->attrs.border_width,
1185 cw->attrs.y + cw->attrs.border_width);
1186
1187 if (visible != None)
1188 {
1189 XFixesTranslateRegion (xdisplay, visible,
1190 cw->attrs.x + cw->attrs.border_width,
1191 cw->attrs.y + cw->attrs.border_width);
1192
1193 XFixesIntersectRegion (xdisplay, visible, visible, border);
1194 XFixesDestroyRegion (xdisplay, border);
1195
1196 return visible;
1197 }
1198
1199 return border;
1200 }
1201
1202 static XRenderPictFormat *
get_window_format(MetaCompWindow * cw)1203 get_window_format (MetaCompWindow *cw)
1204 {
1205 MetaScreen *screen = cw->screen;
1206 MetaDisplay *display = meta_screen_get_display (screen);
1207 Display *xdisplay = meta_display_get_xdisplay (display);
1208 XRenderPictFormat *format;
1209 int screen_number = meta_screen_get_screen_number (screen);
1210
1211 format = XRenderFindVisualFormat (xdisplay, cw->attrs.visual);
1212 if (!format)
1213 format = XRenderFindVisualFormat (xdisplay,
1214 DefaultVisual (xdisplay, screen_number));
1215 return format;
1216 }
1217
1218 static Picture
get_window_picture(MetaCompWindow * cw)1219 get_window_picture (MetaCompWindow *cw)
1220 {
1221 MetaScreen *screen = cw->screen;
1222 MetaDisplay *display = meta_screen_get_display (screen);
1223 Display *xdisplay = meta_display_get_xdisplay (display);
1224 XRenderPictureAttributes pa;
1225 XRenderPictFormat *format;
1226 Drawable draw;
1227 int error_code;
1228
1229 draw = cw->id;
1230
1231 meta_error_trap_push (display);
1232
1233 if (cw->back_pixmap == None)
1234 cw->back_pixmap = XCompositeNameWindowPixmap (xdisplay, cw->id);
1235
1236 error_code = meta_error_trap_pop_with_return (display, FALSE);
1237 if (error_code != 0)
1238 cw->back_pixmap = None;
1239
1240 if (cw->back_pixmap != None)
1241 draw = cw->back_pixmap;
1242
1243 format = get_window_format (cw);
1244 if (format)
1245 {
1246 Picture pict;
1247
1248 pa.subwindow_mode = IncludeInferiors;
1249
1250 meta_error_trap_push (display);
1251 pict = XRenderCreatePicture (xdisplay, draw, format, CPSubwindowMode, &pa);
1252 meta_error_trap_pop (display, FALSE);
1253
1254 return pict;
1255 }
1256
1257 return None;
1258 }
1259
1260 static void
paint_dock_shadows(MetaScreen * screen,Picture root_buffer,XserverRegion region)1261 paint_dock_shadows (MetaScreen *screen,
1262 Picture root_buffer,
1263 XserverRegion region)
1264 {
1265 MetaDisplay *display = meta_screen_get_display (screen);
1266 Display *xdisplay = meta_display_get_xdisplay (display);
1267 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
1268 GSList *d;
1269
1270 if (info == NULL)
1271 {
1272 return;
1273 }
1274
1275 for (d = info->dock_windows; d; d = d->next)
1276 {
1277 MetaCompWindow *cw = d->data;
1278 XserverRegion shadow_clip;
1279
1280 if (cw->shadow)
1281 {
1282 shadow_clip = XFixesCreateRegion (xdisplay, NULL, 0);
1283 XFixesIntersectRegion (xdisplay, shadow_clip,
1284 cw->border_clip, region);
1285
1286 XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0, shadow_clip);
1287
1288 XRenderComposite (xdisplay, PictOpOver, info->black_picture,
1289 cw->shadow, root_buffer,
1290 0, 0, 0, 0,
1291 cw->attrs.x + cw->shadow_dx,
1292 cw->attrs.y + cw->shadow_dy,
1293 cw->shadow_width, cw->shadow_height);
1294 XFixesDestroyRegion (xdisplay, shadow_clip);
1295 }
1296 }
1297 }
1298
1299 #ifdef HAVE_PRESENT
1300 static gboolean
present_flip(MetaScreen * screen,XserverRegion region,Pixmap pixmap)1301 present_flip (MetaScreen *screen, XserverRegion region, Pixmap pixmap)
1302 {
1303 static uint32_t present_serial;
1304 gboolean debug;
1305
1306 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
1307 MetaDisplay *display = meta_screen_get_display (screen);
1308 Display *xdisplay = meta_display_get_xdisplay (display);
1309
1310 meta_error_trap_push (display);
1311 XPresentPixmap(xdisplay,
1312 info->output,
1313 pixmap,
1314 present_serial,
1315 None,
1316 region,
1317 0, 0,
1318 None, None, None, PresentOptionNone,
1319 0, 1, 0, NULL, 0);
1320
1321 int error_code;
1322 error_code = meta_error_trap_pop_with_return (display, FALSE);
1323 if (error_code)
1324 {
1325 debug = DISPLAY_COMPOSITOR (display)->debug;
1326
1327 if (debug)
1328 fprintf (stderr, "XPresentPixmap window %p pixmap %p error: %i\n",
1329 (void *)info->output, (void *)pixmap, error_code);
1330
1331 if (error_code == BadWindow)
1332 g_warning ("XPresent is not compatible with your current system configuration.");
1333
1334 /* Disable the Present extension for this session to prevent frozen windows */
1335 info->use_present = FALSE;
1336 return FALSE;
1337 }
1338
1339 present_serial++;
1340
1341 return TRUE;
1342 }
1343 #endif /* HAVE_PRESENT */
1344
1345 static void
paint_windows(MetaScreen * screen,GList * windows,Picture root_buffer,Pixmap root_pixmap,XserverRegion region)1346 paint_windows (MetaScreen *screen,
1347 GList *windows,
1348 Picture root_buffer,
1349 Pixmap root_pixmap,
1350 XserverRegion region)
1351 {
1352 MetaDisplay *display = meta_screen_get_display (screen);
1353 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
1354 Display *xdisplay = meta_display_get_xdisplay (display);
1355 GList *index, *last;
1356 int screen_width, screen_height;
1357 MetaCompWindow *cw;
1358 XserverRegion paint_region, desktop_region;
1359
1360 if (info == NULL)
1361 {
1362 return;
1363 }
1364
1365 meta_screen_get_size (screen, &screen_width, &screen_height);
1366
1367 if (region == None)
1368 {
1369 XRectangle r;
1370 r.x = 0;
1371 r.y = 0;
1372 r.width = screen_width;
1373 r.height = screen_height;
1374 paint_region = XFixesCreateRegion (xdisplay, &r, 1);
1375 }
1376 else
1377 {
1378 paint_region = XFixesCreateRegion (xdisplay, NULL, 0);
1379 XFixesCopyRegion (xdisplay, paint_region, region);
1380 }
1381
1382 desktop_region = None;
1383
1384 /*
1385 * Painting from top to bottom, reducing the clipping area at
1386 * each iteration. Only the opaque windows are painted 1st.
1387 */
1388 last = NULL;
1389 for (index = windows; index; index = index->next)
1390 {
1391 /* Store the last window we dealt with */
1392 last = index;
1393
1394 cw = (MetaCompWindow *) index->data;
1395 if (!cw->damaged)
1396 {
1397 /* Not damaged */
1398 continue;
1399 }
1400
1401 if (cw->attrs.map_state != IsViewable)
1402 continue;
1403
1404 #if 0
1405 if ((cw->attrs.x + cw->attrs.width < 1) ||
1406 (cw->attrs.y + cw->attrs.height < 1) ||
1407 (cw->attrs.x >= screen_width) || (cw->attrs.y >= screen_height))
1408 {
1409 /* Off screen */
1410 continue;
1411 }
1412 #endif
1413
1414 if (cw->picture == None)
1415 cw->picture = get_window_picture (cw);
1416
1417 /* If the clip region of the screen has been changed
1418 then we need to recreate the extents of the window */
1419 if (info->clip_changed)
1420 {
1421 if (cw->border_size)
1422 {
1423 XFixesDestroyRegion (xdisplay, cw->border_size);
1424 cw->border_size = None;
1425 }
1426
1427 #if 0
1428 if (cw->extents)
1429 {
1430 XFixesDestroyRegion (xdisplay, cw->extents);
1431 cw->extents = None;
1432 }
1433 #endif
1434 }
1435
1436 if (cw->border_size == None)
1437 cw->border_size = border_size (cw);
1438
1439 if (cw->extents == None)
1440 cw->extents = win_extents (cw);
1441
1442 if (cw->mode == WINDOW_SOLID)
1443 {
1444 int x, y, wid, hei;
1445
1446 x = cw->attrs.x;
1447 y = cw->attrs.y;
1448 wid = cw->attrs.width + cw->attrs.border_width * 2;
1449 hei = cw->attrs.height + cw->attrs.border_width * 2;
1450
1451 XFixesSetPictureClipRegion (xdisplay, root_buffer,
1452 0, 0, paint_region);
1453 XRenderComposite (xdisplay, PictOpSrc, cw->picture,
1454 None, root_buffer, 0, 0, 0, 0,
1455 x, y, wid, hei);
1456
1457 if (cw->type == META_COMP_WINDOW_DESKTOP)
1458 {
1459 if(desktop_region)
1460 {
1461 XFixesUnionRegion (xdisplay, desktop_region, desktop_region, paint_region);
1462 }
1463 else
1464 {
1465 desktop_region = XFixesCreateRegion (xdisplay, 0, 0);
1466 XFixesCopyRegion (xdisplay, desktop_region, paint_region);
1467 }
1468 }
1469
1470 XFixesSubtractRegion (xdisplay, paint_region,
1471 paint_region, cw->border_size);
1472 }
1473
1474 if (!cw->border_clip)
1475 {
1476 cw->border_clip = XFixesCreateRegion (xdisplay, 0, 0);
1477 XFixesCopyRegion (xdisplay, cw->border_clip, paint_region);
1478 }
1479 }
1480
1481 XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0, paint_region);
1482 paint_root (screen, root_buffer);
1483
1484 paint_dock_shadows (screen, root_buffer, desktop_region == None ?
1485 paint_region : desktop_region);
1486 if (desktop_region != None)
1487 XFixesDestroyRegion (xdisplay, desktop_region);
1488
1489 /*
1490 * Painting from bottom to top, translucent windows and shadows are painted
1491 */
1492 for (index = last; index; index = index->prev)
1493 {
1494 cw = (MetaCompWindow *) index->data;
1495
1496 if (cw->picture)
1497 {
1498 if (cw->shadow && cw->type != META_COMP_WINDOW_DOCK)
1499 {
1500 XserverRegion shadow_clip;
1501
1502 shadow_clip = XFixesCreateRegion (xdisplay, NULL, 0);
1503 XFixesSubtractRegion (xdisplay, shadow_clip, cw->border_clip,
1504 cw->border_size);
1505 XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0,
1506 shadow_clip);
1507
1508 XRenderComposite (xdisplay, PictOpOver, info->black_picture,
1509 cw->shadow, root_buffer,
1510 0, 0, 0, 0,
1511 cw->attrs.x + cw->shadow_dx,
1512 cw->attrs.y + cw->shadow_dy,
1513 cw->shadow_width, cw->shadow_height);
1514 if (shadow_clip)
1515 XFixesDestroyRegion (xdisplay, shadow_clip);
1516 }
1517
1518 if ((cw->opacity != (guint) OPAQUE) && !(cw->alpha_pict))
1519 {
1520 cw->alpha_pict = solid_picture (display, screen, FALSE,
1521 (double) cw->opacity / OPAQUE,
1522 0, 0, 0);
1523 }
1524
1525 XFixesIntersectRegion (xdisplay, cw->border_clip, cw->border_clip,
1526 cw->border_size);
1527 XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0,
1528 cw->border_clip);
1529 if (cw->mode == WINDOW_ARGB)
1530 {
1531 int x, y, wid, hei;
1532
1533 x = cw->attrs.x;
1534 y = cw->attrs.y;
1535 wid = cw->attrs.width + cw->attrs.border_width * 2;
1536 hei = cw->attrs.height + cw->attrs.border_width * 2;
1537
1538 XRenderComposite (xdisplay, PictOpOver, cw->picture,
1539 cw->alpha_pict, root_buffer, 0, 0, 0, 0,
1540 x, y, wid, hei);
1541 }
1542 }
1543
1544 if (cw->border_clip)
1545 {
1546 XFixesDestroyRegion (xdisplay, cw->border_clip);
1547 cw->border_clip = None;
1548 }
1549 }
1550
1551 XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0, region);
1552
1553 #ifdef HAVE_PRESENT
1554 if (info->use_present)
1555 info->present_pending = present_flip (screen, region, root_pixmap);
1556
1557 if (!info->use_present || !info->present_pending)
1558 #endif /* HAVE_PRESENT */
1559 {
1560 XRenderComposite (xdisplay, PictOpSrc, root_buffer, None,
1561 info->root_picture, 0, 0, 0, 0, 0, 0,
1562 screen_width, screen_height);
1563 }
1564
1565 XFlush (xdisplay);
1566 XFixesDestroyRegion (xdisplay, paint_region);
1567 }
1568
1569 static void
paint_all(MetaScreen * screen,XserverRegion region,int b)1570 paint_all (MetaScreen *screen,
1571 XserverRegion region,
1572 int b)
1573 {
1574 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
1575 MetaDisplay *display = meta_screen_get_display (screen);
1576 Display *xdisplay = meta_display_get_xdisplay (display);
1577 int screen_width, screen_height;
1578
1579 meta_screen_get_size (screen, &screen_width, &screen_height);
1580
1581 if (DISPLAY_COMPOSITOR (display)->show_redraw)
1582 {
1583 Picture overlay;
1584
1585 dump_xserver_region ("paint_all", display, region);
1586
1587 /* Make a random colour overlay */
1588 overlay = solid_picture (display, screen, TRUE, 1, /* 0.3, alpha */
1589 ((double) (rand () % 100)) / 100.0,
1590 ((double) (rand () % 100)) / 100.0,
1591 ((double) (rand () % 100)) / 100.0);
1592
1593 /* Set clipping to the given region */
1594 XFixesSetPictureClipRegion (xdisplay, info->root_picture, 0, 0, region);
1595
1596 XRenderComposite (xdisplay, PictOpOver, overlay, None, info->root_picture,
1597 0, 0, 0, 0, 0, 0, screen_width, screen_height);
1598 XRenderFreePicture (xdisplay, overlay);
1599 XFlush (xdisplay);
1600 usleep (100 * 1000);
1601 }
1602
1603 if (info->root_pixmaps[b] == None)
1604 info->root_pixmaps[b] = create_root_pixmap (screen);
1605
1606 if (info->root_buffers[b] == None)
1607 info->root_buffers[b] = create_root_buffer (screen, info->root_pixmaps[b]);
1608
1609 paint_windows (screen, info->windows, info->root_buffers[b], info->root_pixmaps[b], region);
1610 }
1611
1612 static void
repair_screen(MetaScreen * screen)1613 repair_screen (MetaScreen *screen)
1614 {
1615 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
1616 MetaDisplay *display = meta_screen_get_display (screen);
1617 Display *xdisplay = meta_display_get_xdisplay (display);
1618
1619 g_return_if_fail(info != NULL);
1620
1621 if (info->all_damage != None)
1622 {
1623 #ifdef HAVE_PRESENT
1624 if (info->use_present)
1625 {
1626 if (!info->present_pending)
1627 {
1628 XserverRegion damage = info->all_damage;
1629 meta_error_trap_push (display);
1630 if (info->prev_damage)
1631 {
1632 XFixesUnionRegion(xdisplay, info->prev_damage, info->prev_damage, damage);
1633 damage = info->prev_damage;
1634 }
1635
1636 paint_all (screen, damage, info->root_current);
1637
1638 if (++info->root_current >= NUM_BUFFER)
1639 info->root_current = 0;
1640
1641 if (info->prev_damage)
1642 XFixesDestroyRegion (xdisplay, info->prev_damage);
1643
1644 info->prev_damage = info->all_damage;
1645 info->all_damage = None;
1646 info->clip_changed = FALSE;
1647 meta_error_trap_pop (display, FALSE);
1648 }
1649 }
1650 else
1651 #endif /* HAVE_PRESENT */
1652 {
1653 meta_error_trap_push (display);
1654 paint_all (screen, info->all_damage, info->root_current);
1655 XFixesDestroyRegion (xdisplay, info->all_damage);
1656 info->all_damage = None;
1657 info->clip_changed = FALSE;
1658 meta_error_trap_pop (display, FALSE);
1659 }
1660 }
1661 }
1662
1663 static void
repair_display(MetaDisplay * display)1664 repair_display (MetaDisplay *display)
1665 {
1666 GSList *screens = meta_display_get_screens (display);
1667 MetaCompositorXRender *compositor = DISPLAY_COMPOSITOR (display);
1668
1669 #ifdef USE_IDLE_REPAINT
1670 if (compositor->repaint_id > 0)
1671 {
1672 g_source_remove (compositor->repaint_id);
1673 compositor->repaint_id = 0;
1674 }
1675 #endif
1676
1677 for (; screens; screens = screens->next)
1678 repair_screen ((MetaScreen *) screens->data);
1679 }
1680
1681 #ifdef USE_IDLE_REPAINT
1682 static gboolean
compositor_idle_cb(gpointer data)1683 compositor_idle_cb (gpointer data)
1684 {
1685 MetaCompositorXRender *compositor = (MetaCompositorXRender *) data;
1686
1687 compositor->repaint_id = 0;
1688 repair_display (compositor->display);
1689
1690 return FALSE;
1691 }
1692
1693 static void
add_repair(MetaDisplay * display)1694 add_repair (MetaDisplay *display)
1695 {
1696 MetaCompositorXRender *compositor = DISPLAY_COMPOSITOR (display);
1697
1698 if (compositor->repaint_id > 0)
1699 return;
1700
1701 #if 1
1702 compositor->repaint_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE,
1703 compositor_idle_cb, compositor,
1704 NULL);
1705 #else
1706 /* Limit it to 50fps */
1707 compositor->repaint_id = g_timeout_add_full (G_PRIORITY_HIGH, 20,
1708 compositor_idle_cb, compositor,
1709 NULL);
1710 #endif
1711 }
1712 #endif
1713
1714 static void
add_damage(MetaScreen * screen,XserverRegion damage)1715 add_damage (MetaScreen *screen,
1716 XserverRegion damage)
1717 {
1718 MetaDisplay *display = meta_screen_get_display (screen);
1719 Display *xdisplay = meta_display_get_xdisplay (display);
1720 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
1721
1722 /* dump_xserver_region ("add_damage", display, damage); */
1723
1724 if (info != NULL)
1725 {
1726 if (info->all_damage)
1727 {
1728 XFixesUnionRegion (xdisplay, info->all_damage, info->all_damage, damage);
1729 XFixesDestroyRegion (xdisplay, damage);
1730 }
1731 else
1732 {
1733 info->all_damage = damage;
1734 }
1735 }
1736
1737 #ifdef USE_IDLE_REPAINT
1738 add_repair (display);
1739 #endif
1740 }
1741
1742 static void
damage_screen(MetaScreen * screen)1743 damage_screen (MetaScreen *screen)
1744 {
1745 MetaDisplay *display = meta_screen_get_display (screen);
1746 Display *xdisplay = meta_display_get_xdisplay (display);
1747 XserverRegion region;
1748 int width, height;
1749 XRectangle r;
1750
1751 r.x = 0;
1752 r.y = 0;
1753 meta_screen_get_size (screen, &width, &height);
1754 r.width = width;
1755 r.height = height;
1756
1757 region = XFixesCreateRegion (xdisplay, &r, 1);
1758 dump_xserver_region ("damage_screen", display, region);
1759 add_damage (screen, region);
1760 }
1761
1762 static void
repair_win(MetaCompWindow * cw)1763 repair_win (MetaCompWindow *cw)
1764 {
1765 MetaScreen *screen = cw->screen;
1766 MetaDisplay *display = meta_screen_get_display (screen);
1767 Display *xdisplay = meta_display_get_xdisplay (display);
1768 XserverRegion parts;
1769
1770 meta_error_trap_push (display);
1771 if (!cw->damaged)
1772 {
1773 parts = win_extents (cw);
1774 XDamageSubtract (xdisplay, cw->damage, None, None);
1775 }
1776 else
1777 {
1778 parts = XFixesCreateRegion (xdisplay, 0, 0);
1779 XDamageSubtract (xdisplay, cw->damage, None, parts);
1780 XFixesTranslateRegion (xdisplay, parts,
1781 cw->attrs.x + cw->attrs.border_width,
1782 cw->attrs.y + cw->attrs.border_width);
1783 }
1784
1785 meta_error_trap_pop (display, FALSE);
1786
1787 dump_xserver_region ("repair_win", display, parts);
1788 add_damage (screen, parts);
1789 cw->damaged = TRUE;
1790 }
1791
1792 static void
free_win(MetaCompWindow * cw,gboolean destroy)1793 free_win (MetaCompWindow *cw,
1794 gboolean destroy)
1795 {
1796 MetaDisplay *display = meta_screen_get_display (cw->screen);
1797 Display *xdisplay = meta_display_get_xdisplay (display);
1798 MetaCompScreen *info = meta_screen_get_compositor_data (cw->screen);
1799
1800 /* See comment in map_win */
1801 if (cw->back_pixmap && destroy)
1802 {
1803 XFreePixmap (xdisplay, cw->back_pixmap);
1804 cw->back_pixmap = None;
1805 }
1806
1807 if (cw->shaded_back_pixmap && destroy)
1808 {
1809 XFreePixmap (xdisplay, cw->shaded_back_pixmap);
1810 cw->shaded_back_pixmap = None;
1811 }
1812
1813 if (cw->picture)
1814 {
1815 XRenderFreePicture (xdisplay, cw->picture);
1816 cw->picture = None;
1817 }
1818
1819 if (cw->shadow)
1820 {
1821 XRenderFreePicture (xdisplay, cw->shadow);
1822 cw->shadow = None;
1823 }
1824
1825 if (cw->alpha_pict)
1826 {
1827 XRenderFreePicture (xdisplay, cw->alpha_pict);
1828 cw->alpha_pict = None;
1829 }
1830
1831 if (cw->shadow_pict)
1832 {
1833 XRenderFreePicture (xdisplay, cw->shadow_pict);
1834 cw->shadow_pict = None;
1835 }
1836
1837 if (cw->border_size)
1838 {
1839 XFixesDestroyRegion (xdisplay, cw->border_size);
1840 cw->border_size = None;
1841 }
1842
1843 if (cw->border_clip)
1844 {
1845 XFixesDestroyRegion (xdisplay, cw->border_clip);
1846 cw->border_clip = None;
1847 }
1848
1849 if (cw->extents)
1850 {
1851 XFixesDestroyRegion (xdisplay, cw->extents);
1852 cw->extents = None;
1853 }
1854
1855 if (destroy)
1856 {
1857 if (cw->damage != None) {
1858 meta_error_trap_push (display);
1859 XDamageDestroy (xdisplay, cw->damage);
1860 meta_error_trap_pop (display, FALSE);
1861
1862 cw->damage = None;
1863 }
1864
1865 /* The window may not have been added to the list in this case,
1866 but we can check anyway */
1867 if (info!=NULL && cw->type == META_COMP_WINDOW_DOCK)
1868 info->dock_windows = g_slist_remove (info->dock_windows, cw);
1869
1870 g_free (cw);
1871 }
1872 }
1873
1874 static void
constrain_tooltip_onscreen(MetaDisplay * display,MetaScreen * screen,MetaCompWindow * cw,Window id)1875 constrain_tooltip_onscreen (MetaDisplay *display,
1876 MetaScreen *screen,
1877 MetaCompWindow *cw,
1878 Window id)
1879 {
1880 MetaWorkspace *workspace;
1881 MetaRectangle work_area, win_rect;
1882 const MetaXineramaScreenInfo* xinerama;
1883 gint new_x, new_y;
1884 gint active_workspace_num;
1885
1886 /* Why this is here:
1887 * As of gtk 3.24, tooltips are positioned differently, and can end up off the
1888 * screen in certain situations in hidpi.
1889 *
1890 * See: https://github.com/GNOME/gtk/commit/14d22cb3233e
1891 *
1892 * If the panel is too tall (around > 25 or so), tooltip positioning fails both
1893 * tests in gdkwindowimpl.c (maybe_flip_position()) skipping repositioning of the
1894 * tooltip inside the workarea. This only occurs on bottom panels.
1895 *
1896 * Since the calculations are based upon the monitor's workarea and the 'attach'
1897 * (gdk) window's rectangle, there's no way to compensate for or fool gtk into
1898 * displaying it correctly. So here, we do our own check and adjustment. */
1899
1900 active_workspace_num = meta_core_get_active_workspace (cw->attrs.screen);
1901
1902 workspace = meta_screen_get_workspace_by_index (screen,
1903 active_workspace_num);
1904
1905 win_rect.x = cw->attrs.x;
1906 win_rect.y = cw->attrs.y;
1907 win_rect.width = cw->attrs.width;
1908 win_rect.height = cw->attrs.height;
1909
1910 xinerama = meta_screen_get_xinerama_for_rect (screen,
1911 &win_rect);
1912
1913 meta_workspace_get_work_area_for_xinerama (workspace,
1914 xinerama->number,
1915 &work_area);
1916
1917 new_x = win_rect.x;
1918 new_y = win_rect.y;
1919
1920 /* Valid tooltip positions seem to cheat into the panel by a few pixels - maybe
1921 * accounting for shadow margin. There's no reason the fix these, but they'd
1922 * be caught here otherwise, so 10px of overshoot in the direction of the panel
1923 * is allowed. The tooltips we're out to catch are the ones on the complete other
1924 * side of the panel (off screren), so there won't be any confusion. */
1925 if (win_rect.y < work_area.y - 10)
1926 {
1927 new_y = work_area.y;
1928 }
1929 else if (win_rect.y + win_rect.height > work_area.y + work_area.height + 10)
1930 {
1931 new_y = (work_area.y + work_area.height - win_rect.height);
1932 }
1933
1934 if (win_rect.x < work_area.x - 10)
1935 {
1936 new_x = work_area.x;
1937 }
1938 else if (win_rect.x + win_rect.width > work_area.x + work_area.width + 10)
1939 {
1940 new_x = (work_area.x + work_area.width - win_rect.width);
1941 }
1942
1943 if (new_x != win_rect.x || new_y != win_rect.y)
1944 {
1945 if (DISPLAY_COMPOSITOR (display)->debug)
1946 {
1947 fprintf(stderr, "Constraining tooltip onscreen x:%d -> %d, y:%d -> %d\n",
1948 win_rect.x,new_x, win_rect.y,new_y);
1949 }
1950
1951 XMoveWindow (display->xdisplay, cw->id, new_x, new_y);
1952 }
1953 }
1954
1955 static void
map_win(MetaDisplay * display,MetaScreen * screen,Window id)1956 map_win (MetaDisplay *display,
1957 MetaScreen *screen,
1958 Window id)
1959 {
1960 MetaCompWindow *cw = find_window_for_screen (screen, id);
1961 Display *xdisplay = meta_display_get_xdisplay (display);
1962
1963 if (cw == NULL)
1964 return;
1965
1966 if (cw->type == META_COMP_WINDOW_TOOLTIP)
1967 {
1968 constrain_tooltip_onscreen (display, screen, cw, id);
1969 }
1970
1971 /* The reason we deallocate this here and not in unmap
1972 is so that we will still have a valid pixmap for
1973 whenever the window is unmapped */
1974 if (cw->back_pixmap)
1975 {
1976 XFreePixmap (xdisplay, cw->back_pixmap);
1977 cw->back_pixmap = None;
1978 }
1979
1980 if (cw->shaded_back_pixmap)
1981 {
1982 XFreePixmap (xdisplay, cw->shaded_back_pixmap);
1983 cw->shaded_back_pixmap = None;
1984 }
1985
1986 cw->attrs.map_state = IsViewable;
1987 cw->damaged = FALSE;
1988 }
1989
1990 static void
unmap_win(MetaDisplay * display,MetaScreen * screen,Window id)1991 unmap_win (MetaDisplay *display,
1992 MetaScreen *screen,
1993 Window id)
1994 {
1995 MetaCompWindow *cw = find_window_for_screen (screen, id);
1996 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
1997
1998 if (cw == NULL || info == NULL)
1999 {
2000 return;
2001 }
2002
2003 if (cw->window && cw->window == info->focus_window)
2004 info->focus_window = NULL;
2005
2006 cw->attrs.map_state = IsUnmapped;
2007 cw->damaged = FALSE;
2008
2009 if (cw->extents != None)
2010 {
2011 dump_xserver_region ("unmap_win", display, cw->extents);
2012 add_damage (screen, cw->extents);
2013 cw->extents = None;
2014 }
2015
2016 free_win (cw, FALSE);
2017 info->clip_changed = TRUE;
2018 }
2019
2020 static void
determine_mode(MetaDisplay * display,MetaScreen * screen,MetaCompWindow * cw)2021 determine_mode (MetaDisplay *display,
2022 MetaScreen *screen,
2023 MetaCompWindow *cw)
2024 {
2025 XRenderPictFormat *format;
2026 Display *xdisplay = meta_display_get_xdisplay (display);
2027
2028 if (cw->alpha_pict)
2029 {
2030 XRenderFreePicture (xdisplay, cw->alpha_pict);
2031 cw->alpha_pict = None;
2032 }
2033
2034 if (cw->shadow_pict)
2035 {
2036 XRenderFreePicture (xdisplay, cw->shadow_pict);
2037 cw->shadow_pict = None;
2038 }
2039
2040 if (cw->attrs.class == InputOnly)
2041 format = NULL;
2042 else
2043 format = XRenderFindVisualFormat (xdisplay, cw->attrs.visual);
2044
2045 if ((format && format->type == PictTypeDirect && format->direct.alphaMask)
2046 || cw->opacity != (guint) OPAQUE)
2047 cw->mode = WINDOW_ARGB;
2048 else
2049 cw->mode = WINDOW_SOLID;
2050
2051 if (cw->extents)
2052 {
2053 XserverRegion damage;
2054 damage = XFixesCreateRegion (xdisplay, NULL, 0);
2055 XFixesCopyRegion (xdisplay, damage, cw->extents);
2056
2057 dump_xserver_region ("determine_mode", display, damage);
2058 add_damage (screen, damage);
2059 }
2060 }
2061
2062 static gboolean
is_shaped(MetaDisplay * display,Window xwindow)2063 is_shaped (MetaDisplay *display,
2064 Window xwindow)
2065 {
2066 Display *xdisplay = meta_display_get_xdisplay (display);
2067 int xws, yws, xbs, ybs;
2068 unsigned wws, hws, wbs, hbs;
2069 int bounding_shaped, clip_shaped;
2070
2071 if (meta_display_has_shape (display))
2072 {
2073 XShapeQueryExtents (xdisplay, xwindow, &bounding_shaped,
2074 &xws, &yws, &wws, &hws, &clip_shaped,
2075 &xbs, &ybs, &wbs, &hbs);
2076 return (bounding_shaped != 0);
2077 }
2078
2079 return FALSE;
2080 }
2081
2082 static void
get_window_type(MetaDisplay * display,MetaCompWindow * cw)2083 get_window_type (MetaDisplay *display,
2084 MetaCompWindow *cw)
2085 {
2086 MetaCompositorXRender *compositor = DISPLAY_COMPOSITOR (display);
2087 int n_atoms;
2088 Atom *atoms, type_atom;
2089 int i;
2090
2091 type_atom = None;
2092 n_atoms = 0;
2093 atoms = NULL;
2094
2095 meta_prop_get_atom_list (display, cw->id,
2096 compositor->atom_net_wm_window_type,
2097 &atoms, &n_atoms);
2098
2099 for (i = 0; i < n_atoms; i++)
2100 {
2101 if (atoms[i] == compositor->atom_net_wm_window_type_dnd ||
2102 atoms[i] == compositor->atom_net_wm_window_type_desktop ||
2103 atoms[i] == compositor->atom_net_wm_window_type_dock ||
2104 atoms[i] == compositor->atom_net_wm_window_type_toolbar ||
2105 atoms[i] == compositor->atom_net_wm_window_type_menu ||
2106 atoms[i] == compositor->atom_net_wm_window_type_dialog ||
2107 atoms[i] == compositor->atom_net_wm_window_type_normal ||
2108 atoms[i] == compositor->atom_net_wm_window_type_utility ||
2109 atoms[i] == compositor->atom_net_wm_window_type_splash ||
2110 atoms[i] == compositor->atom_net_wm_window_type_dropdown_menu ||
2111 atoms[i] == compositor->atom_net_wm_window_type_tooltip)
2112 {
2113 type_atom = atoms[i];
2114 break;
2115 }
2116 }
2117
2118 meta_XFree (atoms);
2119
2120 if (type_atom == compositor->atom_net_wm_window_type_dnd)
2121 cw->type = META_COMP_WINDOW_DND;
2122 else if (type_atom == compositor->atom_net_wm_window_type_desktop)
2123 cw->type = META_COMP_WINDOW_DESKTOP;
2124 else if (type_atom == compositor->atom_net_wm_window_type_dock)
2125 cw->type = META_COMP_WINDOW_DOCK;
2126 else if (type_atom == compositor->atom_net_wm_window_type_menu)
2127 cw->type = META_COMP_WINDOW_MENU;
2128 else if (type_atom == compositor->atom_net_wm_window_type_dropdown_menu)
2129 cw->type = META_COMP_WINDOW_DROP_DOWN_MENU;
2130 else if (type_atom == compositor->atom_net_wm_window_type_tooltip)
2131 cw->type = META_COMP_WINDOW_TOOLTIP;
2132 else
2133 cw->type = META_COMP_WINDOW_NORMAL;
2134
2135 /* meta_verbose ("Window is %d\n", cw->type); */
2136 }
2137
2138 /* Must be called with an error trap in place */
2139 static void
add_win(MetaScreen * screen,MetaWindow * window,Window xwindow)2140 add_win (MetaScreen *screen,
2141 MetaWindow *window,
2142 Window xwindow)
2143 {
2144 MetaDisplay *display = meta_screen_get_display (screen);
2145 Display *xdisplay = meta_display_get_xdisplay (display);
2146 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
2147 MetaCompWindow *cw;
2148 gulong event_mask;
2149
2150 if (info == NULL)
2151 return;
2152
2153 if (xwindow == info->output)
2154 return;
2155
2156 /* If already added, ignore */
2157 if (find_window_for_screen (screen, xwindow) != NULL)
2158 return;
2159
2160 cw = g_new0 (MetaCompWindow, 1);
2161 cw->screen = screen;
2162 cw->window = window;
2163 cw->id = xwindow;
2164
2165 if (!XGetWindowAttributes (xdisplay, xwindow, &cw->attrs))
2166 {
2167 g_free (cw);
2168 return;
2169 }
2170 get_window_type (display, cw);
2171
2172 /* If Marco has decided not to manage this window then the input events
2173 won't have been set on the window */
2174 event_mask = cw->attrs.your_event_mask | PropertyChangeMask;
2175
2176 XSelectInput (xdisplay, xwindow, event_mask);
2177
2178 cw->back_pixmap = None;
2179 cw->shaded_back_pixmap = None;
2180
2181 cw->damaged = FALSE;
2182 cw->shaped = is_shaped (display, xwindow);
2183
2184 cw->shape_bounds.x = cw->attrs.x;
2185 cw->shape_bounds.y = cw->attrs.y;
2186 cw->shape_bounds.width = cw->attrs.width;
2187 cw->shape_bounds.height = cw->attrs.height;
2188
2189 if (cw->attrs.class == InputOnly)
2190 cw->damage = None;
2191 else
2192 cw->damage = XDamageCreate (xdisplay, xwindow, XDamageReportNonEmpty);
2193
2194 cw->alpha_pict = None;
2195 cw->shadow_pict = None;
2196 cw->border_size = None;
2197 cw->extents = None;
2198 cw->shadow = None;
2199 cw->shadow_dx = 0;
2200 cw->shadow_dy = 0;
2201 cw->shadow_width = 0;
2202 cw->shadow_height = 0;
2203
2204 if (window && meta_window_has_focus (window))
2205 cw->shadow_type = META_SHADOW_LARGE;
2206 else
2207 cw->shadow_type = META_SHADOW_MEDIUM;
2208
2209 cw->opacity = OPAQUE;
2210
2211 cw->border_clip = None;
2212
2213 determine_mode (display, screen, cw);
2214 cw->needs_shadow = window_has_shadow (cw);
2215
2216 /* Only add the window to the list of docks if it needs a shadow */
2217 if (cw->type == META_COMP_WINDOW_DOCK && cw->needs_shadow)
2218 {
2219 meta_verbose ("Appending %p to dock windows\n", cw);
2220 info->dock_windows = g_slist_append (info->dock_windows, cw);
2221 }
2222
2223 /* Add this to the list at the top of the stack
2224 before it is mapped so that map_win can find it again */
2225 info->windows = g_list_prepend (info->windows, cw);
2226 g_hash_table_insert (info->windows_by_xid, (gpointer) xwindow, cw);
2227
2228 if (cw->attrs.map_state == IsViewable)
2229 map_win (display, screen, xwindow);
2230 }
2231
2232 static void
destroy_win(MetaDisplay * display,Window xwindow,gboolean gone)2233 destroy_win (MetaDisplay *display,
2234 Window xwindow,
2235 gboolean gone)
2236 {
2237 MetaScreen *screen;
2238 MetaCompScreen *info;
2239 MetaCompWindow *cw;
2240
2241 cw = find_window_in_display (display, xwindow);
2242
2243 if (cw == NULL)
2244 return;
2245
2246 screen = cw->screen;
2247
2248 if (cw->extents != None)
2249 {
2250 dump_xserver_region ("destroy_win", display, cw->extents);
2251 add_damage (screen, cw->extents);
2252 cw->extents = None;
2253 }
2254
2255 info = meta_screen_get_compositor_data (screen);
2256 if (info != NULL)
2257 {
2258 info->windows = g_list_remove (info->windows, (gconstpointer) cw);
2259 g_hash_table_remove (info->windows_by_xid, (gpointer) xwindow);
2260 }
2261
2262 free_win (cw, TRUE);
2263 }
2264
2265 static void
restack_win(MetaCompWindow * cw,Window above)2266 restack_win (MetaCompWindow *cw,
2267 Window above)
2268 {
2269 MetaScreen *screen;
2270 MetaCompScreen *info;
2271 Window previous_above;
2272 GList *sibling, *next;
2273
2274 screen = cw->screen;
2275 info = meta_screen_get_compositor_data (screen);
2276
2277 if (info == NULL)
2278 {
2279 return;
2280 }
2281
2282 sibling = g_list_find (info->windows, (gconstpointer) cw);
2283 next = g_list_next (sibling);
2284 previous_above = None;
2285
2286 if (next)
2287 {
2288 MetaCompWindow *ncw = (MetaCompWindow *) next->data;
2289 previous_above = ncw->id;
2290 }
2291
2292 /* If above is set to None, the window whose state was changed is on
2293 * the bottom of the stack with respect to sibling.
2294 */
2295 if (above == None)
2296 {
2297 /* Insert at bottom of window stack */
2298 info->windows = g_list_delete_link (info->windows, sibling);
2299 info->windows = g_list_append (info->windows, cw);
2300 }
2301 else if (previous_above != above)
2302 {
2303 GList *index;
2304
2305 for (index = info->windows; index; index = index->next) {
2306 MetaCompWindow *cw2 = (MetaCompWindow *) index->data;
2307 if (cw2->id == above)
2308 break;
2309 }
2310
2311 if (index != NULL)
2312 {
2313 info->windows = g_list_delete_link (info->windows, sibling);
2314 info->windows = g_list_insert_before (info->windows, index, cw);
2315 }
2316 }
2317 }
2318
2319 static void
resize_win(MetaCompWindow * cw,int x,int y,int width,int height,int border_width,gboolean override_redirect)2320 resize_win (MetaCompWindow *cw,
2321 int x,
2322 int y,
2323 int width,
2324 int height,
2325 int border_width,
2326 gboolean override_redirect)
2327 {
2328 MetaScreen *screen = cw->screen;
2329 MetaDisplay *display = meta_screen_get_display (screen);
2330 Display *xdisplay = meta_display_get_xdisplay (display);
2331 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
2332 XserverRegion damage;
2333 XserverRegion shape;
2334 gboolean debug;
2335
2336 debug = DISPLAY_COMPOSITOR (display)->debug;
2337
2338 if (cw->extents)
2339 {
2340 damage = XFixesCreateRegion (xdisplay, NULL, 0);
2341 XFixesCopyRegion (xdisplay, damage, cw->extents);
2342 }
2343 else
2344 {
2345 damage = None;
2346 if (debug)
2347 fprintf (stderr, "no extents to damage !\n");
2348 }
2349
2350 /* { // Damage whole screen each time ! ;-)
2351 XRectangle r;
2352
2353 r.x = 0;
2354 r.y = 0;
2355 meta_screen_get_size (screen, &r.width, &r.height);
2356 fprintf (stderr, "Damage whole screen %d,%d (%d %d)\n",
2357 r.x, r.y, r.width, r.height);
2358
2359 damage = XFixesCreateRegion (xdisplay, &r, 1);
2360 } */
2361
2362 cw->attrs.x = x;
2363 cw->attrs.y = y;
2364
2365 if (cw->attrs.width != width || cw->attrs.height != height)
2366 {
2367 if (cw->shaded_back_pixmap)
2368 {
2369 XFreePixmap (xdisplay, cw->shaded_back_pixmap);
2370 cw->shaded_back_pixmap = None;
2371 }
2372
2373 if (cw->back_pixmap)
2374 {
2375 /* If the window is shaded, we store the old backing pixmap
2376 so we can return a proper image of the window */
2377 if (cw->window && meta_window_is_shaded (cw->window))
2378 {
2379 cw->shaded_back_pixmap = cw->back_pixmap;
2380 cw->back_pixmap = None;
2381 }
2382 else
2383 {
2384 XFreePixmap (xdisplay, cw->back_pixmap);
2385 cw->back_pixmap = None;
2386 }
2387 }
2388
2389 if (cw->picture)
2390 {
2391 XRenderFreePicture (xdisplay, cw->picture);
2392 cw->picture = None;
2393 }
2394
2395 if (cw->shadow)
2396 {
2397 XRenderFreePicture (xdisplay, cw->shadow);
2398 cw->shadow = None;
2399 }
2400 }
2401
2402 cw->attrs.width = width;
2403 cw->attrs.height = height;
2404 cw->attrs.border_width = border_width;
2405 cw->attrs.override_redirect = override_redirect;
2406
2407 if (cw->extents)
2408 XFixesDestroyRegion (xdisplay, cw->extents);
2409
2410 cw->extents = win_extents (cw);
2411
2412 if (damage)
2413 {
2414 if (debug)
2415 fprintf (stderr, "Inexplicable intersection with new extents!\n");
2416
2417 XFixesUnionRegion (xdisplay, damage, damage, cw->extents);
2418 }
2419 else
2420 {
2421 damage = XFixesCreateRegion (xdisplay, NULL, 0);
2422 XFixesCopyRegion (xdisplay, damage, cw->extents);
2423 }
2424
2425 shape = XFixesCreateRegion (xdisplay, &cw->shape_bounds, 1);
2426 XFixesUnionRegion (xdisplay, damage, damage, shape);
2427 XFixesDestroyRegion (xdisplay, shape);
2428
2429 dump_xserver_region ("resize_win", display, damage);
2430 add_damage (screen, damage);
2431
2432 if (info != NULL)
2433 {
2434 info->clip_changed = TRUE;
2435 }
2436 }
2437
2438 /* event processors must all be called with an error trap in place */
2439 static void
process_circulate_notify(MetaCompositorXRender * compositor,XCirculateEvent * event)2440 process_circulate_notify (MetaCompositorXRender *compositor,
2441 XCirculateEvent *event)
2442 {
2443 MetaCompWindow *cw = find_window_in_display (compositor->display,
2444 event->window);
2445 MetaCompWindow *top;
2446 MetaCompScreen *info;
2447 MetaScreen *screen;
2448 GList *first;
2449 Window above;
2450
2451 if (!cw)
2452 return;
2453
2454 screen = cw->screen;
2455 info = meta_screen_get_compositor_data (screen);
2456 first = info->windows;
2457 top = (MetaCompWindow *) first->data;
2458
2459 if ((event->place == PlaceOnTop) && top)
2460 above = top->id;
2461 else
2462 above = None;
2463 restack_win (cw, above);
2464
2465 if (info != NULL)
2466 {
2467 info->clip_changed = TRUE;
2468 }
2469
2470 #ifdef USE_IDLE_REPAINT
2471 add_repair (compositor->display);
2472 #endif
2473 }
2474
2475 static void
process_configure_notify(MetaCompositorXRender * compositor,XConfigureEvent * event)2476 process_configure_notify (MetaCompositorXRender *compositor,
2477 XConfigureEvent *event)
2478 {
2479 MetaDisplay *display = compositor->display;
2480 Display *xdisplay = meta_display_get_xdisplay (display);
2481 MetaCompWindow *cw = find_window_in_display (display, event->window);
2482
2483 if (cw)
2484 {
2485 #if 0
2486 int x = -1, y = -1, width = -1, height = -1;
2487 int ex = -1, ey = -1, ewidth = -1, eheight = -1;
2488 MetaRectangle *rect;
2489
2490 if (cw->window) {
2491 rect = meta_window_get_rect (cw->window);
2492 x = rect->x;
2493 y = rect->y;
2494 width = rect->width;
2495 height = rect->height;
2496 }
2497 fprintf (stderr, "configure notify xy (%d %d) -> (%d %d), wh (%d %d) -> (%d %d)\n",
2498 x, y, event->x, event->y,
2499 width, height, event->width, event->height);
2500 #endif
2501
2502 if (compositor->debug)
2503 {
2504 fprintf (stderr, "configure notify %d %d %d\n", cw->damaged,
2505 cw->shaped, cw->needs_shadow);
2506 dump_xserver_region ("\textents", display, cw->extents);
2507 fprintf (stderr, "\txy (%d %d), wh (%d %d)\n",
2508 event->x, event->y, event->width, event->height);
2509 }
2510
2511 restack_win (cw, event->above);
2512 resize_win (cw, event->x, event->y, event->width, event->height,
2513 event->border_width, event->override_redirect);
2514 }
2515 else
2516 {
2517 MetaScreen *screen;
2518 MetaCompScreen *info;
2519
2520 /* Might be the root window? */
2521 screen = meta_display_screen_for_root (display, event->window);
2522 if (screen == NULL)
2523 return;
2524
2525 info = meta_screen_get_compositor_data (screen);
2526 if (info != NULL)
2527 {
2528 int b;
2529 for (b = 0; b < NUM_BUFFER; b++)
2530 {
2531 if (info->root_buffers[b]) {
2532 XRenderFreePicture (xdisplay, info->root_buffers[b]);
2533 XFreePixmap (xdisplay, info->root_pixmaps[b]);
2534 info->root_buffers[b] = None;
2535 info->root_pixmaps[b] = None;
2536 }
2537 }
2538 }
2539
2540 damage_screen (screen);
2541 }
2542 }
2543
2544 static void
process_property_notify(MetaCompositorXRender * compositor,XPropertyEvent * event)2545 process_property_notify (MetaCompositorXRender *compositor,
2546 XPropertyEvent *event)
2547 {
2548 MetaDisplay *display = compositor->display;
2549 Display *xdisplay = meta_display_get_xdisplay (display);
2550 MetaScreen *screen;
2551 int p;
2552 Atom background_atoms[2];
2553
2554 /* Check for the background property changing */
2555 background_atoms[0] = compositor->atom_x_root_pixmap;
2556 background_atoms[1] = compositor->atom_x_set_root;
2557
2558 for (p = 0; p < 2; p++)
2559 {
2560 if (event->atom == background_atoms[p])
2561 {
2562 screen = meta_display_screen_for_root (display, event->window);
2563 if (screen)
2564 {
2565 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
2566 Window xroot = meta_screen_get_xroot (screen);
2567
2568 if (info != NULL && info->root_tile)
2569 {
2570 XClearArea (xdisplay, xroot, 0, 0, 0, 0, TRUE);
2571 XRenderFreePicture (xdisplay, info->root_tile);
2572 info->root_tile = None;
2573
2574 /* Damage the whole screen as we may need to redraw the
2575 background ourselves */
2576 damage_screen (screen);
2577 #ifdef USE_IDLE_REPAINT
2578 add_repair (display);
2579 #endif
2580
2581 return;
2582 }
2583 }
2584 }
2585 }
2586
2587 /* Check for the opacity changing */
2588 if (event->atom == compositor->atom_net_wm_window_opacity)
2589 {
2590 MetaCompWindow *cw = find_window_in_display (display, event->window);
2591 gulong value;
2592
2593 if (!cw)
2594 {
2595 /* Applications can set this for their toplevel windows, so
2596 * this must be propagated to the window managed by the compositor
2597 */
2598 cw = find_window_for_child_window_in_display (display, event->window);
2599 }
2600
2601 if (!cw)
2602 return;
2603
2604 if (meta_prop_get_cardinal (display, event->window,
2605 compositor->atom_net_wm_window_opacity,
2606 &value) == FALSE)
2607 value = OPAQUE;
2608
2609 cw->opacity = (guint)value;
2610 determine_mode (display, cw->screen, cw);
2611 cw->needs_shadow = window_has_shadow (cw);
2612
2613 if (cw->shadow)
2614 {
2615 XRenderFreePicture (xdisplay, cw->shadow);
2616 cw->shadow = None;
2617 }
2618
2619 if (cw->extents)
2620 XFixesDestroyRegion (xdisplay, cw->extents);
2621 cw->extents = win_extents (cw);
2622
2623 cw->damaged = TRUE;
2624 #ifdef USE_IDLE_REPAINT
2625 add_repair (display);
2626 #endif
2627
2628 return;
2629 }
2630
2631 if (event->atom == compositor->atom_net_wm_window_type) {
2632 MetaCompWindow *cw = find_window_in_display (display, event->window);
2633
2634 if (!cw)
2635 return;
2636
2637 get_window_type (display, cw);
2638 cw->needs_shadow = window_has_shadow (cw);
2639 return;
2640 }
2641 }
2642
2643 static void
expose_area(MetaScreen * screen,XRectangle * rects,int nrects)2644 expose_area (MetaScreen *screen,
2645 XRectangle *rects,
2646 int nrects)
2647 {
2648 MetaDisplay *display = meta_screen_get_display (screen);
2649 Display *xdisplay = meta_display_get_xdisplay (display);
2650 XserverRegion region;
2651
2652 region = XFixesCreateRegion (xdisplay, rects, nrects);
2653
2654 dump_xserver_region ("expose_area", display, region);
2655 add_damage (screen, region);
2656 }
2657
2658 static void
process_expose(MetaCompositorXRender * compositor,XExposeEvent * event)2659 process_expose (MetaCompositorXRender *compositor,
2660 XExposeEvent *event)
2661 {
2662 MetaCompWindow *cw = find_window_in_display (compositor->display,
2663 event->window);
2664 MetaScreen *screen = NULL;
2665 XRectangle rect[1];
2666 int origin_x = 0, origin_y = 0;
2667
2668 if (cw != NULL)
2669 {
2670 screen = cw->screen;
2671 origin_x = cw->attrs.x; /* + cw->attrs.border_width; ? */
2672 origin_y = cw->attrs.y; /* + cw->attrs.border_width; ? */
2673 }
2674 else
2675 {
2676 screen = meta_display_screen_for_root (compositor->display,
2677 event->window);
2678 if (screen == NULL)
2679 return;
2680 }
2681
2682 rect[0].x = event->x + origin_x;
2683 rect[0].y = event->y + origin_y;
2684 rect[0].width = event->width;
2685 rect[0].height = event->height;
2686
2687 expose_area (screen, rect, 1);
2688 }
2689
2690 static void
process_unmap(MetaCompositorXRender * compositor,XUnmapEvent * event)2691 process_unmap (MetaCompositorXRender *compositor,
2692 XUnmapEvent *event)
2693 {
2694 MetaCompWindow *cw;
2695
2696 if (event->from_configure)
2697 {
2698 /* Ignore unmap caused by parent's resize */
2699 return;
2700 }
2701
2702 cw = find_window_in_display (compositor->display, event->window);
2703 if (cw)
2704 unmap_win (compositor->display, cw->screen, event->window);
2705 }
2706
2707 static void
process_map(MetaCompositorXRender * compositor,XMapEvent * event)2708 process_map (MetaCompositorXRender *compositor,
2709 XMapEvent *event)
2710 {
2711 MetaCompWindow *cw = find_window_in_display (compositor->display,
2712 event->window);
2713
2714 if (cw)
2715 map_win (compositor->display, cw->screen, event->window);
2716 }
2717
2718 static void
process_reparent(MetaCompositorXRender * compositor,XReparentEvent * event,MetaWindow * window)2719 process_reparent (MetaCompositorXRender *compositor,
2720 XReparentEvent *event,
2721 MetaWindow *window)
2722 {
2723 MetaScreen *screen;
2724
2725 screen = meta_display_screen_for_root (compositor->display, event->parent);
2726 if (screen != NULL)
2727 add_win (screen, window, event->window);
2728 else
2729 destroy_win (compositor->display, event->window, FALSE);
2730 }
2731
2732 static void
process_create(MetaCompositorXRender * compositor,XCreateWindowEvent * event,MetaWindow * window)2733 process_create (MetaCompositorXRender *compositor,
2734 XCreateWindowEvent *event,
2735 MetaWindow *window)
2736 {
2737 MetaScreen *screen;
2738 /* We are only interested in top level windows, others will
2739 be caught by normal marco functions */
2740
2741 screen = meta_display_screen_for_root (compositor->display, event->parent);
2742 if (screen == NULL)
2743 return;
2744
2745 if (!find_window_in_display (compositor->display, event->window))
2746 add_win (screen, window, event->window);
2747 }
2748
2749 static void
process_destroy(MetaCompositorXRender * compositor,XDestroyWindowEvent * event)2750 process_destroy (MetaCompositorXRender *compositor,
2751 XDestroyWindowEvent *event)
2752 {
2753 destroy_win (compositor->display, event->window, FALSE);
2754 }
2755
2756 static void
process_damage(MetaCompositorXRender * compositor,XDamageNotifyEvent * event)2757 process_damage (MetaCompositorXRender *compositor,
2758 XDamageNotifyEvent *event)
2759 {
2760 MetaCompWindow *cw = find_window_in_display (compositor->display,
2761 event->drawable);
2762 if (cw == NULL)
2763 return;
2764
2765 repair_win (cw);
2766
2767 #ifdef USE_IDLE_REPAINT
2768 if (event->more == FALSE)
2769 add_repair (compositor->display);
2770 #endif
2771 }
2772
2773 static void
process_shape(MetaCompositorXRender * compositor,XShapeEvent * event)2774 process_shape (MetaCompositorXRender *compositor,
2775 XShapeEvent *event)
2776 {
2777 MetaCompWindow *cw = find_window_in_display (compositor->display,
2778 event->window);
2779
2780 if (cw == NULL)
2781 return;
2782
2783 if (event->kind == ShapeBounding)
2784 {
2785 if (!event->shaped && cw->shaped)
2786 cw->shaped = FALSE;
2787
2788 resize_win (cw, cw->attrs.x, cw->attrs.y,
2789 event->width + event->x, event->height + event->y,
2790 cw->attrs.border_width, cw->attrs.override_redirect);
2791
2792 if (event->shaped && !cw->shaped)
2793 cw->shaped = TRUE;
2794
2795 if (event->shaped == True)
2796 {
2797 cw->shape_bounds.x = cw->attrs.x + event->x;
2798 cw->shape_bounds.y = cw->attrs.y + event->y;
2799 cw->shape_bounds.width = event->width;
2800 cw->shape_bounds.height = event->height;
2801 }
2802 else
2803 {
2804 cw->shape_bounds.x = cw->attrs.x;
2805 cw->shape_bounds.y = cw->attrs.y;
2806 cw->shape_bounds.width = cw->attrs.width;
2807 cw->shape_bounds.height = cw->attrs.height;
2808 }
2809 }
2810 }
2811
2812 #ifdef HAVE_PRESENT
2813 static void
xrender_present_complete(MetaScreen * screen,XPresentCompleteNotifyEvent * ce)2814 xrender_present_complete(MetaScreen *screen,
2815 XPresentCompleteNotifyEvent *ce)
2816 {
2817 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
2818
2819 info->present_pending = False;
2820 repair_screen(screen);
2821 }
2822 #endif /* HAVE_PRESENT */
2823
2824 static void
process_generic(MetaCompositorXRender * compositor,XGenericEvent * event)2825 process_generic(MetaCompositorXRender *compositor,
2826 XGenericEvent *event)
2827 {
2828 XGenericEventCookie *ge = (XGenericEventCookie *) event;
2829 Display *xdisplay = meta_display_get_xdisplay (compositor->display);
2830 XGetEventData(xdisplay, ge);
2831
2832 switch (ge->evtype)
2833 {
2834 #ifdef HAVE_PRESENT
2835 case PresentConfigureNotify:
2836 break;
2837 case PresentCompleteNotify:
2838 {
2839 if (ge->extension == compositor->present_major)
2840 {
2841 XPresentCompleteNotifyEvent *ce = ge->data;
2842 MetaScreen *screen = find_screen_from_output(compositor->display, ce->window);
2843 if (screen)
2844 xrender_present_complete(screen, ce);
2845 }
2846 }
2847 break;
2848 #endif /* HAVE_PRESENT */
2849 }
2850 XFreeEventData(xdisplay, ge);
2851 }
2852
2853 static int
timeout_debug(MetaCompositorXRender * compositor)2854 timeout_debug (MetaCompositorXRender *compositor)
2855 {
2856 compositor->show_redraw = (g_getenv ("MARCO_DEBUG_REDRAWS") != NULL);
2857 compositor->debug = (g_getenv ("MARCO_DEBUG_COMPOSITOR") != NULL);
2858
2859 return FALSE;
2860 }
2861
2862 static void
xrender_add_window(MetaCompositor * compositor,MetaWindow * window,Window xwindow,XWindowAttributes * attrs)2863 xrender_add_window (MetaCompositor *compositor,
2864 MetaWindow *window,
2865 Window xwindow,
2866 XWindowAttributes *attrs)
2867 {
2868 #ifdef HAVE_COMPOSITE_EXTENSIONS
2869 MetaCompositorXRender *xrc = (MetaCompositorXRender *) compositor;
2870 MetaScreen *screen = meta_screen_for_x_screen (attrs->screen);
2871
2872 meta_error_trap_push (xrc->display);
2873 add_win (screen, window, xwindow);
2874 meta_error_trap_pop (xrc->display, FALSE);
2875 #endif
2876 }
2877
2878 static void
xrender_remove_window(MetaCompositor * compositor,Window xwindow)2879 xrender_remove_window (MetaCompositor *compositor,
2880 Window xwindow)
2881 {
2882 #ifdef HAVE_COMPOSITE_EXTENSIONS
2883 #endif
2884 }
2885
2886 static void
show_overlay_window(MetaScreen * screen,Window cow)2887 show_overlay_window (MetaScreen *screen,
2888 Window cow)
2889 {
2890 MetaDisplay *display = meta_screen_get_display (screen);
2891 Display *xdisplay = meta_display_get_xdisplay (display);
2892 XserverRegion region;
2893
2894 region = XFixesCreateRegion (xdisplay, NULL, 0);
2895
2896 XFixesSetWindowShapeRegion (xdisplay, cow, ShapeBounding, 0, 0, 0);
2897 XFixesSetWindowShapeRegion (xdisplay, cow, ShapeInput, 0, 0, region);
2898
2899 XFixesDestroyRegion (xdisplay, region);
2900
2901 damage_screen (screen);
2902 }
2903
2904 static void
hide_overlay_window(MetaScreen * screen,Window cow)2905 hide_overlay_window (MetaScreen *screen,
2906 Window cow)
2907 {
2908 MetaDisplay *display = meta_screen_get_display (screen);
2909 Display *xdisplay = meta_display_get_xdisplay (display);
2910 XserverRegion region;
2911
2912 region = XFixesCreateRegion (xdisplay, NULL, 0);
2913 XFixesSetWindowShapeRegion (xdisplay, cow, ShapeBounding, 0, 0, region);
2914 XFixesDestroyRegion (xdisplay, region);
2915 }
2916
2917 static Window
get_output_window(MetaScreen * screen)2918 get_output_window (MetaScreen *screen)
2919 {
2920 MetaDisplay *display = meta_screen_get_display (screen);
2921 Display *xdisplay = meta_display_get_xdisplay (display);
2922 Window output, xroot;
2923
2924 xroot = meta_screen_get_xroot (screen);
2925
2926 output = XCompositeGetOverlayWindow (xdisplay, xroot);
2927 XSelectInput (xdisplay, output, ExposureMask);
2928
2929 return output;
2930 }
2931
2932 static void
xrender_manage_screen(MetaCompositor * compositor,MetaScreen * screen)2933 xrender_manage_screen (MetaCompositor *compositor,
2934 MetaScreen *screen)
2935 {
2936 #ifdef HAVE_COMPOSITE_EXTENSIONS
2937 MetaCompositorXRender *xrc = (MetaCompositorXRender *) compositor;
2938 MetaCompScreen *info;
2939 MetaDisplay *display = meta_screen_get_display (screen);
2940 Display *xdisplay = meta_display_get_xdisplay (display);
2941 GdkDisplay *gdk_display = gdk_x11_lookup_xdisplay (xdisplay);
2942 XRenderPictureAttributes pa;
2943 XRenderPictFormat *visual_format;
2944 int screen_number = meta_screen_get_screen_number (screen);
2945 Window xroot = meta_screen_get_xroot (screen);
2946 int b;
2947
2948 /* Check if the screen is already managed */
2949 if (meta_screen_get_compositor_data (screen))
2950 return;
2951
2952 gdk_x11_display_error_trap_push (gdk_display);
2953 XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
2954 XSync (xdisplay, FALSE);
2955
2956 if (gdk_x11_display_error_trap_pop (gdk_display))
2957 {
2958 g_warning ("Another compositing manager is running on screen %i",
2959 screen_number);
2960 return;
2961 }
2962
2963 info = g_new0 (MetaCompScreen, 1);
2964 info->screen = screen;
2965
2966 meta_screen_set_compositor_data (screen, info);
2967
2968 visual_format = XRenderFindVisualFormat (xdisplay, DefaultVisual (xdisplay,
2969 screen_number));
2970 if (!visual_format)
2971 {
2972 g_warning ("Cannot find visual format on screen %i", screen_number);
2973 return;
2974 }
2975
2976 info->output = get_output_window (screen);
2977
2978 pa.subwindow_mode = IncludeInferiors;
2979 info->root_picture = XRenderCreatePicture (xdisplay, info->output,
2980 visual_format,
2981 CPSubwindowMode, &pa);
2982 if (info->root_picture == None)
2983 {
2984 g_warning ("Cannot create root picture on screen %i", screen_number);
2985 return;
2986 }
2987
2988 for (b = 0; b < NUM_BUFFER; b++) {
2989 info->root_buffers[b] = None;
2990 info->root_pixmaps[b] = None;
2991 }
2992 info->black_picture = solid_picture (display, screen, TRUE, 1, 0, 0, 0);
2993
2994 info->root_tile = None;
2995 info->all_damage = None;
2996
2997 info->windows = NULL;
2998 info->windows_by_xid = g_hash_table_new (g_direct_hash, g_direct_equal);
2999
3000 info->focus_window = meta_display_get_focus_window (display);
3001
3002 info->compositor_active = TRUE;
3003 info->overlays = 0;
3004 info->clip_changed = TRUE;
3005
3006 info->have_shadows = (g_getenv("META_DEBUG_NO_SHADOW") == NULL);
3007 if (info->have_shadows)
3008 {
3009 meta_verbose ("Enabling shadows\n");
3010 generate_shadows (info);
3011 }
3012 else
3013 meta_verbose ("Disabling shadows\n");
3014
3015 #ifdef HAVE_PRESENT
3016 if (xrc->has_present)
3017 {
3018 info->present_eid = XPresentSelectInput(xdisplay, info->output,
3019 PresentCompleteNotifyMask);
3020 info->use_present = TRUE;
3021 info->present_pending = FALSE;
3022 }
3023 else
3024 {
3025 info->use_present = FALSE;
3026 g_warning ("XPresent not available");
3027 }
3028 #endif /* HAVE_PRESENT */
3029
3030 XClearArea (xdisplay, info->output, 0, 0, 0, 0, TRUE);
3031
3032 meta_screen_set_cm_selection (screen);
3033
3034 /* Now we're up and running we can show the output if needed */
3035 show_overlay_window (screen, info->output);
3036 #endif
3037 }
3038
3039 static void
xrender_unmanage_screen(MetaCompositor * compositor,MetaScreen * screen)3040 xrender_unmanage_screen (MetaCompositor *compositor,
3041 MetaScreen *screen)
3042 {
3043 #ifdef HAVE_COMPOSITE_EXTENSIONS
3044 MetaDisplay *display = meta_screen_get_display (screen);
3045 Display *xdisplay = meta_display_get_xdisplay (display);
3046 MetaCompScreen *info;
3047 Window xroot = meta_screen_get_xroot (screen);
3048 GList *index;
3049
3050 info = meta_screen_get_compositor_data (screen);
3051
3052 /* This screen isn't managed */
3053 if (info == NULL)
3054 return;
3055
3056 hide_overlay_window (screen, info->output);
3057
3058 /* Destroy the windows */
3059 for (index = info->windows; index; index = index->next)
3060 {
3061 MetaCompWindow *cw = (MetaCompWindow *) index->data;
3062 free_win (cw, TRUE);
3063 }
3064 g_list_free (info->windows);
3065 g_hash_table_destroy (info->windows_by_xid);
3066
3067 if (info->root_picture)
3068 XRenderFreePicture (xdisplay, info->root_picture);
3069
3070 if (info->black_picture)
3071 XRenderFreePicture (xdisplay, info->black_picture);
3072
3073 if (info->have_shadows)
3074 {
3075 int i;
3076
3077 for (i = 0; i < LAST_SHADOW_TYPE; i++)
3078 g_free (info->shadows[i]->gaussian_map);
3079 }
3080
3081 XCompositeUnredirectSubwindows (xdisplay, xroot,
3082 CompositeRedirectManual);
3083 meta_screen_unset_cm_selection (screen);
3084
3085 XCompositeReleaseOverlayWindow (xdisplay, info->output);
3086
3087 g_free (info);
3088
3089 meta_screen_set_compositor_data (screen, NULL);
3090 #endif
3091 }
3092
3093 static void
xrender_set_updates(MetaCompositor * compositor,MetaWindow * window,gboolean updates)3094 xrender_set_updates (MetaCompositor *compositor,
3095 MetaWindow *window,
3096 gboolean updates)
3097 {
3098 #ifdef HAVE_COMPOSITE_EXTENSIONS
3099
3100 #endif
3101 }
3102
3103 static void
xrender_destroy(MetaCompositor * compositor)3104 xrender_destroy (MetaCompositor *compositor)
3105 {
3106 #ifdef HAVE_COMPOSITE_EXTENSIONS
3107 g_free (compositor);
3108 #endif
3109 }
3110
3111 #if 0
3112 /* Taking these out because they're empty and never called, and the
3113 * compiler complains -- tthurman
3114 */
3115
3116 static void
3117 xrender_begin_move (MetaCompositor *compositor,
3118 MetaWindow *window,
3119 MetaRectangle *initial,
3120 int grab_x,
3121 int grab_y)
3122 {
3123 #ifdef HAVE_COMPOSITE_EXTENSIONS
3124 #endif
3125 }
3126
3127 static void
3128 xrender_update_move (MetaCompositor *compositor,
3129 MetaWindow *window,
3130 int x,
3131 int y)
3132 {
3133 #ifdef HAVE_COMPOSITE_EXTENSIONS
3134 #endif
3135 }
3136
3137 static void
3138 xrender_end_move (MetaCompositor *compositor,
3139 MetaWindow *window)
3140 {
3141 #ifdef HAVE_COMPOSITE_EXTENSIONS
3142 #endif
3143 }
3144
3145 #endif /* 0 */
3146
3147 static void
xrender_free_window(MetaCompositor * compositor,MetaWindow * window)3148 xrender_free_window (MetaCompositor *compositor,
3149 MetaWindow *window)
3150 {
3151 #ifdef HAVE_COMPOSITE_EXTENSIONS
3152 MetaCompositorXRender *xrc;
3153 MetaFrame *frame;
3154 Window xwindow;
3155
3156 xrc = (MetaCompositorXRender *) compositor;
3157 frame = meta_window_get_frame (window);
3158 xwindow = None;
3159
3160 if (frame)
3161 {
3162 xwindow = meta_frame_get_xwindow (frame);
3163 }
3164 else
3165 {
3166 /* FIXME: When an undecorated window is hidden this is called, but the
3167 * window does not get readded if it is subsequentally shown again. See:
3168 * http://bugzilla.gnome.org/show_bug.cgi?id=504876
3169 */
3170 /* xwindow = meta_window_get_xwindow (window); */
3171 }
3172
3173 if (xwindow != None)
3174 destroy_win (xrc->display, xwindow, FALSE);
3175 #endif
3176 }
3177
3178 static void
xrender_process_event(MetaCompositor * compositor,XEvent * event,MetaWindow * window)3179 xrender_process_event (MetaCompositor *compositor,
3180 XEvent *event,
3181 MetaWindow *window)
3182 {
3183 #ifdef HAVE_COMPOSITE_EXTENSIONS
3184 MetaCompositorXRender *xrc = (MetaCompositorXRender *) compositor;
3185 /*
3186 * This trap is so that none of the compositor functions cause
3187 * X errors. This is really a hack, but I'm afraid I don't understand
3188 * enough about Marco/X to know how else you are supposed to do it
3189 */
3190 meta_error_trap_push (xrc->display);
3191 switch (event->type)
3192 {
3193 case CirculateNotify:
3194 process_circulate_notify (xrc, (XCirculateEvent *) event);
3195 break;
3196
3197 case ConfigureNotify:
3198 process_configure_notify (xrc, (XConfigureEvent *) event);
3199 break;
3200
3201 case PropertyNotify:
3202 process_property_notify (xrc, (XPropertyEvent *) event);
3203 break;
3204
3205 case Expose:
3206 process_expose (xrc, (XExposeEvent *) event);
3207 break;
3208
3209 case UnmapNotify:
3210 process_unmap (xrc, (XUnmapEvent *) event);
3211 break;
3212
3213 case MapNotify:
3214 process_map (xrc, (XMapEvent *) event);
3215 break;
3216
3217 case ReparentNotify:
3218 process_reparent (xrc, (XReparentEvent *) event, window);
3219 break;
3220
3221 case CreateNotify:
3222 process_create (xrc, (XCreateWindowEvent *) event, window);
3223 break;
3224
3225 case DestroyNotify:
3226 process_destroy (xrc, (XDestroyWindowEvent *) event);
3227 break;
3228
3229 case GenericEvent:
3230 process_generic (xrc, (XGenericEvent *) event);
3231 break;
3232
3233 default:
3234 if (event->type == meta_display_get_damage_event_base (xrc->display) + XDamageNotify)
3235 process_damage (xrc, (XDamageNotifyEvent *) event);
3236 #ifdef HAVE_SHAPE
3237 else if (event->type == meta_display_get_shape_event_base (xrc->display) + ShapeNotify)
3238 process_shape (xrc, (XShapeEvent *) event);
3239 #endif /* HAVE_SHAPE */
3240 else
3241 {
3242 meta_error_trap_pop (xrc->display, FALSE);
3243 return;
3244 }
3245 break;
3246 }
3247
3248 meta_error_trap_pop (xrc->display, FALSE);
3249 #ifndef USE_IDLE_REPAINT
3250 repair_display (xrc->display);
3251 #endif
3252
3253 return;
3254 #endif
3255 }
3256
3257 static cairo_surface_t *
xrender_get_window_surface(MetaCompositor * compositor,MetaWindow * window)3258 xrender_get_window_surface (MetaCompositor *compositor,
3259 MetaWindow *window)
3260 {
3261 #ifdef HAVE_COMPOSITE_EXTENSIONS
3262 MetaFrame *frame;
3263 Window xwindow;
3264 MetaScreen *screen;
3265 MetaCompWindow *cw;
3266 MetaCompositorXRender *xrc;
3267 Display *display;
3268 Pixmap pixmap;
3269
3270 frame = meta_window_get_frame (window);
3271
3272 if (frame)
3273 xwindow = meta_frame_get_xwindow (frame);
3274 else
3275 xwindow = meta_window_get_xwindow (window);
3276
3277 screen = meta_window_get_screen (window);
3278 cw = find_window_for_screen (screen, xwindow);
3279
3280 if (cw == NULL)
3281 return NULL;
3282
3283 xrc = (MetaCompositorXRender *) compositor;
3284 display = meta_display_get_xdisplay (xrc->display);
3285
3286 if (meta_window_is_shaded (window))
3287 pixmap = cw->shaded_back_pixmap;
3288 else
3289 pixmap = cw->back_pixmap;
3290
3291 return cairo_xlib_surface_create (display, pixmap, cw->attrs.visual,
3292 cw->attrs.width, cw->attrs.height);
3293 #endif
3294 }
3295
3296 static void
xrender_set_active_window(MetaCompositor * compositor,MetaScreen * screen,MetaWindow * window)3297 xrender_set_active_window (MetaCompositor *compositor,
3298 MetaScreen *screen,
3299 MetaWindow *window)
3300 {
3301 #ifdef HAVE_COMPOSITE_EXTENSIONS
3302 MetaCompositorXRender *xrc = (MetaCompositorXRender *) compositor;
3303 MetaDisplay *display;
3304 Display *xdisplay;
3305 MetaCompWindow *old_focus = NULL, *new_focus = NULL;
3306 MetaCompScreen *info = NULL;
3307 MetaWindow *old_focus_win = NULL;
3308
3309 if (compositor == NULL)
3310 return;
3311
3312 display = xrc->display;
3313 xdisplay = meta_display_get_xdisplay (display);
3314 info = meta_screen_get_compositor_data (screen);
3315
3316 if (info != NULL)
3317 {
3318 old_focus_win = info->focus_window;
3319 }
3320
3321 if (old_focus_win)
3322 {
3323 MetaFrame *f = meta_window_get_frame (old_focus_win);
3324
3325 old_focus = find_window_for_screen (screen,
3326 f ? meta_frame_get_xwindow (f) :
3327 meta_window_get_xwindow (old_focus_win));
3328 }
3329
3330 if (window)
3331 {
3332 MetaFrame *f = meta_window_get_frame (window);
3333 new_focus = find_window_for_screen (screen,
3334 f ? meta_frame_get_xwindow (f) :
3335 meta_window_get_xwindow (window));
3336 }
3337
3338 if (info != NULL)
3339 {
3340 info->focus_window = window;
3341 }
3342
3343 if (old_focus)
3344 {
3345 XserverRegion damage;
3346
3347 /* Tear down old shadows */
3348 old_focus->shadow_type = META_SHADOW_MEDIUM;
3349 determine_mode (display, screen, old_focus);
3350 old_focus->needs_shadow = window_has_shadow (old_focus);
3351
3352 if (old_focus->attrs.map_state == IsViewable)
3353 {
3354 if (old_focus->shadow)
3355 {
3356 XRenderFreePicture (xdisplay, old_focus->shadow);
3357 old_focus->shadow = None;
3358 }
3359
3360 if (old_focus->extents)
3361 {
3362 damage = XFixesCreateRegion (xdisplay, NULL, 0);
3363 XFixesCopyRegion (xdisplay, damage, old_focus->extents);
3364 XFixesDestroyRegion (xdisplay, old_focus->extents);
3365 }
3366 else
3367 damage = None;
3368
3369 /* Build new extents */
3370 old_focus->extents = win_extents (old_focus);
3371
3372 if (damage)
3373 XFixesUnionRegion (xdisplay, damage, damage, old_focus->extents);
3374 else
3375 {
3376 damage = XFixesCreateRegion (xdisplay, NULL, 0);
3377 XFixesCopyRegion (xdisplay, damage, old_focus->extents);
3378 }
3379
3380 dump_xserver_region ("resize_win", display, damage);
3381 add_damage (screen, damage);
3382
3383 if (info != NULL)
3384 {
3385 info->clip_changed = TRUE;
3386 }
3387 }
3388 }
3389
3390 if (new_focus)
3391 {
3392 XserverRegion damage;
3393
3394 new_focus->shadow_type = META_SHADOW_LARGE;
3395 determine_mode (display, screen, new_focus);
3396 new_focus->needs_shadow = window_has_shadow (new_focus);
3397
3398 if (new_focus->shadow)
3399 {
3400 XRenderFreePicture (xdisplay, new_focus->shadow);
3401 new_focus->shadow = None;
3402 }
3403
3404 if (new_focus->extents)
3405 {
3406 damage = XFixesCreateRegion (xdisplay, NULL, 0);
3407 XFixesCopyRegion (xdisplay, damage, new_focus->extents);
3408 XFixesDestroyRegion (xdisplay, new_focus->extents);
3409 }
3410 else
3411 damage = None;
3412
3413 /* Build new extents */
3414 new_focus->extents = win_extents (new_focus);
3415
3416 if (damage)
3417 XFixesUnionRegion (xdisplay, damage, damage, new_focus->extents);
3418 else
3419 {
3420 damage = XFixesCreateRegion (xdisplay, NULL, 0);
3421 XFixesCopyRegion (xdisplay, damage, new_focus->extents);
3422 }
3423
3424 dump_xserver_region ("resize_win", display, damage);
3425 add_damage (screen, damage);
3426
3427 if (info != NULL)
3428 {
3429 info->clip_changed = TRUE;
3430 }
3431 }
3432 #ifdef USE_IDLE_REPAINT
3433 add_repair (display);
3434 #endif
3435 #endif
3436 }
3437
3438 static void
xrender_maximize_window(MetaCompositor * compositor,MetaWindow * window)3439 xrender_maximize_window (MetaCompositor *compositor,
3440 MetaWindow *window)
3441 {
3442 #ifdef HAVE_COMPOSITE_EXTENSIONS
3443 MetaFrame *frame = meta_window_get_frame (window);
3444 Window xid = frame ? meta_frame_get_xwindow (frame) : meta_window_get_xwindow (window);
3445 MetaCompWindow *cw = find_window_in_display (meta_window_get_display (window), xid);
3446
3447 if (!cw)
3448 return;
3449
3450 cw->needs_shadow = window_has_shadow (cw);
3451 #endif
3452 }
3453
3454 static void
xrender_unmaximize_window(MetaCompositor * compositor,MetaWindow * window)3455 xrender_unmaximize_window (MetaCompositor *compositor,
3456 MetaWindow *window)
3457 {
3458 #ifdef HAVE_COMPOSITE_EXTENSIONS
3459 MetaFrame *frame = meta_window_get_frame (window);
3460 Window xid = frame ? meta_frame_get_xwindow (frame) : meta_window_get_xwindow (window);
3461 MetaCompWindow *cw = find_window_in_display (meta_window_get_display (window), xid);
3462
3463 if (!cw)
3464 return;
3465
3466 cw->needs_shadow = window_has_shadow (cw);
3467 #endif
3468 }
3469
3470 static MetaCompositor comp_info = {
3471 xrender_destroy,
3472 xrender_manage_screen,
3473 xrender_unmanage_screen,
3474 xrender_add_window,
3475 xrender_remove_window,
3476 xrender_set_updates,
3477 xrender_process_event,
3478 xrender_get_window_surface,
3479 xrender_set_active_window,
3480 xrender_free_window,
3481 xrender_maximize_window,
3482 xrender_unmaximize_window,
3483 };
3484
3485 MetaCompositor *
meta_compositor_xrender_new(MetaDisplay * display)3486 meta_compositor_xrender_new (MetaDisplay *display)
3487 {
3488 #ifdef HAVE_COMPOSITE_EXTENSIONS
3489 char *atom_names[] = {
3490 "_XROOTPMAP_ID",
3491 "_XSETROOT_ID",
3492 "_NET_WM_WINDOW_OPACITY",
3493 "_NET_WM_WINDOW_TYPE_DND",
3494 "_NET_WM_WINDOW_TYPE",
3495 "_NET_WM_WINDOW_TYPE_DESKTOP",
3496 "_NET_WM_WINDOW_TYPE_DOCK",
3497 "_NET_WM_WINDOW_TYPE_MENU",
3498 "_NET_WM_WINDOW_TYPE_DIALOG",
3499 "_NET_WM_WINDOW_TYPE_NORMAL",
3500 "_NET_WM_WINDOW_TYPE_UTILITY",
3501 "_NET_WM_WINDOW_TYPE_SPLASH",
3502 "_NET_WM_WINDOW_TYPE_TOOLBAR",
3503 "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU",
3504 "_NET_WM_WINDOW_TYPE_TOOLTIP"
3505 };
3506 Atom atoms[G_N_ELEMENTS(atom_names)];
3507 MetaCompositorXRender *xrc;
3508 MetaCompositor *compositor;
3509 Display *xdisplay = meta_display_get_xdisplay (display);
3510
3511 xrc = g_new (MetaCompositorXRender, 1);
3512 xrc->compositor = comp_info;
3513
3514 compositor = (MetaCompositor *) xrc;
3515
3516 xrc->display = display;
3517
3518 meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
3519 XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names),
3520 False, atoms);
3521
3522 xrc->atom_x_root_pixmap = atoms[0];
3523 xrc->atom_x_set_root = atoms[1];
3524 xrc->atom_net_wm_window_opacity = atoms[2];
3525 xrc->atom_net_wm_window_type_dnd = atoms[3];
3526 xrc->atom_net_wm_window_type = atoms[4];
3527 xrc->atom_net_wm_window_type_desktop = atoms[5];
3528 xrc->atom_net_wm_window_type_dock = atoms[6];
3529 xrc->atom_net_wm_window_type_menu = atoms[7];
3530 xrc->atom_net_wm_window_type_dialog = atoms[8];
3531 xrc->atom_net_wm_window_type_normal = atoms[9];
3532 xrc->atom_net_wm_window_type_utility = atoms[10];
3533 xrc->atom_net_wm_window_type_splash = atoms[11];
3534 xrc->atom_net_wm_window_type_toolbar = atoms[12];
3535 xrc->atom_net_wm_window_type_dropdown_menu = atoms[13];
3536 xrc->atom_net_wm_window_type_tooltip = atoms[14];
3537 xrc->show_redraw = FALSE;
3538 xrc->debug = FALSE;
3539 #ifdef HAVE_PRESENT
3540 xrc->has_present = XPresentQueryExtension(xdisplay, &xrc->present_major, NULL, NULL);
3541 #endif /* HAVE_PRESENT */
3542
3543 #ifdef USE_IDLE_REPAINT
3544 meta_verbose ("Using idle repaint\n");
3545 xrc->repaint_id = 0;
3546 #endif
3547
3548 xrc->enabled = TRUE;
3549 g_timeout_add (2000, (GSourceFunc) timeout_debug, xrc);
3550
3551 return compositor;
3552 #else
3553 return NULL;
3554 #endif
3555 }
3556
3557 #endif /* HAVE_COMPOSITE_EXTENSIONS */
3558
3559