compositor-xrender.c

Go to the documentation of this file.
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
00002 
00003 /* 
00004  * Copyright (C) 2007 Iain Holmes
00005  * Based on xcompmgr - (c) 2003 Keith Packard
00006  *          xfwm4    - (c) 2005-2007 Olivier Fourdan
00007  * 
00008  * This program is free software; you can redistribute it and/or
00009  * modify it under the terms of the GNU General Public License as
00010  * published by the Free Software Foundation; either version 2 of the
00011  * License, or (at your option) any later version.
00012  *
00013  * This program is distributed in the hope that it will be useful, but
00014  * WITHOUT ANY WARRANTY; without even the implied warranty of
00015  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016  * General Public License for more details.
00017  * 
00018  * You should have received a copy of the GNU General Public License
00019  * along with this program; if not, write to the Free Software
00020  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00021  * 02111-1307, USA.
00022  */
00023 
00024 #define _GNU_SOURCE
00025 #define _XOPEN_SOURCE 500 /* for usleep() */
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 /* Don't have a cow man...HAAHAAHAA */
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; /* May be NULL if this window isn't managed by Metacity */
00178   Window id;
00179   XWindowAttributes attrs;
00180 
00181 #ifdef HAVE_NAME_WINDOW_PIXMAP
00182   Pixmap back_pixmap;
00183 
00184   /* When the window is shaded back_pixmap will be replaced with the pixmap
00185      for the shaded window. This is a copy of the original unshaded window
00186      so that we can still see what the window looked like when it is needed 
00187      for the _get_window_pixmap function */
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 /* Gaussian stuff for creating the shadows */
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 * A picture will help
00327 *
00328 *      -center   0                width  width+center
00329 *  -center +-----+-------------------+-----+
00330 *          |     |                   |     |
00331 *          |     |                   |     |
00332 *        0 +-----+-------------------+-----+
00333 *          |     |                   |     |
00334 *          |     |                   |     |
00335 *          |     |                   |     |
00336 *   height +-----+-------------------+-----+
00337 *          |     |                   |     |
00338 * height+  |     |                   |     |
00339 *  center  +-----+-------------------+-----+
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 /* precompute shadow corners and sides to save time for large windows */
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    * Build the gaussian in sections
00516    */
00517 
00518   /*
00519    * centre (fill the complete data array
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    * corners
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   /* top/bottom */
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    * sides
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       /* Background default to just plain ugly grey */
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   /* Always put a shadow around windows with a frame - This should override
00896      the restriction about not putting a shadow around shaped windows
00897      as the frame might be the reason the window is shaped */
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   /* Never put a shadow around shaped windows */
00907   if (cw->shaped) {
00908     meta_verbose ("Window has no shadow as it is shaped\n");
00909     return FALSE;
00910   }
00911 
00912   /* Don't put shadow around DND icon windows */
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    * Painting from top to bottom, reducing the clipping area at 
01165    * each iteration. Only the opaque windows are painted 1st.
01166    */
01167   last = NULL;
01168   for (index = windows; index; index = index->next) 
01169     {
01170       /* Store the last window we dealt with */
01171       last = index;
01172 
01173       cw = (MetaCompWindow *) index->data;
01174       if (!cw->damaged) 
01175         {
01176           /* Not damaged */
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           /* Off screen */
01186           continue;
01187         }
01188 #endif
01189 
01190       if (cw->picture == None) 
01191         cw->picture = get_window_picture (cw);
01192 
01193       /* If the clip region of the screen has been changed
01194          then we need to recreate the extents of the window */
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    * Painting from bottom to top, translucent windows and shadows are painted
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   /* Set clipping to the given region */
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       /* Make a random colour overlay */
01367       overlay = solid_picture (display, screen, TRUE, 1, /* 0.3, alpha */
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   /* Limit it to 50fps */
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   /*  dump_xserver_region ("add_damage", display, damage); */
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       /* See comment in map_win */
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       /* The window may not have been added to the list in this case,
01611          but we can check anyway */
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   /* The reason we deallocate this here and not in unmap
01632      is so that we will still have a valid pixmap for 
01633      whenever the window is unmapped */
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 /*   meta_verbose ("Window is %d\n", cw->type); */
01797 }
01798   
01799 /* Must be called with an error trap in place */
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   /* If Metacity has decided not to manage this window then the input events
01830      won't have been set on the window */
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   /* Only add the window to the list of docks if it needs a shadow */
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   /* Add this to the list at the top of the stack
01879      before it is mapped so that map_win can find it again */
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   /* If above is set to None, the window whose state was changed is on 
01948    * the bottom of the stack with respect to sibling.
01949    */
01950   if (above == None) 
01951     {
01952       /* Insert at bottom of window stack */
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   /*  { // Damage whole screen each time ! ;-)
02005     XRectangle r;
02006 
02007     r.x = 0;
02008     r.y = 0;
02009     meta_screen_get_size (screen, &r.width, &r.height);
02010     fprintf (stderr, "Damage whole screen %d,%d (%d %d)\n",
02011              r.x, r.y, r.width, r.height);
02012     
02013     damage = XFixesCreateRegion (xdisplay, &r, 1);
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               /* If the window is shaded, we store the old backing pixmap
02033                  so we can return a proper image of the window */
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 /* event processors must all be called with an error trap in place */
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       /* Might be the root window? */
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   /* Check for the background property changing */
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                   /* Damage the whole screen as we may need to redraw the 
02221                      background ourselves */
02222                   damage_screen (screen);
02223 #ifdef USE_IDLE_REPAINT
02224                   add_repair (display);
02225 #endif
02226 
02227                   return;
02228                 }
02229             }
02230         }
02231     }
02232 
02233   /* Check for the opacity changing */
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           /* Applications can set this for their toplevel windows, so
02242            * this must be propagated to the window managed by the compositor
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; /* + cw->attrs.border_width; ? */
02318       origin_y = cw->attrs.y; /* + cw->attrs.border_width; ? */
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       /* Ignore unmap caused by parent's resize */
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   /* We are only interested in top level windows, others will
02386      be caught by normal metacity functions */
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   /* Check if the screen is already managed */
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   /* Now we're up and running we can show the output if needed */
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   /* This screen isn't managed */
02640   if (info == NULL)
02641     return;
02642 
02643   hide_overlay_window (screen, info->output);
02644 
02645   /* Destroy the windows */
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 /* Taking these out because they're empty and never called, and the
02702  * compiler complains -- tthurman
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   /* FIXME: When an undecorated window is hidden this is called, 
02740      but the window does not get readded if it is subsequentally shown again 
02741      See http://bugzilla.gnome.org/show_bug.cgi?id=504876 
02742 
02743      I don't *think* theres any need for this call anyway, leaving it out
02744      does not seem to cause any side effects so far, but I should check with
02745      someone who understands more. */
02746   /* destroy_win (compositor->display, window->xwindow, FALSE); */
02747 #endif
02748 }
02749 #endif /* 0 */
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    * This trap is so that none of the compositor functions cause
02760    * X errors. This is really a hack, but I'm afraid I don't understand
02761    * enough about Metacity/X to know how else you are supposed to do it
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 /* HAVE_SHAPE */
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       /* Tear down old shadows */
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           /* Build new extents */
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       /* Build new extents */
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 }

Generated on Sat Aug 23 22:04:16 2008 for metacity by  doxygen 1.5.5