[mutter/wip/cb2eb3: 46/55] frames: Add a GtkWindow per frame



commit b6468a7fa53aca942c03bc287c4819d215201dc0
Author: Jasper St. Pierre <jstpierre mecheye net>
Date:   Fri May 4 19:50:57 2012 -0300

    frames: Add a GtkWindow per frame
    
    Now, now, it's not as bad as it sounds. We're using
    gtk_widget_set_parent_window, as used by glade to embed
    toplevel windows, to do our magic.

 src/ui/frames.c |  629 +++++++++++++++----------------------------------------
 src/ui/frames.h |   47 ++---
 src/ui/ui.c     |   24 +--
 src/ui/ui.h     |    7 -
 4 files changed, 195 insertions(+), 512 deletions(-)
---
diff --git a/src/ui/frames.c b/src/ui/frames.c
index d9036c5..39f57d7 100644
--- a/src/ui/frames.c
+++ b/src/ui/frames.c
@@ -37,51 +37,19 @@
 
 #include "theme-private.h"
 
-#include <cairo-xlib.h>
-
 #ifdef HAVE_SHAPE
 #include <X11/extensions/shape.h>
 #endif
 
-#define DEFAULT_INNER_BUTTON_BORDER 3
-
-static void meta_frames_destroy       (GtkWidget       *object);
-static void meta_frames_finalize      (GObject         *object);
-static void meta_frames_style_updated (GtkWidget       *widget);
-static void meta_frames_map           (GtkWidget       *widget);
-static void meta_frames_unmap         (GtkWidget       *widget);
-
-static void meta_frames_update_prelit_control (MetaFrames      *frames,
-                                               MetaUIFrame     *frame,
-                                               MetaFrameControl control);
-static gboolean meta_frames_button_press_event    (GtkWidget           *widget,
-                                                   GdkEventButton      *event);
-static gboolean meta_frames_button_release_event  (GtkWidget           *widget,
-                                                   GdkEventButton      *event);
-static gboolean meta_frames_motion_notify_event   (GtkWidget           *widget,
-                                                   GdkEventMotion      *event);
-static gboolean meta_frames_destroy_event         (GtkWidget           *widget,
-                                                   GdkEventAny         *event);
-static gboolean meta_frames_draw                  (GtkWidget           *widget,
-                                                   cairo_t             *cr);
-static gboolean meta_frames_enter_notify_event    (GtkWidget           *widget,
-                                                   GdkEventCrossing    *event);
-static gboolean meta_frames_leave_notify_event    (GtkWidget           *widget,
-                                                   GdkEventCrossing    *event);
-
-static void meta_frames_attach_style (MetaFrames  *frames,
-                                      MetaUIFrame *frame);
-
-static void meta_frames_paint        (MetaFrames   *frames,
-                                      MetaUIFrame  *frame,
-                                      cairo_t      *cr);
-
-static void meta_frames_calc_geometry (MetaFrames        *frames,
-                                       MetaUIFrame         *frame,
-                                       MetaFrameGeometry *fgeom);
-
-static void meta_frames_ensure_layout (MetaFrames      *frames,
-                                       MetaUIFrame     *frame);
+static void meta_uiframe_update_prelit_control (MetaUIFrame     *frame,
+                                                MetaFrameControl control);
+
+static void meta_uiframe_attach_style (MetaUIFrame *frame);
+
+static void meta_uiframe_calc_geometry (MetaUIFrame         *frame,
+                                        MetaFrameGeometry *fgeom);
+
+static void meta_uiframe_ensure_layout (MetaUIFrame     *frame);
 
 static MetaUIFrame* meta_frames_lookup_window (MetaFrames *frames,
                                                Window      xwindow);
@@ -91,59 +59,25 @@ static void meta_frames_button_layout_changed (MetaFrames *frames);
 
 static GdkRectangle*    control_rect (MetaFrameControl   control,
                                       MetaFrameGeometry *fgeom);
-static MetaFrameControl get_control  (MetaFrames        *frames,
-                                      MetaUIFrame       *frame,
+static MetaFrameControl get_control  (MetaUIFrame       *frame,
                                       int                x,
                                       int                y);
-static void invalidate_whole_window (MetaFrames *frames,
-                                     MetaUIFrame *frame);
-
-G_DEFINE_TYPE (MetaFrames, meta_frames, GTK_TYPE_WINDOW);
-
-static GObject *
-meta_frames_constructor (GType                  gtype,
-                         guint                  n_properties,
-                         GObjectConstructParam *properties)
-{
-  GObject *object;
-  GObjectClass *gobject_class;
-
-  gobject_class = G_OBJECT_CLASS (meta_frames_parent_class);
-  object = gobject_class->constructor (gtype, n_properties, properties);
 
-  g_object_set (object,
-                "type", GTK_WINDOW_POPUP,
-                NULL);
-
-  return object;
-}
+G_DEFINE_TYPE (MetaUIFrame, meta_uiframe, GTK_TYPE_WINDOW);
 
 static void
-meta_frames_class_init (MetaFramesClass *class)
+meta_uiframe_finalize (GObject *obj)
 {
-  GObjectClass   *gobject_class;
-  GtkWidgetClass *widget_class;
+  MetaUIFrame *frame = META_UIFRAME (obj);
 
-  gobject_class = G_OBJECT_CLASS (class);
-  widget_class = (GtkWidgetClass*) class;
-
-  gobject_class->constructor = meta_frames_constructor;
-  gobject_class->finalize = meta_frames_finalize;
+  if (frame->window)
+    g_object_unref (frame->window);
 
-  widget_class->destroy = meta_frames_destroy;
-
-  widget_class->style_updated = meta_frames_style_updated;
+  if (frame->layout)
+    g_object_unref (G_OBJECT (frame->layout));
 
-  widget_class->map = meta_frames_map;
-  widget_class->unmap = meta_frames_unmap;
-  
-  widget_class->draw = meta_frames_draw;
-  widget_class->destroy_event = meta_frames_destroy_event;  
-  widget_class->button_press_event = meta_frames_button_press_event;
-  widget_class->button_release_event = meta_frames_button_release_event;
-  widget_class->motion_notify_event = meta_frames_motion_notify_event;
-  widget_class->enter_notify_event = meta_frames_enter_notify_event;
-  widget_class->leave_notify_event = meta_frames_leave_notify_event;
+  if (frame->title)
+    g_free (frame->title);
 }
 
 static gint
@@ -173,131 +107,75 @@ prefs_changed_callback (MetaPreference pref,
   switch (pref)
     {
     case META_PREF_BUTTON_LAYOUT:
-      meta_frames_button_layout_changed (META_FRAMES (data));
+      meta_frames_button_layout_changed ((MetaFrames *) data);
       break;
     default:
       break;
     }
 }
 
-static void
-meta_frames_init (MetaFrames *frames)
+MetaFrames*
+meta_frames_new ()
 {
-  frames->frames = g_hash_table_new (unsigned_long_hash, unsigned_long_equal);
-
-  frames->expose_delay_count = 0;
-
-  gtk_widget_set_double_buffered (GTK_WIDGET (frames), FALSE);
-
+  MetaFrames *frames = g_slice_new (MetaFrames);
+  frames->frames = g_hash_table_new_full (unsigned_long_hash, unsigned_long_equal,
+                                          NULL, (GDestroyNotify) gtk_widget_destroy);
   meta_prefs_add_listener (prefs_changed_callback, frames);
+  return frames;
 }
 
-static void
-listify_func (gpointer key, gpointer value, gpointer data)
-{
-  GSList **listp;
-
-  listp = data;
-  *listp = g_slist_prepend (*listp, value);
-}
-
-static void
-meta_frames_destroy (GtkWidget *object)
+void
+meta_frames_free (MetaFrames *frames)
 {
-  GSList *winlist;
-  GSList *tmp;
-  MetaFrames *frames;
-  
-  frames = META_FRAMES (object);
-
-  winlist = NULL;
-  g_hash_table_foreach (frames->frames, listify_func, &winlist);
-
-  /* Unmanage all frames */
-  for (tmp = winlist; tmp != NULL; tmp = tmp->next)
-    {
-      MetaUIFrame *frame;
-
-      frame = tmp->data;
-
-      meta_frames_unmanage_window (frames, frame->xwindow);
-    }
-  g_slist_free (winlist);
-
-  GTK_WIDGET_CLASS (meta_frames_parent_class)->destroy (object);
+  g_assert (g_hash_table_size (frames->frames) == 0);
+  meta_prefs_remove_listener (prefs_changed_callback, frames);
+  g_hash_table_unref (frames->frames);
+  g_slice_free (MetaFrames, frames);
 }
 
 static void
-meta_frames_finalize (GObject *object)
+meta_uiframe_init (MetaUIFrame *frame)
 {
-  MetaFrames *frames;
-  
-  frames = META_FRAMES (object);
-
-  meta_prefs_remove_listener (prefs_changed_callback, frames);
-  
-  g_assert (g_hash_table_size (frames->frames) == 0);
-  g_hash_table_destroy (frames->frames);
-
-  G_OBJECT_CLASS (meta_frames_parent_class)->finalize (object);
 }
 
 static void
 queue_draw_func (gpointer key, gpointer value, gpointer data)
 {
-  MetaUIFrame *frame;
-  MetaFrames *frames;
-
-  frames = META_FRAMES (data);
-  frame = value;
-
-  invalidate_whole_window (frames, frame);
+  gtk_widget_queue_draw (GTK_WIDGET (value));
 }
 
 static void
 meta_frames_button_layout_changed (MetaFrames *frames)
 {
-  g_hash_table_foreach (frames->frames,
-                        queue_draw_func, frames);
-}
-
-static void
-reattach_style_func (gpointer key, gpointer value, gpointer data)
-{
-  MetaUIFrame *frame;
-  MetaFrames *frames;
-
-  frames = META_FRAMES (data);
-  frame = value;
-
-  meta_frames_attach_style (frames, frame);
+  g_hash_table_foreach (frames->frames, queue_draw_func, NULL);
 }
 
+/* In order to use a style with a window it has to be attached to that
+ * window. Actually, the colormaps just have to match, but since GTK+
+ * already takes care of making sure that its cheap to attach a style
+ * to multiple windows with the same colormap, we can just go ahead
+ * and attach separately for each window.
+ */
 static void
-meta_frames_style_updated  (GtkWidget *widget)
+meta_uiframe_attach_style (MetaUIFrame *frame)
 {
-  MetaFrames *frames;
-
-  frames = META_FRAMES (widget);
+  char *variant = NULL;
 
-  g_hash_table_foreach (frames->frames,
-                        reattach_style_func, frames);
+  meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
+                 frame->xwindow,
+                 META_CORE_GET_THEME_VARIANT, &variant,
+                 META_CORE_GET_END);
 
-  GTK_WIDGET_CLASS (meta_frames_parent_class)->style_updated (widget);
+  frame->tv = meta_theme_get_variant (meta_theme_get_current (),
+                                      variant);
 }
 
 static void
-meta_frames_ensure_layout (MetaFrames  *frames,
-                           MetaUIFrame *frame)
+meta_uiframe_ensure_layout (MetaUIFrame *frame)
 {
-  GtkWidget *widget;
   MetaFrameFlags flags;
   MetaFrameType type;
 
-  widget = GTK_WIDGET (frames);
-
-  g_return_if_fail (gtk_widget_get_realized (widget));
-      
   meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow,
                  META_CORE_GET_FRAME_FLAGS, &flags,
                  META_CORE_GET_FRAME_TYPE, &type,
@@ -305,7 +183,7 @@ meta_frames_ensure_layout (MetaFrames  *frames,
   
   if (frame->layout == NULL)
     {
-      frame->layout = gtk_widget_create_pango_layout (widget, frame->title);
+      frame->layout = gtk_widget_create_pango_layout (GTK_WIDGET (frame), frame->title);
 
       pango_layout_set_ellipsize (frame->layout, PANGO_ELLIPSIZE_END);
       pango_layout_set_auto_dir (frame->layout, FALSE);
@@ -317,9 +195,8 @@ meta_frames_ensure_layout (MetaFrames  *frames,
 }
 
 static void
-meta_frames_calc_geometry (MetaFrames        *frames,
-                           MetaUIFrame       *frame,
-                           MetaFrameGeometry *fgeom)
+meta_uiframe_calc_geometry (MetaUIFrame       *frame,
+                            MetaFrameGeometry *fgeom)
 {
   int width, height;
   MetaFrameFlags flags;
@@ -333,7 +210,7 @@ meta_frames_calc_geometry (MetaFrames        *frames,
                  META_CORE_GET_FRAME_TYPE, &type,
                  META_CORE_GET_END);
 
-  meta_frames_ensure_layout (frames, frame);
+  meta_uiframe_ensure_layout (frame);
 
   meta_prefs_get_button_layout (&button_layout);
   
@@ -346,40 +223,6 @@ meta_frames_calc_geometry (MetaFrames        *frames,
                             fgeom);
 }
 
-MetaFrames*
-meta_frames_new (int screen_number)
-{
-  GdkScreen *screen;
-
-  screen = gdk_display_get_screen (gdk_display_get_default (),
-                                   screen_number);
-
-  return g_object_new (META_TYPE_FRAMES,
-                       "screen", screen,
-                       NULL);  
-}
-
-/* In order to use a style with a window it has to be attached to that
- * window. Actually, the colormaps just have to match, but since GTK+
- * already takes care of making sure that its cheap to attach a style
- * to multiple windows with the same colormap, we can just go ahead
- * and attach separately for each window.
- */
-static void
-meta_frames_attach_style (MetaFrames  *frames,
-                          MetaUIFrame *frame)
-{
-  char *variant = NULL;
-
-  meta_core_get (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
-                 frame->xwindow,
-                 META_CORE_GET_THEME_VARIANT, &variant,
-                 META_CORE_GET_END);
-
-  frame->tv = meta_theme_get_variant (meta_theme_get_current (),
-                                      variant);
-}
-
 void
 meta_frames_manage_window (MetaFrames *frames,
                            Window      xwindow,
@@ -389,18 +232,31 @@ meta_frames_manage_window (MetaFrames *frames,
 
   g_assert (window);
 
-  frame = g_new (MetaUIFrame, 1);
-  
-  frame->window = window;
+  frame = g_object_new (META_TYPE_UIFRAME,
+                        "type", GTK_WINDOW_POPUP,
+                        "app-paintable", TRUE,
+                        NULL);
+
+  /* This fakes out the widget so it won't actually
+   * get realized as a server-side window. */
+
+  /* XXX: the gtk_widget_set_parent_window call unsets is_toplevel,
+   * leading to the widget not being realized, which triggers all sorts
+   * of assertions. Company suggested the below hack until we have
+   * something better. */
+
+  /* gtk_widget_set_parent_window (GTK_WIDGET (frame), window); */
+  g_object_set_data (G_OBJECT (frame), "gtk-parent-window", g_object_ref (window));
 
-  gdk_window_set_user_data (frame->window, frames);
+
+  gdk_window_set_user_data (window, frame);
+  gtk_widget_show (GTK_WIDGET (frame));
 
   /* Don't set event mask here, it's in frame.c */
-  
+  frame->window = g_object_ref (window);
   frame->xwindow = xwindow;
   frame->layout = NULL;
   frame->title = NULL;
-  frame->expose_delayed = FALSE;
   frame->shape_applied = FALSE;
   frame->prelit_control = META_FRAME_CONTROL_NONE;
 
@@ -410,7 +266,7 @@ meta_frames_manage_window (MetaFrames *frames,
    */
   
   meta_core_grab_buttons (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()), frame->xwindow);
-  
+
   g_hash_table_replace (frames->frames, &frame->xwindow, frame);
 }
 
@@ -431,41 +287,12 @@ meta_frames_unmanage_window (MetaFrames *frames,
 
       gdk_window_set_user_data (frame->window, NULL);
 
-      if (frames->last_motion_frame == frame)
-        frames->last_motion_frame = NULL;
-      
       g_hash_table_remove (frames->frames, &frame->xwindow);
-
-      gdk_window_destroy (frame->window);
-
-      if (frame->layout)
-        g_object_unref (G_OBJECT (frame->layout));
-
-      if (frame->title)
-        g_free (frame->title);
-      
-      g_free (frame);
     }
   else
     meta_warning ("Frame 0x%lx not managed, can't unmanage\n", xwindow);
 }
 
-static void
-meta_frames_map (GtkWidget *widget)
-{
-  /* We override the parent map function to a no-op because we don't
-   * want to actually show the GDK window. But GTK needs to think that
-   * the widget is mapped or it won't deliver the events we care about.
-   */
-  gtk_widget_set_mapped (widget, TRUE);
-}
-
-static void
-meta_frames_unmap (GtkWidget *widget)
-{
-  gtk_widget_set_mapped (widget, FALSE);
-}
-
 static MetaUIFrame*
 meta_frames_lookup_window (MetaFrames *frames,
                            Window      xwindow)
@@ -498,7 +325,7 @@ meta_frames_get_borders (MetaFrames *frames,
 
   g_return_if_fail (type < META_FRAME_TYPE_LAST);
 
-  meta_frames_ensure_layout (frames, frame);
+  meta_uiframe_ensure_layout (frame);
   
   /* We can't get the full geometry, because that depends on
    * the client window size and probably we're being called
@@ -527,7 +354,7 @@ meta_frames_render_background (MetaFrames *frames,
                  META_CORE_GET_FRAME_FLAGS, &flags,
                  META_CORE_GET_END);
 
-  meta_frames_calc_geometry (frames, frame, &fgeom);
+  meta_uiframe_calc_geometry (frame, &fgeom);
   meta_theme_render_background (frame->tv->style_context, cr, flags, &fgeom, frame->layout);
 }
 
@@ -555,26 +382,17 @@ meta_frames_move_resize_frame (MetaFrames *frames,
                                int         height)
 {
   MetaUIFrame *frame = meta_frames_lookup_window (frames, xwindow);
-  int old_width, old_height;
-  
-  old_width = gdk_window_get_width (frame->window);
-  old_height = gdk_window_get_height (frame->window);
 
   gdk_window_move_resize (frame->window, x, y, width, height);
-
-  if (old_width != width || old_height != height)
-    invalidate_whole_window (frames, frame);
+  gtk_widget_set_size_request (GTK_WIDGET (frame), width, height);
 }
 
 void
 meta_frames_queue_draw (MetaFrames *frames,
                         Window      xwindow)
 {
-  MetaUIFrame *frame;
-  
-  frame = meta_frames_lookup_window (frames, xwindow);
-
-  invalidate_whole_window (frames, frame);
+  MetaUIFrame *frame = meta_frames_lookup_window (frames, xwindow);
+  gtk_widget_queue_draw (GTK_WIDGET (frame));
 }
 
 void
@@ -597,7 +415,7 @@ meta_frames_set_title (MetaFrames *frames,
       frame->layout = NULL;
     }
 
-  invalidate_whole_window (frames, frame);
+  gtk_widget_queue_draw (GTK_WIDGET (frame));
 }
 
 void
@@ -605,13 +423,11 @@ meta_frames_update_frame_style (MetaFrames *frames,
                                 Window      xwindow)
 {
   MetaUIFrame *frame;
-
   frame = meta_frames_lookup_window (frames, xwindow);
-
   g_assert (frame);
 
-  meta_frames_attach_style (frames, frame);
-  invalidate_whole_window (frames, frame);
+  meta_uiframe_attach_style (frame);
+  gtk_widget_queue_draw (GTK_WIDGET (frame));
 }
 
 void
@@ -619,26 +435,19 @@ meta_frames_repaint_frame (MetaFrames *frames,
                            Window      xwindow)
 {
   MetaUIFrame *frame;
-  
   frame = meta_frames_lookup_window (frames, xwindow);
-
   g_assert (frame);
-
-  /* repaint everything, so the other frame don't
-   * lag behind if they are exposed
-   */
-  gdk_window_process_all_updates ();
+  gtk_widget_queue_draw (GTK_WIDGET (frame));
 }
 
 static void
-redraw_control (MetaFrames *frames,
-                MetaUIFrame *frame,
+redraw_control (MetaUIFrame *frame,
                 MetaFrameControl control)
 {
   MetaFrameGeometry fgeom;
   GdkRectangle *rect;
   
-  meta_frames_calc_geometry (frames, frame, &fgeom);
+  meta_uiframe_calc_geometry (frame, &fgeom);
 
   rect = control_rect (control, &fgeom);
 
@@ -780,26 +589,21 @@ meta_frame_right_click_event(MetaUIFrame     *frame,
 }
 
 static gboolean
-meta_frames_button_press_event (GtkWidget      *widget,
-                                GdkEventButton *event)
+meta_uiframe_button_press_event (GtkWidget      *widget,
+                                 GdkEventButton *event)
 {
   MetaUIFrame *frame;
-  MetaFrames *frames;
   MetaFrameControl control;
   Display *display;
-  
-  frames = META_FRAMES (widget);
+
+  frame = META_UIFRAME (widget);
+
   display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
 
   /* Remember that the display may have already done something with this event.
    * If so there's probably a GrabOp in effect.
    */
-  
-  frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
-  if (frame == NULL)
-    return FALSE;
-
-  control = get_control (frames, frame, event->x, event->y);
+  control = get_control (frame, event->x, event->y);
 
   /* focus on click, even if click was on client area */
   if (event->button == 1 &&
@@ -901,7 +705,7 @@ meta_frames_button_press_event (GtkWidget      *widget,
                                event->y_root);      
       
       frame->prelit_control = control;
-      redraw_control (frames, frame, control);
+      redraw_control (frame, control);
 
       if (op == META_GRAB_OP_CLICKING_MENU)
         {
@@ -909,7 +713,7 @@ meta_frames_button_press_event (GtkWidget      *widget,
           GdkRectangle *rect;
           int dx, dy;
           
-          meta_frames_calc_geometry (frames, frame, &fgeom);
+          meta_uiframe_calc_geometry (frame, &fgeom);
           
           rect = control_rect (META_FRAME_CONTROL_MENU, &fgeom);
 
@@ -1039,8 +843,7 @@ meta_frames_notify_menu_hide (MetaFrames *frames)
 
           if (frame)
             {
-              redraw_control (frames, frame,
-                              META_FRAME_CONTROL_MENU);
+              redraw_control (frame, META_FRAME_CONTROL_MENU);
               meta_core_end_grab_op (display, CurrentTime);
             }
         }
@@ -1048,20 +851,15 @@ meta_frames_notify_menu_hide (MetaFrames *frames)
 }
 
 static gboolean
-meta_frames_button_release_event    (GtkWidget           *widget,
-                                     GdkEventButton      *event)
+meta_uiframe_button_release_event    (GtkWidget           *widget,
+                                      GdkEventButton      *event)
 {
   MetaUIFrame *frame;
-  MetaFrames *frames;
   MetaGrabOp op;
   Display *display;
   
-  frames = META_FRAMES (widget);
+  frame = META_UIFRAME (widget);
   display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
-  
-  frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
-  if (frame == NULL)
-    return FALSE;
 
   op = meta_core_get_grab_op (display);
 
@@ -1077,7 +875,7 @@ meta_frames_button_release_event    (GtkWidget           *widget,
     {
       MetaFrameControl control;
 
-      control = get_control (frames, frame, event->x, event->y);
+      control = get_control (frame, event->x, event->y);
       
       switch (op)
         {
@@ -1169,16 +967,15 @@ meta_frames_button_release_event    (GtkWidget           *widget,
        * prelit so to let the user know that it can now be pressed.
        * :)
        */
-      meta_frames_update_prelit_control (frames, frame, control);
+      meta_uiframe_update_prelit_control (frame, control);
     }
   
   return TRUE;
 }
 
 static void
-meta_frames_update_prelit_control (MetaFrames      *frames,
-                                   MetaUIFrame     *frame,
-                                   MetaFrameControl control)
+meta_uiframe_update_prelit_control (MetaUIFrame     *frame,
+                                    MetaFrameControl control)
 {
   MetaFrameControl old_control;
   MetaCursor cursor;
@@ -1279,27 +1076,20 @@ meta_frames_update_prelit_control (MetaFrames      *frames,
 
   frame->prelit_control = control;
 
-  redraw_control (frames, frame, old_control);
-  redraw_control (frames, frame, control);
+  redraw_control (frame, old_control);
+  redraw_control (frame, control);
 }
 
 static gboolean
-meta_frames_motion_notify_event     (GtkWidget           *widget,
-                                     GdkEventMotion      *event)
+meta_uiframe_motion_notify_event     (GtkWidget           *widget,
+                                      GdkEventMotion      *event)
 {
   MetaUIFrame *frame;
-  MetaFrames *frames;
   MetaGrabOp grab_op;
   Display *display;
   
-  frames = META_FRAMES (widget);
+  frame = META_UIFRAME (widget);
   display = GDK_DISPLAY_XDISPLAY (gdk_window_get_display (event->window));
-  
-  frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
-  if (frame == NULL)
-    return FALSE;
-
-  frames->last_motion_frame = frame;
 
   grab_op = meta_core_get_grab_op (display);
   
@@ -1326,7 +1116,7 @@ meta_frames_motion_notify_event     (GtkWidget           *widget,
         /* Control is set to none unless it matches
          * the current grab
          */
-        control = get_control (frames, frame, x, y);
+        control = get_control (frame, x, y);
         if (! ((control == META_FRAME_CONTROL_MENU &&
                 grab_op == META_GRAB_OP_CLICKING_MENU) ||
                (control == META_FRAME_CONTROL_DELETE &&
@@ -1352,7 +1142,7 @@ meta_frames_motion_notify_event     (GtkWidget           *widget,
            control = META_FRAME_CONTROL_NONE;
         
         /* Update prelit control and cursor */
-        meta_frames_update_prelit_control (frames, frame, control);
+        meta_uiframe_update_prelit_control (frame, control);
       }
       break;
     case META_GRAB_OP_NONE:
@@ -1363,10 +1153,10 @@ meta_frames_motion_notify_event     (GtkWidget           *widget,
         gdk_window_get_device_position (frame->window, event->device,
                                         &x, &y, NULL);
 
-        control = get_control (frames, frame, x, y);
+        control = get_control (frame, x, y);
 
         /* Update prelit control and cursor */
-        meta_frames_update_prelit_control (frames, frame, control);
+        meta_uiframe_update_prelit_control (frame, control);
       }
       break;
 
@@ -1377,22 +1167,6 @@ meta_frames_motion_notify_event     (GtkWidget           *widget,
   return TRUE;
 }
 
-static gboolean
-meta_frames_destroy_event           (GtkWidget           *widget,
-                                     GdkEventAny         *event)
-{
-  MetaUIFrame *frame;
-  MetaFrames *frames;
-
-  frames = META_FRAMES (widget);
-
-  frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
-  if (frame == NULL)
-    return FALSE;
-  
-  return TRUE;
-}
-
 static void
 clip_to_screen (cairo_region_t *region,
                 MetaUIFrame    *frame)
@@ -1460,61 +1234,9 @@ subtract_client_area (cairo_region_t *region,
   cairo_region_destroy (tmp_region);
 }
 
-static gboolean
-meta_frames_draw (GtkWidget *widget,
-                  cairo_t   *cr)
-{
-  MetaUIFrame *frame;
-  MetaFrames *frames;
-  cairo_region_t *region;
-  cairo_rectangle_int_t clip;
-  cairo_surface_t *target;
-
-  frames = META_FRAMES (widget);
-  target = cairo_get_target (cr);
-  gdk_cairo_get_clip_rectangle (cr, &clip);
-
-  g_assert (cairo_surface_get_type (target) == CAIRO_SURFACE_TYPE_XLIB);
-  frame = meta_frames_lookup_window (frames, cairo_xlib_surface_get_drawable (target));
-  if (frame == NULL)
-    return FALSE;
-
-  if (frames->expose_delay_count > 0)
-    {
-      /* Redraw this entire frame later */
-      frame->expose_delayed = TRUE;
-      return TRUE;
-    }
-
-  region = cairo_region_create_rectangle (&clip);
-
-  clip_to_screen (region, frame);
-  subtract_client_area (region, frame);
-
-  if (cairo_region_num_rectangles (region) == 0)
-    goto out;
-
-  gdk_cairo_region (cr, region);
-  cairo_clip (cr);
-
-  cairo_save (cr);
-  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-  cairo_set_source_rgba (cr, 1, 1, 1, 1);
-  cairo_paint (cr);
-  cairo_restore (cr);
-
-  meta_frames_paint (frames, frame, cr);
-
- out:
-  cairo_region_destroy (region);
-  
-  return TRUE;
-}
-
 static void
-meta_frames_paint (MetaFrames   *frames,
-                   MetaUIFrame  *frame,
-                   cairo_t      *cr)
+meta_uiframe_paint (MetaUIFrame  *frame,
+                    cairo_t      *cr)
 {
   MetaFrameFlags flags;
   MetaFrameType type;
@@ -1620,7 +1342,7 @@ meta_frames_paint (MetaFrames   *frames,
                  META_CORE_GET_CLIENT_HEIGHT, &h,
                  META_CORE_GET_END);
 
-  meta_frames_ensure_layout (frames, frame);
+  meta_uiframe_ensure_layout (frame);
 
   meta_prefs_get_button_layout (&button_layout);
 
@@ -1637,39 +1359,65 @@ meta_frames_paint (MetaFrames   *frames,
 }
 
 static gboolean
-meta_frames_enter_notify_event      (GtkWidget           *widget,
-                                     GdkEventCrossing    *event)
+meta_uiframe_draw (GtkWidget *widget,
+                   cairo_t   *cr)
 {
   MetaUIFrame *frame;
-  MetaFrames *frames;
-  MetaFrameControl control;
-  
-  frames = META_FRAMES (widget);
+  cairo_region_t *region;
+  cairo_rectangle_int_t clip;
 
-  frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
-  if (frame == NULL)
-    return FALSE;
+  frame = META_UIFRAME (widget);
+  gdk_cairo_get_clip_rectangle (cr, &clip);
+
+  region = cairo_region_create_rectangle (&clip);
+
+  clip_to_screen (region, frame);
+  subtract_client_area (region, frame);
+
+  if (cairo_region_num_rectangles (region) == 0)
+    goto out;
+
+  gdk_cairo_region (cr, region);
+  cairo_clip (cr);
+
+  cairo_save (cr);
+  cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
+  cairo_set_source_rgba (cr, 1, 1, 1, 1);
+  cairo_paint (cr);
+  cairo_restore (cr);
+
+  meta_uiframe_paint (frame, cr);
+
+  GTK_WIDGET_CLASS (meta_uiframe_parent_class)->draw (widget, cr);
 
-  control = get_control (frames, frame, event->x, event->y);
-  meta_frames_update_prelit_control (frames, frame, control);
+ out:
+  cairo_region_destroy (region);
   
   return TRUE;
 }
 
 static gboolean
-meta_frames_leave_notify_event      (GtkWidget           *widget,
-                                     GdkEventCrossing    *event)
+meta_uiframe_enter_notify_event      (GtkWidget           *widget,
+                                      GdkEventCrossing    *event)
 {
   MetaUIFrame *frame;
-  MetaFrames *frames;
+  MetaFrameControl control;
+  
+  frame = META_UIFRAME (widget);
 
-  frames = META_FRAMES (widget);
+  control = get_control (frame, event->x, event->y);
+  meta_uiframe_update_prelit_control (frame, control);
+  
+  return TRUE;
+}
 
-  frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window));
-  if (frame == NULL)
-    return FALSE;
+static gboolean
+meta_uiframe_leave_notify_event      (GtkWidget           *widget,
+                                      GdkEventCrossing    *event)
+{
+  MetaUIFrame *frame = META_UIFRAME (widget);
 
-  meta_frames_update_prelit_control (frames, frame, META_FRAME_CONTROL_NONE);
+  meta_uiframe_update_prelit_control (frame, META_FRAME_CONTROL_NONE);
   
   return TRUE;
 }
@@ -1744,8 +1492,7 @@ control_rect (MetaFrameControl control,
 
 #define TOP_RESIZE_HEIGHT 4
 static MetaFrameControl
-get_control (MetaFrames *frames,
-             MetaUIFrame *frame,
+get_control (MetaUIFrame *frame,
              int x, int y)
 {
   MetaFrameGeometry fgeom;
@@ -1755,7 +1502,7 @@ get_control (MetaFrames *frames,
   gboolean has_north_resize;
   cairo_rectangle_int_t client;
 
-  meta_frames_calc_geometry (frames, frame, &fgeom);
+  meta_uiframe_calc_geometry (frame, &fgeom);
   get_client_rect (&fgeom, fgeom.width, fgeom.height, &client);
 
   if (POINT_IN_RECT (x, y, client))
@@ -1897,53 +1644,21 @@ get_control (MetaFrames *frames,
     return META_FRAME_CONTROL_TITLE;
 }
 
-void
-meta_frames_push_delay_exposes (MetaFrames *frames)
-{
-  if (frames->expose_delay_count == 0)
-    {
-      /* Make sure we've repainted things */
-      gdk_window_process_all_updates ();
-      XFlush (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
-    }
-  
-  frames->expose_delay_count += 1;
-}
-
 static void
-queue_pending_exposes_func (gpointer key, gpointer value, gpointer data)
+meta_uiframe_class_init (MetaUIFrameClass *class)
 {
-  MetaUIFrame *frame;
-  MetaFrames *frames;
-
-  frames = META_FRAMES (data);
-  frame = value;
-
-  if (frame->expose_delayed)
-    {
-      invalidate_whole_window (frames, frame);
-      frame->expose_delayed = FALSE;
-    }
-}
+  GObjectClass   *gobject_class;
+  GtkWidgetClass *widget_class;
 
-void
-meta_frames_pop_delay_exposes  (MetaFrames *frames)
-{
-  g_return_if_fail (frames->expose_delay_count > 0);
-  
-  frames->expose_delay_count -= 1;
+  gobject_class = G_OBJECT_CLASS (class);
+  widget_class = GTK_WIDGET_CLASS (class);
 
-  if (frames->expose_delay_count == 0)
-    {
-      g_hash_table_foreach (frames->frames,
-                            queue_pending_exposes_func,
-                            frames);
-    }
-}
+  gobject_class->finalize = meta_uiframe_finalize;
 
-static void
-invalidate_whole_window (MetaFrames *frames,
-                         MetaUIFrame *frame)
-{
-  gdk_window_invalidate_rect (frame->window, NULL, FALSE);
+  widget_class->draw = meta_uiframe_draw;
+  widget_class->button_press_event = meta_uiframe_button_press_event;
+  widget_class->button_release_event = meta_uiframe_button_release_event;
+  widget_class->motion_notify_event = meta_uiframe_motion_notify_event;
+  widget_class->enter_notify_event = meta_uiframe_enter_notify_event;
+  widget_class->leave_notify_event = meta_uiframe_leave_notify_event;
 }
diff --git a/src/ui/frames.h b/src/ui/frames.h
index df7859d..4427fe3 100644
--- a/src/ui/frames.h
+++ b/src/ui/frames.h
@@ -59,51 +59,45 @@ typedef enum
  * as subwindows.
  */
 
-#define META_TYPE_FRAMES            (meta_frames_get_type ())
-#define META_FRAMES(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_FRAMES, MetaFrames))
-#define META_FRAMES_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_FRAMES, MetaFramesClass))
-#define META_IS_FRAMES(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_FRAMES))
-#define META_IS_FRAMES_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_FRAMES))
-#define META_FRAMES_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_FRAMES, MetaFramesClass))
+#define META_TYPE_UIFRAME            (meta_uiframe_get_type ())
+#define META_UIFRAME(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_UIFRAME, MetaUIFrame))
+#define META_UIFRAME_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_UIFRAME, MetaUIFrameClass))
+#define META_IS_UIFRAME(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_UIFRAME))
+#define META_IS_UIFRAME_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_UIFRAME))
+#define META_UIFRAME_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_UIFRAME, MetaUIFrameClass))
 
-typedef struct _MetaFrames        MetaFrames;
-typedef struct _MetaFramesClass   MetaFramesClass;
-
-typedef struct _MetaUIFrame         MetaUIFrame;
+typedef struct _MetaUIFrame        MetaUIFrame;
+typedef struct _MetaUIFrameClass   MetaUIFrameClass;
 
 struct _MetaUIFrame
 {
+  GtkWindow parent_instance;
+
   Window xwindow;
   GdkWindow *window;
   MetaThemeVariant *tv;
   PangoLayout *layout;
   char *title; /* NULL once we have a layout */
-  guint expose_delayed : 1;
   guint shape_applied : 1;
-
-  /* FIXME get rid of this, it can just be in the MetaFrames struct */
   MetaFrameControl prelit_control;
 };
 
-struct _MetaFrames
+struct _MetaUIFrameClass
 {
-  GtkWindow parent_instance;
-
-  GHashTable *frames;
-  MetaUIFrame *last_motion_frame;
-
-  int expose_delay_count;
+  GtkWindowClass parent_class;
 };
 
-struct _MetaFramesClass
-{
-  GtkWindowClass parent_class;
+typedef struct _MetaFrames         MetaFrames;
 
+struct _MetaFrames
+{
+  GHashTable *frames;
 };
 
-GType        meta_frames_get_type               (void) G_GNUC_CONST;
+GType        meta_uiframe_get_type (void) G_GNUC_CONST;
 
-MetaFrames *meta_frames_new (int screen_number);
+MetaFrames *meta_frames_new ();
+void        meta_frames_free (MetaFrames *frames);
 
 void meta_frames_manage_window (MetaFrames *frames,
                                 Window      xwindow,
@@ -141,7 +135,4 @@ void meta_frames_notify_menu_hide (MetaFrames *frames);
 
 Window meta_frames_get_moving_frame (MetaFrames *frames);
 
-void meta_frames_push_delay_exposes (MetaFrames *frames);
-void meta_frames_pop_delay_exposes  (MetaFrames *frames);
-
 #endif
diff --git a/src/ui/ui.c b/src/ui/ui.c
index 12ce748..e01ec04 100644
--- a/src/ui/ui.c
+++ b/src/ui/ui.c
@@ -284,11 +284,7 @@ meta_ui_new (Display *xdisplay,
   gdisplay = gdk_x11_lookup_xdisplay (xdisplay);
   g_assert (gdisplay == gdk_display_get_default ());
 
-  ui->frames = meta_frames_new (XScreenNumberOfScreen (screen));
-  /* This does not actually show any widget. MetaFrames has been hacked so
-   * that showing it doesn't actually do anything. But we need the flags
-   * set for GTK to deliver events properly. */
-  gtk_widget_show (GTK_WIDGET (ui->frames));
+  ui->frames = meta_frames_new ();
 
   g_object_set_data (G_OBJECT (gdisplay), "meta-ui", ui);
 
@@ -300,7 +296,7 @@ meta_ui_free (MetaUI *ui)
 {
   GdkDisplay *gdisplay;
 
-  gtk_widget_destroy (GTK_WIDGET (ui->frames));
+  meta_frames_free (ui->frames);
 
   gdisplay = gdk_x11_lookup_xdisplay (ui->xdisplay);
   g_object_set_data (G_OBJECT (gdisplay), "meta-ui", NULL);
@@ -556,18 +552,6 @@ meta_gdk_pixbuf_get_from_pixmap (Pixmap       xpixmap,
   return retval;
 }
 
-void
-meta_ui_push_delay_exposes (MetaUI *ui)
-{
-  meta_frames_push_delay_exposes (ui->frames);
-}
-
-void
-meta_ui_pop_delay_exposes  (MetaUI *ui)
-{
-  meta_frames_pop_delay_exposes (ui->frames);
-}
-
 GdkPixbuf*
 meta_ui_get_default_window_icon (MetaUI *ui)
 {
@@ -907,7 +891,7 @@ meta_ui_window_is_widget (MetaUI *ui,
     {
       void *user_data = NULL;
       gdk_window_get_user_data (window, &user_data);
-      return user_data != NULL && user_data != ui->frames;
+      return user_data != NULL && !META_IS_UIFRAME (user_data);
     }
   else
     return FALSE;
@@ -961,7 +945,7 @@ meta_ui_get_drag_threshold (MetaUI *ui)
   GtkSettings *settings;
   int threshold;
 
-  settings = gtk_widget_get_settings (GTK_WIDGET (ui->frames));
+  settings = gtk_settings_get_default ();
 
   threshold = 8;
   g_object_get (G_OBJECT (settings), "gtk-dnd-drag-threshold", &threshold, NULL);
diff --git a/src/ui/ui.h b/src/ui/ui.h
index 930e6eb..00c8656 100644
--- a/src/ui/ui.h
+++ b/src/ui/ui.h
@@ -124,13 +124,6 @@ GdkPixbuf* meta_gdk_pixbuf_get_from_pixmap (Pixmap       xpixmap,
                                             int          width,
                                             int          height);
 
-/* Used when we have a server grab and draw all over everything,
- * then we need to handle exposes after doing that, instead of
- * during it
- */
-void      meta_ui_push_delay_exposes (MetaUI *ui);
-void      meta_ui_pop_delay_exposes  (MetaUI *ui);
-
 GdkPixbuf* meta_ui_get_default_window_icon (MetaUI *ui);
 GdkPixbuf* meta_ui_get_default_mini_icon (MetaUI *ui);
 



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