[glade/ui-incubator: 11/11] Implemented inline Drag and Drop



commit 77bb90212ad52f0c987133c60aad11c73710955f
Author: Juan Pablo Ugarte <juanpablougarte gmail com>
Date:   Mon Dec 17 22:35:51 2012 -0300

    Implemented inline Drag and Drop

 gladeui/glade-design-layout.c  |  262 ++++++++++++++----
 gladeui/glade-design-private.h |   12 +
 gladeui/glade-design-view.c    |  580 ++++++++++++++++++++++++++++------------
 plugins/gtk+/glade-fixed.c     |   24 ++-
 plugins/gtk+/glade-gtk.c       |    3 +
 5 files changed, 647 insertions(+), 234 deletions(-)
---
diff --git a/gladeui/glade-design-layout.c b/gladeui/glade-design-layout.c
index 8a180c1..210555b 100644
--- a/gladeui/glade-design-layout.c
+++ b/gladeui/glade-design-layout.c
@@ -38,6 +38,7 @@
 #define GLADE_DESIGN_LAYOUT_GET_PRIVATE(object) (G_TYPE_INSTANCE_GET_PRIVATE ((object),  \
 						 GLADE_TYPE_DESIGN_LAYOUT,               \
 						 GladeDesignLayoutPrivate))
+#define GLADE_DESIGN_LAYOUT_PRIVATE(object) (((GladeDesignLayout*)object)->priv)
 
 #define OUTLINE_WIDTH     4
 #define PADDING           12
@@ -104,6 +105,11 @@ struct _GladeDesignLayoutPrivate
   gint new_width;               /* user's new requested width */
   gint new_height;              /* user's new requested height */
 
+  /* Drag & Drop */
+  GtkWidget *drag_source;
+  GtkWidget *drag_icon;
+  gint drag_x, drag_y;
+
   /* Properties */
   GladeDesignView *view;
   GladeProject *project;
@@ -227,7 +233,7 @@ glade_design_layout_leave_notify_event (GtkWidget *widget, GdkEventCrossing *ev)
       ev->window != gtk_widget_get_window (widget))
     return FALSE;
 
-  priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
+  priv = GLADE_DESIGN_LAYOUT_PRIVATE (widget);
 
   if (priv->activity == ACTIVITY_NONE)
     gdl_set_cursor (priv, NULL);
@@ -355,11 +361,23 @@ glade_design_layout_motion_notify_event (GtkWidget *widget, GdkEventMotion *ev)
   if ((child = gtk_bin_get_child (GTK_BIN (widget))) == NULL)
     return FALSE;
 
-  priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
+  priv = GLADE_DESIGN_LAYOUT_PRIVATE (widget);
 
   x = ev->x;
   y = ev->y;
 
+  if (ev->state & GDK_BUTTON1_MASK && priv->drag_source &&
+      gtk_drag_check_threshold (priv->drag_source, priv->drag_x, priv->drag_y, x, y))
+    {
+      static GtkTargetList *target = NULL;
+
+      if (target == NULL)
+        target = gtk_target_list_new (_glade_design_layout_get_dnd_target (), 1);
+
+      gtk_drag_begin (widget, target, GDK_ACTION_COPY, 1, (GdkEvent*)ev);
+      return TRUE;
+    }
+
   gtk_widget_get_allocation (child, &allocation);
 
   allocation.x += priv->child_offset;
@@ -573,7 +591,7 @@ glade_design_layout_button_press_event (GtkWidget *widget, GdkEventButton *ev)
       (child = gtk_bin_get_child (GTK_BIN (widget))) == NULL)
     return FALSE;
 
-  priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
+  priv = GLADE_DESIGN_LAYOUT_PRIVATE (widget);
 
   x = ev->x;
   y = ev->y;
@@ -695,7 +713,7 @@ glade_design_layout_button_release_event (GtkWidget *widget,
   if ((child = gtk_bin_get_child (GTK_BIN (widget))) == NULL)
     return FALSE;
 
-  priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
+  priv = GLADE_DESIGN_LAYOUT_PRIVATE (widget);
 
   /* Check if margins where edited and execute corresponding glade command */
   if (priv->selection && priv->activity == ACTIVITY_MARGINS)
@@ -756,7 +774,7 @@ glade_design_layout_get_preferred_height (GtkWidget *widget,
   gint child_height = 0;
   guint border_width = 0;
 
-  priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
+  priv = GLADE_DESIGN_LAYOUT_PRIVATE (widget);
 
   *minimum = 0;
 
@@ -889,7 +907,7 @@ glade_design_layout_size_allocate (GtkWidget *widget,
 
   if (child && gtk_widget_get_visible (child))
     {
-      GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
+      GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_PRIVATE (widget);
       GtkAllocation alloc;
       gint height, offset;
 
@@ -917,7 +935,7 @@ glade_design_layout_size_allocate (GtkWidget *widget,
 static void
 on_glade_widget_name_notify (GObject *gobject, GParamSpec *pspec, GladeDesignLayout *layout) 
 {
-  GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (layout);
+  GladeDesignLayoutPrivate *priv = layout->priv;
   
   pango_layout_set_text (priv->widget_name, glade_widget_get_name (GLADE_WIDGET (gobject)), -1);
   gtk_widget_queue_resize (GTK_WIDGET (layout));
@@ -926,8 +944,8 @@ on_glade_widget_name_notify (GObject *gobject, GParamSpec *pspec, GladeDesignLay
 static void
 glade_design_layout_add (GtkContainer *container, GtkWidget *widget)
 {
-  GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (container);
   GladeDesignLayout *layout = GLADE_DESIGN_LAYOUT (container);
+  GladeDesignLayoutPrivate *priv = layout->priv;
   GladeWidget *gchild;
 
   layout->priv->current_width = 0;
@@ -1179,7 +1197,7 @@ draw_selection (cairo_t *cr,
   cairo_stroke (cr);
 }
 
-#define DIMENSION_OFFSET 10
+#define DIMENSION_OFFSET 9
 #define DIMENSION_LINE_OFFSET 4
 
 static void
@@ -1489,7 +1507,7 @@ draw_selection_nodes (cairo_t *cr,
 static gboolean
 glade_design_layout_draw (GtkWidget *widget, cairo_t *cr)
 {
-  GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
+  GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_PRIVATE (widget);
   GdkWindow *window = gtk_widget_get_window (widget);
 
   if (gtk_cairo_should_draw_window (cr, window))
@@ -1568,7 +1586,7 @@ to_child (GladeDesignLayout *bin,
           double        *x_out,
           double        *y_out)
 {
-  GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (bin);
+  GladeDesignLayoutPrivate *priv = bin->priv;
   *x_out = widget_x - priv->child_offset;
   *y_out = widget_y - priv->child_offset;
 }
@@ -1580,7 +1598,7 @@ to_parent (GladeDesignLayout *bin,
            double        *x_out,
            double        *y_out)
 {
-  GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (bin);
+  GladeDesignLayoutPrivate *priv = bin->priv;
   *x_out = offscreen_x + priv->child_offset;
   *y_out = offscreen_y + priv->child_offset;
 }
@@ -1591,7 +1609,7 @@ pick_offscreen_child (GdkWindow     *offscreen_window,
                       double         widget_y,
                       GladeDesignLayout *bin)
 {
-  GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (bin);
+  GladeDesignLayoutPrivate *priv = bin->priv;
   GtkWidget *child = gtk_bin_get_child (GTK_BIN (bin));
 
   if (child && gtk_widget_get_visible (child))
@@ -1660,12 +1678,11 @@ glade_design_layout_realize (GtkWidget * widget)
 {
   GladeDesignLayoutPrivate *priv;
   GdkWindowAttr attributes;
-  GtkWidget *child;
   gint attributes_mask, border_width;
   GtkAllocation allocation;
   GdkDisplay *display;
     
-  priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
+  priv = GLADE_DESIGN_LAYOUT_PRIVATE (widget);
 
   gtk_widget_set_realized (widget, TRUE);
     
@@ -1700,26 +1717,14 @@ glade_design_layout_realize (GtkWidget * widget)
                     G_CALLBACK (pick_offscreen_child), widget);
 
   /* Offscreen window */
-  child = gtk_bin_get_child (GTK_BIN (widget));
   attributes.window_type = GDK_WINDOW_OFFSCREEN;
   attributes.x = attributes.y = 0;
-
-  if (child && gtk_widget_get_visible (child))
-    {
-      GtkAllocation alloc;
-
-      gtk_widget_get_allocation (child, &alloc);
-      attributes.width = alloc.width;
-      attributes.height = alloc.height;
-    }
-    else
-      attributes.width = attributes.height = 0;
+  attributes.width = attributes.height = 0;
 
   priv->offscreen_window = gdk_window_new (gtk_widget_get_root_window (widget),
                                            &attributes, attributes_mask);
   gdk_window_set_user_data (priv->offscreen_window, widget);
   
-  if (child) gtk_widget_set_parent_window (child, priv->offscreen_window);
   gdk_offscreen_window_set_embedder (priv->offscreen_window, priv->window);
 
   g_signal_connect (priv->offscreen_window, "to-embedder",
@@ -1756,7 +1761,7 @@ glade_design_layout_unrealize (GtkWidget * widget)
   GladeDesignLayoutPrivate *priv;
   gint i;
   
-  priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (widget);
+  priv = GLADE_DESIGN_LAYOUT_PRIVATE (widget);
 
   if (priv->offscreen_window)
     {
@@ -1786,26 +1791,6 @@ glade_design_layout_unrealize (GtkWidget * widget)
   GTK_WIDGET_CLASS (glade_design_layout_parent_class)->unrealize (widget);
 }
 
-void
-_glade_design_layout_get_colors (GtkStyleContext *context, 
-                                 GdkRGBA *c1, GdkRGBA *c2,
-                                 GdkRGBA *c3, GdkRGBA *c4)
-{
-  gfloat off;
-  
-  gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, c1);
-  gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, c2);
-
-  gtk_style_context_get_background_color (context, GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED, c3);
-  gtk_style_context_get_color (context, GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED, c4);
-
-  off = ((c1->red + c1->green + c1->blue)/3 < .5) ? .16 : -.16;
-   
-  c1->red += off;
-  c1->green += off;
-  c1->blue += off;
-}
-
 static void
 glade_design_layout_style_updated (GtkWidget *widget)
 {
@@ -1883,7 +1868,7 @@ glade_design_layout_set_property (GObject *object,
     {
       case PROP_DESIGN_VIEW:
         {
-          GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (object);
+          GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_PRIVATE (object);
           priv->view = GLADE_DESIGN_VIEW (g_value_get_object (value));
           priv->project = glade_design_view_get_project (priv->view);
           g_signal_connect (priv->project, "notify::pointer-mode",
@@ -1907,7 +1892,7 @@ glade_design_layout_get_property (GObject *object,
   switch (prop_id)
     {
       case PROP_DESIGN_VIEW:
-        g_value_set_object (value, GLADE_DESIGN_LAYOUT_GET_PRIVATE (object)->view);
+        g_value_set_object (value, GLADE_DESIGN_LAYOUT_PRIVATE (object)->view);
         break;
 
       default:
@@ -1919,7 +1904,7 @@ glade_design_layout_get_property (GObject *object,
 static void
 on_project_selection_changed (GladeProject *project, GladeDesignLayout *layout)
 {
-  GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (layout);
+  GladeDesignLayoutPrivate *priv = layout->priv;
   GladePointerMode mode = glade_project_get_pointer_mode (project);
 
   if (priv->selection)
@@ -1943,7 +1928,7 @@ glade_design_layout_constructor (GType                  type,
                                                                            n_construct_params,
                                                                            construct_params);
 
-  priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (object);
+  priv = GLADE_DESIGN_LAYOUT_PRIVATE (object);
 
   g_signal_connect (priv->project,
                     "selection-changed",
@@ -1958,19 +1943,100 @@ glade_design_layout_constructor (GType                  type,
 static void
 glade_design_layout_finalize (GObject *object)
 {
-  GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (object);
+  GladeDesignLayout *layout = GLADE_DESIGN_LAYOUT (object);
+  GladeDesignLayoutPrivate *priv = layout->priv;
 
   g_signal_handlers_disconnect_by_func (priv->project,
                                         on_project_selection_changed,
-                                        GLADE_DESIGN_LAYOUT (object));
+                                        layout);
   g_signal_handlers_disconnect_by_func (priv->project,
                                         on_pointer_mode_notify,
-                                        GLADE_DESIGN_LAYOUT (object));
+                                        layout);
 
   G_OBJECT_CLASS (glade_design_layout_parent_class)->finalize (object);
 }
 
 static void
+glade_design_layout_drag_begin (GtkWidget *widget, GdkDragContext *context)
+{
+  GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_PRIVATE (widget);
+  cairo_pattern_t *pattern;
+  cairo_surface_t *surface;
+  GtkAllocation alloc;
+  GtkWidget *window;
+  GdkScreen *screen;
+  cairo_t *cr;
+  gint x, y;
+
+  gtk_widget_get_allocation (priv->drag_source, &alloc);
+
+  gtk_widget_translate_coordinates (priv->drag_source, widget,
+                                    alloc.x, alloc.y,
+                                    &x, &y);
+
+  screen = gdk_window_get_screen (gdk_drag_context_get_source_window (context));
+  window = gtk_window_new (GTK_WINDOW_POPUP);
+  gtk_window_set_type_hint (GTK_WINDOW (window), GDK_WINDOW_TYPE_HINT_DND);
+  gtk_window_set_screen (GTK_WINDOW (window), screen);
+
+  gtk_widget_set_events (window, GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK);
+  gtk_widget_set_app_paintable (window, TRUE);
+
+  gtk_widget_set_size_request (window, alloc.width, alloc.height);
+  gtk_widget_realize (window);
+
+  surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24, alloc.width, alloc.height);
+  cr = cairo_create (surface);
+
+  gdk_cairo_set_source_window (cr, priv->window, alloc.x - x, alloc.y - y);
+  cairo_paint (cr);
+  cairo_surface_flush (surface);
+  
+  pattern = cairo_pattern_create_for_surface (surface);
+  
+  gdk_window_set_background_pattern (gtk_widget_get_window (window), pattern);
+
+  gtk_window_set_opacity (GTK_WINDOW (window), .5);
+  gtk_drag_set_icon_widget (context, window, priv->drag_x, priv->drag_y);
+
+  cairo_destroy (cr);
+  cairo_pattern_destroy (pattern);
+  cairo_surface_destroy (surface);
+
+  priv->drag_icon = g_object_ref_sink (window);
+}
+
+static void
+glade_design_layout_drag_data_get (GtkWidget        *widget,
+                                   GdkDragContext   *context,
+                                   GtkSelectionData *data,
+                                   guint             info,
+                                   guint             time)
+{
+  GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_PRIVATE (widget);
+
+  if (priv->drag_source)
+    {
+      static GdkAtom type = 0;
+
+      if (!type)
+        type = gdk_atom_intern_static_string (GDL_DND_TARGET_WIDGET);
+
+      gtk_selection_data_set (data, type, sizeof (gpointer),
+                              (const guchar *)&priv->drag_source, sizeof (gpointer));
+    }
+}
+
+static void
+glade_design_layout_drag_end (GtkWidget *widget, GdkDragContext *context)
+{
+  GladeDesignLayoutPrivate *priv = GLADE_DESIGN_LAYOUT_PRIVATE (widget);
+
+  g_clear_object (&priv->drag_icon);
+  priv->drag_source = NULL;
+}
+
+static void
 glade_design_layout_class_init (GladeDesignLayoutClass * klass)
 {
   GObjectClass *object_class;
@@ -2002,6 +2068,9 @@ glade_design_layout_class_init (GladeDesignLayoutClass * klass)
   widget_class->get_preferred_height_for_width = glade_design_layout_get_preferred_height_for_width;
   widget_class->size_allocate = glade_design_layout_size_allocate;
   widget_class->style_updated = glade_design_layout_style_updated;
+  widget_class->drag_begin = glade_design_layout_drag_begin;
+  widget_class->drag_end = glade_design_layout_drag_end;
+  widget_class->drag_data_get = glade_design_layout_drag_data_get;
 
   g_object_class_install_property (object_class, PROP_DESIGN_VIEW,
                                    g_param_spec_object ("design-view", _("Design View"),
@@ -2131,6 +2200,60 @@ _glade_design_layout_coords_from_event (GdkWindow *parent,
   *y = yy;
 }
 
+void
+_glade_design_layout_get_colors (GtkStyleContext *context, 
+                                 GdkRGBA *c1, GdkRGBA *c2,
+                                 GdkRGBA *c3, GdkRGBA *c4)
+{
+  gfloat off;
+  
+  gtk_style_context_get_background_color (context, GTK_STATE_FLAG_NORMAL, c1);
+  gtk_style_context_get_color (context, GTK_STATE_FLAG_NORMAL, c2);
+
+  gtk_style_context_get_background_color (context, GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED, c3);
+  gtk_style_context_get_color (context, GTK_STATE_FLAG_SELECTED | GTK_STATE_FLAG_FOCUSED, c4);
+
+  off = ((c1->red + c1->green + c1->blue)/3 < .5) ? .16 : -.16;
+   
+  c1->red += off;
+  c1->green += off;
+  c1->blue += off;
+}
+
+GtkTargetEntry *
+_glade_design_layout_get_dnd_target (void)
+{
+  static GtkTargetEntry target = {GDL_DND_TARGET_WIDGET, GTK_TARGET_SAME_APP, GDL_DND_INFO_WIDGET};
+  return &target;
+}
+
+void
+_glade_design_layout_get_hot_point (GladeDesignLayout *layout,
+                                    gint *x,
+                                    gint *y)
+{
+  GladeDesignLayoutPrivate *priv = layout->priv;
+
+  if (x)
+    *x = priv->drag_x;
+
+  if (y)
+    *y = priv->drag_y;
+}
+
+static gboolean
+widget_is_inside_fixed (GladeWidget *widget)
+{
+  while (widget)
+    {
+      if (GTK_IS_FIXED (glade_widget_get_object (widget)))
+        return TRUE;
+      widget = glade_widget_get_parent (widget);
+    }
+
+  return FALSE;
+}
+
 /*
  * _glade_design_layout_do_event:
  * @layout: A #GladeDesignLayout
@@ -2147,15 +2270,38 @@ _glade_design_layout_do_event (GladeDesignLayout *layout, GdkEvent *event)
   GtkWidget *widget = GTK_WIDGET (layout);
   GladeFindInContainerData data = { widget, 0, };
   GladeDesignLayoutPrivate *priv;
+  GladePointerMode mode;
   gboolean retval;
   GList *l;
 
-  priv = GLADE_DESIGN_LAYOUT_GET_PRIVATE (layout);
+  priv = layout->priv;
 
   _glade_design_layout_coords_from_event (priv->window, event, &data.x, &data.y);
 
+  mode = glade_project_get_pointer_mode (priv->project);
+  glade_design_layout_find_inside_container (widget, &data);
+
+  if (event->type == GDK_BUTTON_PRESS && event->button.button == 1 &&
+      ((event->button.state & GDK_SHIFT_MASK && mode == GLADE_POINTER_SELECT) ||
+       mode == GLADE_POINTER_DRAG_RESIZE))
+    {
+      GObject *source;
+              
+      if (data.gwidget && (source = glade_widget_get_object (data.gwidget)) &&
+          (event->button.state & GDK_SHIFT_MASK || !widget_is_inside_fixed (data.gwidget)))
+        {
+          priv->drag_source = GTK_WIDGET (source);
+
+          gtk_widget_translate_coordinates (widget, priv->drag_source,
+                                            data.x, data.y,
+                                            &priv->drag_x, &priv->drag_y);
+          return TRUE;
+        }
+    }
+  
   /* Check if we want to enter in margin edit mode */
   if (event->type == GDK_BUTTON_PRESS && event->button.button == 1 &&
+      mode != GLADE_POINTER_DRAG_RESIZE &&
       (l = glade_project_selection_get (priv->project)) &&
       g_list_next (l) == NULL && GTK_IS_WIDGET (l->data) && 
       gtk_widget_is_ancestor (l->data, widget))
@@ -2175,8 +2321,6 @@ _glade_design_layout_do_event (GladeDesignLayout *layout, GdkEvent *event)
     }
 
   _glade_design_view_freeze (priv->view);
-
-  glade_design_layout_find_inside_container (widget, &data);
   
   /* Try the placeholder first */
   if (data.placeholder && gtk_widget_event (data.placeholder, event)) 
diff --git a/gladeui/glade-design-private.h b/gladeui/glade-design-private.h
index a6babec..a8046f4 100644
--- a/gladeui/glade-design-private.h
+++ b/gladeui/glade-design-private.h
@@ -25,6 +25,12 @@
 #ifndef __GLADE_DESIGN_PRIVATE_H__
 #define __GLADE_DESIGN_PRIVATE_H__
 
+#define GDL_DND_INFO_WIDGET 15956
+#define GDL_DND_TARGET_WIDGET "glade/x-widget"
+
+#include "glade-design-view.h"
+#include "glade-design-layout.h"
+
 G_BEGIN_DECLS
 
 void _glade_design_view_freeze (GladeDesignView *view);
@@ -47,6 +53,12 @@ void _glade_design_layout_draw_pushpin (cairo_t *cr,
                                         GdkRGBA *bg,
                                         GdkRGBA *fg);
 
+void            _glade_design_layout_get_hot_point (GladeDesignLayout *layout,
+                                                    gint *x,
+                                                    gint *y);
+
+GtkTargetEntry *_glade_design_layout_get_dnd_target (void);
+
 G_END_DECLS
 
 #endif /* __GLADE_DESIGN_PRIVATE_H__ */
diff --git a/gladeui/glade-design-view.c b/gladeui/glade-design-view.c
index aae16ff..fa93142 100644
--- a/gladeui/glade-design-view.c
+++ b/gladeui/glade-design-view.c
@@ -63,6 +63,8 @@ struct _GladeDesignViewPrivate
 
   GtkToolPalette *palette;
   GladeWidgetAdaptor *drag_adaptor;
+  GtkWidget *drag_source;
+  GtkWidget *drag_target;
 };
 
 static GtkVBoxClass *parent_class = NULL;
@@ -103,30 +105,36 @@ on_layout_size_allocate (GtkWidget *widget, GtkAllocation *alloc, GladeDesignVie
 static void
 glade_design_view_selection_changed (GladeProject *project, GladeDesignView *view)
 {
-  GladeWidget *gwidget, *gtoplevel;
-  GObject *toplevel;
-  GtkWidget *layout;
   GList *selection;
 
   /* Check if its only one widget selected and scroll viewport to show toplevel */
   if ((selection = glade_project_selection_get (project)) &&
       g_list_next (selection) == NULL &&
-      GTK_IS_WIDGET (selection->data) &&
-      !GLADE_IS_PLACEHOLDER (selection->data) &&
-      (gwidget = glade_widget_get_from_gobject (G_OBJECT (selection->data))) &&
-      (gtoplevel = glade_widget_get_toplevel (gwidget)) &&
-      (toplevel = glade_widget_get_object (gtoplevel)) &&
-      GTK_IS_WIDGET (toplevel) &&
-      (layout = gtk_widget_get_parent (GTK_WIDGET (toplevel))) &&
-      GLADE_IS_DESIGN_LAYOUT (layout))
+      GTK_IS_WIDGET (selection->data))
     {
-      GtkAllocation alloc;
-      gtk_widget_get_allocation (layout, &alloc);
-          
-      if (alloc.x < 0)
-        g_signal_connect (layout, "size-allocate", G_CALLBACK (on_layout_size_allocate), view);
-      else
-        glade_design_layout_scroll (view, alloc.x, alloc.y, alloc.width, alloc.height);
+      GladeWidget *gwidget, *gtoplevel;
+      GObject *toplevel;
+      
+      if (!GLADE_IS_PLACEHOLDER (selection->data) &&
+          (gwidget = glade_widget_get_from_gobject (G_OBJECT (selection->data))) &&
+          (gtoplevel = glade_widget_get_toplevel (gwidget)) &&
+          (toplevel = glade_widget_get_object (gtoplevel)) &&
+          GTK_IS_WIDGET (toplevel))
+        {
+          GtkWidget *layout;
+
+          if ((layout = gtk_widget_get_parent (GTK_WIDGET (toplevel))) &&
+              GLADE_IS_DESIGN_LAYOUT (layout))
+            {
+              GtkAllocation alloc;
+              gtk_widget_get_allocation (layout, &alloc);
+
+              if (alloc.x < 0)
+                g_signal_connect (layout, "size-allocate", G_CALLBACK (on_layout_size_allocate), view);
+              else
+                glade_design_layout_scroll (view, alloc.x, alloc.y, alloc.width, alloc.height);
+            }
+        }
     }
 }
 
@@ -151,8 +159,9 @@ glade_design_view_add_toplevel (GladeDesignView *view, GladeWidget *widget)
   if ((toplevels = glade_project_toplevels (view->priv->project)))
     gtk_box_reorder_child (GTK_BOX (view->priv->layout_box), layout, 
                            g_list_index (toplevels, GTK_WIDGET (object)));
-  
+
   gtk_container_add (GTK_CONTAINER (layout), GTK_WIDGET (object));
+
   gtk_widget_show (GTK_WIDGET (object));
   gtk_widget_show (layout);
 }
@@ -326,7 +335,6 @@ glade_design_view_init (GladeDesignView *view)
   view->priv->layout_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
   gtk_widget_set_valign (view->priv->layout_box, GTK_ALIGN_START);
   gtk_container_set_border_width (GTK_CONTAINER (view->priv->layout_box), 0);
-  gtk_box_pack_end (GTK_BOX (view->priv->layout_box), gtk_fixed_new (), FALSE, FALSE, 0);
 
   view->priv->scrolled_window = gtk_scrolled_window_new (NULL, NULL);
   gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW
@@ -354,95 +362,16 @@ glade_design_view_init (GladeDesignView *view)
 }
 
 static void
-glade_design_view_class_init (GladeDesignViewClass *klass)
-{
-  GObjectClass *object_class;
-  GtkWidgetClass *widget_class;
-
-  parent_class = g_type_class_peek_parent (klass);
-  object_class = G_OBJECT_CLASS (klass);
-  widget_class = GTK_WIDGET_CLASS (klass);
-
-  object_class->get_property = glade_design_view_get_property;
-  object_class->set_property = glade_design_view_set_property;
-
-  widget_class->draw = glade_design_view_draw;
-  
-  g_object_class_install_property (object_class,
-                                   PROP_PROJECT,
-                                   g_param_spec_object ("project",
-                                                        "Project",
-                                                        "The project for this view",
-                                                        GLADE_TYPE_PROJECT,
-                                                        G_PARAM_READWRITE |
-                                                        G_PARAM_CONSTRUCT_ONLY));
-  g_object_class_install_property (object_class,
-                                   PROP_DRAG_SOURCE,
-                                   g_param_spec_object ("drag-source",
-                                                        "Drag Source",
-                                                        "A palette to use as the source of drag events for this view",
-                                                        GTK_TYPE_TOOL_PALETTE,
-                                                        G_PARAM_READWRITE));
-
-  g_type_class_add_private (object_class, sizeof (GladeDesignViewPrivate));
-}
-
-/* Private API */
-
-void
-_glade_design_view_freeze (GladeDesignView *view)
-{
-  g_return_if_fail (GLADE_IS_DESIGN_VIEW (view));
-  
-  g_signal_handlers_block_by_func (view->priv->project,
-                                   glade_design_view_selection_changed,
-                                   view);
-}
-
-void
-_glade_design_view_thaw   (GladeDesignView *view)
-{
-  g_return_if_fail (GLADE_IS_DESIGN_VIEW (view));
-  
-  g_signal_handlers_unblock_by_func (view->priv->project,
-                                     glade_design_view_selection_changed,
-                                     view);
-}
-
-/* Public API */
-
-GladeProject *
-glade_design_view_get_project (GladeDesignView *view)
-{
-  g_return_val_if_fail (GLADE_IS_DESIGN_VIEW (view), NULL);
-
-  return view->priv->project;
-
-}
-
-GtkWidget *
-glade_design_view_new (GladeProject *project)
+glade_design_view_finalize (GObject *object)
 {
-  GladeDesignView *view;
+  GladeDesignView *view = GLADE_DESIGN_VIEW (object);
+  GladeDesignViewPrivate *priv = view->priv;
 
-  g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
-
-  view = g_object_new (GLADE_TYPE_DESIGN_VIEW, "project", project, NULL);
-
-  return GTK_WIDGET (view);
-}
-
-GladeDesignView *
-glade_design_view_get_from_project (GladeProject *project)
-{
-  gpointer p;
-
-  g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
-
-  p = g_object_get_data (G_OBJECT (project), GLADE_DESIGN_VIEW_KEY);
-
-  return (p != NULL) ? GLADE_DESIGN_VIEW (p) : NULL;
+  /* Yup, disconnect every handler that reference this view */
+  g_signal_handlers_disconnect_by_data (priv->project, view);
+  g_signal_handlers_disconnect_by_data (priv->project, priv->scrolled_window);
 
+  G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
 static GtkWidget *
@@ -486,107 +415,419 @@ widget_get_child_from_position (GtkWidget *toplevel, GtkWidget *widget, gint x,
   return retval;
 }
 
+static GtkWidget *
+widget_get_gchild_from_position (GtkWidget *toplevel, GtkWidget *widget, gint x, gint y)
+{
+  GtkWidget *retval = widget_get_child_from_position (toplevel, widget, x, y);
+
+  while (retval)
+    {
+      if (retval == toplevel || GLADE_IS_PLACEHOLDER (retval) ||
+          glade_widget_get_from_gobject (retval))
+        return retval;
+
+      retval = gtk_widget_get_parent (retval);
+    }
+
+  return NULL;
+}
+
 static gboolean
-widget_is_outside_glade_ancestor (GtkWidget *widget)
+drag_highlight_draw (GtkWidget *widget, cairo_t *cr, GladeDesignView *view)
 {
-  while (widget)
+  GtkStyleContext *context;
+  gint width, height;
+  GdkRGBA c;
+
+  context = gtk_widget_get_style_context (GTK_WIDGET (view));
+  width = gtk_widget_get_allocated_width (widget);
+  height = gtk_widget_get_allocated_height (widget);
+
+  gtk_style_context_get_background_color (context, GTK_STATE_FLAG_SELECTED |
+                                          GTK_STATE_FLAG_FOCUSED, &c);
+
+  if (GLADE_IS_PLACEHOLDER (widget))
     {
-      if (glade_widget_get_from_gobject (widget))
-        return TRUE;
+      cairo_pattern_t *gradient;
+      gdouble w, h;
 
-      widget = gtk_widget_get_parent (widget);
+      w = gtk_widget_get_allocated_width (widget)/2.0;
+      h = gtk_widget_get_allocated_height (widget)/2.0;
+      gradient = cairo_pattern_create_radial (w, h, MIN (width, height)/6,
+                                              w, h, MAX (w, h));
+      cairo_pattern_add_color_stop_rgba (gradient, 0, c.red, c.green, c.blue, .08);
+      cairo_pattern_add_color_stop_rgba (gradient, 1, c.red, c.green, c.blue, .28);
+
+      cairo_set_source (cr, gradient);
+
+      cairo_rectangle (cr, 0, 0, width, height);
+      cairo_fill (cr);
+
+      cairo_pattern_destroy (gradient);
+    }
+  else
+    {
+      cairo_set_line_width (cr, 2);
+      gdk_cairo_set_source_rgba (cr, &c);
+      cairo_rectangle (cr, 1, 1, width-2, height-2);
+      cairo_stroke (cr);
     }
 
   return FALSE;
 }
 
+static void
+glade_design_view_drag_highlight (GladeDesignView *view, GtkWidget *widget)
+{
+  g_signal_connect_after (widget, "draw", G_CALLBACK (drag_highlight_draw), view);
+  gtk_widget_queue_draw (widget);
+}
+
+static void 
+glade_design_view_drag_unhighlight (GladeDesignView *view, GtkWidget *widget)
+{
+  g_signal_handlers_disconnect_by_func (widget, drag_highlight_draw, view);
+  gtk_widget_queue_draw (widget);
+}
+
 static gboolean
-on_drag_motion (GtkWidget *widget,
-                GdkDragContext *context,
-                gint x, gint y,
-                guint time)
+glade_design_view_drag_motion (GtkWidget *widget,
+                               GdkDragContext *context,
+                               gint x, gint y,
+                               guint time)
 {
   GladeDesignViewPrivate *priv = GLADE_DESIGN_VIEW (widget)->priv;
+  GdkDragAction drag_action = GDK_ACTION_COPY;
   GtkWidget *child;
 
-  child = widget_get_child_from_position (widget, widget, x, y);
-
-  if (!priv->drag_adaptor)
+  child = widget_get_gchild_from_position (widget, widget, x, y);
+  
+  if (!(priv->drag_adaptor || priv->drag_source))
     {
       GdkAtom target = gtk_drag_dest_find_target (widget, context, NULL);
 
-      if (!target)
-        return FALSE;
+      if (target)
+        gtk_drag_get_data (widget, context, target, time);
+    }
+
+  if (child)
+    {
+      GladeWidget *gwidget;
+
+      if (priv->drag_source &&
+          (priv->drag_source == child || gtk_widget_is_ancestor (child, priv->drag_source) ||
+           (!GLADE_IS_PLACEHOLDER (child) && 
+            !GTK_IS_FIXED (child) &&
+            (glade_widget_get_from_gobject (child) ||
+             ((gwidget = glade_widget_get_from_gobject (priv->drag_source)) &&
+             !glade_widget_get_parent (gwidget)
+            ))
+         )))
+        drag_action = 0;
+
+      if (priv->drag_adaptor &&
+          ((GLADE_IS_PLACEHOLDER (child) && GWA_IS_TOPLEVEL (priv->drag_adaptor)) ||
+           (!GLADE_IS_PLACEHOLDER (child) && !GTK_IS_FIXED (child) &&
+            glade_widget_get_from_gobject (child))))
+        drag_action = 0;
+    }
+  else
+    drag_action = 0;
+  
+  gdk_drag_status (context, drag_action, time);
 
-      gtk_drag_get_data (widget, context, target, time);
+  if (priv->drag_target != child)
+    {
+      if (priv->drag_target)
+        {
+          glade_design_view_drag_unhighlight (GLADE_DESIGN_VIEW (widget),
+                                              priv->drag_target);
+          priv->drag_target = NULL;
+        }
+
+      if (drag_action == GDK_ACTION_COPY)
+        {
+          glade_design_view_drag_highlight (GLADE_DESIGN_VIEW (widget), child);
+          priv->drag_target = child;
+        }
     }
   
-  if (child &&
-      ((priv->drag_adaptor && GLADE_IS_PLACEHOLDER (child) &&
-        GWA_IS_TOPLEVEL (priv->drag_adaptor)) ||
-       (!GLADE_IS_PLACEHOLDER (child) &&
-        widget_is_outside_glade_ancestor (child)) ))
+  return drag_action != 0;
+}
+
+static void
+glade_design_view_drag_leave (GtkWidget      *widget,
+                              GdkDragContext *drag_context,
+                              guint           time)
+{
+  GladeDesignViewPrivate *priv = GLADE_DESIGN_VIEW (widget)->priv;
+
+  if (priv->drag_target)
     {
-      gdk_drag_status (context, 0, time);
-      return FALSE;
+      glade_design_view_drag_unhighlight (GLADE_DESIGN_VIEW (widget),
+                                          priv->drag_target);
+      priv->drag_target = NULL;
     }
+}
 
-  gdk_drag_status (context, GDK_ACTION_COPY, time);
-  return TRUE;
+static void
+on_drag_item_drag_end (GtkWidget *widget,
+                       GdkDragContext *context, 
+                       GladeDesignView *view)
+{
+  GladeDesignViewPrivate *priv = view->priv;
+
+  priv->drag_adaptor = NULL;
+  priv->drag_source = NULL;
+  priv->drag_target = NULL;
+  
+  g_signal_handlers_disconnect_by_func (widget, on_drag_item_drag_end, view);
 }
 
 static void
-on_drag_data_received (GtkWidget        *widget,
-                       GdkDragContext   *context,
-                       gint              x,
-                       gint              y,
-                       GtkSelectionData *selection,
-                       guint             info,
-                       guint             time)
+glade_design_view_drag_data_received (GtkWidget        *widget,
+                                      GdkDragContext   *context,
+                                      gint              x,
+                                      gint              y,
+                                      GtkSelectionData *selection,
+                                      guint             info,
+                                      guint             time)
 {
   GladeDesignViewPrivate *priv = GLADE_DESIGN_VIEW (widget)->priv;
-  GtkWidget *item;
+  GdkAtom target = gtk_selection_data_get_target (selection);
+  const GtkTargetEntry *palette_target;
 
-  item = gtk_tool_palette_get_drag_item (priv->palette, selection);
-  g_return_if_fail (item);
+  if (info == GDL_DND_INFO_WIDGET &&
+      g_strcmp0 (gdk_atom_name (target), GDL_DND_TARGET_WIDGET) == 0)
+    {
+      const guchar *data = gtk_selection_data_get_data (selection);
+      
+      if (data)
+        priv->drag_source = *((GtkWidget **)data);
+    }
+  else if (priv->palette &&
+           (palette_target = gtk_tool_palette_get_drag_target_item ()) &&
+           palette_target->info == info &&
+           g_strcmp0 (gdk_atom_name (target), palette_target->target) == 0)
+    {
+      GtkWidget *item = gtk_tool_palette_get_drag_item (priv->palette, selection);
 
-  priv->drag_adaptor = g_object_get_data (G_OBJECT (item), "glade-widget-adaptor");
+      if (item)
+        priv->drag_adaptor = g_object_get_data (G_OBJECT (item), "glade-widget-adaptor");
+    }
+  else
+    return;
+
+  g_signal_connect (gtk_drag_get_source_widget (context), "drag-end",
+                    G_CALLBACK (on_drag_item_drag_end),
+                    GLADE_DESIGN_VIEW (widget));
+}
+
+
+static void
+glade_design_view_fixed_move (GladeWidget *gsource,
+                              GtkWidget *widget,
+                              GdkDragContext *context,
+                              GtkWidget *child,
+                              gint x,
+                              gint y)
+{
+  GladeProperty *prop_x, *prop_y;
+  gint dx, dy, hx, hy;
+  GtkWidget *layout;
+
+  gtk_widget_translate_coordinates (widget, child, x, y, &dx, &dy);
+
+  prop_x = glade_widget_get_pack_property (gsource, "x");
+  prop_y = glade_widget_get_pack_property (gsource, "y");
+
+  layout = gtk_drag_get_source_widget (context);
+
+  if (layout && GLADE_IS_DESIGN_LAYOUT (layout))
+    _glade_design_layout_get_hot_point (GLADE_DESIGN_LAYOUT (layout), &hx, &hy);
+  else
+    hx = hy = 0;
+
+  glade_command_set_property (prop_x, dx - hx);
+  glade_command_set_property (prop_y, dy - hy);
 }
 
 static gboolean
-on_drag_drop (GtkWidget       *widget,
-              GdkDragContext  *context,
-              gint             x,
-              gint             y,
-              guint            time)  
+glade_design_view_drag_drop (GtkWidget       *widget,
+                             GdkDragContext  *context,
+                             gint             x,
+                             gint             y,
+                             guint            time)  
 {
   GladeDesignViewPrivate *priv = GLADE_DESIGN_VIEW (widget)->priv;
   GtkWidget *child;
 
-  if (!priv->drag_adaptor)
-    return FALSE;
+  child = widget_get_gchild_from_position (widget, widget, x, y);
   
-  child = widget_get_child_from_position (widget, widget, x, y);
-    
-  if (child && GLADE_IS_PLACEHOLDER (child))
+  if (priv->drag_source)
     {
-      GladePlaceholder *placeholder = GLADE_PLACEHOLDER (child);
+      GladeWidget *gsource = glade_widget_get_from_gobject (priv->drag_source);
+      GList widgets = {gsource, NULL, NULL};
 
-      glade_command_create (priv->drag_adaptor,
-                            glade_placeholder_get_parent (placeholder),
-                            placeholder, 
-                            priv->project);
+      if (GLADE_IS_PLACEHOLDER (child))
+        {
+          GladePlaceholder *placeholder = GLADE_PLACEHOLDER (child);
+          GladeWidget *parent = glade_placeholder_get_parent (placeholder);
+
+          /* Check for recursive paste */
+          if (parent != gsource)
+            glade_command_dnd (&widgets, parent, placeholder);
+        }
+      else if (GTK_IS_FIXED (child))
+        {
+          GladeWidget *parent = glade_widget_get_from_gobject (child);
+          
+          glade_command_push_group ("Drag and Drop");
+          if (parent != glade_widget_get_parent (gsource))
+            glade_command_dnd (&widgets, parent, NULL);
+          
+          glade_design_view_fixed_move (gsource, widget, context, child, x, y);
+          glade_command_pop_group ();
+        }
+      else if (!glade_widget_get_from_gobject (child))
+        glade_command_dnd (&widgets, NULL, NULL);
     }
-  else
+  else if (child && priv->drag_adaptor)
     {
-      glade_command_create (priv->drag_adaptor, NULL, NULL, priv->project);
+      if (GLADE_IS_PLACEHOLDER (child))
+        {
+          GladePlaceholder *placeholder = GLADE_PLACEHOLDER (child);
+
+          glade_command_create (priv->drag_adaptor,
+                                glade_placeholder_get_parent (placeholder),
+                                placeholder, 
+                                priv->project);
+        }
+      else if (GTK_IS_FIXED (child))
+        {
+          GladeWidget *parent = glade_widget_get_from_gobject (child);
+
+          if (parent)
+            {
+              GladeWidget *gsource;
+              glade_command_push_group ("Drag and Drop");
+
+              gsource = glade_command_create (priv->drag_adaptor,
+                                              parent, NULL,
+                                              priv->project);
+
+              glade_design_view_fixed_move (gsource, widget, context, child, x, y);
+              glade_command_pop_group ();
+            }
+        }
+      else
+        {
+          glade_command_create (priv->drag_adaptor, NULL, NULL, priv->project);
+        }
     }
 
   gtk_drag_finish (context, TRUE, FALSE, time);
-  priv->drag_adaptor = NULL;
+
   return TRUE;
 }
 
+static void
+glade_design_view_class_init (GladeDesignViewClass *klass)
+{
+  GObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+
+  parent_class = g_type_class_peek_parent (klass);
+  object_class = G_OBJECT_CLASS (klass);
+  widget_class = GTK_WIDGET_CLASS (klass);
+
+  object_class->finalize = glade_design_view_finalize;
+  object_class->get_property = glade_design_view_get_property;
+  object_class->set_property = glade_design_view_set_property;
+
+  widget_class->drag_motion = glade_design_view_drag_motion;
+  widget_class->drag_leave = glade_design_view_drag_leave;
+  widget_class->drag_data_received = glade_design_view_drag_data_received;
+  widget_class->drag_drop = glade_design_view_drag_drop;
+  widget_class->draw = glade_design_view_draw;
+  
+  g_object_class_install_property (object_class,
+                                   PROP_PROJECT,
+                                   g_param_spec_object ("project",
+                                                        "Project",
+                                                        "The project for this view",
+                                                        GLADE_TYPE_PROJECT,
+                                                        G_PARAM_READWRITE |
+                                                        G_PARAM_CONSTRUCT_ONLY));
+  g_object_class_install_property (object_class,
+                                   PROP_DRAG_SOURCE,
+                                   g_param_spec_object ("drag-source",
+                                                        "Drag Source",
+                                                        "A palette to use as the source of drag events for this view",
+                                                        GTK_TYPE_TOOL_PALETTE,
+                                                        G_PARAM_READWRITE));
+
+  g_type_class_add_private (object_class, sizeof (GladeDesignViewPrivate));
+}
+
+/* Private API */
+
+void
+_glade_design_view_freeze (GladeDesignView *view)
+{
+  g_return_if_fail (GLADE_IS_DESIGN_VIEW (view));
+  
+  g_signal_handlers_block_by_func (view->priv->project,
+                                   glade_design_view_selection_changed,
+                                   view);
+}
+
+void
+_glade_design_view_thaw   (GladeDesignView *view)
+{
+  g_return_if_fail (GLADE_IS_DESIGN_VIEW (view));
+  
+  g_signal_handlers_unblock_by_func (view->priv->project,
+                                     glade_design_view_selection_changed,
+                                     view);
+}
+
+/* Public API */
+
+GladeProject *
+glade_design_view_get_project (GladeDesignView *view)
+{
+  g_return_val_if_fail (GLADE_IS_DESIGN_VIEW (view), NULL);
+
+  return view->priv->project;
+
+}
+
+GtkWidget *
+glade_design_view_new (GladeProject *project)
+{
+  GladeDesignView *view;
+
+  g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
+
+  view = g_object_new (GLADE_TYPE_DESIGN_VIEW, "project", project, NULL);
+
+  return GTK_WIDGET (view);
+}
+
+GladeDesignView *
+glade_design_view_get_from_project (GladeProject *project)
+{
+  gpointer p;
+
+  g_return_val_if_fail (GLADE_IS_PROJECT (project), NULL);
+
+  p = g_object_get_data (G_OBJECT (project), GLADE_DESIGN_VIEW_KEY);
+
+  return (p != NULL) ? GLADE_DESIGN_VIEW (p) : NULL;
+
+}
+
 void
 glade_design_view_set_drag_source (GladeDesignView *view, GtkToolPalette *source)
 {
@@ -605,20 +846,23 @@ glade_design_view_set_drag_source (GladeDesignView *view, GtkToolPalette *source
   target = GTK_WIDGET (view);
   priv->palette = source;
 
+  gtk_drag_dest_set (target, 0, NULL, 0, GDK_ACTION_COPY);
+
   if (priv->palette)
     {
-      g_signal_connect (target, "drag-motion", G_CALLBACK (on_drag_motion), NULL);
-      g_signal_connect (target, "drag-data-received", G_CALLBACK (on_drag_data_received), NULL);
-      g_signal_connect (target, "drag-drop", G_CALLBACK (on_drag_drop), NULL);
+      GtkTargetEntry targets[2];
+      GtkTargetList *list;
 
       gtk_tool_palette_add_drag_dest (priv->palette, target, 0,
                                       GTK_TOOL_PALETTE_DRAG_ITEMS,
                                       GDK_ACTION_COPY);
-    }
-  else
-    {
-      g_signal_handlers_disconnect_by_func (target, on_drag_motion, NULL);
-      g_signal_handlers_disconnect_by_func (target, on_drag_data_received, NULL);
-      g_signal_handlers_disconnect_by_func (target, on_drag_drop, NULL);
+
+      targets[0] = *gtk_tool_palette_get_drag_target_item ();
+      targets[1] = *_glade_design_layout_get_dnd_target ();
+
+      list = gtk_target_list_new (targets, 2);
+      gtk_drag_dest_set_target_list (target, list);
+
+      gtk_target_list_unref (list);
     }
 }
diff --git a/plugins/gtk+/glade-fixed.c b/plugins/gtk+/glade-fixed.c
index 9880851..0362ed0 100644
--- a/plugins/gtk+/glade-fixed.c
+++ b/plugins/gtk+/glade-fixed.c
@@ -280,21 +280,31 @@ glade_fixed_filter_event (GladeFixed *fixed,
 static void
 glade_fixed_handle_swindow (GladeFixed *fixed, GdkRectangle *area)
 {
-  GtkWidget *swindow = NULL, *swindow_child = NULL;
+  GtkWidget *swindow = NULL, *swindow_child = NULL, *widget;
   GtkAdjustment *hadj, *vadj;
   GtkAllocation child_allocation;
   GtkWidget *fixed_widget;
+  GladeWidget *gwidget;
   gint x, y;
 
-  fixed_widget = GTK_WIDGET (glade_widget_get_object (GLADE_WIDGET (fixed)));
+  widget = fixed_widget = GTK_WIDGET (glade_widget_get_object (GLADE_WIDGET (fixed)));
 
-  swindow_child = swindow = fixed_widget;
-  while (swindow && !GTK_IS_SCROLLED_WINDOW (swindow))
+  while (widget && !GTK_IS_SCROLLED_WINDOW (widget) &&
+         (
+          ((gwidget = glade_widget_get_from_gobject (widget)) &&
+           glade_widget_get_parent (gwidget)) ||
+          !gwidget))
     {
-      if (!GTK_IS_VIEWPORT (swindow))
-        swindow_child = swindow;
+      if (!GTK_IS_VIEWPORT (widget))
+        swindow_child = widget;
 
-      swindow = gtk_widget_get_parent (swindow);
+      if (GTK_IS_SCROLLED_WINDOW (widget))
+        {
+          swindow = widget;
+          break;
+        }
+
+      widget = gtk_widget_get_parent (widget);
     }
 
   if (swindow)
diff --git a/plugins/gtk+/glade-gtk.c b/plugins/gtk+/glade-gtk.c
index f095994..9e147aa 100644
--- a/plugins/gtk+/glade-gtk.c
+++ b/plugins/gtk+/glade-gtk.c
@@ -3640,6 +3640,9 @@ void
 glade_gtk_fixed_layout_post_create (GladeWidgetAdaptor * adaptor,
                                     GObject * object, GladeCreateReason reason)
 {
+  /* Set a minimun size so you can actually see it if you added to a box */
+  gtk_widget_set_size_request (GTK_WIDGET (object), 32, 32);
+  
   /* Sync up size request at project load time */
   if (reason == GLADE_CREATE_LOAD)
     g_signal_connect_after (object, "realize",



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