metacity r3653 - in trunk: . src/core



Author: iain
Date: Tue Mar 18 23:42:20 2008
New Revision: 3653
URL: http://svn.gnome.org/viewvc/metacity?rev=3653&view=rev

Log:
2008-03-18  Iain Holmes  <iain gnome org>

        * src/core/compositor.c (window_has_shadow): Allow shaped 
windows
        _with frames_ to have shadows.
        (meta_compositor_set_active_window): Watch for the focus of 
windows
        and change the size of the drop shadows.
        (generate_shadows): Create differently sized shadows.
        (meta_compositor_get_window_pixmap): Get the xwindow correctly.

        * src/core/window.c (meta_window_notify_focus): Set the active 
window
        in the compositor.



Modified:
   trunk/ChangeLog
   trunk/src/core/compositor.c
   trunk/src/core/compositor.h
   trunk/src/core/window.c

Modified: trunk/src/core/compositor.c
==============================================================================
--- trunk/src/core/compositor.c	(original)
+++ trunk/src/core/compositor.c	Tue Mar 18 23:42:20 2008
@@ -83,6 +83,14 @@
   META_COMP_WINDOW_DOCK
 } MetaCompWindowType;
 
+typedef enum _MetaShadowType
+{
+  META_SHADOW_SMALL,
+  META_SHADOW_MEDIUM,
+  META_SHADOW_LARGE,
+  LAST_SHADOW_TYPE
+} MetaShadowType;
+
 struct _MetaCompositor 
 {
   MetaDisplay *display;
@@ -106,18 +114,25 @@
   double *data;
 } conv;
 
+typedef struct _shadow 
+{
+  conv *gaussian_map;
+  guchar *shadow_corner;
+  guchar *shadow_top;
+} shadow;
+ 
 typedef struct _MetaCompScreen 
 {
   MetaScreen *screen;
   GList *windows;
   GHashTable *windows_by_xid;
 
+  MetaWindow *focus_window;
+
   Window output;
 
   gboolean have_shadows;
-  conv *gaussian_map;
-  guchar *shadow_corner;
-  guchar *shadow_top;
+  shadow *shadows[LAST_SHADOW_TYPE];
 
   Picture root_picture;
   Picture root_buffer;
@@ -154,13 +169,15 @@
 
   gboolean damaged;
   gboolean shaped;
-  gboolean needs_shadow;
 
   MetaCompWindowType type;
 
   Damage damage;
   Picture picture;
   Picture alpha_pict;
+
+  gboolean needs_shadow;
+  MetaShadowType shadow_type;
   Picture shadow_pict;
 
   XserverRegion border_size;
@@ -185,9 +202,16 @@
 #define WINDOW_SOLID 0
 #define WINDOW_ARGB 1
 
-#define SHADOW_RADIUS 6.0
-#define SHADOW_OFFSET_X (SHADOW_RADIUS * -3 / 2)
-#define SHADOW_OFFSET_Y (SHADOW_RADIUS * -5 / 4)
+#define SHADOW_SMALL_RADIUS 3.0
+#define SHADOW_MEDIUM_RADIUS 6.0
+#define SHADOW_LARGE_RADIUS 12.0
+
+#define SHADOW_SMALL_OFFSET_X (SHADOW_SMALL_RADIUS * -3 / 2)
+#define SHADOW_SMALL_OFFSET_Y (SHADOW_SMALL_RADIUS * -3 / 2)
+#define SHADOW_MEDIUM_OFFSET_X (SHADOW_MEDIUM_RADIUS * -3 / 2)
+#define SHADOW_MEDIUM_OFFSET_Y (SHADOW_MEDIUM_RADIUS * -5 / 4)
+#define SHADOW_LARGE_OFFSET_X -15
+#define SHADOW_LARGE_OFFSET_Y -15
 
 #define SHADOW_OPACITY 0.66
  
@@ -343,73 +367,93 @@
 
 /* precompute shadow corners and sides to save time for large windows */
 static void
-presum_gaussian (MetaCompScreen *info)
+presum_gaussian (shadow *shad)
 {
   int centre;
   int opacity, x, y;
   int msize;
   conv *map;
 
-  map = info->gaussian_map;
+  map = shad->gaussian_map;
   msize = map->size;
   centre = map->size / 2;
 
-  if (info->shadow_corner)
-    g_free (info->shadow_corner);
-  if (info->shadow_top)
-    g_free (info->shadow_top);
+  if (shad->shadow_corner)
+    g_free (shad->shadow_corner);
+  if (shad->shadow_top)
+    g_free (shad->shadow_top);
 
-  info->shadow_corner = (guchar *)(g_malloc ((msize + 1) * (msize + 1) * 26));
-  info->shadow_top = (guchar *) (g_malloc ((msize + 1) * 26));
+  shad->shadow_corner = (guchar *)(g_malloc ((msize + 1) * (msize + 1) * 26));
+  shad->shadow_top = (guchar *) (g_malloc ((msize + 1) * 26));
   
   for (x = 0; x <= msize; x++) 
     {
       
-      info->shadow_top[25 * (msize + 1) + x] =
+      shad->shadow_top[25 * (msize + 1) + x] =
         sum_gaussian (map, 1, x - centre, centre, msize * 2, msize * 2);
       for (opacity = 0; opacity < 25; opacity++) 
         {
-          info->shadow_top[opacity * (msize + 1) + x] =
-            info->shadow_top[25 * (msize + 1) + x] * opacity / 25;
+          shad->shadow_top[opacity * (msize + 1) + x] =
+            shad->shadow_top[25 * (msize + 1) + x] * opacity / 25;
         }
       
       for (y = 0; y <= x; y++) 
         {
-          info->shadow_corner[25 * (msize + 1) * (msize + 1) 
+          shad->shadow_corner[25 * (msize + 1) * (msize + 1) 
                               + y * (msize + 1) 
                               + x]
             = sum_gaussian (map, 1, x - centre, y - centre,
                             msize * 2, msize * 2);
           
-          info->shadow_corner[25 * (msize + 1) * (msize + 1) 
+          shad->shadow_corner[25 * (msize + 1) * (msize + 1) 
                               + x * (msize + 1) + y] =
-            info->shadow_corner[25 * (msize + 1) * (msize + 1) 
+            shad->shadow_corner[25 * (msize + 1) * (msize + 1) 
                                 + y * (msize + 1) + x];
           
           for (opacity = 0; opacity < 25; opacity++) 
             {
-              info->shadow_corner[opacity * (msize + 1) * (msize + 1) 
+              shad->shadow_corner[opacity * (msize + 1) * (msize + 1) 
                                   + y * (msize + 1) + x]
-                = info->shadow_corner[opacity * (msize + 1) * (msize + 1) 
+                = shad->shadow_corner[opacity * (msize + 1) * (msize + 1) 
                                       + x * (msize + 1) + y]
-                = info->shadow_corner[25 * (msize + 1) * (msize + 1) 
+                = shad->shadow_corner[25 * (msize + 1) * (msize + 1) 
                                       + y * (msize + 1) + x] * opacity / 25;
             }
         }
     }
 }
 
+static void
+generate_shadows (MetaCompScreen *info)
+{
+  double radii[LAST_SHADOW_TYPE] = {SHADOW_SMALL_RADIUS,
+                                    SHADOW_MEDIUM_RADIUS,
+                                    SHADOW_LARGE_RADIUS};
+  int i;
+
+  for (i = 0; i < LAST_SHADOW_TYPE; i++) {
+    shadow *shad = g_new0 (shadow, 1);
+
+    shad->gaussian_map = make_gaussian_map (radii[i]);
+    presum_gaussian (shad);
+
+    info->shadows[i] = shad;
+  }
+}
+
 static XImage *
-make_shadow (MetaDisplay *display,
-             MetaScreen  *screen,
-             double       opacity,
-             int          width,
-             int          height)
+make_shadow (MetaDisplay   *display,
+             MetaScreen    *screen,
+             MetaShadowType shadow_type,
+             double         opacity,
+             int            width,
+             int            height)
 {
   MetaCompScreen *info = screen->compositor_data;
   XImage *ximage;
   guchar *data;
-  int msize = info->gaussian_map->size;
+  shadow *shad = info->shadows[shadow_type];
+  int msize = shad->gaussian_map->size;
   int ylimit, xlimit;
   int swidth = width + msize;
   int sheight = height + msize;
@@ -439,9 +483,9 @@
    * centre (fill the complete data array
    */
   if (msize > 0)
-    d = info->shadow_top[opacity_int * (msize + 1) + msize];
+    d = shad->shadow_top[opacity_int * (msize + 1) + msize];
   else
-    d = sum_gaussian (info->gaussian_map, opacity, centre, 
+    d = sum_gaussian (shad->gaussian_map, opacity, centre, 
                       centre, width, height);
   memset (data, d, sheight * swidth);
 
@@ -462,9 +506,9 @@
         {
           
           if (xlimit == msize && ylimit == msize)
-            d = info->shadow_corner[opacity_int * (msize + 1) * (msize + 1) + y * (msize + 1) + x]; 
+            d = shad->shadow_corner[opacity_int * (msize + 1) * (msize + 1) + y * (msize + 1) + x]; 
           else
-            d = sum_gaussian (info->gaussian_map, opacity, x - centre, 
+            d = sum_gaussian (shad->gaussian_map, opacity, x - centre, 
                               y - centre, width, height);
           
           data[y * swidth + x] = d;
@@ -481,9 +525,9 @@
       for (y = 0; y < ylimit; y++) 
         {
           if (ylimit == msize)
-            d = info->shadow_top[opacity_int * (msize + 1) + y];
+            d = shad->shadow_top[opacity_int * (msize + 1) + y];
           else
-            d = sum_gaussian (info->gaussian_map, opacity, centre, 
+            d = sum_gaussian (shad->gaussian_map, opacity, centre, 
                               y - centre, width, height);
 
           memset (&data[y * swidth + msize], d, x_diff);
@@ -497,10 +541,10 @@
   for (x = 0; x < xlimit; x++) 
     {
       if (xlimit == msize)
-        d = info->shadow_top[opacity_int * (msize + 1) + x];
+        d = shad->shadow_top[opacity_int * (msize + 1) + x];
       else
-        d = sum_gaussian (info->gaussian_map, opacity, x - centre, 
-                        centre, width, height);
+        d = sum_gaussian (shad->gaussian_map, opacity, x - centre, 
+                          centre, width, height);
     
       for (y = msize; y < sheight - msize; y++) 
         {
@@ -513,21 +557,23 @@
 }
 
 static Picture
-shadow_picture (MetaDisplay *display,
-                MetaScreen  *screen,
-                double       opacity,
-                Picture      alpha_pict,
-                int          width,
-                int          height,
-                int         *wp,
-                int         *hp)
+shadow_picture (MetaDisplay   *display,
+                MetaScreen    *screen,
+                MetaShadowType shadow_type,
+                double         opacity,
+                Picture        alpha_pict,
+                int            width,
+                int            height,
+                int           *wp,
+                int           *hp)
 {
   XImage *shadow_image;
   Pixmap shadow_pixmap;
   Picture shadow_picture;
   GC gc;
 
-  shadow_image = make_shadow (display, screen, opacity, width, height);
+  shadow_image = make_shadow (display, screen, shadow_type,
+                              opacity, width, height);
   if (!shadow_image)
     return None;
 
@@ -777,13 +823,9 @@
   if (((MetaCompScreen *)cw->screen->compositor_data)->have_shadows == FALSE) 
     return FALSE;
 
-  /* Never put a shadow around shaped windows */
-  if (cw->shaped) {
-    meta_verbose ("Window has no shadow as it is shaped\n");
-    return FALSE;
-  }
-
-  /* Always put a shadow around windows with a frame */
+  /* Always put a shadow around windows with a frame - This should override
+     the restriction about not putting a shadow around shaped windows
+     as the frame might be the reason the window is shaped */
   if (cw->window) 
     {
       if (cw->window->frame) {
@@ -792,6 +834,12 @@
       }
     }
 
+  /* Never put a shadow around shaped windows */
+  if (cw->shaped) {
+    meta_verbose ("Window has no shadow as it is shaped\n");
+    return FALSE;
+  }
+
   /* Don't put shadow around DND icon windows */
   if (cw->type == META_COMP_WINDOW_DND ||
       cw->type == META_COMP_WINDOW_DESKTOP) {
@@ -808,6 +856,12 @@
   return FALSE;
 }
 
+double shadow_offsets_x[LAST_SHADOW_TYPE] = {SHADOW_SMALL_OFFSET_X,
+                                             SHADOW_MEDIUM_OFFSET_X,
+                                             SHADOW_LARGE_OFFSET_X};
+double shadow_offsets_y[LAST_SHADOW_TYPE] = {SHADOW_SMALL_OFFSET_Y,
+                                             SHADOW_MEDIUM_OFFSET_Y,
+                                             SHADOW_LARGE_OFFSET_Y};
 static XserverRegion
 win_extents (MetaCompWindow *cw)
 {
@@ -829,8 +883,8 @@
     {
       XRectangle sr;
 
-      cw->shadow_dx = SHADOW_OFFSET_X;
-      cw->shadow_dy = SHADOW_OFFSET_Y;
+      cw->shadow_dx = shadow_offsets_x [cw->shadow_type];
+      cw->shadow_dy = shadow_offsets_y [cw->shadow_type];
 
       if (!cw->shadow) 
         {
@@ -838,7 +892,8 @@
           if (cw->opacity != (guint) OPAQUE)
             opacity = opacity * ((double) cw->opacity) / ((double) OPAQUE);
           
-          cw->shadow = shadow_picture (display, screen, opacity, cw->alpha_pict,
+          cw->shadow = shadow_picture (display, screen, cw->shadow_type, 
+                                       opacity, cw->alpha_pict,
                                        cw->attrs.width + cw->attrs.border_width * 2,
                                        cw->attrs.height + cw->attrs.border_width * 2,
                                        &cw->shadow_width, &cw->shadow_height);
@@ -1692,6 +1747,12 @@
   cw->shadow_dy = 0;
   cw->shadow_width = 0;
   cw->shadow_height = 0;
+
+  if (window && window->has_focus)
+    cw->shadow_type = META_SHADOW_LARGE;
+  else
+    cw->shadow_type = META_SHADOW_MEDIUM;
+
   cw->opacity = OPAQUE;
   
   cw->border_clip = None;
@@ -2437,13 +2498,20 @@
   info->windows = NULL;
   info->windows_by_xid = g_hash_table_new (g_direct_hash, g_direct_equal);
 
+  info->focus_window = display->focus_window;
+
   info->compositor_active = TRUE;
   info->overlays = 0;
   info->clip_changed = TRUE;
 
   info->have_shadows = (g_getenv("META_DEBUG_NO_SHADOW") == NULL);
-  info->gaussian_map = make_gaussian_map (SHADOW_RADIUS);
-  presum_gaussian (info);
+  if (info->have_shadows)
+    {
+      meta_verbose ("Enabling shadows\n");
+      generate_shadows (info);
+    }
+  else
+    meta_verbose ("Disabling shadows\n");
 
   XClearArea (display->xdisplay, info->output, 0, 0, 0, 0, TRUE);
 
@@ -2484,7 +2552,13 @@
   if (info->black_picture)
     XRenderFreePicture (display->xdisplay, info->black_picture);
 
-  g_free (info->gaussian_map);
+  if (info->have_shadows) 
+    {
+      int i;
+      
+      for (i = 0; i < LAST_SHADOW_TYPE; i++)
+        g_free (info->shadows[i]->gaussian_map);
+    }
 
   XCompositeUnredirectSubwindows (display->xdisplay, screen->xroot,
                                   CompositeRedirectManual);
@@ -2637,13 +2711,9 @@
 #ifdef HAVE_COMPOSITE_EXTENSIONS
   MetaCompWindow *cw = NULL;
 
-  if (window->frame)
-    {
-      cw = find_window_for_screen (window->screen, window->frame->xwindow);
-      if (cw == NULL)
-        cw = find_window_for_screen (window->screen, window->xwindow);
-    }
-
+  cw = find_window_for_screen (window->screen,
+                               window->frame ? window->frame->xwindow : 
+                               window->xwindow);
   if (cw == NULL)
     return None;
 
@@ -2660,3 +2730,115 @@
     return None;
 #endif
 }
+
+void
+meta_compositor_set_active_window (MetaCompositor *compositor,
+                                   MetaWindow     *window)
+{
+#ifdef HAVE_COMPOSITE_EXTENSIONS
+  MetaDisplay *display = compositor->display;
+  Display *xdisplay = display->xdisplay;
+  MetaScreen *screen = window->screen;
+  MetaCompWindow *old_focus = NULL, *new_focus = NULL;
+  MetaCompScreen *info = screen->compositor_data;
+  MetaWindow *old_focus_win = info->focus_window;
+
+  if (old_focus_win) 
+    {
+      old_focus = find_window_for_screen (screen, 
+                                          old_focus_win->frame ? old_focus_win->frame->xwindow :
+                                          old_focus_win->xwindow);
+    }
+  new_focus = find_window_for_screen (screen,
+                                      window->frame ? window->frame->xwindow :
+                                      window->xwindow);
+
+  info->focus_window = window;
+  if (old_focus)
+    {
+      XserverRegion damage;
+
+      /* Tear down old shadows */
+      old_focus->shadow_type = META_SHADOW_MEDIUM;
+      determine_mode (display, screen, old_focus);
+      old_focus->needs_shadow = window_has_shadow (old_focus);
+
+      if (old_focus->attrs.map_state == IsViewable)
+        {
+          if (old_focus->shadow)
+            {
+              XRenderFreePicture (xdisplay, old_focus->shadow);
+              old_focus->shadow = None;
+            }
+          
+          if (old_focus->extents)
+            {
+              damage = XFixesCreateRegion (xdisplay, NULL, 0);
+              XFixesCopyRegion (xdisplay, damage, old_focus->extents);
+              XFixesDestroyRegion (xdisplay, old_focus->extents);
+            }
+          else
+            damage = None;
+          
+          /* Build new extents */
+          old_focus->extents = win_extents (old_focus);
+          
+          if (damage) 
+            XFixesUnionRegion (xdisplay, damage, damage, old_focus->extents);      
+          else
+            {
+              damage = XFixesCreateRegion (xdisplay, NULL, 0);
+              XFixesCopyRegion (xdisplay, damage, old_focus->extents);
+            }
+          
+          dump_xserver_region ("resize_win", display, damage);
+          add_damage (screen, damage);
+          
+          info->clip_changed = TRUE;
+        }
+    }
+
+  if (new_focus)
+    {
+      XserverRegion damage;
+
+      new_focus->shadow_type = META_SHADOW_LARGE;
+      determine_mode (display, screen, new_focus);
+      new_focus->needs_shadow = window_has_shadow (new_focus);
+      
+      if (new_focus->shadow)
+        {
+          XRenderFreePicture (xdisplay, new_focus->shadow);
+          new_focus->shadow = None;
+        }
+      
+      if (new_focus->extents)
+        {
+          damage = XFixesCreateRegion (xdisplay, NULL, 0);
+          XFixesCopyRegion (xdisplay, damage, new_focus->extents);
+          XFixesDestroyRegion (xdisplay, new_focus->extents);
+        }
+      else
+        damage = None;
+      
+      /* Build new extents */
+      new_focus->extents = win_extents (new_focus);
+      
+      if (damage) 
+        XFixesUnionRegion (xdisplay, damage, damage, new_focus->extents);      
+      else
+        {
+          damage = XFixesCreateRegion (xdisplay, NULL, 0);
+          XFixesCopyRegion (xdisplay, damage, new_focus->extents);
+        }
+      
+      dump_xserver_region ("resize_win", display, damage);
+      add_damage (screen, damage);
+
+      info->clip_changed = TRUE;
+    }
+#ifdef USE_IDLE_REPAINT
+  add_repair (display);
+#endif
+#endif
+}

Modified: trunk/src/core/compositor.h
==============================================================================
--- trunk/src/core/compositor.h	(original)
+++ trunk/src/core/compositor.h	Tue Mar 18 23:42:20 2008
@@ -64,5 +64,7 @@
 				  MetaWindow *window);
 Pixmap meta_compositor_get_window_pixmap (MetaCompositor *compositor,
                                           MetaWindow     *window);
+void meta_compositor_set_active_window (MetaCompositor *compositor,
+                                        MetaWindow     *window);
 
 #endif /* META_COMPOSITOR_H */

Modified: trunk/src/core/window.c
==============================================================================
--- trunk/src/core/window.c	(original)
+++ trunk/src/core/window.c	Tue Mar 18 23:42:20 2008
@@ -5203,6 +5203,8 @@
                       "* Focus --> %s\n", window->desc);
           window->display->focus_window = window;
           window->has_focus = TRUE;
+          meta_compositor_set_active_window (window->display->compositor,
+                                             window);
 
           /* Move to the front of the focusing workspace's MRU list.
            * We should only be "removing" it from the MRU list if it's



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]