[gimp] app: remove most of our own dockable DND code



commit 58d5cd29076962ca88fa799eccdf522d03235d18
Author: Michael Natterer <mitch gimp org>
Date:   Fri Jun 8 01:37:19 2018 +0200

    app: remove most of our own dockable DND code
    
    and use GtkNotebook's implementation instead. This is mostly moving
    dockable adding and removing code to GtkNotebook::page_added() and
    ::page_removed() and removing lots of code.

 app/widgets/gimpdnd.c         |   2 +-
 app/widgets/gimpdnd.h         |   4 +-
 app/widgets/gimpdock.c        |  24 +-
 app/widgets/gimpdockable.c    | 162 +---------
 app/widgets/gimpdockable.h    |  11 -
 app/widgets/gimpdockbook.c    | 708 ++++++++++++------------------------------
 app/widgets/gimpdockbook.h    |   3 -
 app/widgets/gimpdockcolumns.c |  23 +-
 app/widgets/gimppanedbox.c    |  89 ++++--
 app/widgets/widgets-enums.h   |   4 +-
 app/widgets/widgets-types.h   |   3 +-
 11 files changed, 279 insertions(+), 754 deletions(-)
---
diff --git a/app/widgets/gimpdnd.c b/app/widgets/gimpdnd.c
index d0f372f149..340e5ec489 100644
--- a/app/widgets/gimpdnd.c
+++ b/app/widgets/gimpdnd.c
@@ -599,7 +599,7 @@ static const GimpDndDataDef dnd_data_defs[] =
   },
 
   {
-    GIMP_TARGET_DIALOG,
+    GIMP_TARGET_NOTEBOOK_TAB,
 
     NULL,
     NULL,
diff --git a/app/widgets/gimpdnd.h b/app/widgets/gimpdnd.h
index 34d03a0c67..59a62ea280 100644
--- a/app/widgets/gimpdnd.h
+++ b/app/widgets/gimpdnd.h
@@ -91,8 +91,8 @@
 #define GIMP_TARGET_TOOL_INFO \
         { "application/x-gimp-tool-info-name", GTK_TARGET_SAME_APP, GIMP_DND_TYPE_TOOL_INFO }
 
-#define GIMP_TARGET_DIALOG \
-        { "application/x-gimp-dialog", GTK_TARGET_SAME_APP, GIMP_DND_TYPE_DIALOG }
+#define GIMP_TARGET_NOTEBOOK_TAB \
+        { "GTK_NOTEBOOK_TAB", GTK_TARGET_SAME_APP, GIMP_DND_TYPE_NOTEBOOK_TAB }
 
 
 /*  dnd initialization  */
diff --git a/app/widgets/gimpdock.c b/app/widgets/gimpdock.c
index d346518c0f..41179a761e 100644
--- a/app/widgets/gimpdock.c
+++ b/app/widgets/gimpdock.c
@@ -77,7 +77,8 @@ static void       gimp_dock_real_book_added        (GimpDock     *dock,
 static void       gimp_dock_real_book_removed      (GimpDock     *dock,
                                                     GimpDockbook *dockbook);
 static void       gimp_dock_invalidate_description (GimpDock     *dock);
-static gboolean   gimp_dock_dropped_cb             (GtkWidget    *source,
+static gboolean   gimp_dock_dropped_cb             (GtkWidget    *notebook,
+                                                    GtkWidget    *child,
                                                     gint          insert_index,
                                                     gpointer      data);
 
@@ -290,22 +291,21 @@ gimp_dock_invalidate_description (GimpDock *dock)
 }
 
 static gboolean
-gimp_dock_dropped_cb (GtkWidget *source,
+gimp_dock_dropped_cb (GtkWidget *notebook,
+                      GtkWidget *child,
                       gint       insert_index,
                       gpointer   data)
 {
   GimpDock          *dock     = GIMP_DOCK (data);
-  GimpDockable      *dockable = gimp_dockbook_drag_source_to_dockable (source);
+  GimpDockbook      *dockbook = GIMP_DOCKBOOK (notebook);
+  GimpDockable      *dockable = GIMP_DOCKABLE (child);
   GimpDialogFactory *factory;
-  GtkWidget         *dockbook = NULL;
-
-  if (!dockable )
-    return FALSE;
+  GtkWidget         *new_dockbook;
 
   /*  if dropping to the same dock, take care that we don't try
    *  to reorder the *only* dockable in the dock
    */
-  if (gimp_dockbook_get_dock (gimp_dockable_get_dockbook (dockable)) == dock)
+  if (gimp_dockbook_get_dock (dockbook) == dock)
     {
       GList *children;
       gint   n_books;
@@ -323,15 +323,15 @@ gimp_dock_dropped_cb (GtkWidget *source,
 
   /* Detach the dockable from the old dockbook */
   g_object_ref (dockable);
-  gimp_dockbook_remove (gimp_dockable_get_dockbook (dockable), dockable);
+  gtk_notebook_detach_tab (GTK_NOTEBOOK (notebook), child);
 
   /* Create a new dockbook */
   factory = gimp_dock_get_dialog_factory (dock);
-  dockbook = gimp_dockbook_new (gimp_dialog_factory_get_menu_factory (factory));
-  gimp_dock_add_book (dock, GIMP_DOCKBOOK (dockbook), insert_index);
+  new_dockbook = gimp_dockbook_new (gimp_dialog_factory_get_menu_factory (factory));
+  gimp_dock_add_book (dock, GIMP_DOCKBOOK (new_dockbook), insert_index);
 
   /* Add the dockable to new new dockbook */
-  gimp_dockbook_add (GIMP_DOCKBOOK (dockbook), dockable, -1);
+  gimp_dockbook_add (GIMP_DOCKBOOK (new_dockbook), dockable, -1);
   g_object_unref (dockable);
 
   return TRUE;
diff --git a/app/widgets/gimpdockable.c b/app/widgets/gimpdockable.c
index d67483dbd9..6587a21f5f 100644
--- a/app/widgets/gimpdockable.c
+++ b/app/widgets/gimpdockable.c
@@ -67,12 +67,6 @@ struct _GimpDockablePrivate
   GimpDockbook *dockbook;
 
   GimpContext  *context;
-
-  GimpPanedBox *drag_handler;
-
-  /*  drag icon hotspot  */
-  gint          drag_x;
-  gint          drag_y;
 };
 
 
@@ -89,20 +83,6 @@ static void       gimp_dockable_get_property         (GObject        *object,
                                                       GValue         *value,
                                                       GParamSpec     *pspec);
 
-static void       gimp_dockable_drag_leave           (GtkWidget      *widget,
-                                                      GdkDragContext *context,
-                                                      guint           time);
-static gboolean   gimp_dockable_drag_motion          (GtkWidget      *widget,
-                                                      GdkDragContext *context,
-                                                      gint            x,
-                                                      gint            y,
-                                                      guint           time);
-static gboolean   gimp_dockable_drag_drop            (GtkWidget      *widget,
-                                                      GdkDragContext *context,
-                                                      gint            x,
-                                                      gint            y,
-                                                      guint           time);
-
 static void       gimp_dockable_style_updated        (GtkWidget      *widget);
 
 static void       gimp_dockable_add                  (GtkContainer   *container,
@@ -124,7 +104,7 @@ G_DEFINE_TYPE_WITH_CODE (GimpDockable, gimp_dockable, GTK_TYPE_BIN,
 
 #define parent_class gimp_dockable_parent_class
 
-static const GtkTargetEntry dialog_target_table[] = { GIMP_TARGET_DIALOG };
+static const GtkTargetEntry dialog_target_table[] = { GIMP_TARGET_NOTEBOOK_TAB };
 
 
 static void
@@ -139,9 +119,6 @@ gimp_dockable_class_init (GimpDockableClass *klass)
   object_class->get_property  = gimp_dockable_get_property;
 
   widget_class->style_updated = gimp_dockable_style_updated;
-  widget_class->drag_leave    = gimp_dockable_drag_leave;
-  widget_class->drag_motion   = gimp_dockable_drag_motion;
-  widget_class->drag_drop     = gimp_dockable_drag_drop;
 
   container_class->add        = gimp_dockable_add;
   container_class->child_type = gimp_dockable_child_type;
@@ -172,8 +149,6 @@ gimp_dockable_init (GimpDockable *dockable)
                                              GimpDockablePrivate);
 
   dockable->p->tab_style = GIMP_TAB_STYLE_PREVIEW;
-  dockable->p->drag_x    = GIMP_DOCKABLE_DRAG_OFFSET;
-  dockable->p->drag_y    = GIMP_DOCKABLE_DRAG_OFFSET;
 
   gtk_drag_dest_set (GTK_WIDGET (dockable),
                      0,
@@ -263,69 +238,6 @@ gimp_dockable_get_property (GObject    *object,
     }
 }
 
-static void
-gimp_dockable_drag_leave (GtkWidget      *widget,
-                          GdkDragContext *context,
-                          guint           time)
-{
-  gimp_highlight_widget (widget, FALSE);
-}
-
-static gboolean
-gimp_dockable_drag_motion (GtkWidget      *widget,
-                           GdkDragContext *context,
-                           gint            x,
-                           gint            y,
-                           guint           time)
-{
-  GimpDockable *dockable = GIMP_DOCKABLE (widget);
-
-  if (gimp_paned_box_will_handle_drag (dockable->p->drag_handler,
-                                       widget,
-                                       context,
-                                       x, y,
-                                       time))
-    {
-      gdk_drag_status (context, 0, time);
-      gimp_highlight_widget (widget, FALSE);
-
-      return FALSE;
-    }
-
-  gdk_drag_status (context, GDK_ACTION_MOVE, time);
-  gimp_highlight_widget (widget, TRUE);
-
-  /* Return TRUE so drag_leave() is called */
-  return TRUE;
-}
-
-static gboolean
-gimp_dockable_drag_drop (GtkWidget      *widget,
-                         GdkDragContext *context,
-                         gint            x,
-                         gint            y,
-                         guint           time)
-{
-  GimpDockable *dockable = GIMP_DOCKABLE (widget);
-  gboolean      dropped;
-
-  if (gimp_paned_box_will_handle_drag (dockable->p->drag_handler,
-                                       widget,
-                                       context,
-                                       x, y,
-                                       time))
-    {
-      return FALSE;
-    }
-
-  dropped = gimp_dockbook_drop_dockable (GIMP_DOCKABLE (widget)->p->dockbook,
-                                         gtk_drag_get_source_widget (context));
-
-  gtk_drag_finish (context, dropped, TRUE, time);
-
-  return TRUE;
-}
-
 static void
 gimp_dockable_style_updated (GtkWidget *widget)
 {
@@ -561,38 +473,6 @@ gimp_dockable_get_locked (GimpDockable *dockable)
   return dockable->p->locked;
 }
 
-void
-gimp_dockable_set_drag_pos (GimpDockable *dockable,
-                            gint          drag_x,
-                            gint          drag_y)
-{
-  g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
-
-  dockable->p->drag_x = drag_x;
-  dockable->p->drag_y = drag_y;
-}
-
-void
-gimp_dockable_get_drag_pos (GimpDockable *dockable,
-                            gint         *drag_x,
-                            gint         *drag_y)
-{
-  g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
-
-  if (drag_x != NULL)
-    *drag_x = dockable->p->drag_x;
-  if (drag_y != NULL)
-    *drag_y = dockable->p->drag_y;
-}
-
-GimpPanedBox *
-gimp_dockable_get_drag_handler (GimpDockable *dockable)
-{
-  g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
-
-  return dockable->p->drag_handler;
-}
-
 void
 gimp_dockable_set_locked (GimpDockable *dockable,
                           gboolean      lock)
@@ -638,29 +518,6 @@ gimp_dockable_create_tab_widget (GimpDockable *dockable,
                                                 tab_style, size, FALSE);
 }
 
-GtkWidget *
-gimp_dockable_create_drag_widget (GimpDockable *dockable)
-{
-  GtkWidget *frame;
-  GtkWidget *widget;
-
-  g_return_val_if_fail (GIMP_IS_DOCKABLE (dockable), NULL);
-
-  frame = gtk_frame_new (NULL);
-  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
-
-  widget = gimp_dockable_new_tab_widget_internal (dockable,
-                                                  dockable->p->context,
-                                                  GIMP_TAB_STYLE_ICON_BLURB,
-                                                  GTK_ICON_SIZE_DND,
-                                                  TRUE);
-  gtk_container_set_border_width (GTK_CONTAINER (widget), 6);
-  gtk_container_add (GTK_CONTAINER (frame), widget);
-  gtk_widget_show (widget);
-
-  return frame;
-}
-
 void
 gimp_dockable_set_context (GimpDockable *dockable,
                            GimpContext  *context)
@@ -698,23 +555,6 @@ gimp_dockable_get_menu (GimpDockable  *dockable,
   return NULL;
 }
 
-/**
- * gimp_dockable_set_drag_handler:
- * @dockable:
- * @handler:
- *
- * Set a drag handler that will be asked if it will handle drag events
- * before the dockable handles the event itself.
- **/
-void
-gimp_dockable_set_drag_handler (GimpDockable *dockable,
-                                GimpPanedBox *handler)
-{
-  g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
-
-  dockable->p->drag_handler = handler;
-}
-
 void
 gimp_dockable_detach (GimpDockable *dockable)
 {
diff --git a/app/widgets/gimpdockable.h b/app/widgets/gimpdockable.h
index d778366aa7..4b754dc308 100644
--- a/app/widgets/gimpdockable.h
+++ b/app/widgets/gimpdockable.h
@@ -74,14 +74,6 @@ GtkWidget     * gimp_dockable_get_icon             (GimpDockable   *dockable,
                                                     GtkIconSize     size);
 
 gboolean        gimp_dockable_get_locked           (GimpDockable   *dockable);
-void            gimp_dockable_set_drag_pos         (GimpDockable   *dockable,
-                                                    gint            drag_x,
-                                                    gint            drag_y);
-void            gimp_dockable_get_drag_pos         (GimpDockable   *dockable,
-                                                    gint           *drag_x,
-                                                    gint           *drag_y);
-GimpPanedBox  * gimp_dockable_get_drag_handler     (GimpDockable   *dockable);
-
 void            gimp_dockable_set_locked           (GimpDockable   *dockable,
                                                     gboolean        lock);
 gboolean        gimp_dockable_is_locked            (GimpDockable   *dockable);
@@ -92,14 +84,11 @@ GtkWidget     * gimp_dockable_create_tab_widget    (GimpDockable   *dockable,
                                                     GimpContext    *context,
                                                     GimpTabStyle    tab_style,
                                                     GtkIconSize     size);
-GtkWidget     * gimp_dockable_create_drag_widget   (GimpDockable   *dockable);
 void            gimp_dockable_set_context          (GimpDockable   *dockable,
                                                     GimpContext    *context);
 GimpUIManager * gimp_dockable_get_menu             (GimpDockable   *dockable,
                                                     const gchar   **ui_path,
                                                     gpointer       *popup_data);
-void            gimp_dockable_set_drag_handler     (GimpDockable   *dockable,
-                                                    GimpPanedBox   *drag_handler);
 
 void            gimp_dockable_detach               (GimpDockable   *dockable);
 
diff --git a/app/widgets/gimpdockbook.c b/app/widgets/gimpdockbook.c
index 87cb41e762..bb7212c79e 100644
--- a/app/widgets/gimpdockbook.c
+++ b/app/widgets/gimpdockbook.c
@@ -89,9 +89,6 @@ struct _GimpDockbookPrivate
 static void         gimp_dockbook_dispose               (GObject        *object);
 static void         gimp_dockbook_finalize              (GObject        *object);
 
-static void         gimp_dockbook_drag_leave            (GtkWidget      *widget,
-                                                         GdkDragContext *context,
-                                                         guint           time);
 static gboolean     gimp_dockbook_drag_motion           (GtkWidget      *widget,
                                                          GdkDragContext *context,
                                                          gint            x,
@@ -104,43 +101,25 @@ static gboolean     gimp_dockbook_drag_drop             (GtkWidget      *widget,
                                                          guint           time);
 static gboolean     gimp_dockbook_popup_menu            (GtkWidget      *widget);
 
+static GtkNotebook *gimp_dockbook_create_window         (GtkNotebook    *notebook,
+                                                         GtkWidget      *page,
+                                                         gint            x,
+                                                         gint            y);
+static void         gimp_dockbook_page_added            (GtkNotebook    *notebook,
+                                                         GtkWidget      *child,
+                                                         guint           page_num);
+static void         gimp_dockbook_page_removed          (GtkNotebook    *notebook,
+                                                         GtkWidget      *child,
+                                                         guint           page_num);
+static void         gimp_dockbook_page_reordered        (GtkNotebook    *notebook,
+                                                         GtkWidget      *child,
+                                                         guint           page_num);
+
 static gboolean     gimp_dockbook_menu_button_press     (GimpDockbook   *dockbook,
                                                          GdkEventButton *bevent,
                                                          GtkWidget      *button);
 static gboolean     gimp_dockbook_show_menu             (GimpDockbook   *dockbook);
 static void         gimp_dockbook_menu_end              (GimpDockable   *dockable);
-static void         gimp_dockbook_dockable_added        (GimpDockbook   *dockbook,
-                                                         GimpDockable   *dockable);
-static void         gimp_dockbook_dockable_removed      (GimpDockbook   *dockbook,
-                                                         GimpDockable   *dockable);
-static void         gimp_dockbook_tab_drag_source_setup (GtkWidget      *widget,
-                                                         GimpDockable   *dockable);
-static void         gimp_dockbook_tab_drag_begin        (GtkWidget      *widget,
-                                                         GdkDragContext *context,
-                                                         GimpDockable   *dockable);
-static void         gimp_dockbook_tab_drag_end          (GtkWidget      *widget,
-                                                         GdkDragContext *context,
-                                                         GimpDockable   *dockable);
-static void         gimp_dockbook_tab_drag_leave        (GtkWidget      *widget,
-                                                         GdkDragContext *context,
-                                                         guint           time,
-                                                         GimpDockable   *dockable);
-static gboolean     gimp_dockbook_tab_drag_motion       (GtkWidget      *widget,
-                                                         GdkDragContext *context,
-                                                         gint            x,
-                                                         gint            y,
-                                                         guint           time,
-                                                         GimpDockable   *dockable);
-static gboolean     gimp_dockbook_tab_drag_drop         (GtkWidget      *widget,
-                                                         GdkDragContext *context,
-                                                         gint            x,
-                                                         gint            y,
-                                                         guint           time);
-
-static void         gimp_dockbook_add_tab_timeout       (GimpDockbook   *dockbook,
-                                                         GimpDockable   *dockable);
-static void         gimp_dockbook_remove_tab_timeout    (GimpDockbook   *dockbook);
-static gboolean     gimp_dockbook_tab_timeout           (GimpDockbook   *dockbook);
 static void         gimp_dockbook_tab_locked_notify     (GimpDockable   *dockable,
                                                          GParamSpec     *pspec,
                                                          GimpDockbook   *dockbook);
@@ -154,14 +133,15 @@ G_DEFINE_TYPE (GimpDockbook, gimp_dockbook, GTK_TYPE_NOTEBOOK)
 
 static guint dockbook_signals[LAST_SIGNAL] = { 0 };
 
-static const GtkTargetEntry dialog_target_table[] = { GIMP_TARGET_DIALOG };
+static const GtkTargetEntry dialog_target_table[] = { GIMP_TARGET_NOTEBOOK_TAB };
 
 
 static void
 gimp_dockbook_class_init (GimpDockbookClass *klass)
 {
-  GObjectClass   *object_class = G_OBJECT_CLASS (klass);
-  GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+  GObjectClass     *object_class   = G_OBJECT_CLASS (klass);
+  GtkWidgetClass   *widget_class   = GTK_WIDGET_CLASS (klass);
+  GtkNotebookClass *notebook_class = GTK_NOTEBOOK_CLASS (klass);
 
   dockbook_signals[DOCKABLE_ADDED] =
     g_signal_new ("dockable-added",
@@ -193,17 +173,21 @@ gimp_dockbook_class_init (GimpDockbookClass *klass)
                   G_TYPE_NONE, 1,
                   GIMP_TYPE_DOCKABLE);
 
-  object_class->dispose     = gimp_dockbook_dispose;
-  object_class->finalize    = gimp_dockbook_finalize;
+  object_class->dispose          = gimp_dockbook_dispose;
+  object_class->finalize         = gimp_dockbook_finalize;
 
-  widget_class->drag_leave    = gimp_dockbook_drag_leave;
-  widget_class->drag_motion   = gimp_dockbook_drag_motion;
-  widget_class->drag_drop     = gimp_dockbook_drag_drop;
-  widget_class->popup_menu    = gimp_dockbook_popup_menu;
+  widget_class->drag_motion      = gimp_dockbook_drag_motion;
+  widget_class->drag_drop        = gimp_dockbook_drag_drop;
+  widget_class->popup_menu       = gimp_dockbook_popup_menu;
 
-  klass->dockable_added     = gimp_dockbook_dockable_added;
-  klass->dockable_removed   = gimp_dockbook_dockable_removed;
-  klass->dockable_reordered = NULL;
+  notebook_class->create_window  = gimp_dockbook_create_window;
+  notebook_class->page_added     = gimp_dockbook_page_added;
+  notebook_class->page_removed   = gimp_dockbook_page_removed;
+  notebook_class->page_reordered = gimp_dockbook_page_reordered;
+
+  klass->dockable_added          = NULL;
+  klass->dockable_removed        = NULL;
+  klass->dockable_reordered      = NULL;
 
   gtk_widget_class_install_style_property (widget_class,
                                            g_param_spec_enum ("tab-icon-size",
@@ -230,6 +214,7 @@ gimp_dockbook_init (GimpDockbook *dockbook)
   gtk_notebook_set_scrollable (notebook, TRUE);
   gtk_notebook_set_show_border (notebook, FALSE);
   gtk_notebook_set_show_tabs (notebook, TRUE);
+  gtk_notebook_set_group_name (notebook, "gimp-dockbook");
 
   gtk_drag_dest_set (GTK_WIDGET (dockbook),
                      0,
@@ -269,8 +254,6 @@ gimp_dockbook_dispose (GObject *object)
   GList        *children;
   GList        *list;
 
-  gimp_dockbook_remove_tab_timeout (dockbook);
-
   children = gtk_container_get_children (GTK_CONTAINER (object));
 
   for (list = children; list; list = g_list_next (list))
@@ -298,14 +281,6 @@ gimp_dockbook_finalize (GObject *object)
   G_OBJECT_CLASS (parent_class)->finalize (object);
 }
 
-static void
-gimp_dockbook_drag_leave (GtkWidget      *widget,
-                          GdkDragContext *context,
-                          guint           time)
-{
-  gimp_highlight_widget (widget, FALSE);
-}
-
 static gboolean
 gimp_dockbook_drag_motion (GtkWidget      *widget,
                            GdkDragContext *context,
@@ -322,16 +297,12 @@ gimp_dockbook_drag_motion (GtkWidget      *widget,
                                        time))
     {
       gdk_drag_status (context, 0, time);
-      gimp_highlight_widget (widget, FALSE);
 
       return FALSE;
     }
 
-  gdk_drag_status (context, GDK_ACTION_MOVE, time);
-  gimp_highlight_widget (widget, TRUE);
-
-  /* Return TRUE so drag_leave() is called */
-  return TRUE;
+  return GTK_WIDGET_CLASS (parent_class)->drag_motion (widget, context,
+                                                       x, y, time);
 }
 
 static gboolean
@@ -342,7 +313,6 @@ gimp_dockbook_drag_drop (GtkWidget      *widget,
                          guint           time)
 {
   GimpDockbook *dockbook = GIMP_DOCKBOOK (widget);
-  gboolean      dropped;
 
   if (gimp_paned_box_will_handle_drag (dockbook->p->drag_handler,
                                        widget,
@@ -353,12 +323,24 @@ gimp_dockbook_drag_drop (GtkWidget      *widget,
       return FALSE;
     }
 
-  dropped = gimp_dockbook_drop_dockable (dockbook,
-                                         gtk_drag_get_source_widget (context));
+  if (widget == gtk_drag_get_source_widget (context))
+    {
+      GList *children   = gtk_container_get_children (GTK_CONTAINER (widget));
+      gint   n_children = g_list_length (children);
+
+      g_list_free (children);
 
-  gtk_drag_finish (context, dropped, TRUE, time);
+      /* we dragged the only tab, and want to drop it back on the same
+       * notebook, this would remove and add the page, causing the
+       * dockbook to be destroyed in the process because it becomes
+       * empty
+       */
+      if (n_children == 1)
+        return FALSE;
+    }
 
-  return TRUE;
+  return GTK_WIDGET_CLASS (parent_class)->drag_drop (widget, context,
+                                                     x, y, time);
 }
 
 static gboolean
@@ -367,6 +349,131 @@ gimp_dockbook_popup_menu (GtkWidget *widget)
   return gimp_dockbook_show_menu (GIMP_DOCKBOOK (widget));
 }
 
+static GtkNotebook *
+gimp_dockbook_create_window (GtkNotebook *notebook,
+                             GtkWidget   *page,
+                             gint         x,
+                             gint         y)
+{
+  GimpDockbook      *dockbook = GIMP_DOCKBOOK (notebook);
+  GimpDockable      *dockable = GIMP_DOCKABLE (page);
+  GimpDialogFactory *dialog_factory;
+  GimpMenuFactory   *menu_factory;
+  GimpDockWindow    *src_dock_window;
+  GimpDock          *src_dock;
+  GtkWidget         *new_dock;
+  GimpDockWindow    *new_dock_window;
+  GtkWidget         *new_dockbook;
+
+  src_dock        = gimp_dockbook_get_dock (dockbook);
+  src_dock_window = gimp_dock_window_from_dock (src_dock);
+
+  dialog_factory = gimp_dock_get_dialog_factory (src_dock);
+  menu_factory   = gimp_dialog_factory_get_menu_factory (dialog_factory);
+
+  new_dock = gimp_dock_with_window_new (dialog_factory,
+                                        gimp_widget_get_monitor (page),
+                                        FALSE);
+
+  new_dock_window = gimp_dock_window_from_dock (GIMP_DOCK (new_dock));
+  gtk_window_set_position (GTK_WINDOW (new_dock_window), GTK_WIN_POS_MOUSE);
+  if (src_dock_window)
+    gimp_dock_window_setup (new_dock_window, src_dock_window);
+
+  new_dockbook = gimp_dockbook_new (menu_factory);
+
+  gimp_dock_add_book (GIMP_DOCK (new_dock), GIMP_DOCKBOOK (new_dockbook), 0);
+
+  gtk_widget_show (GTK_WIDGET (new_dock_window));
+  gtk_widget_show (new_dock);
+
+  return GTK_NOTEBOOK (new_dockbook);
+}
+
+static void
+gimp_dockbook_page_added (GtkNotebook *notebook,
+                          GtkWidget   *child,
+                          guint        page_num)
+{
+  GimpDockbook *dockbook = GIMP_DOCKBOOK (notebook);
+  GimpDockable *dockable = GIMP_DOCKABLE (child);
+  GtkWidget    *tab_widget;
+  GtkWidget    *menu_widget;
+
+  GIMP_LOG (DND, "GimpDockable %p added to GimpDockbook %p",
+            dockable, dockbook);
+
+  tab_widget = gimp_dockbook_create_tab_widget (dockbook, dockable);
+
+  /* For the notebook right-click menu, always use the icon style */
+  menu_widget =
+    gimp_dockable_create_tab_widget (dockable,
+                                     gimp_dock_get_context (dockbook->p->dock),
+                                     GIMP_TAB_STYLE_ICON_BLURB,
+                                     GTK_ICON_SIZE_MENU);
+
+  gtk_notebook_set_tab_label (notebook, child, tab_widget);
+  gtk_notebook_set_menu_label (notebook, child, menu_widget);
+
+  if (! gimp_dockable_is_locked (dockable))
+    {
+      gtk_notebook_set_tab_reorderable (notebook, child, TRUE);
+      gtk_notebook_set_tab_detachable (notebook, child, TRUE);
+    }
+
+  gimp_dockable_set_dockbook (dockable, dockbook);
+
+  gimp_dockable_set_context (dockable,
+                             gimp_dock_get_context (dockbook->p->dock));
+
+  g_signal_connect (dockable, "notify::locked",
+                    G_CALLBACK (gimp_dockbook_tab_locked_notify),
+                    dockbook);
+
+  gtk_notebook_set_current_page (notebook, page_num);
+
+  g_signal_emit (dockbook, dockbook_signals[DOCKABLE_ADDED], 0, dockable);
+}
+
+static void
+gimp_dockbook_page_removed (GtkNotebook *notebook,
+                            GtkWidget   *child,
+                            guint        page_num)
+{
+  GimpDockbook *dockbook = GIMP_DOCKBOOK (notebook);
+  GimpDockable *dockable = GIMP_DOCKABLE (child);
+
+  GIMP_LOG (DND, "GimpDockable removed %p from GimpDockbook %p",
+            dockable, dockbook);
+
+  g_signal_handlers_disconnect_by_func (dockable,
+                                        G_CALLBACK (gimp_dockbook_tab_locked_notify),
+                                        dockbook);
+
+  gimp_dockable_set_dockbook (dockable, NULL);
+
+  gimp_dockable_set_context (dockable, NULL);
+
+  g_signal_emit (dockbook, dockbook_signals[DOCKABLE_REMOVED], 0, dockable);
+
+  if (dockbook->p->dock)
+    {
+      GList *children = gtk_container_get_children (GTK_CONTAINER (dockbook));
+
+      if (! children)
+        gimp_dock_remove_book (dockbook->p->dock, dockbook);
+
+      g_list_free (children);
+    }
+}
+
+static void
+gimp_dockbook_page_reordered (GtkNotebook *notebook,
+                              GtkWidget   *child,
+                              guint        page_num)
+{
+}
+
 static gboolean
 gimp_dockbook_menu_button_press (GimpDockbook   *dockbook,
                                  GdkEventButton *bevent,
@@ -530,20 +637,8 @@ gimp_dockbook_menu_end (GimpDockable *dockable)
   g_object_unref (dockable);
 }
 
-static void
-gimp_dockbook_dockable_added (GimpDockbook *dockbook,
-                              GimpDockable *dockable)
-{
-  gtk_notebook_set_current_page (GTK_NOTEBOOK (dockbook),
-                                 gtk_notebook_page_num (GTK_NOTEBOOK (dockbook),
-                                                        GTK_WIDGET (dockable)));
-}
 
-static void
-gimp_dockbook_dockable_removed (GimpDockbook *dockbook,
-                                GimpDockable *dockable)
-{
-}
+/*  public functions  */
 
 GtkWidget *
 gimp_dockbook_new (GimpMenuFactory *menu_factory)
@@ -595,9 +690,6 @@ gimp_dockbook_add (GimpDockbook *dockbook,
                    GimpDockable *dockable,
                    gint          position)
 {
-  GtkWidget *tab_widget;
-  GtkWidget *menu_widget;
-
   g_return_if_fail (GIMP_IS_DOCKBOOK (dockbook));
   g_return_if_fail (dockbook->p->dock != NULL);
   g_return_if_fail (GIMP_IS_DOCKABLE (dockable));
@@ -605,48 +697,21 @@ gimp_dockbook_add (GimpDockbook *dockbook,
 
   GIMP_LOG (DND, "Adding GimpDockable %p to GimpDockbook %p", dockable, dockbook);
 
-  tab_widget = gimp_dockbook_create_tab_widget (dockbook, dockable);
-
-  g_return_if_fail (GTK_IS_WIDGET (tab_widget));
-
-  /* For the notebook right-click menu, always use the icon style */
-  menu_widget =
-    gimp_dockable_create_tab_widget (dockable,
-                                     gimp_dock_get_context (dockbook->p->dock),
-                                     GIMP_TAB_STYLE_ICON_BLURB,
-                                     GTK_ICON_SIZE_MENU);
-
-  g_return_if_fail (GTK_IS_WIDGET (menu_widget));
-
-  gimp_dockable_set_drag_handler (dockable, dockbook->p->drag_handler);
-
   if (position == -1)
     {
-      gtk_notebook_append_page_menu (GTK_NOTEBOOK (dockbook),
-                                     GTK_WIDGET (dockable),
-                                     tab_widget,
-                                     menu_widget);
+      gtk_notebook_append_page (GTK_NOTEBOOK (dockbook),
+                                GTK_WIDGET (dockable),
+                                NULL);
     }
   else
     {
-      gtk_notebook_insert_page_menu (GTK_NOTEBOOK (dockbook),
-                                     GTK_WIDGET (dockable),
-                                     tab_widget,
-                                     menu_widget,
-                                     position);
+      gtk_notebook_insert_page (GTK_NOTEBOOK (dockbook),
+                                GTK_WIDGET (dockable),
+                                NULL,
+                                position);
     }
 
   gtk_widget_show (GTK_WIDGET (dockable));
-
-  gimp_dockable_set_dockbook (dockable, dockbook);
-
-  gimp_dockable_set_context (dockable, gimp_dock_get_context (dockbook->p->dock));
-
-  g_signal_connect (dockable, "notify::locked",
-                    G_CALLBACK (gimp_dockbook_tab_locked_notify),
-                    dockbook);
-
-  g_signal_emit (dockbook, dockbook_signals[DOCKABLE_ADDED], 0, dockable);
 }
 
 /**
@@ -704,36 +769,7 @@ gimp_dockbook_remove (GimpDockbook *dockbook,
 
   GIMP_LOG (DND, "Removing GimpDockable %p from GimpDockbook %p", dockable, dockbook);
 
-  gimp_dockable_set_drag_handler (dockable, NULL);
-
-  g_object_ref (dockable);
-
-  g_signal_handlers_disconnect_by_func (dockable,
-                                        G_CALLBACK (gimp_dockbook_tab_locked_notify),
-                                        dockbook);
-
-  if (dockbook->p->tab_hover_dockable == dockable)
-    gimp_dockbook_remove_tab_timeout (dockbook);
-
-  gimp_dockable_set_dockbook (dockable, NULL);
-
-  gimp_dockable_set_context (dockable, NULL);
-
   gtk_container_remove (GTK_CONTAINER (dockbook), GTK_WIDGET (dockable));
-
-  g_signal_emit (dockbook, dockbook_signals[DOCKABLE_REMOVED], 0, dockable);
-
-  g_object_unref (dockable);
-
-  if (dockbook->p->dock)
-    {
-      GList *children = gtk_container_get_children (GTK_CONTAINER (dockbook));
-
-      if (! children)
-        gimp_dock_remove_book (dockbook->p->dock, dockbook);
-
-      g_list_free (children);
-    }
 }
 
 /**
@@ -778,7 +814,7 @@ gimp_dockbook_create_tab_widget (GimpDockbook *dockbook,
                                      gimp_dockable_get_tab_style (dockable),
                                      tab_size);
 
-  if (! GIMP_IS_VIEW (tab_widget))
+  if (GIMP_IS_VIEW (tab_widget))
     {
       GtkWidget *event_box;
 
@@ -841,76 +877,9 @@ gimp_dockbook_create_tab_widget (GimpDockbook *dockbook,
                              gimp_dockable_get_blurb (dockable),
                              gimp_dockable_get_help_id (dockable));
 
-  g_object_set_data (G_OBJECT (tab_widget), "gimp-dockable", dockable);
-
-  gimp_dockbook_tab_drag_source_setup (tab_widget, dockable);
-
-  g_signal_connect_object (tab_widget, "drag-begin",
-                           G_CALLBACK (gimp_dockbook_tab_drag_begin),
-                           dockable, 0);
-  g_signal_connect_object (tab_widget, "drag-end",
-                           G_CALLBACK (gimp_dockbook_tab_drag_end),
-                           dockable, 0);
-
-  g_signal_connect_object (dockable, "drag-begin",
-                           G_CALLBACK (gimp_dockbook_tab_drag_begin),
-                           dockable, 0);
-  g_signal_connect_object (dockable, "drag-end",
-                           G_CALLBACK (gimp_dockbook_tab_drag_end),
-                           dockable, 0);
-
-  gtk_drag_dest_set (tab_widget,
-                     0,
-                     dialog_target_table, G_N_ELEMENTS (dialog_target_table),
-                     GDK_ACTION_MOVE);
-  g_signal_connect_object (tab_widget, "drag-leave",
-                           G_CALLBACK (gimp_dockbook_tab_drag_leave),
-                           dockable, 0);
-  g_signal_connect_object (tab_widget, "drag-motion",
-                           G_CALLBACK (gimp_dockbook_tab_drag_motion),
-                           dockable, 0);
-  g_signal_connect_object (tab_widget, "drag-drop",
-                           G_CALLBACK (gimp_dockbook_tab_drag_drop),
-                           dockbook, 0);
-
   return tab_widget;
 }
 
-gboolean
-gimp_dockbook_drop_dockable (GimpDockbook *dockbook,
-                             GtkWidget    *drag_source)
-{
-  g_return_val_if_fail (GIMP_IS_DOCKBOOK (dockbook), FALSE);
-
-  if (drag_source)
-    {
-      GimpDockable *dockable =
-        gimp_dockbook_drag_source_to_dockable (drag_source);
-
-      if (dockable)
-        {
-          if (gimp_dockable_get_dockbook (dockable) == dockbook)
-            {
-              gtk_notebook_reorder_child (GTK_NOTEBOOK (dockbook),
-                                          GTK_WIDGET (dockable), -1);
-            }
-          else
-            {
-              g_object_ref (dockable);
-
-              gimp_dockbook_remove (gimp_dockable_get_dockbook (dockable), dockable);
-              gimp_dockbook_add (dockbook, dockable, -1);
-
-              g_object_unref (dockable);
-            }
-
-          return TRUE;
-        }
-    }
-
-  return FALSE;
-}
-
 /**
  * gimp_dockable_set_drag_handler:
  * @dockable:
@@ -928,317 +897,20 @@ gimp_dockbook_set_drag_handler (GimpDockbook *dockbook,
   dockbook->p->drag_handler = drag_handler;
 }
 
-/**
- * gimp_dockbook_drag_source_to_dockable:
- * @drag_source: A drag-and-drop source widget
- *
- * Gets the dockable associated with a drag-and-drop source. If
- * successful, the function will also cleanup the dockable.
- *
- * Returns: The dockable
- **/
-GimpDockable *
-gimp_dockbook_drag_source_to_dockable (GtkWidget *drag_source)
-{
-  GimpDockable *dockable = NULL;
-
-  if (GIMP_IS_DOCKABLE (drag_source))
-    dockable = GIMP_DOCKABLE (drag_source);
-  else
-    dockable = g_object_get_data (G_OBJECT (drag_source),
-                                  "gimp-dockable");
 
-  if (dockable)
-    g_object_set_data (G_OBJECT (dockable),
-                       "gimp-dock-drag-widget", NULL);
-
-  return dockable;
-}
-
-/*  tab DND source side  */
-
-static void
-gimp_dockbook_tab_drag_source_setup (GtkWidget    *widget,
-                                     GimpDockable *dockable)
-{
-  if (gimp_dockable_is_locked (dockable))
-    {
-      if (widget)
-        gtk_drag_source_unset (widget);
-
-      gtk_drag_source_unset (GTK_WIDGET (dockable));
-    }
-  else
-    {
-      if (widget)
-        gtk_drag_source_set (widget,
-                             GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
-                             dialog_target_table,
-                             G_N_ELEMENTS (dialog_target_table),
-                             GDK_ACTION_MOVE);
-
-      gtk_drag_source_set (GTK_WIDGET (dockable),
-                           GDK_BUTTON1_MASK | GDK_BUTTON2_MASK,
-                           dialog_target_table,
-                           G_N_ELEMENTS (dialog_target_table),
-                           GDK_ACTION_MOVE);
-    }
-}
-
-static void
-gimp_dockbook_tab_drag_begin (GtkWidget      *widget,
-                              GdkDragContext *context,
-                              GimpDockable   *dockable)
-{
-  GtkAllocation   allocation;
-  GtkWidget      *window;
-  GtkWidget      *view;
-  GtkRequisition  requisition;
-  gint            drag_x;
-  gint            drag_y;
-
-  gtk_widget_get_allocation (widget, &allocation);
-
-  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), gtk_widget_get_screen (widget));
-
-  view = gimp_dockable_create_drag_widget (dockable);
-  gtk_container_add (GTK_CONTAINER (window), view);
-  gtk_widget_show (view);
-
-  gtk_widget_get_preferred_size (view, &requisition, NULL);
-
-  if (requisition.width < allocation.width)
-    gtk_widget_set_size_request (view, allocation.width, -1);
-
-  gtk_widget_show (window);
-
-  g_object_set_data_full (G_OBJECT (dockable), "gimp-dock-drag-widget",
-                          window,
-                          (GDestroyNotify) gtk_widget_destroy);
-
-  gimp_dockable_get_drag_pos (dockable, &drag_x, &drag_y);
-  gtk_drag_set_icon_widget (context, window, drag_x, drag_y);
-
-  /*
-   * Set the source dockable insensitive to give a visual clue that
-   * it's the dockable that's being dragged around
-   */
-  gtk_widget_set_sensitive (GTK_WIDGET (dockable), FALSE);
-}
-
-static void
-gimp_dockbook_tab_drag_end (GtkWidget      *widget,
-                            GdkDragContext *context,
-                            GimpDockable   *dockable)
-{
-  GtkWidget *drag_widget;
-
-  drag_widget = g_object_get_data (G_OBJECT (dockable),
-                                   "gimp-dock-drag-widget");
-
-  /*  finding the drag_widget means the drop was not successful, so
-   *  pop up a new dock and move the dockable there
-   */
-  if (drag_widget)
-    {
-      g_object_set_data (G_OBJECT (dockable), "gimp-dock-drag-widget", NULL);
-      gimp_dockable_detach (dockable);
-    }
-
-  gimp_dockable_set_drag_pos (dockable,
-                              GIMP_DOCKABLE_DRAG_OFFSET,
-                              GIMP_DOCKABLE_DRAG_OFFSET);
-  gtk_widget_set_sensitive (GTK_WIDGET (dockable), TRUE);
-}
-
-
-/*  tab DND target side  */
-
-static void
-gimp_dockbook_tab_drag_leave (GtkWidget      *widget,
-                              GdkDragContext *context,
-                              guint           time,
-                              GimpDockable   *dockable)
-{
-  GimpDockbook *dockbook = gimp_dockable_get_dockbook (dockable);
-
-  gimp_dockbook_remove_tab_timeout (dockbook);
-
-  gimp_highlight_widget (widget, FALSE);
-}
-
-static gboolean
-gimp_dockbook_tab_drag_motion (GtkWidget      *widget,
-                               GdkDragContext *context,
-                               gint            x,
-                               gint            y,
-                               guint           time,
-                               GimpDockable   *dockable)
-{
-  GimpDockbook  *dockbook = gimp_dockable_get_dockbook (dockable);
-  GtkTargetList *target_list;
-  GdkAtom        target_atom;
-  gboolean       handle;
-
-  if (gimp_paned_box_will_handle_drag (dockbook->p->drag_handler,
-                                       widget,
-                                       context,
-                                       x, y,
-                                       time))
-    {
-      gdk_drag_status (context, 0, time);
-      gimp_highlight_widget (widget, FALSE);
-
-      return FALSE;
-    }
-
-  if (! dockbook->p->tab_hover_timeout ||
-      dockbook->p->tab_hover_dockable != dockable)
-    {
-      gint page_num;
-
-      gimp_dockbook_remove_tab_timeout (dockbook);
-
-      page_num = gtk_notebook_page_num (GTK_NOTEBOOK (dockbook),
-                                        GTK_WIDGET (dockable));
-
-      if (page_num != gtk_notebook_get_current_page (GTK_NOTEBOOK (dockbook)))
-        gimp_dockbook_add_tab_timeout (dockbook, dockable);
-    }
-
-  target_list = gtk_drag_dest_get_target_list (widget);
-  target_atom = gtk_drag_dest_find_target (widget, context, target_list);
-
-  handle = gtk_target_list_find (target_list, target_atom, NULL);
-
-  gdk_drag_status (context, handle ? GDK_ACTION_MOVE : 0, time);
-  gimp_highlight_widget (widget, handle);
-
-  /* Return TRUE so drag_leave() is called */
-  return TRUE;
-}
-
-static gboolean
-gimp_dockbook_tab_drag_drop (GtkWidget      *widget,
-                             GdkDragContext *context,
-                             gint            x,
-                             gint            y,
-                             guint           time)
-{
-  GimpDockable *dest_dockable;
-  GtkWidget    *source;
-  gboolean      dropped = FALSE;
-
-  dest_dockable = g_object_get_data (G_OBJECT (widget), "gimp-dockable");
-
-  source = gtk_drag_get_source_widget (context);
-
-  if (gimp_paned_box_will_handle_drag (gimp_dockable_get_drag_handler (dest_dockable),
-                                       widget,
-                                       context,
-                                       x, y,
-                                       time))
-    {
-      return FALSE;
-    }
-
-  if (dest_dockable && source)
-    {
-      GimpDockable *src_dockable =
-        gimp_dockbook_drag_source_to_dockable (source);
-
-      if (src_dockable)
-        {
-          gint dest_index;
-
-          dest_index =
-            gtk_notebook_page_num (GTK_NOTEBOOK (gimp_dockable_get_dockbook (dest_dockable)),
-                                   GTK_WIDGET (dest_dockable));
-
-          if (gimp_dockable_get_dockbook (src_dockable) !=
-              gimp_dockable_get_dockbook (dest_dockable))
-            {
-              g_object_ref (src_dockable);
-
-              gimp_dockbook_remove (gimp_dockable_get_dockbook (src_dockable), src_dockable);
-              gimp_dockbook_add (gimp_dockable_get_dockbook (dest_dockable), src_dockable,
-                                 dest_index);
-
-              g_object_unref (src_dockable);
-
-              dropped = TRUE;
-            }
-          else if (src_dockable != dest_dockable)
-            {
-              gtk_notebook_reorder_child (GTK_NOTEBOOK (gimp_dockable_get_dockbook (src_dockable)),
-                                          GTK_WIDGET (src_dockable),
-                                          dest_index);
-
-              g_signal_emit (gimp_dockable_get_dockbook (src_dockable),
-                             dockbook_signals[DOCKABLE_REORDERED], 0,
-                             src_dockable);
-
-              dropped = TRUE;
-            }
-        }
-    }
-
-  gtk_drag_finish (context, dropped, TRUE, time);
-
-  return TRUE;
-}
-
-static void
-gimp_dockbook_add_tab_timeout (GimpDockbook *dockbook,
-                               GimpDockable *dockable)
-{
-  dockbook->p->tab_hover_timeout =
-    g_timeout_add (TAB_HOVER_TIMEOUT,
-                   (GSourceFunc) gimp_dockbook_tab_timeout,
-                   dockbook);
-
-  dockbook->p->tab_hover_dockable = dockable;
-}
-
-static void
-gimp_dockbook_remove_tab_timeout (GimpDockbook *dockbook)
-{
-  if (dockbook->p->tab_hover_timeout)
-    {
-      g_source_remove (dockbook->p->tab_hover_timeout);
-      dockbook->p->tab_hover_timeout  = 0;
-      dockbook->p->tab_hover_dockable = NULL;
-    }
-}
-
-static gboolean
-gimp_dockbook_tab_timeout (GimpDockbook *dockbook)
-{
-  gint page_num;
-
-  page_num = gtk_notebook_page_num (GTK_NOTEBOOK (dockbook),
-                                    GTK_WIDGET (dockbook->p->tab_hover_dockable));
-  gtk_notebook_set_current_page (GTK_NOTEBOOK (dockbook), page_num);
-
-  dockbook->p->tab_hover_timeout  = 0;
-  dockbook->p->tab_hover_dockable = NULL;
-
-  return FALSE;
-}
+/*  private functions  */
 
 static void
 gimp_dockbook_tab_locked_notify (GimpDockable *dockable,
                                  GParamSpec   *pspec,
                                  GimpDockbook *dockbook)
 {
-  GtkWidget *tab_widget;
-
-  tab_widget = gtk_notebook_get_tab_label (GTK_NOTEBOOK (dockbook),
-                                           GTK_WIDGET (dockable));
+  gboolean locked = gimp_dockable_is_locked (dockable);
 
-  gimp_dockbook_tab_drag_source_setup (tab_widget, dockable);
+  gtk_notebook_set_tab_reorderable (GTK_NOTEBOOK (dockbook),
+                                    GTK_WIDGET (dockable), ! locked);
+  gtk_notebook_set_tab_detachable (GTK_NOTEBOOK (dockbook),
+                                   GTK_WIDGET (dockable), ! locked);
 }
 
 static void
diff --git a/app/widgets/gimpdockbook.h b/app/widgets/gimpdockbook.h
index 1bcc41d728..7c0f26e11b 100644
--- a/app/widgets/gimpdockbook.h
+++ b/app/widgets/gimpdockbook.h
@@ -77,11 +77,8 @@ void            gimp_dockbook_update_with_context       (GimpDockbook    *dockbo
                                                          GimpContext     *context);
 GtkWidget    *  gimp_dockbook_create_tab_widget         (GimpDockbook    *dockbook,
                                                          GimpDockable    *dockable);
-gboolean        gimp_dockbook_drop_dockable             (GimpDockbook    *dockbook,
-                                                         GtkWidget       *drag_source);
 void            gimp_dockbook_set_drag_handler          (GimpDockbook    *dockbook,
                                                          GimpPanedBox    *drag_handler);
-GimpDockable *  gimp_dockbook_drag_source_to_dockable   (GtkWidget       *drag_source);
 
 
 #endif /* __GIMP_DOCKBOOK_H__ */
diff --git a/app/widgets/gimpdockcolumns.c b/app/widgets/gimpdockcolumns.c
index f369d8a7c1..e22eb63e12 100644
--- a/app/widgets/gimpdockcolumns.c
+++ b/app/widgets/gimpdockcolumns.c
@@ -79,7 +79,8 @@ static void      gimp_dock_columns_get_property      (GObject         *object,
                                                       guint            property_id,
                                                       GValue          *value,
                                                       GParamSpec      *pspec);
-static gboolean  gimp_dock_columns_dropped_cb        (GtkWidget       *source,
+static gboolean  gimp_dock_columns_dropped_cb        (GtkWidget       *notebook,
+                                                      GtkWidget       *child,
                                                       gint             insert_index,
                                                       gpointer         data);
 static void      gimp_dock_columns_real_dock_added   (GimpDockColumns *dock_columns,
@@ -286,29 +287,27 @@ gimp_dock_columns_get_property (GObject    *object,
 }
 
 static gboolean
-gimp_dock_columns_dropped_cb (GtkWidget *source,
+gimp_dock_columns_dropped_cb (GtkWidget *notebook,
+                              GtkWidget *child,
                               gint       insert_index,
                               gpointer   data)
 {
   GimpDockColumns *dock_columns = GIMP_DOCK_COLUMNS (data);
-  GimpDockable    *dockable     = gimp_dockbook_drag_source_to_dockable (source);
-  GtkWidget       *dockbook     = NULL;
-
-  if (! dockable)
-    return FALSE;
+  GimpDockable    *dockable     = GIMP_DOCKABLE (child);
+  GtkWidget       *new_dockbook = NULL;
 
   /* Create a new dock (including a new dockbook) */
   gimp_dock_columns_prepare_dockbook (dock_columns,
                                       insert_index,
-                                      &dockbook);
+                                      &new_dockbook);
 
   /* Move the dockable to the new dockbook */
-  g_object_ref (dockbook);
+  g_object_ref (new_dockbook);
   g_object_ref (dockable);
-  gimp_dockbook_remove (gimp_dockable_get_dockbook (dockable), dockable);
-  gimp_dockbook_add (GIMP_DOCKBOOK (dockbook), dockable, -1);
+  gtk_notebook_detach_tab (GTK_NOTEBOOK (notebook), child);
+  gimp_dockbook_add (GIMP_DOCKBOOK (new_dockbook), dockable, -1);
   g_object_unref (dockable);
-  g_object_unref (dockbook);
+  g_object_unref (new_dockbook);
 
   return TRUE;
 }
diff --git a/app/widgets/gimppanedbox.c b/app/widgets/gimppanedbox.c
index 954fb8e903..3e6b1e8ceb 100644
--- a/app/widgets/gimppanedbox.c
+++ b/app/widgets/gimppanedbox.c
@@ -51,7 +51,7 @@
  * order to be inserted and get space on their own (rather than
  * inserted among others and sharing space)
  */
-#define DROP_AREA_SIZE            6
+#define DROP_AREA_SIZE            12
 
 #define INSERT_INDEX_UNUSED       G_MININT
 
@@ -98,6 +98,13 @@ static gboolean  gimp_paned_box_drag_drop               (GtkWidget      *widget,
                                                          gint            x,
                                                          gint            y,
                                                          guint           time);
+static void      gimp_paned_box_drag_data_received      (GtkWidget      *widget,
+                                                         GdkDragContext *context,
+                                                         gint            x,
+                                                         gint            y,
+                                                         GtkSelectionData *data,
+                                                         guint           info,
+                                                         guint           time);
 static void      gimp_paned_box_set_widget_drag_handler (GtkWidget      *widget,
                                                          GimpPanedBox   *handler);
 static gint      gimp_paned_box_get_drop_area_size      (GimpPanedBox   *paned_box);
@@ -108,7 +115,7 @@ G_DEFINE_TYPE (GimpPanedBox, gimp_paned_box, GTK_TYPE_BOX)
 
 #define parent_class gimp_paned_box_parent_class
 
-static const GtkTargetEntry dialog_target_table[] = { GIMP_TARGET_DIALOG };
+static const GtkTargetEntry dialog_target_table[] = { GIMP_TARGET_NOTEBOOK_TAB };
 
 
 static void
@@ -117,11 +124,12 @@ gimp_paned_box_class_init (GimpPanedBoxClass *klass)
   GObjectClass   *object_class = G_OBJECT_CLASS (klass);
   GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
 
-  object_class->dispose     = gimp_paned_box_dispose;
+  object_class->dispose            = gimp_paned_box_dispose;
 
-  widget_class->drag_leave  = gimp_paned_box_drag_leave;
-  widget_class->drag_motion = gimp_paned_box_drag_motion;
-  widget_class->drag_drop   = gimp_paned_box_drag_drop;
+  widget_class->drag_leave         = gimp_paned_box_drag_leave;
+  widget_class->drag_motion        = gimp_paned_box_drag_motion;
+  widget_class->drag_drop          = gimp_paned_box_drag_drop;
+  widget_class->drag_data_received = gimp_paned_box_drag_data_received;
 
   g_type_class_add_private (klass, sizeof (GimpPanedBoxPrivate));
 }
@@ -310,7 +318,6 @@ gimp_paned_box_drag_leave (GtkWidget      *widget,
                            guint           time)
 {
   gimp_paned_box_hide_drop_indicator (GIMP_PANED_BOX (widget));
-  gimp_highlight_widget (widget, FALSE);
 }
 
 static gboolean
@@ -320,16 +327,16 @@ gimp_paned_box_drag_motion (GtkWidget      *widget,
                             gint            y,
                             guint           time)
 {
-  GimpPanedBox  *paned_box      = GIMP_PANED_BOX (widget);
-  gint           insert_index   = INSERT_INDEX_UNUSED;
-  gint           dnd_window_x   = 0;
-  gint           dnd_window_y   = 0;
-  gint           dnd_window_w   = 0;
-  gint           dnd_window_h   = 0;
-  GtkAllocation  allocation     = { 0, };
-  GtkOrientation orientation    = 0;
-  gboolean       handle         = FALSE;
-  gint           drop_area_size = gimp_paned_box_get_drop_area_size (paned_box);
+  GimpPanedBox  *paned_box    = GIMP_PANED_BOX (widget);
+  gint           insert_index = INSERT_INDEX_UNUSED;
+  gint           dnd_window_x;
+  gint           dnd_window_y;
+  gint           dnd_window_w;
+  gint           dnd_window_h;
+  GtkAllocation  allocation;
+  GtkOrientation orientation;
+  gboolean       handle;
+  gint           drop_area_size;
 
   if (gimp_paned_box_will_handle_drag (paned_box->p->drag_handler,
                                        widget,
@@ -338,17 +345,19 @@ gimp_paned_box_drag_motion (GtkWidget      *widget,
                                        time))
     {
       gdk_drag_status (context, 0, time);
-      gimp_highlight_widget (widget, FALSE);
 
       return FALSE;
     }
 
+  drop_area_size = gimp_paned_box_get_drop_area_size (paned_box);
+
   gtk_widget_get_allocation (widget, &allocation);
 
   /* See if we're at the edge of the dock If there are no dockables,
    * the entire paned box is a drop area
    */
   orientation = gtk_orientable_get_orientation (GTK_ORIENTABLE (paned_box));
+
   if (orientation == GTK_ORIENTATION_HORIZONTAL)
     {
       dnd_window_y = 0;
@@ -367,6 +376,7 @@ gimp_paned_box_drag_motion (GtkWidget      *widget,
           insert_index = 0;
           dnd_window_x = 0;
         }
+
       if (x > allocation.width - drop_area_size)
         {
           insert_index = -1;
@@ -391,6 +401,7 @@ gimp_paned_box_drag_motion (GtkWidget      *widget,
           insert_index = 0;
           dnd_window_y = 0;
         }
+
       if (y > allocation.height - drop_area_size)
         {
           insert_index = -1;
@@ -402,11 +413,12 @@ gimp_paned_box_drag_motion (GtkWidget      *widget,
    * drop will create a new dock column
    */
   handle = (insert_index != INSERT_INDEX_UNUSED);
+
   if (handle)
     {
       gimp_paned_box_position_drop_indicator (paned_box,
-                                              allocation.x + dnd_window_x,
-                                              allocation.y + dnd_window_y,
+                                              dnd_window_x,
+                                              dnd_window_y,
                                               dnd_window_w,
                                               dnd_window_h);
     }
@@ -419,7 +431,6 @@ gimp_paned_box_drag_motion (GtkWidget      *widget,
   paned_box->p->insert_index = insert_index;
 
   gdk_drag_status (context, handle ? GDK_ACTION_MOVE : 0, time);
-  gimp_highlight_widget (widget, handle);
 
   /* Return TRUE so drag_leave() is called */
   return TRUE;
@@ -433,7 +444,7 @@ gimp_paned_box_drag_drop (GtkWidget      *widget,
                           guint           time)
 {
   GimpPanedBox *paned_box = GIMP_PANED_BOX (widget);
-  gboolean      dropped   = FALSE;
+  GdkAtom       target;
 
   if (gimp_paned_box_will_handle_drag (paned_box->p->drag_handler,
                                        widget,
@@ -444,22 +455,38 @@ gimp_paned_box_drag_drop (GtkWidget      *widget,
       return FALSE;
     }
 
+  target = gtk_drag_dest_find_target (widget, context, NULL);
+
+  gtk_drag_get_data (widget, context, target, time);
+
+  return TRUE;
+}
+
+static void
+gimp_paned_box_drag_data_received (GtkWidget        *widget,
+                                   GdkDragContext   *context,
+                                   gint              x,
+                                   gint              y,
+                                   GtkSelectionData *data,
+                                   guint             info,
+                                   guint             time)
+{
+  GimpPanedBox  *paned_box = GIMP_PANED_BOX (widget);
+  GtkWidget     *notebook  = gtk_drag_get_source_widget (context);
+  GtkWidget    **child     = (gpointer) gtk_selection_data_get_data (data);
+  gboolean      dropped    = FALSE;
+
   if (paned_box->p->dropped_cb)
     {
-      GtkWidget *source = gtk_drag_get_source_widget (context);
-
-      if (source)
-        dropped = paned_box->p->dropped_cb (source,
-                                            paned_box->p->insert_index,
-                                            paned_box->p->dropped_cb_data);
+      dropped = paned_box->p->dropped_cb (notebook,
+                                          *child,
+                                          paned_box->p->insert_index,
+                                          paned_box->p->dropped_cb_data);
     }
 
   gtk_drag_finish (context, dropped, TRUE, time);
-
-  return TRUE;
 }
 
-
 GtkWidget *
 gimp_paned_box_new (gboolean       homogeneous,
                     gint           spacing,
diff --git a/app/widgets/widgets-enums.h b/app/widgets/widgets-enums.h
index c476044834..2fe0c64451 100644
--- a/app/widgets/widgets-enums.h
+++ b/app/widgets/widgets-enums.h
@@ -181,9 +181,9 @@ typedef enum  /*< skip >*/
   GIMP_DND_TYPE_IMAGEFILE    = 21,
   GIMP_DND_TYPE_TEMPLATE     = 22,
   GIMP_DND_TYPE_TOOL_INFO    = 23,
-  GIMP_DND_TYPE_DIALOG       = 24,
+  GIMP_DND_TYPE_NOTEBOOK_TAB = 24,
 
-  GIMP_DND_TYPE_LAST         = GIMP_DND_TYPE_DIALOG
+  GIMP_DND_TYPE_LAST         = GIMP_DND_TYPE_NOTEBOOK_TAB
 } GimpDndType;
 
 typedef enum  /*< skip >*/
diff --git a/app/widgets/widgets-types.h b/app/widgets/widgets-types.h
index f1128e717f..189d820333 100644
--- a/app/widgets/widgets-types.h
+++ b/app/widgets/widgets-types.h
@@ -303,7 +303,8 @@ typedef void        (* GimpMenuPositionFunc)         (GtkMenu           *menu,
                                                       gint              *x,
                                                       gint              *y,
                                                       gpointer           data);
-typedef gboolean    (* GimpPanedBoxDroppedFunc)      (GtkWidget         *source,
+typedef gboolean    (* GimpPanedBoxDroppedFunc)      (GtkWidget         *notebook,
+                                                      GtkWidget         *child,
                                                       gint               insert_index,
                                                       gpointer           data);
 


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