00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #define _GNU_SOURCE
00025 #define _XOPEN_SOURCE 500
00026
00027 #include <config.h>
00028
00029 #include <stdlib.h>
00030 #include <string.h>
00031 #include <math.h>
00032 #include <unistd.h>
00033
00034 #include <gdk/gdk.h>
00035
00036 #include "display.h"
00037 #include "screen.h"
00038 #include "frame.h"
00039 #include "errors.h"
00040 #include "window.h"
00041 #include "compositor-private.h"
00042 #include "compositor-xrender.h"
00043 #include "xprops.h"
00044 #include <X11/Xatom.h>
00045 #include <X11/extensions/shape.h>
00046 #include <X11/extensions/Xcomposite.h>
00047 #include <X11/extensions/Xdamage.h>
00048 #include <X11/extensions/Xfixes.h>
00049 #include <X11/extensions/Xrender.h>
00050
00051 #if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 2
00052 #define HAVE_NAME_WINDOW_PIXMAP 1
00053 #endif
00054
00055 #if COMPOSITE_MAJOR > 0 || COMPOSITE_MINOR >= 3
00056 #define HAVE_COW 1
00057 #else
00058
00059 #endif
00060
00061 #define USE_IDLE_REPAINT 1
00062
00063 #ifdef HAVE_COMPOSITE_EXTENSIONS
00064 static inline gboolean
00065 composite_at_least_version (MetaDisplay *display,
00066 int maj, int min)
00067 {
00068 static int major = -1;
00069 static int minor = -1;
00070
00071 if (major == -1)
00072 meta_display_get_compositor_version (display, &major, &minor);
00073
00074 return (major > maj || (major == maj && minor >= min));
00075 }
00076
00077 #define have_name_window_pixmap(display) \
00078 composite_at_least_version (display, 0, 2)
00079 #define have_cow(display) \
00080 composite_at_least_version (display, 0, 3)
00081
00082 #endif
00083
00084 typedef enum _MetaCompWindowType
00085 {
00086 META_COMP_WINDOW_NORMAL,
00087 META_COMP_WINDOW_DND,
00088 META_COMP_WINDOW_DESKTOP,
00089 META_COMP_WINDOW_DOCK,
00090 META_COMP_WINDOW_MENU,
00091 META_COMP_WINDOW_DROP_DOWN_MENU,
00092 META_COMP_WINDOW_TOOLTIP,
00093 } MetaCompWindowType;
00094
00095 typedef enum _MetaShadowType
00096 {
00097 META_SHADOW_SMALL,
00098 META_SHADOW_MEDIUM,
00099 META_SHADOW_LARGE,
00100 LAST_SHADOW_TYPE
00101 } MetaShadowType;
00102
00103 typedef struct _MetaCompositorXRender
00104 {
00105 MetaCompositor compositor;
00106
00107 MetaDisplay *display;
00108
00109 Atom atom_x_root_pixmap;
00110 Atom atom_x_set_root;
00111 Atom atom_net_wm_window_opacity;
00112 Atom atom_net_wm_window_type_dnd;
00113
00114 Atom atom_net_wm_window_type;
00115 Atom atom_net_wm_window_type_desktop;
00116 Atom atom_net_wm_window_type_dock;
00117 Atom atom_net_wm_window_type_menu;
00118 Atom atom_net_wm_window_type_dialog;
00119 Atom atom_net_wm_window_type_normal;
00120 Atom atom_net_wm_window_type_utility;
00121 Atom atom_net_wm_window_type_splash;
00122 Atom atom_net_wm_window_type_toolbar;
00123 Atom atom_net_wm_window_type_dropdown_menu;
00124 Atom atom_net_wm_window_type_tooltip;
00125
00126 #ifdef USE_IDLE_REPAINT
00127 guint repaint_id;
00128 #endif
00129 guint enabled : 1;
00130 guint show_redraw : 1;
00131 guint debug : 1;
00132 } MetaCompositorXRender;
00133
00134 typedef struct _conv
00135 {
00136 int size;
00137 double *data;
00138 } conv;
00139
00140 typedef struct _shadow
00141 {
00142 conv *gaussian_map;
00143 guchar *shadow_corner;
00144 guchar *shadow_top;
00145 } shadow;
00146
00147 typedef struct _MetaCompScreen
00148 {
00149 MetaScreen *screen;
00150 GList *windows;
00151 GHashTable *windows_by_xid;
00152
00153 MetaWindow *focus_window;
00154
00155 Window output;
00156
00157 gboolean have_shadows;
00158 shadow *shadows[LAST_SHADOW_TYPE];
00159
00160 Picture root_picture;
00161 Picture root_buffer;
00162 Picture black_picture;
00163 Picture trans_black_picture;
00164 Picture root_tile;
00165 XserverRegion all_damage;
00166
00167 guint overlays;
00168 gboolean compositor_active;
00169 gboolean clip_changed;
00170
00171 GSList *dock_windows;
00172 } MetaCompScreen;
00173
00174 typedef struct _MetaCompWindow
00175 {
00176 MetaScreen *screen;
00177 MetaWindow *window;
00178 Window id;
00179 XWindowAttributes attrs;
00180
00181 #ifdef HAVE_NAME_WINDOW_PIXMAP
00182 Pixmap back_pixmap;
00183
00184
00185
00186
00187
00188 Pixmap shaded_back_pixmap;
00189 #endif
00190
00191 int mode;
00192
00193 gboolean damaged;
00194 gboolean shaped;
00195
00196 MetaCompWindowType type;
00197
00198 Damage damage;
00199 Picture picture;
00200 Picture alpha_pict;
00201
00202 gboolean needs_shadow;
00203 MetaShadowType shadow_type;
00204 Picture shadow_pict;
00205
00206 XserverRegion border_size;
00207 XserverRegion extents;
00208
00209 Picture shadow;
00210 int shadow_dx;
00211 int shadow_dy;
00212 int shadow_width;
00213 int shadow_height;
00214
00215 guint opacity;
00216
00217 XserverRegion border_clip;
00218
00219 gboolean updates_frozen;
00220 gboolean update_pending;
00221 } MetaCompWindow;
00222
00223 #define OPAQUE 0xffffffff
00224
00225 #define WINDOW_SOLID 0
00226 #define WINDOW_ARGB 1
00227
00228 #define SHADOW_SMALL_RADIUS 3.0
00229 #define SHADOW_MEDIUM_RADIUS 6.0
00230 #define SHADOW_LARGE_RADIUS 12.0
00231
00232 #define SHADOW_SMALL_OFFSET_X (SHADOW_SMALL_RADIUS * -3 / 2)
00233 #define SHADOW_SMALL_OFFSET_Y (SHADOW_SMALL_RADIUS * -3 / 2)
00234 #define SHADOW_MEDIUM_OFFSET_X (SHADOW_MEDIUM_RADIUS * -3 / 2)
00235 #define SHADOW_MEDIUM_OFFSET_Y (SHADOW_MEDIUM_RADIUS * -5 / 4)
00236 #define SHADOW_LARGE_OFFSET_X -15
00237 #define SHADOW_LARGE_OFFSET_Y -15
00238
00239 #define SHADOW_OPACITY 0.66
00240
00241 #define TRANS_OPACITY 0.75
00242
00243 #define DISPLAY_COMPOSITOR(display) ((MetaCompositorXRender *) meta_display_get_compositor (display))
00244
00245
00246 static double
00247 gaussian (double r,
00248 double x,
00249 double y)
00250 {
00251 return ((1 / (sqrt (2 * G_PI * r))) *
00252 exp ((- (x * x + y * y)) / (2 * r * r)));
00253 }
00254
00255 static conv *
00256 make_gaussian_map (double r)
00257 {
00258 conv *c;
00259 int size, centre;
00260 int x, y;
00261 double t, g;
00262
00263 size = ((int) ceil ((r * 3)) + 1) & ~1;
00264 centre = size / 2;
00265 c = g_malloc (sizeof (conv) + size * size * sizeof (double));
00266 c->size = size;
00267 c->data = (double *) (c + 1);
00268 t = 0.0;
00269
00270 for (y = 0; y < size; y++)
00271 {
00272 for (x = 0; x < size; x++)
00273 {
00274 g = gaussian (r, (double) (x - centre), (double) (y - centre));
00275 t += g;
00276 c->data[y * size + x] = g;
00277 }
00278 }
00279
00280 for (y = 0; y < size; y++)
00281 {
00282 for (x = 0; x < size; x++)
00283 {
00284 c->data[y * size + x] /= t;
00285 }
00286 }
00287
00288 return c;
00289 }
00290
00291 static void
00292 dump_xserver_region (const char *location,
00293 MetaDisplay *display,
00294 XserverRegion region)
00295 {
00296 MetaCompositorXRender *compositor = DISPLAY_COMPOSITOR (display);
00297 Display *xdisplay = meta_display_get_xdisplay (display);
00298 int nrects;
00299 XRectangle *rects;
00300 XRectangle bounds;
00301
00302 if (!compositor->debug)
00303 return;
00304
00305 if (region)
00306 {
00307 rects = XFixesFetchRegionAndBounds (xdisplay, region, &nrects, &bounds);
00308 if (nrects > 0)
00309 {
00310 int i;
00311 fprintf (stderr, "%s (XSR): %d rects, bounds: %d,%d (%d,%d)\n",
00312 location, nrects, bounds.x, bounds.y, bounds.width, bounds.height);
00313 for (i = 1; i < nrects; i++)
00314 fprintf (stderr, "\t%d,%d (%d,%d)\n",
00315 rects[i].x, rects[i].y, rects[i].width, rects[i].height);
00316 }
00317 else
00318 fprintf (stderr, "%s (XSR): empty\n", location);
00319 XFree (rects);
00320 }
00321 else
00322 fprintf (stderr, "%s (XSR): null\n", location);
00323 }
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341 static guchar
00342 sum_gaussian (conv *map,
00343 double opacity,
00344 int x,
00345 int y,
00346 int width,
00347 int height)
00348 {
00349 double *g_data, *g_line;
00350 double v;
00351 int fx, fy;
00352 int fx_start, fx_end;
00353 int fy_start, fy_end;
00354 int g_size, centre;
00355
00356 g_line = map->data;
00357 g_size = map->size;
00358 centre = g_size / 2;
00359 fx_start = centre - x;
00360 if (fx_start < 0)
00361 fx_start = 0;
00362
00363 fx_end = width + centre - x;
00364 if (fx_end > g_size)
00365 fx_end = g_size;
00366
00367 fy_start = centre - y;
00368 if (fy_start < 0)
00369 fy_start = 0;
00370
00371 fy_end = height + centre - y;
00372 if (fy_end > g_size)
00373 fy_end = g_size;
00374
00375 g_line = g_line + fy_start * g_size + fx_start;
00376
00377 v = 0.0;
00378 for (fy = fy_start; fy < fy_end; fy++)
00379 {
00380 g_data = g_line;
00381 g_line += g_size;
00382
00383 for (fx = fx_start; fx < fx_end; fx++)
00384 v += *g_data++;
00385 }
00386
00387 if (v > 1.0)
00388 v = 1.0;
00389
00390 return ((guchar) (v * opacity * 255.0));
00391 }
00392
00393
00394 static void
00395 presum_gaussian (shadow *shad)
00396 {
00397 int centre;
00398 int opacity, x, y;
00399 int msize;
00400 conv *map;
00401
00402 map = shad->gaussian_map;
00403 msize = map->size;
00404 centre = map->size / 2;
00405
00406 if (shad->shadow_corner)
00407 g_free (shad->shadow_corner);
00408 if (shad->shadow_top)
00409 g_free (shad->shadow_top);
00410
00411 shad->shadow_corner = (guchar *)(g_malloc ((msize + 1) * (msize + 1) * 26));
00412 shad->shadow_top = (guchar *) (g_malloc ((msize + 1) * 26));
00413
00414 for (x = 0; x <= msize; x++)
00415 {
00416
00417 shad->shadow_top[25 * (msize + 1) + x] =
00418 sum_gaussian (map, 1, x - centre, centre, msize * 2, msize * 2);
00419 for (opacity = 0; opacity < 25; opacity++)
00420 {
00421 shad->shadow_top[opacity * (msize + 1) + x] =
00422 shad->shadow_top[25 * (msize + 1) + x] * opacity / 25;
00423 }
00424
00425 for (y = 0; y <= x; y++)
00426 {
00427 shad->shadow_corner[25 * (msize + 1) * (msize + 1)
00428 + y * (msize + 1)
00429 + x]
00430 = sum_gaussian (map, 1, x - centre, y - centre,
00431 msize * 2, msize * 2);
00432
00433 shad->shadow_corner[25 * (msize + 1) * (msize + 1)
00434 + x * (msize + 1) + y] =
00435 shad->shadow_corner[25 * (msize + 1) * (msize + 1)
00436 + y * (msize + 1) + x];
00437
00438 for (opacity = 0; opacity < 25; opacity++)
00439 {
00440 shad->shadow_corner[opacity * (msize + 1) * (msize + 1)
00441 + y * (msize + 1) + x]
00442 = shad->shadow_corner[opacity * (msize + 1) * (msize + 1)
00443 + x * (msize + 1) + y]
00444 = shad->shadow_corner[25 * (msize + 1) * (msize + 1)
00445 + y * (msize + 1) + x] * opacity / 25;
00446 }
00447 }
00448 }
00449 }
00450
00451 static void
00452 generate_shadows (MetaCompScreen *info)
00453 {
00454 double radii[LAST_SHADOW_TYPE] = {SHADOW_SMALL_RADIUS,
00455 SHADOW_MEDIUM_RADIUS,
00456 SHADOW_LARGE_RADIUS};
00457 int i;
00458
00459 for (i = 0; i < LAST_SHADOW_TYPE; i++) {
00460 shadow *shad = g_new0 (shadow, 1);
00461
00462 shad->gaussian_map = make_gaussian_map (radii[i]);
00463 presum_gaussian (shad);
00464
00465 info->shadows[i] = shad;
00466 }
00467 }
00468
00469 static XImage *
00470 make_shadow (MetaDisplay *display,
00471 MetaScreen *screen,
00472 MetaShadowType shadow_type,
00473 double opacity,
00474 int width,
00475 int height)
00476 {
00477 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
00478 Display *xdisplay = meta_display_get_xdisplay (display);
00479 XImage *ximage;
00480 guchar *data;
00481 shadow *shad;
00482 int msize;
00483 int ylimit, xlimit;
00484 int swidth, sheight;
00485 int centre;
00486 int x, y;
00487 guchar d;
00488 int x_diff;
00489 int opacity_int = (int)(opacity * 25);
00490 int screen_number = meta_screen_get_screen_number (screen);
00491
00492 if (info==NULL)
00493 {
00494 return NULL;
00495 }
00496
00497 shad = info->shadows[shadow_type];
00498 msize = shad->gaussian_map->size;
00499 swidth = width + msize;
00500 sheight = height + msize;
00501 centre = msize / 2;
00502
00503 data = g_malloc (swidth * sheight * sizeof (guchar));
00504
00505 ximage = XCreateImage (xdisplay, DefaultVisual (xdisplay, screen_number),
00506 8, ZPixmap, 0, (char *) data,
00507 swidth, sheight, 8, swidth * sizeof (guchar));
00508 if (!ximage)
00509 {
00510 g_free (data);
00511 return NULL;
00512 }
00513
00514
00515
00516
00517
00518
00519
00520
00521 if (msize > 0)
00522 d = shad->shadow_top[opacity_int * (msize + 1) + msize];
00523 else
00524 d = sum_gaussian (shad->gaussian_map, opacity, centre,
00525 centre, width, height);
00526 memset (data, d, sheight * swidth);
00527
00528
00529
00530
00531 ylimit = msize;
00532 if (ylimit > sheight / 2)
00533 ylimit = (sheight + 1) / 2;
00534
00535 xlimit = msize;
00536 if (xlimit > swidth / 2)
00537 xlimit = (swidth + 1) / 2;
00538
00539 for (y = 0; y < ylimit; y++)
00540 {
00541 for (x = 0; x < xlimit; x++)
00542 {
00543
00544 if (xlimit == msize && ylimit == msize)
00545 d = shad->shadow_corner[opacity_int * (msize + 1) * (msize + 1) + y * (msize + 1) + x];
00546 else
00547 d = sum_gaussian (shad->gaussian_map, opacity, x - centre,
00548 y - centre, width, height);
00549
00550 data[y * swidth + x] = d;
00551 data[(sheight - y - 1) * swidth + x] = d;
00552 data[(sheight - y - 1) * swidth + (swidth - x - 1)] = d;
00553 data[y * swidth + (swidth - x - 1)] = d;
00554 }
00555 }
00556
00557
00558 x_diff = swidth - (msize * 2);
00559 if (x_diff > 0 && ylimit > 0)
00560 {
00561 for (y = 0; y < ylimit; y++)
00562 {
00563 if (ylimit == msize)
00564 d = shad->shadow_top[opacity_int * (msize + 1) + y];
00565 else
00566 d = sum_gaussian (shad->gaussian_map, opacity, centre,
00567 y - centre, width, height);
00568
00569 memset (&data[y * swidth + msize], d, x_diff);
00570 memset (&data[(sheight - y - 1) * swidth + msize], d, x_diff);
00571 }
00572 }
00573
00574
00575
00576
00577 for (x = 0; x < xlimit; x++)
00578 {
00579 if (xlimit == msize)
00580 d = shad->shadow_top[opacity_int * (msize + 1) + x];
00581 else
00582 d = sum_gaussian (shad->gaussian_map, opacity, x - centre,
00583 centre, width, height);
00584
00585 for (y = msize; y < sheight - msize; y++)
00586 {
00587 data[y * swidth + x] = d;
00588 data[y * swidth + (swidth - x - 1)] = d;
00589 }
00590 }
00591
00592 return ximage;
00593 }
00594
00595 static Picture
00596 shadow_picture (MetaDisplay *display,
00597 MetaScreen *screen,
00598 MetaShadowType shadow_type,
00599 double opacity,
00600 Picture alpha_pict,
00601 int width,
00602 int height,
00603 int *wp,
00604 int *hp)
00605 {
00606 Display *xdisplay = meta_display_get_xdisplay (display);
00607 XImage *shadow_image;
00608 Pixmap shadow_pixmap;
00609 Picture shadow_picture;
00610 Window xroot = meta_screen_get_xroot (screen);
00611 GC gc;
00612
00613 shadow_image = make_shadow (display, screen, shadow_type,
00614 opacity, width, height);
00615 if (!shadow_image)
00616 return None;
00617
00618 shadow_pixmap = XCreatePixmap (xdisplay, xroot,
00619 shadow_image->width, shadow_image->height, 8);
00620 if (!shadow_pixmap)
00621 {
00622 XDestroyImage (shadow_image);
00623 return None;
00624 }
00625
00626 shadow_picture = XRenderCreatePicture (xdisplay, shadow_pixmap,
00627 XRenderFindStandardFormat (xdisplay,
00628 PictStandardA8),
00629 0, 0);
00630 if (!shadow_picture)
00631 {
00632 XDestroyImage (shadow_image);
00633 XFreePixmap (xdisplay, shadow_pixmap);
00634 return None;
00635 }
00636
00637 gc = XCreateGC (xdisplay, shadow_pixmap, 0, 0);
00638 if (!gc)
00639 {
00640 XDestroyImage (shadow_image);
00641 XFreePixmap (xdisplay, shadow_pixmap);
00642 XRenderFreePicture (xdisplay, shadow_picture);
00643 return None;
00644 }
00645
00646 XPutImage (xdisplay, shadow_pixmap, gc, shadow_image, 0, 0, 0, 0,
00647 shadow_image->width, shadow_image->height);
00648 *wp = shadow_image->width;
00649 *hp = shadow_image->height;
00650
00651 XFreeGC (xdisplay, gc);
00652 XDestroyImage (shadow_image);
00653 XFreePixmap (xdisplay, shadow_pixmap);
00654
00655 return shadow_picture;
00656 }
00657
00658 static MetaCompWindow *
00659 find_window_for_screen (MetaScreen *screen,
00660 Window xwindow)
00661 {
00662 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
00663
00664 if (info == NULL)
00665 return NULL;
00666
00667 return g_hash_table_lookup (info->windows_by_xid, (gpointer) xwindow);
00668 }
00669
00670 static MetaCompWindow *
00671 find_window_in_display (MetaDisplay *display,
00672 Window xwindow)
00673 {
00674 GSList *index;
00675
00676 for (index = meta_display_get_screens (display); index; index = index->next)
00677 {
00678 MetaCompWindow *cw = find_window_for_screen (index->data, xwindow);
00679
00680 if (cw != NULL)
00681 return cw;
00682 }
00683
00684 return NULL;
00685 }
00686
00687 static MetaCompWindow *
00688 find_window_for_child_window_in_display (MetaDisplay *display,
00689 Window xwindow)
00690 {
00691 Window ignored1, *ignored2;
00692 Window parent;
00693 guint ignored_children;
00694
00695 XQueryTree (meta_display_get_xdisplay (display), xwindow, &ignored1,
00696 &parent, &ignored2, &ignored_children);
00697
00698 if (parent != None)
00699 return find_window_in_display (display, parent);
00700
00701 return NULL;
00702 }
00703
00704 static Picture
00705 solid_picture (MetaDisplay *display,
00706 MetaScreen *screen,
00707 gboolean argb,
00708 double a,
00709 double r,
00710 double g,
00711 double b)
00712 {
00713 Display *xdisplay = meta_display_get_xdisplay (display);
00714 Pixmap pixmap;
00715 Picture picture;
00716 XRenderPictureAttributes pa;
00717 XRenderPictFormat *render_format;
00718 XRenderColor c;
00719 Window xroot = meta_screen_get_xroot (screen);
00720
00721 render_format = XRenderFindStandardFormat (xdisplay,
00722 argb ? PictStandardARGB32 : PictStandardA8);
00723
00724 pixmap = XCreatePixmap (xdisplay, xroot, 1, 1, argb ? 32 : 8);
00725 g_return_val_if_fail (pixmap != None, None);
00726
00727 pa.repeat = TRUE;
00728 picture = XRenderCreatePicture (xdisplay, pixmap, render_format,
00729 CPRepeat, &pa);
00730 if (picture == None)
00731 {
00732 XFreePixmap (xdisplay, pixmap);
00733 g_warning ("(picture != None) failed");
00734 return None;
00735 }
00736
00737 c.alpha = a * 0xffff;
00738 c.red = r * 0xffff;
00739 c.green = g * 0xffff;
00740 c.blue = b * 0xffff;
00741
00742 XRenderFillRectangle (xdisplay, PictOpSrc, picture, &c, 0, 0, 1, 1);
00743 XFreePixmap (xdisplay, pixmap);
00744
00745 return picture;
00746 }
00747
00748 static Picture
00749 root_tile (MetaScreen *screen)
00750 {
00751 MetaDisplay *display = meta_screen_get_display (screen);
00752 Display *xdisplay = meta_display_get_xdisplay (display);
00753 Picture picture;
00754 Pixmap pixmap;
00755 gboolean fill = FALSE;
00756 XRenderPictureAttributes pa;
00757 XRenderPictFormat *format;
00758 int p;
00759 Atom background_atoms[2];
00760 Atom pixmap_atom;
00761 int screen_number = meta_screen_get_screen_number (screen);
00762 Window xroot = meta_screen_get_xroot (screen);
00763
00764 pixmap = None;
00765 background_atoms[0] = DISPLAY_COMPOSITOR (display)->atom_x_root_pixmap;
00766 background_atoms[1] = DISPLAY_COMPOSITOR (display)->atom_x_set_root;
00767
00768 pixmap_atom = XInternAtom (xdisplay, "PIXMAP", False);
00769 for (p = 0; p < 2; p++)
00770 {
00771 Atom actual_type;
00772 int actual_format;
00773 gulong nitems, bytes_after;
00774 guchar *prop;
00775
00776 if (XGetWindowProperty (xdisplay, xroot,
00777 background_atoms[p],
00778 0, 4, FALSE, AnyPropertyType,
00779 &actual_type, &actual_format,
00780 &nitems, &bytes_after, &prop) == Success)
00781 {
00782 if (actual_type == pixmap_atom &&
00783 actual_format == 32 &&
00784 nitems == 1)
00785 {
00786 memcpy (&pixmap, prop, 4);
00787 XFree (prop);
00788 fill = FALSE;
00789 break;
00790 }
00791 }
00792 }
00793
00794 if (!pixmap)
00795 {
00796 pixmap = XCreatePixmap (xdisplay, xroot, 1, 1,
00797 DefaultDepth (xdisplay, screen_number));
00798 g_return_val_if_fail (pixmap != None, None);
00799 fill = TRUE;
00800 }
00801
00802 pa.repeat = TRUE;
00803 format = XRenderFindVisualFormat (xdisplay, DefaultVisual (xdisplay,
00804 screen_number));
00805 g_return_val_if_fail (format != NULL, None);
00806
00807 picture = XRenderCreatePicture (xdisplay, pixmap, format, CPRepeat, &pa);
00808 if ((picture != None) && (fill))
00809 {
00810 XRenderColor c;
00811
00812
00813 c.red = 0x8080;
00814 c.green = 0x8080;
00815 c.blue = 0x8080;
00816 c.alpha = 0xffff;
00817
00818 XRenderFillRectangle (xdisplay, PictOpSrc, picture, &c, 0, 0, 1, 1);
00819 XFreePixmap (xdisplay, pixmap);
00820 }
00821
00822 return picture;
00823 }
00824
00825 static Picture
00826 create_root_buffer (MetaScreen *screen)
00827 {
00828 MetaDisplay *display = meta_screen_get_display (screen);
00829 Display *xdisplay = meta_display_get_xdisplay (display);
00830 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
00831 Picture pict;
00832 XRenderPictFormat *format;
00833 Pixmap root_pixmap;
00834 Visual *visual;
00835 int depth, screen_width, screen_height, screen_number;
00836
00837 if (info == NULL)
00838 {
00839 return None;
00840 }
00841
00842 meta_screen_get_size (screen, &screen_width, &screen_height);
00843 screen_number = meta_screen_get_screen_number (screen);
00844 visual = DefaultVisual (xdisplay, screen_number);
00845 depth = DefaultDepth (xdisplay, screen_number);
00846
00847 format = XRenderFindVisualFormat (xdisplay, visual);
00848 g_return_val_if_fail (format != NULL, None);
00849
00850 root_pixmap = XCreatePixmap (xdisplay, info->output,
00851 screen_width, screen_height, depth);
00852 g_return_val_if_fail (root_pixmap != None, None);
00853
00854 pict = XRenderCreatePicture (xdisplay, root_pixmap, format, 0, NULL);
00855 XFreePixmap (xdisplay, root_pixmap);
00856
00857 return pict;
00858 }
00859
00860 static void
00861 paint_root (MetaScreen *screen,
00862 Picture root_buffer)
00863 {
00864 MetaDisplay *display = meta_screen_get_display (screen);
00865 Display *xdisplay = meta_display_get_xdisplay (display);
00866 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
00867 int width, height;
00868
00869 if (info == NULL)
00870 {
00871 return;
00872 }
00873
00874 g_return_if_fail (root_buffer != None);
00875
00876 if (info->root_tile == None)
00877 {
00878 info->root_tile = root_tile (screen);
00879 g_return_if_fail (info->root_tile != None);
00880 }
00881
00882 meta_screen_get_size (screen, &width, &height);
00883 XRenderComposite (xdisplay, PictOpSrc, info->root_tile, None, root_buffer,
00884 0, 0, 0, 0, 0, 0, width, height);
00885 }
00886
00887 static gboolean
00888 window_has_shadow (MetaCompWindow *cw)
00889 {
00890 MetaCompScreen *info = meta_screen_get_compositor_data (cw->screen);
00891
00892 if (info == NULL || info->have_shadows == FALSE)
00893 return FALSE;
00894
00895
00896
00897
00898 if (cw->window)
00899 {
00900 if (meta_window_get_frame (cw->window)) {
00901 meta_verbose ("Window has shadow because it has a frame\n");
00902 return TRUE;
00903 }
00904 }
00905
00906
00907 if (cw->shaped) {
00908 meta_verbose ("Window has no shadow as it is shaped\n");
00909 return FALSE;
00910 }
00911
00912
00913 if (cw->type == META_COMP_WINDOW_DND ||
00914 cw->type == META_COMP_WINDOW_DESKTOP) {
00915 meta_verbose ("Window has no shadow as it is DND or Desktop\n");
00916 return FALSE;
00917 }
00918
00919 if (cw->mode != WINDOW_ARGB) {
00920 meta_verbose ("Window has shadow as it is not ARGB\n");
00921 return TRUE;
00922 }
00923
00924 if (cw->type == META_COMP_WINDOW_MENU ||
00925 cw->type == META_COMP_WINDOW_DROP_DOWN_MENU) {
00926 meta_verbose ("Window has shadow as it is a menu\n");
00927 return TRUE;
00928 }
00929
00930 if (cw->type == META_COMP_WINDOW_TOOLTIP) {
00931 meta_verbose ("Window has shadow as it is a tooltip\n");
00932 return TRUE;
00933 }
00934
00935 meta_verbose ("Window has no shadow as it fell through\n");
00936 return FALSE;
00937 }
00938
00939 double shadow_offsets_x[LAST_SHADOW_TYPE] = {SHADOW_SMALL_OFFSET_X,
00940 SHADOW_MEDIUM_OFFSET_X,
00941 SHADOW_LARGE_OFFSET_X};
00942 double shadow_offsets_y[LAST_SHADOW_TYPE] = {SHADOW_SMALL_OFFSET_Y,
00943 SHADOW_MEDIUM_OFFSET_Y,
00944 SHADOW_LARGE_OFFSET_Y};
00945 static XserverRegion
00946 win_extents (MetaCompWindow *cw)
00947 {
00948 MetaScreen *screen = cw->screen;
00949 MetaDisplay *display = meta_screen_get_display (screen);
00950 Display *xdisplay = meta_display_get_xdisplay (display);
00951 XRectangle r;
00952
00953 r.x = cw->attrs.x;
00954 r.y = cw->attrs.y;
00955 r.width = cw->attrs.width + cw->attrs.border_width * 2;
00956 r.height = cw->attrs.height + cw->attrs.border_width * 2;
00957
00958 if (cw->needs_shadow)
00959 {
00960 XRectangle sr;
00961
00962 cw->shadow_dx = shadow_offsets_x [cw->shadow_type];
00963 cw->shadow_dy = shadow_offsets_y [cw->shadow_type];
00964
00965 if (!cw->shadow)
00966 {
00967 double opacity = SHADOW_OPACITY;
00968 if (cw->opacity != (guint) OPAQUE)
00969 opacity = opacity * ((double) cw->opacity) / ((double) OPAQUE);
00970
00971 cw->shadow = shadow_picture (display, screen, cw->shadow_type,
00972 opacity, cw->alpha_pict,
00973 cw->attrs.width + cw->attrs.border_width * 2,
00974 cw->attrs.height + cw->attrs.border_width * 2,
00975 &cw->shadow_width, &cw->shadow_height);
00976 }
00977
00978 sr.x = cw->attrs.x + cw->shadow_dx;
00979 sr.y = cw->attrs.y + cw->shadow_dy;
00980 sr.width = cw->shadow_width;
00981 sr.height = cw->shadow_height;
00982
00983 if (sr.x < r.x)
00984 {
00985 r.width = (r.x + r.width) - sr.x;
00986 r.x = sr.x;
00987 }
00988
00989 if (sr.y < r.y)
00990 {
00991 r.height = (r.y + r.height) - sr.y;
00992 r.y = sr.y;
00993 }
00994
00995 if (sr.x + sr.width > r.x + r.width)
00996 r.width = sr.x + sr.width - r.x;
00997
00998 if (sr.y + sr.height > r.y + r.height)
00999 r.height = sr.y + sr.height - r.y;
01000 }
01001
01002 return XFixesCreateRegion (xdisplay, &r, 1);
01003 }
01004
01005 static XserverRegion
01006 border_size (MetaCompWindow *cw)
01007 {
01008 MetaScreen *screen = cw->screen;
01009 MetaDisplay *display = meta_screen_get_display (screen);
01010 Display *xdisplay = meta_display_get_xdisplay (display);
01011 XserverRegion border;
01012
01013 meta_error_trap_push (display);
01014 border = XFixesCreateRegionFromWindow (xdisplay, cw->id,
01015 WindowRegionBounding);
01016 meta_error_trap_pop (display, FALSE);
01017
01018 g_return_val_if_fail (border != None, None);
01019 XFixesTranslateRegion (xdisplay, border,
01020 cw->attrs.x + cw->attrs.border_width,
01021 cw->attrs.y + cw->attrs.border_width);
01022 return border;
01023 }
01024
01025 static XRenderPictFormat *
01026 get_window_format (MetaCompWindow *cw)
01027 {
01028 MetaScreen *screen = cw->screen;
01029 MetaDisplay *display = meta_screen_get_display (screen);
01030 Display *xdisplay = meta_display_get_xdisplay (display);
01031 XRenderPictFormat *format;
01032 int screen_number = meta_screen_get_screen_number (screen);
01033
01034 format = XRenderFindVisualFormat (xdisplay, cw->attrs.visual);
01035 if (!format)
01036 format = XRenderFindVisualFormat (xdisplay,
01037 DefaultVisual (xdisplay, screen_number));
01038 return format;
01039 }
01040
01041 static Picture
01042 get_window_picture (MetaCompWindow *cw)
01043 {
01044 MetaScreen *screen = cw->screen;
01045 MetaDisplay *display = meta_screen_get_display (screen);
01046 Display *xdisplay = meta_display_get_xdisplay (display);
01047 XRenderPictureAttributes pa;
01048 XRenderPictFormat *format;
01049 Drawable draw;
01050
01051 draw = cw->id;
01052
01053 meta_error_trap_push (display);
01054
01055 #ifdef HAVE_NAME_WINDOW_PIXMAP
01056 if (have_name_window_pixmap (display))
01057 {
01058 if (cw->back_pixmap == None)
01059 cw->back_pixmap = XCompositeNameWindowPixmap (xdisplay, cw->id);
01060
01061 if (cw->back_pixmap != None)
01062 draw = cw->back_pixmap;
01063 }
01064 #endif
01065
01066 format = get_window_format (cw);
01067 if (format)
01068 {
01069 Picture pict;
01070
01071 pa.subwindow_mode = IncludeInferiors;
01072
01073 pict = XRenderCreatePicture (xdisplay, draw, format, CPSubwindowMode, &pa);
01074 meta_error_trap_pop (display, FALSE);
01075
01076 return pict;
01077 }
01078
01079 meta_error_trap_pop (display, FALSE);
01080 return None;
01081 }
01082
01083 static void
01084 paint_dock_shadows (MetaScreen *screen,
01085 Picture root_buffer,
01086 XserverRegion region)
01087 {
01088 MetaDisplay *display = meta_screen_get_display (screen);
01089 Display *xdisplay = meta_display_get_xdisplay (display);
01090 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
01091 GSList *d;
01092
01093 if (info == NULL)
01094 {
01095 return;
01096 }
01097
01098 for (d = info->dock_windows; d; d = d->next)
01099 {
01100 MetaCompWindow *cw = d->data;
01101 XserverRegion shadow_clip;
01102
01103 if (cw->shadow)
01104 {
01105 shadow_clip = XFixesCreateRegion (xdisplay, NULL, 0);
01106 XFixesIntersectRegion (xdisplay, shadow_clip,
01107 cw->border_clip, region);
01108
01109 XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0, shadow_clip);
01110
01111 XRenderComposite (xdisplay, PictOpOver, info->black_picture,
01112 cw->shadow, root_buffer,
01113 0, 0, 0, 0,
01114 cw->attrs.x + cw->shadow_dx,
01115 cw->attrs.y + cw->shadow_dy,
01116 cw->shadow_width, cw->shadow_height);
01117 XFixesDestroyRegion (xdisplay, shadow_clip);
01118 }
01119 }
01120 }
01121
01122 static void
01123 paint_windows (MetaScreen *screen,
01124 GList *windows,
01125 Picture root_buffer,
01126 XserverRegion region)
01127 {
01128 MetaDisplay *display = meta_screen_get_display (screen);
01129 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
01130 Display *xdisplay = meta_display_get_xdisplay (display);
01131 GList *index, *last;
01132 int screen_width, screen_height, screen_number;
01133 Window xroot;
01134 MetaCompWindow *cw;
01135 XserverRegion paint_region, desktop_region;
01136
01137 if (info == NULL)
01138 {
01139 return;
01140 }
01141
01142 meta_screen_get_size (screen, &screen_width, &screen_height);
01143 screen_number = meta_screen_get_screen_number (screen);
01144 xroot = meta_screen_get_xroot (screen);
01145
01146 if (region == None)
01147 {
01148 XRectangle r;
01149 r.x = 0;
01150 r.y = 0;
01151 r.width = screen_width;
01152 r.height = screen_height;
01153 paint_region = XFixesCreateRegion (xdisplay, &r, 1);
01154 }
01155 else
01156 {
01157 paint_region = XFixesCreateRegion (xdisplay, NULL, 0);
01158 XFixesCopyRegion (xdisplay, paint_region, region);
01159 }
01160
01161 desktop_region = None;
01162
01163
01164
01165
01166
01167 last = NULL;
01168 for (index = windows; index; index = index->next)
01169 {
01170
01171 last = index;
01172
01173 cw = (MetaCompWindow *) index->data;
01174 if (!cw->damaged)
01175 {
01176
01177 continue;
01178 }
01179
01180 #if 0
01181 if ((cw->attrs.x + cw->attrs.width < 1) ||
01182 (cw->attrs.y + cw->attrs.height < 1) ||
01183 (cw->attrs.x >= screen_width) || (cw->attrs.y >= screen_height))
01184 {
01185
01186 continue;
01187 }
01188 #endif
01189
01190 if (cw->picture == None)
01191 cw->picture = get_window_picture (cw);
01192
01193
01194
01195 if (info->clip_changed)
01196 {
01197 if (cw->border_size)
01198 {
01199 XFixesDestroyRegion (xdisplay, cw->border_size);
01200 cw->border_size = None;
01201 }
01202
01203 #if 0
01204 if (cw->extents)
01205 {
01206 XFixesDestroyRegion (xdisplay, cw->extents);
01207 cw->extents = None;
01208 }
01209 #endif
01210 }
01211
01212 if (cw->border_size == None)
01213 cw->border_size = border_size (cw);
01214
01215 if (cw->extents == None)
01216 cw->extents = win_extents (cw);
01217
01218 if (cw->mode == WINDOW_SOLID)
01219 {
01220 int x, y, wid, hei;
01221
01222 #ifdef HAVE_NAME_WINDOW_PIXMAP
01223 if (have_name_window_pixmap (display))
01224 {
01225 x = cw->attrs.x;
01226 y = cw->attrs.y;
01227 wid = cw->attrs.width + cw->attrs.border_width * 2;
01228 hei = cw->attrs.height + cw->attrs.border_width * 2;
01229 }
01230 else
01231 #endif
01232 {
01233 x = cw->attrs.x + cw->attrs.border_width;
01234 y = cw->attrs.y + cw->attrs.border_width;
01235 wid = cw->attrs.width;
01236 hei = cw->attrs.height;
01237 }
01238
01239 XFixesSetPictureClipRegion (xdisplay, root_buffer,
01240 0, 0, paint_region);
01241 XRenderComposite (xdisplay, PictOpSrc, cw->picture,
01242 None, root_buffer, 0, 0, 0, 0,
01243 x, y, wid, hei);
01244
01245 if (cw->type == META_COMP_WINDOW_DESKTOP)
01246 {
01247 desktop_region = XFixesCreateRegion (xdisplay, 0, 0);
01248 XFixesCopyRegion (xdisplay, desktop_region, paint_region);
01249 }
01250
01251 XFixesSubtractRegion (xdisplay, paint_region,
01252 paint_region, cw->border_size);
01253 }
01254
01255 if (!cw->border_clip)
01256 {
01257 cw->border_clip = XFixesCreateRegion (xdisplay, 0, 0);
01258 XFixesCopyRegion (xdisplay, cw->border_clip, paint_region);
01259 }
01260 }
01261
01262 XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0, paint_region);
01263 paint_root (screen, root_buffer);
01264
01265 paint_dock_shadows (screen, root_buffer, desktop_region == None ?
01266 paint_region : desktop_region);
01267 if (desktop_region != None)
01268 XFixesDestroyRegion (xdisplay, desktop_region);
01269
01270
01271
01272
01273 for (index = last; index; index = index->prev)
01274 {
01275 cw = (MetaCompWindow *) index->data;
01276
01277 if (cw->picture)
01278 {
01279 if (cw->shadow && cw->type != META_COMP_WINDOW_DOCK)
01280 {
01281 XserverRegion shadow_clip;
01282
01283 shadow_clip = XFixesCreateRegion (xdisplay, NULL, 0);
01284 XFixesSubtractRegion (xdisplay, shadow_clip, cw->border_clip,
01285 cw->border_size);
01286 XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0,
01287 shadow_clip);
01288
01289 XRenderComposite (xdisplay, PictOpOver, info->black_picture,
01290 cw->shadow, root_buffer,
01291 0, 0, 0, 0,
01292 cw->attrs.x + cw->shadow_dx,
01293 cw->attrs.y + cw->shadow_dy,
01294 cw->shadow_width, cw->shadow_height);
01295 if (shadow_clip)
01296 XFixesDestroyRegion (xdisplay, shadow_clip);
01297 }
01298
01299 if ((cw->opacity != (guint) OPAQUE) && !(cw->alpha_pict))
01300 {
01301 cw->alpha_pict = solid_picture (display, screen, FALSE,
01302 (double) cw->opacity / OPAQUE,
01303 0, 0, 0);
01304 }
01305
01306 XFixesIntersectRegion (xdisplay, cw->border_clip, cw->border_clip,
01307 cw->border_size);
01308 XFixesSetPictureClipRegion (xdisplay, root_buffer, 0, 0,
01309 cw->border_clip);
01310 if (cw->mode == WINDOW_ARGB)
01311 {
01312 int x, y, wid, hei;
01313 #ifdef HAVE_NAME_WINDOW_PIXMAP
01314 if (have_name_window_pixmap (display))
01315 {
01316 x = cw->attrs.x;
01317 y = cw->attrs.y;
01318 wid = cw->attrs.width + cw->attrs.border_width * 2;
01319 hei = cw->attrs.height + cw->attrs.border_width * 2;
01320 }
01321 else
01322 #endif
01323 {
01324 x = cw->attrs.x + cw->attrs.border_width;
01325 y = cw->attrs.y + cw->attrs.border_width;
01326 wid = cw->attrs.width;
01327 hei = cw->attrs.height;
01328 }
01329
01330 XRenderComposite (xdisplay, PictOpOver, cw->picture,
01331 cw->alpha_pict, root_buffer, 0, 0, 0, 0,
01332 x, y, wid, hei);
01333 }
01334 }
01335
01336 if (cw->border_clip)
01337 {
01338 XFixesDestroyRegion (xdisplay, cw->border_clip);
01339 cw->border_clip = None;
01340 }
01341 }
01342
01343 XFixesDestroyRegion (xdisplay, paint_region);
01344 }
01345
01346 static void
01347 paint_all (MetaScreen *screen,
01348 XserverRegion region)
01349 {
01350 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
01351 MetaDisplay *display = meta_screen_get_display (screen);
01352 Display *xdisplay = meta_display_get_xdisplay (display);
01353 int screen_width, screen_height;
01354
01355
01356 XFixesSetPictureClipRegion (xdisplay, info->root_picture, 0, 0, region);
01357
01358 meta_screen_get_size (screen, &screen_width, &screen_height);
01359
01360 if (DISPLAY_COMPOSITOR (display)->show_redraw)
01361 {
01362 Picture overlay;
01363
01364 dump_xserver_region ("paint_all", display, region);
01365
01366
01367 overlay = solid_picture (display, screen, TRUE, 1,
01368 ((double) (rand () % 100)) / 100.0,
01369 ((double) (rand () % 100)) / 100.0,
01370 ((double) (rand () % 100)) / 100.0);
01371
01372 XRenderComposite (xdisplay, PictOpOver, overlay, None, info->root_picture,
01373 0, 0, 0, 0, 0, 0, screen_width, screen_height);
01374 XRenderFreePicture (xdisplay, overlay);
01375 XFlush (xdisplay);
01376 usleep (100 * 1000);
01377 }
01378
01379 if (info->root_buffer == None)
01380 info->root_buffer = create_root_buffer (screen);
01381
01382 paint_windows (screen, info->windows, info->root_buffer, region);
01383
01384 XFixesSetPictureClipRegion (xdisplay, info->root_buffer, 0, 0, region);
01385 XRenderComposite (xdisplay, PictOpSrc, info->root_buffer, None,
01386 info->root_picture, 0, 0, 0, 0, 0, 0,
01387 screen_width, screen_height);
01388 }
01389
01390 static void
01391 repair_screen (MetaScreen *screen)
01392 {
01393 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
01394 MetaDisplay *display = meta_screen_get_display (screen);
01395 Display *xdisplay = meta_display_get_xdisplay (display);
01396
01397 if (info!=NULL && info->all_damage != None)
01398 {
01399 meta_error_trap_push (display);
01400 paint_all (screen, info->all_damage);
01401 XFixesDestroyRegion (xdisplay, info->all_damage);
01402 info->all_damage = None;
01403 info->clip_changed = FALSE;
01404 meta_error_trap_pop (display, FALSE);
01405 }
01406 }
01407
01408 static void
01409 repair_display (MetaDisplay *display)
01410 {
01411 GSList *screens = meta_display_get_screens (display);
01412 MetaCompositorXRender *compositor = DISPLAY_COMPOSITOR (display);
01413
01414 #ifdef USE_IDLE_REPAINT
01415 if (compositor->repaint_id > 0)
01416 {
01417 g_source_remove (compositor->repaint_id);
01418 compositor->repaint_id = 0;
01419 }
01420 #endif
01421
01422 for (; screens; screens = screens->next)
01423 repair_screen ((MetaScreen *) screens->data);
01424 }
01425
01426 #ifdef USE_IDLE_REPAINT
01427 static gboolean
01428 compositor_idle_cb (gpointer data)
01429 {
01430 MetaCompositorXRender *compositor = (MetaCompositorXRender *) data;
01431
01432 compositor->repaint_id = 0;
01433 repair_display (compositor->display);
01434
01435 return FALSE;
01436 }
01437
01438 static void
01439 add_repair (MetaDisplay *display)
01440 {
01441 MetaCompositorXRender *compositor = DISPLAY_COMPOSITOR (display);
01442
01443 if (compositor->repaint_id > 0)
01444 return;
01445
01446 #if 1
01447 compositor->repaint_id = g_idle_add_full (G_PRIORITY_HIGH_IDLE,
01448 compositor_idle_cb, compositor,
01449 NULL);
01450 #else
01451
01452 compositor->repaint_id = g_timeout_add_full (G_PRIORITY_HIGH, 20,
01453 compositor_idle_cb, compositor,
01454 NULL);
01455 #endif
01456 }
01457 #endif
01458
01459 static void
01460 add_damage (MetaScreen *screen,
01461 XserverRegion damage)
01462 {
01463 MetaDisplay *display = meta_screen_get_display (screen);
01464 Display *xdisplay = meta_display_get_xdisplay (display);
01465 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
01466
01467
01468
01469 if (info != NULL && info->all_damage)
01470 {
01471 XFixesUnionRegion (xdisplay, info->all_damage, info->all_damage, damage);
01472 XFixesDestroyRegion (xdisplay, damage);
01473 }
01474 else
01475 info->all_damage = damage;
01476
01477 #ifdef USE_IDLE_REPAINT
01478 add_repair (display);
01479 #endif
01480 }
01481
01482 static void
01483 damage_screen (MetaScreen *screen)
01484 {
01485 MetaDisplay *display = meta_screen_get_display (screen);
01486 Display *xdisplay = meta_display_get_xdisplay (display);
01487 XserverRegion region;
01488 int width, height;
01489 XRectangle r;
01490
01491 r.x = 0;
01492 r.y = 0;
01493 meta_screen_get_size (screen, &width, &height);
01494 r.width = width;
01495 r.height = height;
01496
01497 region = XFixesCreateRegion (xdisplay, &r, 1);
01498 dump_xserver_region ("damage_screen", display, region);
01499 add_damage (screen, region);
01500 }
01501
01502 static void
01503 repair_win (MetaCompWindow *cw)
01504 {
01505 MetaScreen *screen = cw->screen;
01506 MetaDisplay *display = meta_screen_get_display (screen);
01507 Display *xdisplay = meta_display_get_xdisplay (display);
01508 XserverRegion parts;
01509
01510 meta_error_trap_push (display);
01511 if (!cw->damaged)
01512 {
01513 parts = win_extents (cw);
01514 XDamageSubtract (xdisplay, cw->damage, None, None);
01515 }
01516 else
01517 {
01518 parts = XFixesCreateRegion (xdisplay, 0, 0);
01519 XDamageSubtract (xdisplay, cw->damage, None, parts);
01520 XFixesTranslateRegion (xdisplay, parts,
01521 cw->attrs.x + cw->attrs.border_width,
01522 cw->attrs.y + cw->attrs.border_width);
01523 }
01524
01525 meta_error_trap_pop (display, FALSE);
01526
01527 dump_xserver_region ("repair_win", display, parts);
01528 add_damage (screen, parts);
01529 cw->damaged = TRUE;
01530 }
01531
01532 static void
01533 free_win (MetaCompWindow *cw,
01534 gboolean destroy)
01535 {
01536 MetaDisplay *display = meta_screen_get_display (cw->screen);
01537 Display *xdisplay = meta_display_get_xdisplay (display);
01538 MetaCompScreen *info = meta_screen_get_compositor_data (cw->screen);
01539
01540 #ifdef HAVE_NAME_WINDOW_PIXMAP
01541 if (have_name_window_pixmap (display))
01542 {
01543
01544 if (cw->back_pixmap && destroy)
01545 {
01546 XFreePixmap (xdisplay, cw->back_pixmap);
01547 cw->back_pixmap = None;
01548 }
01549
01550 if (cw->shaded_back_pixmap && destroy)
01551 {
01552 XFreePixmap (xdisplay, cw->shaded_back_pixmap);
01553 cw->shaded_back_pixmap = None;
01554 }
01555 }
01556 #endif
01557
01558 if (cw->picture)
01559 {
01560 XRenderFreePicture (xdisplay, cw->picture);
01561 cw->picture = None;
01562 }
01563
01564 if (cw->shadow)
01565 {
01566 XRenderFreePicture (xdisplay, cw->shadow);
01567 cw->shadow = None;
01568 }
01569
01570 if (cw->alpha_pict)
01571 {
01572 XRenderFreePicture (xdisplay, cw->alpha_pict);
01573 cw->alpha_pict = None;
01574 }
01575
01576 if (cw->shadow_pict)
01577 {
01578 XRenderFreePicture (xdisplay, cw->shadow_pict);
01579 cw->shadow_pict = None;
01580 }
01581
01582 if (cw->border_size)
01583 {
01584 XFixesDestroyRegion (xdisplay, cw->border_size);
01585 cw->border_size = None;
01586 }
01587
01588 if (cw->border_clip)
01589 {
01590 XFixesDestroyRegion (xdisplay, cw->border_clip);
01591 cw->border_clip = None;
01592 }
01593
01594 if (cw->extents)
01595 {
01596 XFixesDestroyRegion (xdisplay, cw->extents);
01597 cw->extents = None;
01598 }
01599
01600 if (destroy)
01601 {
01602 if (cw->damage != None) {
01603 meta_error_trap_push (display);
01604 XDamageDestroy (xdisplay, cw->damage);
01605 meta_error_trap_pop (display, FALSE);
01606
01607 cw->damage = None;
01608 }
01609
01610
01611
01612 if (info!=NULL && cw->type == META_COMP_WINDOW_DOCK)
01613 info->dock_windows = g_slist_remove (info->dock_windows, cw);
01614
01615 g_free (cw);
01616 }
01617 }
01618
01619 static void
01620 map_win (MetaDisplay *display,
01621 MetaScreen *screen,
01622 Window id)
01623 {
01624 MetaCompWindow *cw = find_window_for_screen (screen, id);
01625 Display *xdisplay = meta_display_get_xdisplay (display);
01626
01627 if (cw == NULL)
01628 return;
01629
01630 #ifdef HAVE_NAME_WINDOW_PIXMAP
01631
01632
01633
01634 if (cw->back_pixmap)
01635 {
01636 XFreePixmap (xdisplay, cw->back_pixmap);
01637 cw->back_pixmap = None;
01638 }
01639
01640 if (cw->shaded_back_pixmap)
01641 {
01642 XFreePixmap (xdisplay, cw->shaded_back_pixmap);
01643 cw->shaded_back_pixmap = None;
01644 }
01645 #endif
01646
01647 cw->attrs.map_state = IsViewable;
01648 cw->damaged = FALSE;
01649 }
01650
01651 static void
01652 unmap_win (MetaDisplay *display,
01653 MetaScreen *screen,
01654 Window id)
01655 {
01656 MetaCompWindow *cw = find_window_for_screen (screen, id);
01657 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
01658
01659 if (cw == NULL || info == NULL)
01660 {
01661 return;
01662 }
01663
01664 if (cw->window && cw->window == info->focus_window)
01665 info->focus_window = NULL;
01666
01667 cw->attrs.map_state = IsUnmapped;
01668 cw->damaged = FALSE;
01669
01670 if (cw->extents != None)
01671 {
01672 dump_xserver_region ("unmap_win", display, cw->extents);
01673 add_damage (screen, cw->extents);
01674 cw->extents = None;
01675 }
01676
01677 free_win (cw, FALSE);
01678 info->clip_changed = TRUE;
01679 }
01680
01681 static void
01682 determine_mode (MetaDisplay *display,
01683 MetaScreen *screen,
01684 MetaCompWindow *cw)
01685 {
01686 XRenderPictFormat *format;
01687 Display *xdisplay = meta_display_get_xdisplay (display);
01688
01689 if (cw->alpha_pict)
01690 {
01691 XRenderFreePicture (xdisplay, cw->alpha_pict);
01692 cw->alpha_pict = None;
01693 }
01694
01695 if (cw->shadow_pict)
01696 {
01697 XRenderFreePicture (xdisplay, cw->shadow_pict);
01698 cw->shadow_pict = None;
01699 }
01700
01701 if (cw->attrs.class == InputOnly)
01702 format = NULL;
01703 else
01704 format = XRenderFindVisualFormat (xdisplay, cw->attrs.visual);
01705
01706 if ((format && format->type == PictTypeDirect && format->direct.alphaMask)
01707 || cw->opacity != (guint) OPAQUE)
01708 cw->mode = WINDOW_ARGB;
01709 else
01710 cw->mode = WINDOW_SOLID;
01711
01712 if (cw->extents)
01713 {
01714 XserverRegion damage;
01715 damage = XFixesCreateRegion (xdisplay, NULL, 0);
01716 XFixesCopyRegion (xdisplay, damage, cw->extents);
01717
01718 dump_xserver_region ("determine_mode", display, damage);
01719 add_damage (screen, damage);
01720 }
01721 }
01722
01723 static gboolean
01724 is_shaped (MetaDisplay *display,
01725 Window xwindow)
01726 {
01727 Display *xdisplay = meta_display_get_xdisplay (display);
01728 int xws, yws, xbs, ybs;
01729 unsigned wws, hws, wbs, hbs;
01730 int bounding_shaped, clip_shaped;
01731
01732 if (meta_display_has_shape (display))
01733 {
01734 XShapeQueryExtents (xdisplay, xwindow, &bounding_shaped,
01735 &xws, &yws, &wws, &hws, &clip_shaped,
01736 &xbs, &ybs, &wbs, &hbs);
01737 return (bounding_shaped != 0);
01738 }
01739
01740 return FALSE;
01741 }
01742
01743 static void
01744 get_window_type (MetaDisplay *display,
01745 MetaCompWindow *cw)
01746 {
01747 MetaCompositorXRender *compositor = DISPLAY_COMPOSITOR (display);
01748 int n_atoms;
01749 Atom *atoms, type_atom;
01750 int i;
01751
01752 type_atom = None;
01753 n_atoms = 0;
01754 atoms = NULL;
01755
01756 meta_prop_get_atom_list (display, cw->id,
01757 compositor->atom_net_wm_window_type,
01758 &atoms, &n_atoms);
01759
01760 for (i = 0; i < n_atoms; i++)
01761 {
01762 if (atoms[i] == compositor->atom_net_wm_window_type_dnd ||
01763 atoms[i] == compositor->atom_net_wm_window_type_desktop ||
01764 atoms[i] == compositor->atom_net_wm_window_type_dock ||
01765 atoms[i] == compositor->atom_net_wm_window_type_toolbar ||
01766 atoms[i] == compositor->atom_net_wm_window_type_menu ||
01767 atoms[i] == compositor->atom_net_wm_window_type_dialog ||
01768 atoms[i] == compositor->atom_net_wm_window_type_normal ||
01769 atoms[i] == compositor->atom_net_wm_window_type_utility ||
01770 atoms[i] == compositor->atom_net_wm_window_type_splash ||
01771 atoms[i] == compositor->atom_net_wm_window_type_dropdown_menu ||
01772 atoms[i] == compositor->atom_net_wm_window_type_tooltip)
01773 {
01774 type_atom = atoms[i];
01775 break;
01776 }
01777 }
01778
01779 meta_XFree (atoms);
01780
01781 if (type_atom == compositor->atom_net_wm_window_type_dnd)
01782 cw->type = META_COMP_WINDOW_DND;
01783 else if (type_atom == compositor->atom_net_wm_window_type_desktop)
01784 cw->type = META_COMP_WINDOW_DESKTOP;
01785 else if (type_atom == compositor->atom_net_wm_window_type_dock)
01786 cw->type = META_COMP_WINDOW_DOCK;
01787 else if (type_atom == compositor->atom_net_wm_window_type_menu)
01788 cw->type = META_COMP_WINDOW_MENU;
01789 else if (type_atom == compositor->atom_net_wm_window_type_dropdown_menu)
01790 cw->type = META_COMP_WINDOW_DROP_DOWN_MENU;
01791 else if (type_atom == compositor->atom_net_wm_window_type_tooltip)
01792 cw->type = META_COMP_WINDOW_TOOLTIP;
01793 else
01794 cw->type = META_COMP_WINDOW_NORMAL;
01795
01796
01797 }
01798
01799
01800 static void
01801 add_win (MetaScreen *screen,
01802 MetaWindow *window,
01803 Window xwindow)
01804 {
01805 MetaDisplay *display = meta_screen_get_display (screen);
01806 Display *xdisplay = meta_display_get_xdisplay (display);
01807 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
01808 MetaCompWindow *cw;
01809 gulong event_mask;
01810
01811 if (info == NULL)
01812 return;
01813
01814 if (xwindow == info->output)
01815 return;
01816
01817 cw = g_new0 (MetaCompWindow, 1);
01818 cw->screen = screen;
01819 cw->window = window;
01820 cw->id = xwindow;
01821
01822 if (!XGetWindowAttributes (xdisplay, xwindow, &cw->attrs))
01823 {
01824 g_free (cw);
01825 return;
01826 }
01827 get_window_type (display, cw);
01828
01829
01830
01831 event_mask = cw->attrs.your_event_mask | PropertyChangeMask;
01832
01833 XSelectInput (xdisplay, xwindow, event_mask);
01834
01835
01836 #ifdef HAVE_NAME_WINDOW_PIXMAP
01837 cw->back_pixmap = None;
01838 cw->shaded_back_pixmap = None;
01839 #endif
01840
01841 cw->damaged = FALSE;
01842 cw->shaped = is_shaped (display, xwindow);
01843
01844 if (cw->attrs.class == InputOnly)
01845 cw->damage = None;
01846 else
01847 cw->damage = XDamageCreate (xdisplay, xwindow, XDamageReportNonEmpty);
01848
01849 cw->alpha_pict = None;
01850 cw->shadow_pict = None;
01851 cw->border_size = None;
01852 cw->extents = None;
01853 cw->shadow = None;
01854 cw->shadow_dx = 0;
01855 cw->shadow_dy = 0;
01856 cw->shadow_width = 0;
01857 cw->shadow_height = 0;
01858
01859 if (window && meta_window_has_focus (window))
01860 cw->shadow_type = META_SHADOW_LARGE;
01861 else
01862 cw->shadow_type = META_SHADOW_MEDIUM;
01863
01864 cw->opacity = OPAQUE;
01865
01866 cw->border_clip = None;
01867
01868 determine_mode (display, screen, cw);
01869 cw->needs_shadow = window_has_shadow (cw);
01870
01871
01872 if (cw->type == META_COMP_WINDOW_DOCK && cw->needs_shadow)
01873 {
01874 meta_verbose ("Appending %p to dock windows\n", cw);
01875 info->dock_windows = g_slist_append (info->dock_windows, cw);
01876 }
01877
01878
01879
01880 info->windows = g_list_prepend (info->windows, cw);
01881 g_hash_table_insert (info->windows_by_xid, (gpointer) xwindow, cw);
01882
01883 if (cw->attrs.map_state == IsViewable)
01884 map_win (display, screen, xwindow);
01885 }
01886
01887 static void
01888 destroy_win (MetaDisplay *display,
01889 Window xwindow,
01890 gboolean gone)
01891 {
01892 MetaScreen *screen;
01893 MetaCompScreen *info;
01894 MetaCompWindow *cw;
01895
01896 cw = find_window_in_display (display, xwindow);
01897
01898 if (cw == NULL)
01899 return;
01900
01901 screen = cw->screen;
01902
01903 if (cw->extents != None)
01904 {
01905 dump_xserver_region ("destroy_win", display, cw->extents);
01906 add_damage (screen, cw->extents);
01907 cw->extents = None;
01908 }
01909
01910 info = meta_screen_get_compositor_data (screen);
01911 if (info != NULL)
01912 {
01913 info->windows = g_list_remove (info->windows, (gconstpointer) cw);
01914 g_hash_table_remove (info->windows_by_xid, (gpointer) xwindow);
01915 }
01916
01917 free_win (cw, TRUE);
01918 }
01919
01920 static void
01921 restack_win (MetaCompWindow *cw,
01922 Window above)
01923 {
01924 MetaScreen *screen;
01925 MetaCompScreen *info;
01926 Window previous_above;
01927 GList *sibling, *next;
01928
01929 screen = cw->screen;
01930 info = meta_screen_get_compositor_data (screen);
01931
01932 if (info == NULL)
01933 {
01934 return;
01935 }
01936
01937 sibling = g_list_find (info->windows, (gconstpointer) cw);
01938 next = g_list_next (sibling);
01939 previous_above = None;
01940
01941 if (next)
01942 {
01943 MetaCompWindow *ncw = (MetaCompWindow *) next->data;
01944 previous_above = ncw->id;
01945 }
01946
01947
01948
01949
01950 if (above == None)
01951 {
01952
01953 info->windows = g_list_delete_link (info->windows, sibling);
01954 info->windows = g_list_append (info->windows, cw);
01955 }
01956 else if (previous_above != above)
01957 {
01958 GList *index;
01959
01960 for (index = info->windows; index; index = index->next) {
01961 MetaCompWindow *cw2 = (MetaCompWindow *) index->data;
01962 if (cw2->id == above)
01963 break;
01964 }
01965
01966 if (index != NULL)
01967 {
01968 info->windows = g_list_delete_link (info->windows, sibling);
01969 info->windows = g_list_insert_before (info->windows, index, cw);
01970 }
01971 }
01972 }
01973
01974 static void
01975 resize_win (MetaCompWindow *cw,
01976 int x,
01977 int y,
01978 int width,
01979 int height,
01980 int border_width,
01981 gboolean override_redirect)
01982 {
01983 MetaScreen *screen = cw->screen;
01984 MetaDisplay *display = meta_screen_get_display (screen);
01985 Display *xdisplay = meta_display_get_xdisplay (display);
01986 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
01987 XserverRegion damage;
01988 gboolean debug;
01989
01990 debug = DISPLAY_COMPOSITOR (display)->debug;
01991
01992 if (cw->extents)
01993 {
01994 damage = XFixesCreateRegion (xdisplay, NULL, 0);
01995 XFixesCopyRegion (xdisplay, damage, cw->extents);
01996 }
01997 else
01998 {
01999 damage = None;
02000 if (debug)
02001 fprintf (stderr, "no extents to damage !\n");
02002 }
02003
02004
02005
02006
02007
02008
02009
02010
02011
02012
02013
02014
02015
02016 cw->attrs.x = x;
02017 cw->attrs.y = y;
02018
02019 if (cw->attrs.width != width || cw->attrs.height != height)
02020 {
02021 #ifdef HAVE_NAME_WINDOW_PIXMAP
02022 if (have_name_window_pixmap (display))
02023 {
02024 if (cw->shaded_back_pixmap)
02025 {
02026 XFreePixmap (xdisplay, cw->shaded_back_pixmap);
02027 cw->shaded_back_pixmap = None;
02028 }
02029
02030 if (cw->back_pixmap)
02031 {
02032
02033
02034 if (cw->window && meta_window_is_shaded (cw->window))
02035 {
02036 cw->shaded_back_pixmap = cw->back_pixmap;
02037 cw->back_pixmap = None;
02038 }
02039 else
02040 {
02041 XFreePixmap (xdisplay, cw->back_pixmap);
02042 cw->back_pixmap = None;
02043 }
02044 }
02045 }
02046 #endif
02047 if (cw->picture)
02048 {
02049 XRenderFreePicture (xdisplay, cw->picture);
02050 cw->picture = None;
02051 }
02052
02053 if (cw->shadow)
02054 {
02055 XRenderFreePicture (xdisplay, cw->shadow);
02056 cw->shadow = None;
02057 }
02058 }
02059
02060 cw->attrs.width = width;
02061 cw->attrs.height = height;
02062 cw->attrs.border_width = border_width;
02063 cw->attrs.override_redirect = override_redirect;
02064
02065 if (cw->extents)
02066 XFixesDestroyRegion (xdisplay, cw->extents);
02067
02068 cw->extents = win_extents (cw);
02069
02070 if (damage)
02071 {
02072 if (debug)
02073 fprintf (stderr, "Inexplicable intersection with new extents!\n");
02074
02075 XFixesUnionRegion (xdisplay, damage, damage, cw->extents);
02076 }
02077 else
02078 {
02079 damage = XFixesCreateRegion (xdisplay, NULL, 0);
02080 XFixesCopyRegion (xdisplay, damage, cw->extents);
02081 }
02082
02083 dump_xserver_region ("resize_win", display, damage);
02084 add_damage (screen, damage);
02085
02086 if (info != NULL)
02087 {
02088 info->clip_changed = TRUE;
02089 }
02090 }
02091
02092
02093 static void
02094 process_circulate_notify (MetaCompositorXRender *compositor,
02095 XCirculateEvent *event)
02096 {
02097 MetaCompWindow *cw = find_window_in_display (compositor->display,
02098 event->window);
02099 MetaCompWindow *top;
02100 MetaCompScreen *info;
02101 MetaScreen *screen;
02102 GList *first;
02103 Window above;
02104
02105 if (!cw)
02106 return;
02107
02108 screen = cw->screen;
02109 info = meta_screen_get_compositor_data (screen);
02110 first = info->windows;
02111 top = (MetaCompWindow *) first->data;
02112
02113 if ((event->place == PlaceOnTop) && top)
02114 above = top->id;
02115 else
02116 above = None;
02117 restack_win (cw, above);
02118
02119 if (info != NULL)
02120 {
02121 info->clip_changed = TRUE;
02122 }
02123
02124 #ifdef USE_IDLE_REPAINT
02125 add_repair (compositor->display);
02126 #endif
02127 }
02128
02129 static void
02130 process_configure_notify (MetaCompositorXRender *compositor,
02131 XConfigureEvent *event)
02132 {
02133 MetaDisplay *display = compositor->display;
02134 Display *xdisplay = meta_display_get_xdisplay (display);
02135 MetaCompWindow *cw = find_window_in_display (display, event->window);
02136
02137 if (cw)
02138 {
02139 #if 0
02140 int x = -1, y = -1, width = -1, height = -1;
02141 int ex = -1, ey = -1, ewidth = -1, eheight = -1;
02142 MetaRectangle *rect;
02143
02144 if (cw->window) {
02145 rect = meta_window_get_rect (cw->window);
02146 x = rect->x;
02147 y = rect->y;
02148 width = rect->width;
02149 height = rect->height;
02150 }
02151 fprintf (stderr, "configure notify xy (%d %d) -> (%d %d), wh (%d %d) -> (%d %d)\n",
02152 x, y, event->x, event->y,
02153 width, height, event->width, event->height);
02154 #endif
02155
02156 if (compositor->debug)
02157 {
02158 fprintf (stderr, "configure notify %d %d %d\n", cw->damaged,
02159 cw->shaped, cw->needs_shadow);
02160 dump_xserver_region ("\textents", display, cw->extents);
02161 fprintf (stderr, "\txy (%d %d), wh (%d %d)\n",
02162 event->x, event->y, event->width, event->height);
02163 }
02164
02165 restack_win (cw, event->above);
02166 resize_win (cw, event->x, event->y, event->width, event->height,
02167 event->border_width, event->override_redirect);
02168 }
02169 else
02170 {
02171 MetaScreen *screen;
02172 MetaCompScreen *info;
02173
02174
02175 screen = meta_display_screen_for_root (display, event->window);
02176 if (screen == NULL)
02177 return;
02178
02179 info = meta_screen_get_compositor_data (screen);
02180 if (info != NULL && info->root_buffer)
02181 {
02182 XRenderFreePicture (xdisplay, info->root_buffer);
02183 info->root_buffer = None;
02184 }
02185
02186 damage_screen (screen);
02187 }
02188 }
02189
02190 static void
02191 process_property_notify (MetaCompositorXRender *compositor,
02192 XPropertyEvent *event)
02193 {
02194 MetaDisplay *display = compositor->display;
02195 Display *xdisplay = meta_display_get_xdisplay (display);
02196 MetaScreen *screen;
02197 int p;
02198 Atom background_atoms[2];
02199
02200
02201 background_atoms[0] = compositor->atom_x_root_pixmap;
02202 background_atoms[1] = compositor->atom_x_set_root;
02203
02204 for (p = 0; p < 2; p++)
02205 {
02206 if (event->atom == background_atoms[p])
02207 {
02208 screen = meta_display_screen_for_root (display, event->window);
02209 if (screen)
02210 {
02211 MetaCompScreen *info = meta_screen_get_compositor_data (screen);
02212 Window xroot = meta_screen_get_xroot (screen);
02213
02214 if (info != NULL && info->root_tile)
02215 {
02216 XClearArea (xdisplay, xroot, 0, 0, 0, 0, TRUE);
02217 XRenderFreePicture (xdisplay, info->root_tile);
02218 info->root_tile = None;
02219
02220
02221
02222 damage_screen (screen);
02223 #ifdef USE_IDLE_REPAINT
02224 add_repair (display);
02225 #endif
02226
02227 return;
02228 }
02229 }
02230 }
02231 }
02232
02233
02234 if (event->atom == compositor->atom_net_wm_window_opacity)
02235 {
02236 MetaCompWindow *cw = find_window_in_display (display, event->window);
02237 gulong value;
02238
02239 if (!cw)
02240 {
02241
02242
02243
02244 cw = find_window_for_child_window_in_display (display, event->window);
02245 }
02246
02247 if (!cw)
02248 return;
02249
02250 if (meta_prop_get_cardinal (display, event->window,
02251 compositor->atom_net_wm_window_opacity,
02252 &value) == FALSE)
02253 value = OPAQUE;
02254
02255 cw->opacity = (guint)value;
02256 determine_mode (display, cw->screen, cw);
02257 cw->needs_shadow = window_has_shadow (cw);
02258
02259 if (cw->shadow)
02260 {
02261 XRenderFreePicture (xdisplay, cw->shadow);
02262 cw->shadow = None;
02263 }
02264
02265 if (cw->extents)
02266 XFixesDestroyRegion (xdisplay, cw->extents);
02267 cw->extents = win_extents (cw);
02268
02269 cw->damaged = TRUE;
02270 #ifdef USE_IDLE_REPAINT
02271 add_repair (display);
02272 #endif
02273
02274 return;
02275 }
02276
02277 if (event->atom == compositor->atom_net_wm_window_type) {
02278 MetaCompWindow *cw = find_window_in_display (display, event->window);
02279
02280 if (!cw)
02281 return;
02282
02283 get_window_type (display, cw);
02284 cw->needs_shadow = window_has_shadow (cw);
02285 return;
02286 }
02287 }
02288
02289 static void
02290 expose_area (MetaScreen *screen,
02291 XRectangle *rects,
02292 int nrects)
02293 {
02294 MetaDisplay *display = meta_screen_get_display (screen);
02295 Display *xdisplay = meta_display_get_xdisplay (display);
02296 XserverRegion region;
02297
02298 region = XFixesCreateRegion (xdisplay, rects, nrects);
02299
02300 dump_xserver_region ("expose_area", display, region);
02301 add_damage (screen, region);
02302 }
02303
02304 static void
02305 process_expose (MetaCompositorXRender *compositor,
02306 XExposeEvent *event)
02307 {
02308 MetaCompWindow *cw = find_window_in_display (compositor->display,
02309 event->window);
02310 MetaScreen *screen = NULL;
02311 XRectangle rect[1];
02312 int origin_x = 0, origin_y = 0;
02313
02314 if (cw != NULL)
02315 {
02316 screen = cw->screen;
02317 origin_x = cw->attrs.x;
02318 origin_y = cw->attrs.y;
02319 }
02320 else
02321 {
02322 screen = meta_display_screen_for_root (compositor->display,
02323 event->window);
02324 if (screen == NULL)
02325 return;
02326 }
02327
02328 rect[0].x = event->x + origin_x;
02329 rect[0].y = event->y + origin_y;
02330 rect[0].width = event->width;
02331 rect[0].height = event->height;
02332
02333 expose_area (screen, rect, 1);
02334 }
02335
02336 static void
02337 process_unmap (MetaCompositorXRender *compositor,
02338 XUnmapEvent *event)
02339 {
02340 MetaCompWindow *cw;
02341
02342 if (event->from_configure)
02343 {
02344
02345 return;
02346 }
02347
02348
02349 cw = find_window_in_display (compositor->display, event->window);
02350 if (cw)
02351 unmap_win (compositor->display, cw->screen, event->window);
02352 }
02353
02354 static void
02355 process_map (MetaCompositorXRender *compositor,
02356 XMapEvent *event)
02357 {
02358 MetaCompWindow *cw = find_window_in_display (compositor->display,
02359 event->window);
02360
02361 if (cw)
02362 map_win (compositor->display, cw->screen, event->window);
02363 }
02364
02365 static void
02366 process_reparent (MetaCompositorXRender *compositor,
02367 XReparentEvent *event,
02368 MetaWindow *window)
02369 {
02370 MetaScreen *screen;
02371
02372 screen = meta_display_screen_for_root (compositor->display, event->parent);
02373 if (screen != NULL)
02374 add_win (screen, window, event->window);
02375 else
02376 destroy_win (compositor->display, event->window, FALSE);
02377 }
02378
02379 static void
02380 process_create (MetaCompositorXRender *compositor,
02381 XCreateWindowEvent *event,
02382 MetaWindow *window)
02383 {
02384 MetaScreen *screen;
02385
02386
02387
02388 screen = meta_display_screen_for_root (compositor->display, event->parent);
02389 if (screen == NULL)
02390 return;
02391
02392 if (!find_window_in_display (compositor->display, event->window))
02393 add_win (screen, window, event->window);
02394 }
02395
02396 static void
02397 process_destroy (MetaCompositorXRender *compositor,
02398 XDestroyWindowEvent *event)
02399 {
02400 destroy_win (compositor->display, event->window, FALSE);
02401 }
02402
02403 static void
02404 process_damage (MetaCompositorXRender *compositor,
02405 XDamageNotifyEvent *event)
02406 {
02407 MetaCompWindow *cw = find_window_in_display (compositor->display,
02408 event->drawable);
02409 if (cw == NULL)
02410 return;
02411
02412 repair_win (cw);
02413
02414 #ifdef USE_IDLE_REPAINT
02415 if (event->more == FALSE)
02416 add_repair (compositor->display);
02417 #endif
02418 }
02419
02420 static void
02421 process_shape (MetaCompositorXRender *compositor,
02422 XShapeEvent *event)
02423 {
02424 MetaCompWindow *cw = find_window_in_display (compositor->display,
02425 event->window);
02426
02427 if (cw == NULL)
02428 return;
02429
02430 if (event->kind == ShapeBounding)
02431 {
02432 if (!event->shaped && cw->shaped)
02433 cw->shaped = FALSE;
02434
02435 resize_win (cw, cw->attrs.x, cw->attrs.y,
02436 event->width + event->x, event->height + event->y,
02437 cw->attrs.border_width, cw->attrs.override_redirect);
02438
02439 if (event->shaped && !cw->shaped)
02440 cw->shaped = TRUE;
02441 }
02442 }
02443
02444 static int
02445 timeout_debug (MetaCompositorXRender *compositor)
02446 {
02447 compositor->show_redraw = (g_getenv ("METACITY_DEBUG_REDRAWS") != NULL);
02448 compositor->debug = (g_getenv ("METACITY_DEBUG_COMPOSITOR") != NULL);
02449
02450 return FALSE;
02451 }
02452
02453 static void
02454 xrender_add_window (MetaCompositor *compositor,
02455 MetaWindow *window,
02456 Window xwindow,
02457 XWindowAttributes *attrs)
02458 {
02459 #ifdef HAVE_COMPOSITE_EXTENSIONS
02460 MetaCompositorXRender *xrc = (MetaCompositorXRender *) compositor;
02461 MetaScreen *screen = meta_screen_for_x_screen (attrs->screen);
02462
02463 meta_error_trap_push (xrc->display);
02464 add_win (screen, window, xwindow);
02465 meta_error_trap_pop (xrc->display, FALSE);
02466 #endif
02467 }
02468
02469 static void
02470 xrender_remove_window (MetaCompositor *compositor,
02471 Window xwindow)
02472 {
02473 #ifdef HAVE_COMPOSITE_EXTENSIONS
02474 #endif
02475 }
02476
02477 static void
02478 show_overlay_window (MetaScreen *screen,
02479 Window cow)
02480 {
02481 MetaDisplay *display = meta_screen_get_display (screen);
02482 Display *xdisplay = meta_display_get_xdisplay (display);
02483
02484 #ifdef HAVE_COW
02485 if (have_cow (display))
02486 {
02487 XserverRegion region;
02488
02489 region = XFixesCreateRegion (xdisplay, NULL, 0);
02490
02491 XFixesSetWindowShapeRegion (xdisplay, cow, ShapeBounding, 0, 0, 0);
02492 XFixesSetWindowShapeRegion (xdisplay, cow, ShapeInput, 0, 0, region);
02493
02494 XFixesDestroyRegion (xdisplay, region);
02495
02496 damage_screen (screen);
02497 }
02498 #endif
02499 }
02500
02501 static void
02502 hide_overlay_window (MetaScreen *screen,
02503 Window cow)
02504 {
02505 #ifdef HAVE_COW
02506 MetaDisplay *display = meta_screen_get_display (screen);
02507 Display *xdisplay = meta_display_get_xdisplay (display);
02508 XserverRegion region;
02509
02510 region = XFixesCreateRegion (xdisplay, NULL, 0);
02511 XFixesSetWindowShapeRegion (xdisplay, cow, ShapeBounding, 0, 0, region);
02512 XFixesDestroyRegion (xdisplay, region);
02513 #endif
02514 }
02515
02516 static Window
02517 get_output_window (MetaScreen *screen)
02518 {
02519 MetaDisplay *display = meta_screen_get_display (screen);
02520 Display *xdisplay = meta_display_get_xdisplay (display);
02521 Window output, xroot;
02522
02523 xroot = meta_screen_get_xroot (screen);
02524
02525 #ifdef HAVE_COW
02526 if (have_cow (display))
02527 {
02528 output = XCompositeGetOverlayWindow (xdisplay, xroot);
02529 XSelectInput (xdisplay, output, ExposureMask);
02530 }
02531 else
02532 #endif
02533 {
02534 output = xroot;
02535 }
02536
02537 return output;
02538 }
02539
02540 static void
02541 xrender_manage_screen (MetaCompositor *compositor,
02542 MetaScreen *screen)
02543 {
02544 #ifdef HAVE_COMPOSITE_EXTENSIONS
02545 MetaCompScreen *info;
02546 MetaDisplay *display = meta_screen_get_display (screen);
02547 Display *xdisplay = meta_display_get_xdisplay (display);
02548 XRenderPictureAttributes pa;
02549 XRenderPictFormat *visual_format;
02550 int screen_number = meta_screen_get_screen_number (screen);
02551 Window xroot = meta_screen_get_xroot (screen);
02552
02553
02554 if (meta_screen_get_compositor_data (screen))
02555 return;
02556
02557 gdk_error_trap_push ();
02558 XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
02559 XSync (xdisplay, FALSE);
02560
02561 if (gdk_error_trap_pop ())
02562 {
02563 g_warning ("Another compositing manager is running on screen %i",
02564 screen_number);
02565 return;
02566 }
02567
02568 info = g_new0 (MetaCompScreen, 1);
02569 info->screen = screen;
02570
02571 meta_screen_set_compositor_data (screen, info);
02572
02573 visual_format = XRenderFindVisualFormat (xdisplay, DefaultVisual (xdisplay,
02574 screen_number));
02575 if (!visual_format)
02576 {
02577 g_warning ("Cannot find visual format on screen %i", screen_number);
02578 return;
02579 }
02580
02581 info->output = get_output_window (screen);
02582
02583 pa.subwindow_mode = IncludeInferiors;
02584 info->root_picture = XRenderCreatePicture (xdisplay, info->output,
02585 visual_format,
02586 CPSubwindowMode, &pa);
02587 if (info->root_picture == None)
02588 {
02589 g_warning ("Cannot create root picture on screen %i", screen_number);
02590 return;
02591 }
02592
02593 info->root_buffer = None;
02594 info->black_picture = solid_picture (display, screen, TRUE, 1, 0, 0, 0);
02595
02596 info->root_tile = None;
02597 info->all_damage = None;
02598
02599 info->windows = NULL;
02600 info->windows_by_xid = g_hash_table_new (g_direct_hash, g_direct_equal);
02601
02602 info->focus_window = meta_display_get_focus_window (display);
02603
02604 info->compositor_active = TRUE;
02605 info->overlays = 0;
02606 info->clip_changed = TRUE;
02607
02608 info->have_shadows = (g_getenv("META_DEBUG_NO_SHADOW") == NULL);
02609 if (info->have_shadows)
02610 {
02611 meta_verbose ("Enabling shadows\n");
02612 generate_shadows (info);
02613 }
02614 else
02615 meta_verbose ("Disabling shadows\n");
02616
02617 XClearArea (xdisplay, info->output, 0, 0, 0, 0, TRUE);
02618
02619 meta_screen_set_cm_selection (screen);
02620
02621
02622 show_overlay_window (screen, info->output);
02623 #endif
02624 }
02625
02626 static void
02627 xrender_unmanage_screen (MetaCompositor *compositor,
02628 MetaScreen *screen)
02629 {
02630 #ifdef HAVE_COMPOSITE_EXTENSIONS
02631 MetaDisplay *display = meta_screen_get_display (screen);
02632 Display *xdisplay = meta_display_get_xdisplay (display);
02633 MetaCompScreen *info;
02634 Window xroot = meta_screen_get_xroot (screen);
02635 GList *index;
02636
02637 info = meta_screen_get_compositor_data (screen);
02638
02639
02640 if (info == NULL)
02641 return;
02642
02643 hide_overlay_window (screen, info->output);
02644
02645
02646 for (index = info->windows; index; index = index->next)
02647 {
02648 MetaCompWindow *cw = (MetaCompWindow *) index->data;
02649 free_win (cw, TRUE);
02650 }
02651 g_list_free (info->windows);
02652 g_hash_table_destroy (info->windows_by_xid);
02653
02654 if (info->root_picture)
02655 XRenderFreePicture (xdisplay, info->root_picture);
02656
02657 if (info->black_picture)
02658 XRenderFreePicture (xdisplay, info->black_picture);
02659
02660 if (info->have_shadows)
02661 {
02662 int i;
02663
02664 for (i = 0; i < LAST_SHADOW_TYPE; i++)
02665 g_free (info->shadows[i]->gaussian_map);
02666 }
02667
02668 XCompositeUnredirectSubwindows (xdisplay, xroot,
02669 CompositeRedirectManual);
02670 meta_screen_unset_cm_selection (screen);
02671
02672 #ifdef HAVE_COW
02673 XCompositeReleaseOverlayWindow (xdisplay, info->output);
02674 #endif
02675
02676 g_free (info);
02677
02678 meta_screen_set_compositor_data (screen, NULL);
02679 #endif
02680 }
02681
02682 static void
02683 xrender_set_updates (MetaCompositor *compositor,
02684 MetaWindow *window,
02685 gboolean updates)
02686 {
02687 #ifdef HAVE_COMPOSITE_EXTENSIONS
02688
02689 #endif
02690 }
02691
02692 static void
02693 xrender_destroy (MetaCompositor *compositor)
02694 {
02695 #ifdef HAVE_COMPOSITE_EXTENSIONS
02696 g_free (compositor);
02697 #endif
02698 }
02699
02700 #if 0
02701
02702
02703
02704
02705 static void
02706 xrender_begin_move (MetaCompositor *compositor,
02707 MetaWindow *window,
02708 MetaRectangle *initial,
02709 int grab_x,
02710 int grab_y)
02711 {
02712 #ifdef HAVE_COMPOSITE_EXTENSIONS
02713 #endif
02714 }
02715
02716 static void
02717 xrender_update_move (MetaCompositor *compositor,
02718 MetaWindow *window,
02719 int x,
02720 int y)
02721 {
02722 #ifdef HAVE_COMPOSITE_EXTENSIONS
02723 #endif
02724 }
02725
02726 static void
02727 xrender_end_move (MetaCompositor *compositor,
02728 MetaWindow *window)
02729 {
02730 #ifdef HAVE_COMPOSITE_EXTENSIONS
02731 #endif
02732 }
02733
02734 static void
02735 xrender_free_window (MetaCompositor *compositor,
02736 MetaWindow *window)
02737 {
02738 #ifdef HAVE_COMPOSITE_EXTENSIONS
02739
02740
02741
02742
02743
02744
02745
02746
02747 #endif
02748 }
02749 #endif
02750
02751 static void
02752 xrender_process_event (MetaCompositor *compositor,
02753 XEvent *event,
02754 MetaWindow *window)
02755 {
02756 #ifdef HAVE_COMPOSITE_EXTENSIONS
02757 MetaCompositorXRender *xrc = (MetaCompositorXRender *) compositor;
02758
02759
02760
02761
02762
02763 meta_error_trap_push (xrc->display);
02764 switch (event->type)
02765 {
02766 case CirculateNotify:
02767 process_circulate_notify (xrc, (XCirculateEvent *) event);
02768 break;
02769
02770 case ConfigureNotify:
02771 process_configure_notify (xrc, (XConfigureEvent *) event);
02772 break;
02773
02774 case PropertyNotify:
02775 process_property_notify (xrc, (XPropertyEvent *) event);
02776 break;
02777
02778 case Expose:
02779 process_expose (xrc, (XExposeEvent *) event);
02780 break;
02781
02782 case UnmapNotify:
02783 process_unmap (xrc, (XUnmapEvent *) event);
02784 break;
02785
02786 case MapNotify:
02787 process_map (xrc, (XMapEvent *) event);
02788 break;
02789
02790 case ReparentNotify:
02791 process_reparent (xrc, (XReparentEvent *) event, window);
02792 break;
02793
02794 case CreateNotify:
02795 process_create (xrc, (XCreateWindowEvent *) event, window);
02796 break;
02797
02798 case DestroyNotify:
02799 process_destroy (xrc, (XDestroyWindowEvent *) event);
02800 break;
02801
02802 default:
02803 if (event->type == meta_display_get_damage_event_base (xrc->display) + XDamageNotify)
02804 process_damage (xrc, (XDamageNotifyEvent *) event);
02805 #ifdef HAVE_SHAPE
02806 else if (event->type == meta_display_get_shape_event_base (xrc->display) + ShapeNotify)
02807 process_shape (xrc, (XShapeEvent *) event);
02808 #endif
02809 else
02810 {
02811 meta_error_trap_pop (xrc->display, FALSE);
02812 return;
02813 }
02814 break;
02815 }
02816
02817 meta_error_trap_pop (xrc->display, FALSE);
02818 #ifndef USE_IDLE_REPAINT
02819 repair_display (xrc->display);
02820 #endif
02821
02822 return;
02823 #endif
02824 }
02825
02826 static Pixmap
02827 xrender_get_window_pixmap (MetaCompositor *compositor,
02828 MetaWindow *window)
02829 {
02830 #ifdef HAVE_COMPOSITE_EXTENSIONS
02831 MetaCompWindow *cw = NULL;
02832 MetaScreen *screen = meta_window_get_screen (window);
02833 MetaFrame *frame = meta_window_get_frame (window);
02834
02835 cw = find_window_for_screen (screen, frame ? meta_frame_get_xwindow (frame) :
02836 meta_window_get_xwindow (window));
02837 if (cw == NULL)
02838 return None;
02839
02840 #ifdef HAVE_NAME_WINDOW_PIXMAP
02841 if (have_name_window_pixmap (meta_window_get_display (window)))
02842 {
02843 if (meta_window_is_shaded (window))
02844 return cw->shaded_back_pixmap;
02845 else
02846 return cw->back_pixmap;
02847 }
02848 else
02849 #endif
02850 return None;
02851 #endif
02852 }
02853
02854 static void
02855 xrender_set_active_window (MetaCompositor *compositor,
02856 MetaScreen *screen,
02857 MetaWindow *window)
02858 {
02859 #ifdef HAVE_COMPOSITE_EXTENSIONS
02860 MetaCompositorXRender *xrc = (MetaCompositorXRender *) compositor;
02861 MetaDisplay *display;
02862 Display *xdisplay;
02863 MetaCompWindow *old_focus = NULL, *new_focus = NULL;
02864 MetaCompScreen *info = NULL;
02865 MetaWindow *old_focus_win = NULL;
02866
02867 if (compositor == NULL)
02868 return;
02869
02870 display = xrc->display;
02871 xdisplay = meta_display_get_xdisplay (display);
02872 info = meta_screen_get_compositor_data (screen);
02873
02874 if (info != NULL)
02875 {
02876 old_focus_win = info->focus_window;
02877 }
02878
02879 if (old_focus_win)
02880 {
02881 MetaFrame *f = meta_window_get_frame (old_focus_win);
02882
02883 old_focus = find_window_for_screen (screen,
02884 f ? meta_frame_get_xwindow (f) :
02885 meta_window_get_xwindow (old_focus_win));
02886 }
02887
02888 if (window)
02889 {
02890 MetaFrame *f = meta_window_get_frame (window);
02891 new_focus = find_window_for_screen (screen,
02892 f ? meta_frame_get_xwindow (f) :
02893 meta_window_get_xwindow (window));
02894 }
02895
02896 if (info != NULL)
02897 {
02898 info->focus_window = window;
02899 }
02900
02901 if (old_focus)
02902 {
02903 XserverRegion damage;
02904
02905
02906 old_focus->shadow_type = META_SHADOW_MEDIUM;
02907 determine_mode (display, screen, old_focus);
02908 old_focus->needs_shadow = window_has_shadow (old_focus);
02909
02910 if (old_focus->attrs.map_state == IsViewable)
02911 {
02912 if (old_focus->shadow)
02913 {
02914 XRenderFreePicture (xdisplay, old_focus->shadow);
02915 old_focus->shadow = None;
02916 }
02917
02918 if (old_focus->extents)
02919 {
02920 damage = XFixesCreateRegion (xdisplay, NULL, 0);
02921 XFixesCopyRegion (xdisplay, damage, old_focus->extents);
02922 XFixesDestroyRegion (xdisplay, old_focus->extents);
02923 }
02924 else
02925 damage = None;
02926
02927
02928 old_focus->extents = win_extents (old_focus);
02929
02930 if (damage)
02931 XFixesUnionRegion (xdisplay, damage, damage, old_focus->extents);
02932 else
02933 {
02934 damage = XFixesCreateRegion (xdisplay, NULL, 0);
02935 XFixesCopyRegion (xdisplay, damage, old_focus->extents);
02936 }
02937
02938 dump_xserver_region ("resize_win", display, damage);
02939 add_damage (screen, damage);
02940
02941 if (info != NULL)
02942 {
02943 info->clip_changed = TRUE;
02944 }
02945 }
02946 }
02947
02948 if (new_focus)
02949 {
02950 XserverRegion damage;
02951
02952 new_focus->shadow_type = META_SHADOW_LARGE;
02953 determine_mode (display, screen, new_focus);
02954 new_focus->needs_shadow = window_has_shadow (new_focus);
02955
02956 if (new_focus->shadow)
02957 {
02958 XRenderFreePicture (xdisplay, new_focus->shadow);
02959 new_focus->shadow = None;
02960 }
02961
02962 if (new_focus->extents)
02963 {
02964 damage = XFixesCreateRegion (xdisplay, NULL, 0);
02965 XFixesCopyRegion (xdisplay, damage, new_focus->extents);
02966 XFixesDestroyRegion (xdisplay, new_focus->extents);
02967 }
02968 else
02969 damage = None;
02970
02971
02972 new_focus->extents = win_extents (new_focus);
02973
02974 if (damage)
02975 XFixesUnionRegion (xdisplay, damage, damage, new_focus->extents);
02976 else
02977 {
02978 damage = XFixesCreateRegion (xdisplay, NULL, 0);
02979 XFixesCopyRegion (xdisplay, damage, new_focus->extents);
02980 }
02981
02982 dump_xserver_region ("resize_win", display, damage);
02983 add_damage (screen, damage);
02984
02985 if (info != NULL)
02986 {
02987 info->clip_changed = TRUE;
02988 }
02989 }
02990 #ifdef USE_IDLE_REPAINT
02991 add_repair (display);
02992 #endif
02993 #endif
02994 }
02995
02996 static MetaCompositor comp_info = {
02997 xrender_destroy,
02998 xrender_manage_screen,
02999 xrender_unmanage_screen,
03000 xrender_add_window,
03001 xrender_remove_window,
03002 xrender_set_updates,
03003 xrender_process_event,
03004 xrender_get_window_pixmap,
03005 xrender_set_active_window
03006 };
03007
03008 MetaCompositor *
03009 meta_compositor_xrender_new (MetaDisplay *display)
03010 {
03011 #ifdef HAVE_COMPOSITE_EXTENSIONS
03012 char *atom_names[] = {
03013 "_XROOTPMAP_ID",
03014 "_XSETROOT_ID",
03015 "_NET_WM_WINDOW_OPACITY",
03016 "_NET_WM_WINDOW_TYPE_DND",
03017 "_NET_WM_WINDOW_TYPE",
03018 "_NET_WM_WINDOW_TYPE_DESKTOP",
03019 "_NET_WM_WINDOW_TYPE_DOCK",
03020 "_NET_WM_WINDOW_TYPE_MENU",
03021 "_NET_WM_WINDOW_TYPE_DIALOG",
03022 "_NET_WM_WINDOW_TYPE_NORMAL",
03023 "_NET_WM_WINDOW_TYPE_UTILITY",
03024 "_NET_WM_WINDOW_TYPE_SPLASH",
03025 "_NET_WM_WINDOW_TYPE_TOOLBAR",
03026 "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU",
03027 "_NET_WM_WINDOW_TYPE_TOOLTIP"
03028 };
03029 Atom atoms[G_N_ELEMENTS(atom_names)];
03030 MetaCompositorXRender *xrc;
03031 MetaCompositor *compositor;
03032 Display *xdisplay = meta_display_get_xdisplay (display);
03033
03034 xrc = g_new (MetaCompositorXRender, 1);
03035 xrc->compositor = comp_info;
03036
03037 compositor = (MetaCompositor *) xrc;
03038
03039 xrc->display = display;
03040
03041 meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
03042 XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names),
03043 False, atoms);
03044
03045 xrc->atom_x_root_pixmap = atoms[0];
03046 xrc->atom_x_set_root = atoms[1];
03047 xrc->atom_net_wm_window_opacity = atoms[2];
03048 xrc->atom_net_wm_window_type_dnd = atoms[3];
03049 xrc->atom_net_wm_window_type = atoms[4];
03050 xrc->atom_net_wm_window_type_desktop = atoms[5];
03051 xrc->atom_net_wm_window_type_dock = atoms[6];
03052 xrc->atom_net_wm_window_type_menu = atoms[7];
03053 xrc->atom_net_wm_window_type_dialog = atoms[8];
03054 xrc->atom_net_wm_window_type_normal = atoms[9];
03055 xrc->atom_net_wm_window_type_utility = atoms[10];
03056 xrc->atom_net_wm_window_type_splash = atoms[11];
03057 xrc->atom_net_wm_window_type_toolbar = atoms[12];
03058 xrc->atom_net_wm_window_type_dropdown_menu = atoms[13];
03059 xrc->atom_net_wm_window_type_tooltip = atoms[14];
03060
03061 #ifdef USE_IDLE_REPAINT
03062 meta_verbose ("Using idle repaint\n");
03063 xrc->repaint_id = 0;
03064 #endif
03065
03066 xrc->enabled = TRUE;
03067 g_timeout_add (2000, (GSourceFunc) timeout_debug, xrc);
03068
03069 return compositor;
03070 #else
03071 return NULL;
03072 #endif
03073 }