]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkhandlebox.c
Fix some issues with background drawing in RTL. (#318781, Eric Cazeaux)
[~andy/gtk] / gtk / gtkhandlebox.c
index b0d556eb9a0bb034f0732de988f257b21d870017..e5f535163d9ed241f3585a63e5576933d4aeccf8 100644 (file)
  * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
  */
 
+#include <config.h>
 #include <stdlib.h>
 #include "gtkhandlebox.h"
+#include "gtkinvisible.h"
 #include "gtkmain.h"
 #include "gtkmarshalers.h"
 #include "gtkwindow.h"
+#include "gtkprivate.h"
 #include "gtkintl.h"
+#include "gtkalias.h"
 
 typedef struct _GtkHandleBoxPrivate GtkHandleBoxPrivate;
 
@@ -138,6 +142,8 @@ static gint gtk_handle_box_motion         (GtkWidget         *widget,
 static gint gtk_handle_box_delete_event   (GtkWidget         *widget,
                                           GdkEventAny       *event);
 static void gtk_handle_box_reattach       (GtkHandleBox      *hb);
+static void gtk_handle_box_end_drag       (GtkHandleBox      *hb,
+                                          guint32            time);
 
 
 static GtkBinClass *parent_class;
@@ -164,7 +170,7 @@ gtk_handle_box_get_type (void)
        (GInstanceInitFunc) gtk_handle_box_init,
       };
 
-      handle_box_type = g_type_register_static (GTK_TYPE_BIN, "GtkHandleBox",
+      handle_box_type = g_type_register_static (GTK_TYPE_BIN, I_("GtkHandleBox"),
                                                &handle_box_info, 0);
     }
 
@@ -195,41 +201,41 @@ gtk_handle_box_class_init (GtkHandleBoxClass *class)
                                                       P_("Deprecated property, use shadow_type instead"),
                                                      GTK_TYPE_SHADOW_TYPE,
                                                      GTK_SHADOW_ETCHED_OUT,
-                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
+                                                      GTK_PARAM_READWRITE));
   g_object_class_install_property (gobject_class,
                                    PROP_SHADOW_TYPE,
-                                   g_param_spec_enum ("shadow_type",
+                                   g_param_spec_enum ("shadow-type",
                                                       P_("Shadow type"),
                                                       P_("Appearance of the shadow that surrounds the container"),
                                                      GTK_TYPE_SHADOW_TYPE,
                                                      GTK_SHADOW_ETCHED_OUT,
-                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
+                                                      GTK_PARAM_READWRITE));
   
   g_object_class_install_property (gobject_class,
                                    PROP_HANDLE_POSITION,
-                                   g_param_spec_enum ("handle_position",
+                                   g_param_spec_enum ("handle-position",
                                                       P_("Handle position"),
                                                       P_("Position of the handle relative to the child widget"),
                                                      GTK_TYPE_POSITION_TYPE,
                                                      GTK_POS_LEFT,
-                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
+                                                      GTK_PARAM_READWRITE));
   
   g_object_class_install_property (gobject_class,
                                    PROP_SNAP_EDGE,
-                                   g_param_spec_enum ("snap_edge",
+                                   g_param_spec_enum ("snap-edge",
                                                       P_("Snap edge"),
                                                       P_("Side of the handlebox that's lined up with the docking point to dock the handlebox"),
                                                      GTK_TYPE_POSITION_TYPE,
                                                      GTK_POS_TOP,
-                                                      G_PARAM_READABLE | G_PARAM_WRITABLE));
+                                                      GTK_PARAM_READWRITE));
 
   g_object_class_install_property (gobject_class,
                                    PROP_SNAP_EDGE_SET,
-                                   g_param_spec_boolean ("snap_edge_set",
+                                   g_param_spec_boolean ("snap-edge-set",
                                                         P_("Snap edge set"),
                                                         P_("Whether to use the value from the snap_edge property or a value derived from handle_position"),
                                                         FALSE,
-                                                        G_PARAM_READABLE | G_PARAM_WRITABLE));
+                                                        GTK_PARAM_READWRITE));
 
   object_class->destroy = gtk_handle_box_destroy;
 
@@ -242,8 +248,6 @@ gtk_handle_box_class_init (GtkHandleBoxClass *class)
   widget_class->size_allocate = gtk_handle_box_size_allocate;
   widget_class->expose_event = gtk_handle_box_expose;
   widget_class->button_press_event = gtk_handle_box_button_changed;
-  widget_class->button_release_event = gtk_handle_box_button_changed;
-  widget_class->motion_notify_event = gtk_handle_box_motion;
   widget_class->delete_event = gtk_handle_box_delete_event;
 
   container_class->add = gtk_handle_box_add;
@@ -253,7 +257,7 @@ gtk_handle_box_class_init (GtkHandleBoxClass *class)
   class->child_detached = NULL;
 
   handle_box_signals[SIGNAL_CHILD_ATTACHED] =
-    g_signal_new ("child_attached",
+    g_signal_new (I_("child_attached"),
                  G_OBJECT_CLASS_TYPE (gobject_class),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GtkHandleBoxClass, child_attached),
@@ -262,7 +266,7 @@ gtk_handle_box_class_init (GtkHandleBoxClass *class)
                  G_TYPE_NONE, 1,
                  GTK_TYPE_WIDGET);
   handle_box_signals[SIGNAL_CHILD_DETACHED] =
-    g_signal_new ("child_detached",
+    g_signal_new (I_("child_detached"),
                  G_OBJECT_CLASS_TYPE (gobject_class),
                  G_SIGNAL_RUN_FIRST,
                  G_STRUCT_OFFSET (GtkHandleBoxClass, child_detached),
@@ -272,7 +276,7 @@ gtk_handle_box_class_init (GtkHandleBoxClass *class)
                  GTK_TYPE_WIDGET);
 }
 
-GtkHandleBoxPrivate *
+static GtkHandleBoxPrivate *
 gtk_handle_box_get_private (GtkHandleBox *hb)
 {
   GtkHandleBoxPrivate *private;
@@ -663,11 +667,9 @@ gtk_handle_box_size_allocate (GtkWidget     *widget,
 
   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
     {
-      GtkWidget *child;
       GtkAllocation child_allocation;
       guint border_width;
 
-      child = bin->child;
       border_width = GTK_CONTAINER (widget)->border_width;
 
       child_allocation.x = border_width;
@@ -804,7 +806,7 @@ gtk_handle_box_set_shadow_type (GtkHandleBox  *handle_box,
   if ((GtkShadowType) handle_box->shadow_type != type)
     {
       handle_box->shadow_type = type;
-      g_object_notify (G_OBJECT (handle_box), "shadow_type");
+      g_object_notify (G_OBJECT (handle_box), "shadow-type");
       gtk_widget_queue_resize (GTK_WIDGET (handle_box));
     }
 }
@@ -835,7 +837,7 @@ gtk_handle_box_set_handle_position  (GtkHandleBox    *handle_box,
   if ((GtkPositionType) handle_box->handle_position != position)
     {
       handle_box->handle_position = position;
-      g_object_notify (G_OBJECT (handle_box), "handle_position");
+      g_object_notify (G_OBJECT (handle_box), "handle-position");
       gtk_widget_queue_resize (GTK_WIDGET (handle_box));
     }
 }
@@ -868,8 +870,8 @@ gtk_handle_box_set_snap_edge        (GtkHandleBox    *handle_box,
       handle_box->snap_edge = edge;
       
       g_object_freeze_notify (G_OBJECT (handle_box));
-      g_object_notify (G_OBJECT (handle_box), "snap_edge");
-      g_object_notify (G_OBJECT (handle_box), "snap_edge_set");
+      g_object_notify (G_OBJECT (handle_box), "snap-edge");
+      g_object_notify (G_OBJECT (handle_box), "snap-edge-set");
       g_object_thaw_notify (G_OBJECT (handle_box));
     }
 }
@@ -900,8 +902,7 @@ gtk_handle_box_paint (GtkWidget      *widget,
 {
   GtkBin *bin;
   GtkHandleBox *hb;
-  guint width;
-  guint height;
+  guint width, height;
   GdkRectangle rect;
   GdkRectangle dest;
   gint handle_position;
@@ -995,6 +996,46 @@ gtk_handle_box_expose (GtkWidget      *widget,
   return FALSE;
 }
 
+static GtkWidget *
+gtk_handle_box_get_invisible (void)
+{
+  static GtkWidget *handle_box_invisible = NULL;
+
+  if (!handle_box_invisible)
+    {
+      handle_box_invisible = gtk_invisible_new ();
+      gtk_widget_show (handle_box_invisible);
+    }
+  
+  return handle_box_invisible;
+}
+
+static gboolean
+gtk_handle_box_grab_event (GtkWidget    *widget,
+                          GdkEvent     *event,
+                          GtkHandleBox *hb)
+{
+  switch (event->type)
+    {
+    case GDK_BUTTON_RELEASE:
+      if (hb->in_drag)         /* sanity check */
+       {
+         gtk_handle_box_end_drag (hb, event->button.time);
+         return TRUE;
+       }
+      break;
+
+    case GDK_MOTION_NOTIFY:
+      return gtk_handle_box_motion (GTK_WIDGET (hb), (GdkEventMotion *)event);
+      break;
+
+    default:
+      break;
+    }
+
+  return FALSE;
+}
+
 static gint
 gtk_handle_box_button_changed (GtkWidget      *widget,
                               GdkEventButton *event)
@@ -1052,6 +1093,7 @@ gtk_handle_box_button_changed (GtkWidget      *widget,
          if (event->type == GDK_BUTTON_PRESS) /* Start a drag */
            {
              GtkHandleBoxPrivate *private = gtk_handle_box_get_private (hb);
+             GtkWidget *invisible = gtk_handle_box_get_invisible ();
              gint desk_x, desk_y;
              gint root_x, root_y;
              gint width, height;
@@ -1059,10 +1101,10 @@ gtk_handle_box_button_changed (GtkWidget      *widget,
              gdk_window_get_deskrelative_origin (hb->bin_window, &desk_x, &desk_y);
              gdk_window_get_origin (hb->bin_window, &root_x, &root_y);
              gdk_drawable_get_size (hb->bin_window, &width, &height);
-
+                 
              private->orig_x = event->x_root;
              private->orig_y = event->y_root;
-             
+                 
              hb->float_allocation.x = root_x - event->x_root;
              hb->float_allocation.y = root_y - event->y_root;
              hb->float_allocation.width = width;
@@ -1071,28 +1113,43 @@ gtk_handle_box_button_changed (GtkWidget      *widget,
              hb->deskoff_x = desk_x - root_x;
              hb->deskoff_y = desk_y - root_y;
              
-             gdk_window_get_origin (widget->window, &root_x, &root_y);
-             gdk_drawable_get_size (widget->window, &width, &height);
+             if (gdk_window_is_viewable (widget->window))
+               {
+                 gdk_window_get_origin (widget->window, &root_x, &root_y);
+                 gdk_drawable_get_size (widget->window, &width, &height);
              
-             hb->attach_allocation.x = root_x;
-             hb->attach_allocation.y = root_y;
-             hb->attach_allocation.width = width;
-             hb->attach_allocation.height = height;
-
+                 hb->attach_allocation.x = root_x;
+                 hb->attach_allocation.y = root_y;
+                 hb->attach_allocation.width = width;
+                 hb->attach_allocation.height = height;
+               }
+             else
+               {
+                 hb->attach_allocation.x = -1;
+                 hb->attach_allocation.y = -1;
+                 hb->attach_allocation.width = 0;
+                 hb->attach_allocation.height = 0;
+               }
              hb->in_drag = TRUE;
              fleur = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
                                                  GDK_FLEUR);
-             if (gdk_pointer_grab (widget->window,
+             if (gdk_pointer_grab (invisible->window,
                                    FALSE,
                                    (GDK_BUTTON1_MOTION_MASK |
                                     GDK_POINTER_MOTION_HINT_MASK |
                                     GDK_BUTTON_RELEASE_MASK),
                                    NULL,
                                    fleur,
-                                   GDK_CURRENT_TIME) != 0)
+                                   event->time) != 0)
                {
                  hb->in_drag = FALSE;
                }
+             else
+               {
+                 gtk_grab_add (invisible);
+                 g_signal_connect (invisible, "event",
+                                   G_CALLBACK (gtk_handle_box_grab_event), hb);
+               }
              
              gdk_cursor_unref (fleur);
              event_handled = TRUE;
@@ -1103,17 +1160,6 @@ gtk_handle_box_button_changed (GtkWidget      *widget,
            }
        }
     }
-  else if (event->type == GDK_BUTTON_RELEASE &&
-          hb->in_drag)
-    {
-      if (event->window != widget->window)
-       return FALSE;
-      
-      gdk_display_pointer_ungrab (gtk_widget_get_display (widget),
-                                 GDK_CURRENT_TIME);
-      hb->in_drag = FALSE;
-      event_handled = TRUE;
-    }
   
   return event_handled;
 }
@@ -1122,7 +1168,7 @@ static gint
 gtk_handle_box_motion (GtkWidget      *widget,
                       GdkEventMotion *event)
 {
-  GtkHandleBox *hb;
+  GtkHandleBox *hb = GTK_HANDLE_BOX (widget);
   gint new_x, new_y;
   gint snap_edge;
   gboolean is_snapped = FALSE;
@@ -1130,13 +1176,8 @@ gtk_handle_box_motion (GtkWidget      *widget,
   GdkGeometry geometry;
   GdkScreen *screen, *pointer_screen;
 
-  hb = GTK_HANDLE_BOX (widget);
   if (!hb->in_drag)
     return FALSE;
-
-  if (!hb->in_drag || (event->window != widget->window))
-    return FALSE;
-  
   handle_position = effective_handle_position (hb);
 
   /* Calculate the attachment point on the float, if the float
@@ -1385,11 +1426,25 @@ gtk_handle_box_reattach (GtkHandleBox *hb)
       hb->float_window_mapped = FALSE;
     }
   if (hb->in_drag)
-    {
-      gdk_display_pointer_ungrab (gtk_widget_get_display (GTK_WIDGET (hb)),
-                                 GDK_CURRENT_TIME);
-      hb->in_drag = FALSE;
-    }
+    gtk_handle_box_end_drag (hb, GDK_CURRENT_TIME);
 
   gtk_widget_queue_resize (GTK_WIDGET (hb));
 }
+
+static void
+gtk_handle_box_end_drag (GtkHandleBox *hb,
+                        guint32       time)
+{
+  GtkWidget *invisible = gtk_handle_box_get_invisible ();
+               
+  hb->in_drag = FALSE;
+
+  gtk_grab_remove (invisible);
+  gdk_pointer_ungrab (time);
+  g_signal_handlers_disconnect_by_func (invisible,
+                                       G_CALLBACK (gtk_handle_box_grab_event),
+                                       hb);
+}
+
+#define __GTK_HANDLE_BOX_C__
+#include "gtkaliasdef.c"