[gimp] app: GimpTool multi-drawable aware.



commit 03af9da83b6c715a0f42e9178c84c5e4d4220c8f
Author: Jehan <jehan girinstud io>
Date:   Mon May 25 11:30:31 2020 +0200

    app: GimpTool multi-drawable aware.
    
    Right now I don't change the logics of any of the tools, except that the
    GimpTool class now stores a list of drawables instead of a single
    drawable. This can be later used on a case-by-case basis to make various
    tools actually work on multiple drawables.

 app/display/gimpdisplayshell-tool-events.c |  9 ++-
 app/tools/gimpbrushtool.c                  | 10 +++-
 app/tools/gimpbucketfilltool.c             | 67 ++++++++++++++++-----
 app/tools/gimpcagetool.c                   | 55 +++++++++++++-----
 app/tools/gimpcroptool.c                   |  5 +-
 app/tools/gimpcurvestool.c                 | 24 ++++++--
 app/tools/gimpfiltertool-widgets.c         | 10 ++--
 app/tools/gimpfiltertool.c                 | 93 +++++++++++++++++++++---------
 app/tools/gimpforegroundselecttool.c       | 46 +++++++++++----
 app/tools/gimpgradienttool.c               | 32 +++++-----
 app/tools/gimplevelstool.c                 | 29 ++++++++--
 app/tools/gimpnpointdeformationtool.c      | 32 +++++-----
 app/tools/gimpoffsettool.c                 | 32 +++++++---
 app/tools/gimpoperationtool.c              |  6 +-
 app/tools/gimppainttool.c                  | 62 ++++++++++++++------
 app/tools/gimpperspectiveclonetool.c       | 30 ++++++++--
 app/tools/gimpseamlessclonetool.c          | 16 +++--
 app/tools/gimptexttool.c                   |  8 ++-
 app/tools/gimpthresholdtool.c              | 29 ++++++++--
 app/tools/gimptool.c                       | 12 ++--
 app/tools/gimptool.h                       |  2 +-
 app/tools/gimptransformgridtool.c          | 32 +++++++---
 app/tools/gimpwarptool.c                   | 67 +++++++++++++--------
 app/tools/tool_manager.c                   |  3 +-
 24 files changed, 506 insertions(+), 205 deletions(-)
---
diff --git a/app/display/gimpdisplayshell-tool-events.c b/app/display/gimpdisplayshell-tool-events.c
index 756a3bdf69..6fd2a75195 100644
--- a/app/display/gimpdisplayshell-tool-events.c
+++ b/app/display/gimpdisplayshell-tool-events.c
@@ -1911,13 +1911,12 @@ gimp_display_shell_initialize_tool (GimpDisplayShell *shell,
       (! gimp_image_is_empty (image) ||
        gimp_tool_control_get_handle_empty_image (active_tool->control)))
     {
-      /*  initialize the current tool if it has no drawable  */
-      if (! active_tool->drawable)
+      /*  initialize the current tool if it has no drawables  */
+      if (! active_tool->drawables)
         {
           initialized = tool_manager_initialize_active (gimp, display);
         }
-      else if ((active_tool->drawable !=
-                gimp_image_get_active_drawable (image)) &&
+      else if (! gimp_image_equal_selected_drawables (image, active_tool->drawables) &&
                (! gimp_tool_control_get_preserve (active_tool->control) &&
                 (gimp_tool_control_get_dirty_mask (active_tool->control) &
                  GIMP_DIRTY_ACTIVE_DRAWABLE)))
@@ -1925,7 +1924,7 @@ gimp_display_shell_initialize_tool (GimpDisplayShell *shell,
           GimpProcedure *procedure = g_object_get_data (G_OBJECT (active_tool),
                                                         "gimp-gegl-procedure");
 
-          if (image == gimp_item_get_image (GIMP_ITEM (active_tool->drawable)))
+          if (image == gimp_item_get_image (GIMP_ITEM (active_tool->drawables->data)))
             {
               /*  When changing between drawables if the *same* image,
                *  stop the tool using its dirty action, so it doesn't
diff --git a/app/tools/gimpbrushtool.c b/app/tools/gimpbrushtool.c
index 08c8ed964f..8fb3e49b07 100644
--- a/app/tools/gimpbrushtool.c
+++ b/app/tools/gimpbrushtool.c
@@ -156,14 +156,20 @@ gimp_brush_tool_oper_update (GimpTool         *tool,
                              GimpDisplay      *display)
 {
   GimpPaintOptions *paint_options = GIMP_PAINT_TOOL_GET_OPTIONS (tool);
-  GimpDrawable     *drawable;
+  GimpDrawable     *drawable      = NULL;
+  GList            *drawables;
 
   gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
 
   GIMP_TOOL_CLASS (parent_class)->oper_update (tool, coords, state,
                                                proximity, display);
 
-  drawable = gimp_image_get_active_drawable (gimp_display_get_image (display));
+  drawables = gimp_image_get_selected_drawables (gimp_display_get_image (display));
+
+  if (drawables)
+    drawable = drawables->data;
+
+  g_list_free (drawables);
 
   if (! gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)) &&
       drawable && proximity)
diff --git a/app/tools/gimpbucketfilltool.c b/app/tools/gimpbucketfilltool.c
index 3c988f6af0..1c323fef44 100644
--- a/app/tools/gimpbucketfilltool.c
+++ b/app/tools/gimpbucketfilltool.c
@@ -327,21 +327,23 @@ gimp_bucket_fill_tool_start (GimpBucketFillTool *tool,
                              const GimpCoords   *coords,
                              GimpDisplay        *display)
 {
-  GimpBucketFillOptions *options  = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
-  GimpContext           *context  = GIMP_CONTEXT (options);
-  GimpImage             *image    = gimp_display_get_image (display);
-  GimpDrawable          *drawable = gimp_image_get_active_drawable (image);
+  GimpBucketFillOptions *options   = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
+  GimpContext           *context   = GIMP_CONTEXT (options);
+  GimpImage             *image     = gimp_display_get_image (display);
+  GList                 *drawables = gimp_image_get_selected_drawables (image);
 
   g_return_if_fail (! tool->priv->filter);
+  g_return_if_fail (g_list_length (drawables) == 1);
 
   gimp_line_art_freeze (tool->priv->line_art);
 
   GIMP_TOOL (tool)->display  = display;
-  GIMP_TOOL (tool)->drawable = drawable;
+  g_list_free (GIMP_TOOL (tool)->drawables);
+  GIMP_TOOL (tool)->drawables = drawables;
 
   gimp_bucket_fill_tool_create_graph (tool);
 
-  tool->priv->filter = gimp_drawable_filter_new (drawable, _("Bucket fill"),
+  tool->priv->filter = gimp_drawable_filter_new (drawables->data, _("Bucket fill"),
                                                  tool->priv->graph,
                                                  GIMP_ICON_TOOL_BUCKET_FILL);
 
@@ -370,10 +372,16 @@ gimp_bucket_fill_tool_preview (GimpBucketFillTool *tool,
                                GimpDisplay        *display,
                                GimpFillOptions    *fill_options)
 {
-  GimpBucketFillOptions *options  = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
-  GimpDisplayShell      *shell    = gimp_display_get_shell (display);
-  GimpImage             *image    = gimp_display_get_image (display);
-  GimpDrawable          *drawable = gimp_image_get_active_drawable (image);
+  GimpBucketFillOptions *options   = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
+  GimpDisplayShell      *shell     = gimp_display_get_shell (display);
+  GimpImage             *image     = gimp_display_get_image (display);
+  GList                 *drawables = gimp_image_get_selected_drawables (image);
+  GimpDrawable          *drawable;
+
+  g_return_if_fail (g_list_length (drawables) == 1);
+
+  drawable = drawables->data;
+  g_list_free (drawables);
 
   if (tool->priv->filter)
     {
@@ -486,8 +494,9 @@ gimp_bucket_fill_tool_halt (GimpBucketFillTool *tool)
   if (gimp_line_art_is_frozen (tool->priv->line_art))
     gimp_line_art_thaw (tool->priv->line_art);
 
-  GIMP_TOOL (tool)->display  = NULL;
-  GIMP_TOOL (tool)->drawable = NULL;
+  GIMP_TOOL (tool)->display   = NULL;
+  g_list_free (GIMP_TOOL (tool)->drawables);
+  GIMP_TOOL (tool)->drawables = NULL;
 }
 
 static void
@@ -539,7 +548,8 @@ gimp_bucket_fill_tool_button_press (GimpTool            *tool,
   GimpBucketFillOptions *options     = GIMP_BUCKET_FILL_TOOL_GET_OPTIONS (tool);
   GimpGuiConfig         *config      = GIMP_GUI_CONFIG (display->gimp->config);
   GimpImage             *image       = gimp_display_get_image (display);
-  GimpDrawable          *drawable    = gimp_image_get_active_drawable (image);
+  GList                 *drawables   = gimp_image_get_selected_drawables (image);
+  GimpDrawable          *drawable;
 
   if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
     {
@@ -548,6 +558,21 @@ gimp_bucket_fill_tool_button_press (GimpTool            *tool,
       return;
     }
 
+  if (g_list_length (drawables) != 1)
+    {
+      if (g_list_length (drawables) > 1)
+        gimp_tool_message_literal (tool, display,
+                                   _("Cannot fill multiple layers. Select only one layer."));
+      else
+        gimp_tool_message_literal (tool, display, _("No selected drawables."));
+
+      g_list_free (drawables);
+      return;
+    }
+
+  drawable = drawables->data;
+  g_list_free (drawables);
+
   if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
     {
       gimp_tool_message_literal (tool, display,
@@ -827,9 +852,14 @@ gimp_bucket_fill_tool_cursor_update (GimpTool         *tool,
   if (gimp_bucket_fill_tool_coords_in_active_pickable (bucket_tool,
                                                        display, coords))
     {
-      GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+      GList        *drawables = gimp_image_get_selected_drawables (image);
+      GimpDrawable *drawable  = NULL;
+
+      if (g_list_length (drawables) == 1)
+        drawable = drawables->data;
 
-      if (! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
+      if (drawable                                                &&
+          ! gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) &&
           ! gimp_item_is_content_locked (GIMP_ITEM (drawable))    &&
           (gimp_item_is_visible (GIMP_ITEM (drawable)) ||
            config->edit_non_visible))
@@ -999,7 +1029,12 @@ gimp_bucket_fill_tool_reset_line_art (GimpBucketFillTool *tool)
 
   if (image)
     {
-      GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+      GList        *drawables = gimp_image_get_selected_drawables (image);
+      GimpDrawable *drawable;
+
+      g_return_if_fail (g_list_length (drawables) == 1);
+      drawable = drawables->data;
+      g_list_free (drawables);
 
       if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
         drawable = NULL;
diff --git a/app/tools/gimpcagetool.c b/app/tools/gimpcagetool.c
index 37bb4c2e58..44a24f4521 100644
--- a/app/tools/gimpcagetool.c
+++ b/app/tools/gimpcagetool.c
@@ -214,12 +214,25 @@ gimp_cage_tool_initialize (GimpTool     *tool,
                            GimpDisplay  *display,
                            GError      **error)
 {
-  GimpGuiConfig *config   = GIMP_GUI_CONFIG (display->gimp->config);
-  GimpImage     *image    = gimp_display_get_image (display);
-  GimpDrawable  *drawable = gimp_image_get_active_drawable (image);
+  GimpGuiConfig *config    = GIMP_GUI_CONFIG (display->gimp->config);
+  GimpImage     *image     = gimp_display_get_image (display);
+  GList         *drawables = gimp_image_get_selected_drawables (image);
+  GimpDrawable  *drawable;
 
-  if (! drawable)
-    return FALSE;
+  if (g_list_length (drawables) != 1)
+    {
+      if (g_list_length (drawables) > 1)
+        g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
+                                   _("Cannot modify multiple layers. Select only one layer."));
+      else
+        g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED, _("No selected drawables."));
+
+      g_list_free (drawables);
+      return FALSE;
+    }
+
+  drawable = drawables->data;
+  g_list_free (drawables);
 
   if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
     {
@@ -693,10 +706,16 @@ gimp_cage_tool_cursor_update (GimpTool         *tool,
     }
   else
     {
-      GimpImage    *image    = gimp_display_get_image (display);
-      GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+      GimpImage    *image     = gimp_display_get_image (display);
+      GList        *drawables = gimp_image_get_selected_drawables (image);
+      GimpDrawable *drawable  = NULL;
 
-      if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) ||
+      if (g_list_length (drawables) == 1)
+        drawable = drawables->data;
+      g_list_free (drawables);
+
+      if (! drawable                                            ||
+          gimp_viewable_get_children (GIMP_VIEWABLE (drawable)) ||
           gimp_item_is_content_locked (GIMP_ITEM (drawable))    ||
           ! (gimp_item_is_visible (GIMP_ITEM (drawable)) ||
              config->edit_non_visible))
@@ -927,10 +946,13 @@ gimp_cage_tool_start (GimpCageTool *ct,
 {
   GimpTool     *tool     = GIMP_TOOL (ct);
   GimpImage    *image    = gimp_display_get_image (display);
-  GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+  GList        *drawables = gimp_image_get_selected_drawables (image);
+
+  g_return_if_fail (g_list_length (drawables) == 1);
 
-  tool->display  = display;
-  tool->drawable = drawable;
+  tool->display   = display;
+  g_list_free (tool->drawables);
+  tool->drawables = drawables;
 
   g_clear_object (&ct->config);
 
@@ -958,7 +980,7 @@ gimp_cage_tool_start (GimpCageTool *ct,
   /* Setting up cage offset to convert the cage point coords to
    * drawable coords
    */
-  gimp_item_get_offset (GIMP_ITEM (tool->drawable),
+  gimp_item_get_offset (GIMP_ITEM (tool->drawables->data),
                         &ct->offset_x, &ct->offset_y);
 
   gimp_draw_tool_start (GIMP_DRAW_TOOL (ct), display);
@@ -987,9 +1009,10 @@ gimp_cage_tool_halt (GimpCageTool *ct)
       gimp_image_flush (gimp_display_get_image (tool->display));
     }
 
-  tool->display  = NULL;
-  tool->drawable = NULL;
-  ct->tool_state = CAGE_STATE_INIT;
+  tool->display   = NULL;
+  g_list_free (tool->drawables);
+  tool->drawables = NULL;
+  ct->tool_state  = CAGE_STATE_INIT;
 
   g_object_set (gimp_tool_get_options (tool),
                 "cage-mode", GIMP_CAGE_MODE_CAGE_CHANGE,
@@ -1274,7 +1297,7 @@ gimp_cage_tool_create_filter (GimpCageTool *ct)
   if (! ct->render_node)
     gimp_cage_tool_create_render_node (ct);
 
-  ct->filter = gimp_drawable_filter_new (GIMP_TOOL (ct)->drawable,
+  ct->filter = gimp_drawable_filter_new (GIMP_TOOL (ct)->drawables->data,
                                          _("Cage transform"),
                                          ct->render_node,
                                          GIMP_ICON_TOOL_CAGE);
diff --git a/app/tools/gimpcroptool.c b/app/tools/gimpcroptool.c
index fa9080da4e..897a7c73b9 100644
--- a/app/tools/gimpcroptool.c
+++ b/app/tools/gimpcroptool.c
@@ -532,8 +532,9 @@ gimp_crop_tool_halt (GimpCropTool *crop_tool)
   gimp_draw_tool_set_widget (GIMP_DRAW_TOOL (tool), NULL);
   g_clear_object (&crop_tool->widget);
 
-  tool->display  = NULL;
-  tool->drawable = NULL;
+  tool->display   = NULL;
+  g_list_free (tool->drawables);
+  tool->drawables = NULL;
 
   gimp_crop_tool_update_option_defaults (crop_tool, TRUE);
 }
diff --git a/app/tools/gimpcurvestool.c b/app/tools/gimpcurvestool.c
index 9112308efa..8d21d8b082 100644
--- a/app/tools/gimpcurvestool.c
+++ b/app/tools/gimpcurvestool.c
@@ -199,7 +199,8 @@ gimp_curves_tool_initialize (GimpTool     *tool,
   GimpFilterTool       *filter_tool = GIMP_FILTER_TOOL (tool);
   GimpCurvesTool       *c_tool      = GIMP_CURVES_TOOL (tool);
   GimpImage            *image       = gimp_display_get_image (display);
-  GimpDrawable         *drawable    = gimp_image_get_active_drawable (image);
+  GList                *drawables;
+  GimpDrawable         *drawable;
   GimpCurvesConfig     *config;
   GimpHistogram        *histogram;
   GimpHistogramChannel  channel;
@@ -209,6 +210,21 @@ gimp_curves_tool_initialize (GimpTool     *tool,
       return FALSE;
     }
 
+  drawables = gimp_image_get_selected_drawables (image);
+  if (g_list_length (drawables) != 1)
+    {
+      if (g_list_length (drawables) > 1)
+        gimp_tool_message_literal (tool, display,
+                                   _("Cannot modify multiple drawables. Select only one."));
+      else
+        gimp_tool_message_literal (tool, display, _("No selected drawables."));
+
+      g_list_free (drawables);
+      return FALSE;
+    }
+  drawable = drawables->data;
+  g_list_free (drawables);
+
   config = GIMP_CURVES_CONFIG (filter_tool->config);
 
   histogram = gimp_histogram_new (config->trc);
@@ -713,7 +729,7 @@ gimp_curves_tool_config_notify (GimpFilterTool   *filter_tool,
 
       histogram = gimp_histogram_new (curves_config->trc);
       g_object_unref (gimp_drawable_calculate_histogram_async
-                      (GIMP_TOOL (filter_tool)->drawable, histogram, FALSE));
+                      (GIMP_TOOL (filter_tool)->drawables->data, histogram, FALSE));
       gimp_histogram_view_set_background (GIMP_HISTOGRAM_VIEW (curves_tool->graph),
                                           histogram);
       g_object_unref (histogram);
@@ -782,7 +798,7 @@ gimp_curves_tool_color_picked (GimpFilterTool *filter_tool,
 {
   GimpCurvesTool   *tool     = GIMP_CURVES_TOOL (filter_tool);
   GimpCurvesConfig *config   = GIMP_CURVES_CONFIG (filter_tool->config);
-  GimpDrawable     *drawable = GIMP_TOOL (tool)->drawable;
+  GimpDrawable     *drawable = GIMP_TOOL (tool)->drawables->data;
   GimpRGB           rgb      = *color;
 
   if (config->trc == GIMP_TRC_LINEAR)
@@ -1015,7 +1031,7 @@ static gboolean
 curves_menu_sensitivity (gint      value,
                          gpointer  data)
 {
-  GimpDrawable         *drawable = GIMP_TOOL (data)->drawable;
+  GimpDrawable         *drawable = GIMP_TOOL (data)->drawables->data;
   GimpHistogramChannel  channel  = value;
 
   if (!drawable)
diff --git a/app/tools/gimpfiltertool-widgets.c b/app/tools/gimpfiltertool-widgets.c
index d5cf6fe4b4..b8acd6cb4b 100644
--- a/app/tools/gimpfiltertool-widgets.c
+++ b/app/tools/gimpfiltertool-widgets.c
@@ -409,7 +409,7 @@ gimp_filter_tool_set_line (Controller    *controller,
     return;
 
   tool     = GIMP_TOOL (controller->filter_tool);
-  drawable = tool->drawable;
+  drawable = tool->drawables->data;
 
   if (drawable)
     {
@@ -486,7 +486,7 @@ gimp_filter_tool_set_slider_line (Controller                 *controller,
     return;
 
   tool     = GIMP_TOOL (controller->filter_tool);
-  drawable = tool->drawable;
+  drawable = tool->drawables->data;
 
   if (drawable)
     {
@@ -572,7 +572,7 @@ gimp_filter_tool_set_transform_grid (Controller        *controller,
     return;
 
   tool     = GIMP_TOOL (controller->filter_tool);
-  drawable = tool->drawable;
+  drawable = tool->drawables->data;
 
   if (drawable)
     {
@@ -662,7 +662,7 @@ gimp_filter_tool_set_transform_grids (Controller        *controller,
 
   tool     = GIMP_TOOL (controller->filter_tool);
   shell    = gimp_display_get_shell (tool->display);
-  drawable = tool->drawable;
+  drawable = tool->drawables->data;
 
   g_signal_handlers_block_by_func (controller->widget,
                                    gimp_filter_tool_transform_grids_changed,
@@ -885,7 +885,7 @@ gimp_filter_tool_set_focus (Controller    *controller,
     return;
 
   tool     = GIMP_TOOL (controller->filter_tool);
-  drawable = tool->drawable;
+  drawable = tool->drawables->data;
 
   if (drawable)
     {
diff --git a/app/tools/gimpfiltertool.c b/app/tools/gimpfiltertool.c
index c0da2bb0d6..db877673b1 100644
--- a/app/tools/gimpfiltertool.c
+++ b/app/tools/gimpfiltertool.c
@@ -283,25 +283,40 @@ gimp_filter_tool_initialize (GimpTool     *tool,
   GimpToolInfo     *tool_info   = tool->tool_info;
   GimpGuiConfig    *config      = GIMP_GUI_CONFIG (display->gimp->config);
   GimpImage        *image       = gimp_display_get_image (display);
-  GimpDrawable     *drawable    = gimp_image_get_active_drawable (image);
   GimpDisplayShell *shell       = gimp_display_get_shell (display);
+  GList            *drawables   = gimp_image_get_selected_drawables (image);
+  GimpDrawable     *drawable;
 
-  if (! drawable)
-    return FALSE;
+  if (g_list_length (drawables) != 1)
+    {
+      if (g_list_length (drawables) > 1)
+        g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
+                                   _("Cannot modify multiple drawables. Select only one."));
+      else
+        g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED, _("No selected drawables."));
+
+      g_list_free (drawables);
+      return FALSE;
+    }
+  drawable = drawables->data;
 
   if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
     {
       g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
                            _("Cannot modify the pixels of layer groups."));
+
+      g_list_free (drawables);
       return FALSE;
     }
 
   if (gimp_item_is_content_locked (GIMP_ITEM (drawable)))
     {
       g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
-                           _("The active layer's pixels are locked."));
+                           _("A selected layer's pixels are locked."));
       if (error)
         gimp_tools_blink_lock_box (display->gimp, GIMP_ITEM (drawable));
+
+      g_list_free (drawables);
       return FALSE;
     }
 
@@ -309,7 +324,9 @@ gimp_filter_tool_initialize (GimpTool     *tool,
       ! config->edit_non_visible)
     {
       g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
-                           _("The active layer is not visible."));
+                           _("A selected layer is not visible."));
+
+      g_list_free (drawables);
       return FALSE;
     }
 
@@ -317,8 +334,9 @@ gimp_filter_tool_initialize (GimpTool     *tool,
 
   gimp_filter_tool_disable_color_picking (filter_tool);
 
-  tool->display  = display;
-  tool->drawable = drawable;
+  tool->display   = display;
+  g_list_free (tool->drawables);
+  tool->drawables = drawables;
 
   if (filter_tool->config)
     gimp_config_reset (GIMP_CONFIG (filter_tool->config));
@@ -486,7 +504,7 @@ gimp_filter_tool_button_press (GimpTool            *tool,
         }
       else if (state & gimp_get_toggle_behavior_mask ())
         {
-          GimpItem *item = GIMP_ITEM (tool->drawable);
+          GimpItem *item = GIMP_ITEM (tool->drawables->data);
           gdouble   pos_x;
           gdouble   pos_y;
 
@@ -702,7 +720,7 @@ gimp_filter_tool_options_notify (GimpTool         *tool,
       if (filter_options->preview_split)
         {
           GimpDisplayShell *shell = gimp_display_get_shell (tool->display);
-          GimpItem         *item  = GIMP_ITEM (tool->drawable);
+          GimpItem         *item  = GIMP_ITEM (tool->drawables->data);
           gint              x, y, width, height;
 
           gimp_display_shell_untransform_viewport (shell, TRUE,
@@ -723,6 +741,8 @@ gimp_filter_tool_options_notify (GimpTool         *tool,
                   position = ((gdouble) ((x + width / 2) -
                                          gimp_item_get_offset_x (item)) /
                               (gdouble) gimp_item_get_width (item));
+
+
                 }
               else
                 {
@@ -770,7 +790,7 @@ gimp_filter_tool_can_pick_color (GimpColorTool    *color_tool,
   GimpFilterTool *filter_tool = GIMP_FILTER_TOOL (color_tool);
   GimpImage      *image       = gimp_display_get_image (display);
 
-  if (gimp_image_get_active_drawable (image) != tool->drawable)
+  if (! gimp_image_equal_selected_drawables (image, tool->drawables))
     return FALSE;
 
   return filter_tool->pick_abyss ||
@@ -791,11 +811,13 @@ gimp_filter_tool_pick_color (GimpColorTool     *color_tool,
   gint            off_x, off_y;
   gboolean        picked;
 
-  gimp_item_get_offset (GIMP_ITEM (tool->drawable), &off_x, &off_y);
+  g_return_val_if_fail (g_list_length (tool->drawables) == 1, FALSE);
+
+  gimp_item_get_offset (GIMP_ITEM (tool->drawables->data), &off_x, &off_y);
 
-  *sample_format = gimp_drawable_get_format (tool->drawable);
+  *sample_format = gimp_drawable_get_format (tool->drawables->data);
 
-  picked = gimp_pickable_pick_color (GIMP_PICKABLE (tool->drawable),
+  picked = gimp_pickable_pick_color (GIMP_PICKABLE (tool->drawables->data),
                                      coords->x - off_x,
                                      coords->y - off_y,
                                      color_tool->options->sample_average,
@@ -946,10 +968,12 @@ gimp_filter_tool_halt (GimpFilterTool *filter_tool)
   if (tool->display)
     {
       GimpImage *image = gimp_display_get_image (tool->display);
+      GList     *iter;
 
-      g_signal_handlers_disconnect_by_func (tool->drawable,
-                                            gimp_filter_tool_lock_position_changed,
-                                            filter_tool);
+      for (iter = tool->drawables; iter; iter = iter->next)
+        g_signal_handlers_disconnect_by_func (iter->data,
+                                              gimp_filter_tool_lock_position_changed,
+                                              filter_tool);
 
       g_signal_handlers_disconnect_by_func (image,
                                             gimp_filter_tool_mask_changed,
@@ -980,7 +1004,6 @@ gimp_filter_tool_halt (GimpFilterTool *filter_tool)
     {
       gimp_drawable_filter_abort (filter_tool->filter);
       g_clear_object (&filter_tool->filter);
-
       gimp_filter_tool_remove_guide (filter_tool);
     }
 
@@ -1005,8 +1028,9 @@ gimp_filter_tool_halt (GimpFilterTool *filter_tool)
 
   gimp_filter_tool_set_widget (filter_tool, NULL);
 
-  tool->display  = NULL;
-  tool->drawable = NULL;
+  tool->display   = NULL;
+  g_list_free (tool->drawables);
+  tool->drawables = NULL;
 }
 
 static void
@@ -1194,8 +1218,9 @@ gimp_filter_tool_create_filter (GimpFilterTool *filter_tool)
     }
 
   gimp_assert (filter_tool->operation);
+  g_return_if_fail (g_list_length (tool->drawables) == 1);
 
-  filter_tool->filter = gimp_drawable_filter_new (tool->drawable,
+  filter_tool->filter = gimp_drawable_filter_new (tool->drawables->data,
                                                   gimp_tool_get_undo_desc (tool),
                                                   filter_tool->operation,
                                                   gimp_tool_get_icon_name (tool));
@@ -1225,16 +1250,18 @@ gimp_filter_tool_update_dialog (GimpFilterTool *filter_tool)
       GimpChannel *mask  = gimp_image_get_mask (image);
       const Babl  *format;
 
+      g_return_if_fail (g_list_length (tool->drawables) == 1);
+
       if (filter_tool->filter)
         format = gimp_drawable_filter_get_format (filter_tool->filter);
       else
-        format = gimp_drawable_get_format (tool->drawable);
+        format = gimp_drawable_get_format (tool->drawables->data);
 
       if (gimp_channel_is_empty (mask))
         {
           gtk_widget_set_visible (
             filter_tool->clip_combo,
-            gimp_item_get_clip (GIMP_ITEM (tool->drawable), FALSE) == FALSE &&
+            gimp_item_get_clip (GIMP_ITEM (tool->drawables->data), FALSE) == FALSE &&
             ! gimp_gegl_node_is_point_operation (filter_tool->operation)    &&
             babl_format_has_alpha (format));
 
@@ -1326,10 +1353,12 @@ gimp_filter_tool_add_guide (GimpFilterTool *filter_tool)
   GimpOrientationType  orientation;
   gint                 position;
 
+  g_return_if_fail (g_list_length (tool->drawables) == 1);
+
   if (filter_tool->preview_guide)
     return;
 
-  item  = GIMP_ITEM (tool->drawable);
+  item  = GIMP_ITEM (tool->drawables->data);
   image = gimp_item_get_image (item);
 
   if (options->preview_split_alignment == GIMP_ALIGN_LEFT ||
@@ -1374,7 +1403,7 @@ gimp_filter_tool_remove_guide (GimpFilterTool *filter_tool)
   if (! filter_tool->preview_guide)
     return;
 
-  image = gimp_item_get_image (GIMP_ITEM (tool->drawable));
+  image = gimp_item_get_image (GIMP_ITEM (tool->drawables->data));
 
   gimp_image_remove_guide (image, filter_tool->preview_guide, FALSE);
 }
@@ -1388,10 +1417,12 @@ gimp_filter_tool_move_guide (GimpFilterTool *filter_tool)
   GimpOrientationType  orientation;
   gint                 position;
 
+  g_return_if_fail (g_list_length (tool->drawables) == 1);
+
   if (! filter_tool->preview_guide)
     return;
 
-  item = GIMP_ITEM (tool->drawable);
+  item = GIMP_ITEM (tool->drawables->data);
 
   if (options->preview_split_alignment == GIMP_ALIGN_LEFT ||
       options->preview_split_alignment == GIMP_ALIGN_RIGHT)
@@ -1447,9 +1478,13 @@ gimp_filter_tool_guide_moved (GimpGuide        *guide,
 {
   GimpTool          *tool    = GIMP_TOOL (filter_tool);
   GimpFilterOptions *options = GIMP_FILTER_TOOL_GET_OPTIONS (filter_tool);
-  GimpItem          *item    = GIMP_ITEM (tool->drawable);
+  GimpItem          *item;
   gdouble            position;
 
+  g_return_if_fail (g_list_length (tool->drawables) == 1);
+
+  item = GIMP_ITEM (tool->drawables->data);
+
   if (options->preview_split_alignment == GIMP_ALIGN_LEFT ||
       options->preview_split_alignment == GIMP_ALIGN_RIGHT)
     {
@@ -1680,7 +1715,7 @@ gimp_filter_tool_get_operation (GimpFilterTool *filter_tool)
                            G_CALLBACK (gimp_filter_tool_config_notify),
                            G_OBJECT (filter_tool), 0);
 
-  if (tool->drawable)
+  if (tool->drawables)
     gimp_filter_tool_create_filter (filter_tool);
 }
 
@@ -1991,6 +2026,8 @@ gimp_filter_tool_get_drawable_area (GimpFilterTool *filter_tool,
   tool     = GIMP_TOOL (filter_tool);
   settings = GIMP_OPERATION_SETTINGS (filter_tool->config);
 
+  g_return_val_if_fail (g_list_length (tool->drawables) == 1, FALSE);
+
   *drawable_offset_x = 0;
   *drawable_offset_y = 0;
 
@@ -1999,7 +2036,7 @@ gimp_filter_tool_get_drawable_area (GimpFilterTool *filter_tool,
   drawable_area->width  = 1;
   drawable_area->height = 1;
 
-  drawable = tool->drawable;
+  drawable = tool->drawables->data;
 
   if (drawable && settings)
     {
diff --git a/app/tools/gimpforegroundselecttool.c b/app/tools/gimpforegroundselecttool.c
index bc72235feb..852a6e1c90 100644
--- a/app/tools/gimpforegroundselecttool.c
+++ b/app/tools/gimpforegroundselecttool.c
@@ -282,11 +282,23 @@ gimp_foreground_select_tool_initialize (GimpTool     *tool,
   GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (tool);
   GimpGuiConfig            *config    = GIMP_GUI_CONFIG (display->gimp->config);
   GimpImage                *image     = gimp_display_get_image (display);
-  GimpDrawable             *drawable  = gimp_image_get_active_drawable (image);
   GimpDisplayShell         *shell     = gimp_display_get_shell (display);
+  GList                    *drawables = gimp_image_get_selected_drawables (image);
+  GimpDrawable             *drawable;
 
-  if (! drawable)
-    return FALSE;
+  if (g_list_length (drawables) != 1)
+    {
+      if (g_list_length (drawables) > 1)
+        g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED,
+                             _("Cannot select from multiple layers."));
+      else
+        g_set_error_literal (error, GIMP_ERROR, GIMP_FAILED, _("No selected drawables."));
+
+      g_list_free (drawables);
+      return FALSE;
+    }
+  drawable = drawables->data;
+  g_list_free (drawables);
 
   if (! gimp_item_is_visible (GIMP_ITEM (drawable)) &&
       ! config->edit_non_visible)
@@ -910,8 +922,15 @@ gimp_foreground_select_tool_confirm (GimpPolygonSelectTool *poly_sel,
 {
   GimpForegroundSelectTool *fg_select = GIMP_FOREGROUND_SELECT_TOOL (poly_sel);
   GimpImage                *image     = gimp_display_get_image (display);
-  GimpDrawable             *drawable  = gimp_image_get_active_drawable (image);
-  GimpItem                 *item      = GIMP_ITEM (drawable);
+  GList                    *drawables = gimp_image_get_selected_drawables (image);
+  GimpDrawable             *drawable;
+  GimpItem                 *item;
+
+  g_return_if_fail (g_list_length (drawables) == 1);
+
+  drawable = drawables->data;
+  item     = GIMP_ITEM (drawable);
+  g_list_free (drawables);
 
   if (drawable && fg_select->state == MATTING_STATE_FREE_SELECT)
     {
@@ -995,8 +1014,9 @@ gimp_foreground_select_tool_halt (GimpForegroundSelectTool *fg_select)
   if (tool->display)
     gimp_image_flush (gimp_display_get_image (tool->display));
 
-  tool->display  = NULL;
-  tool->drawable = NULL;
+  tool->display   = NULL;
+  g_list_free (tool->drawables);
+  tool->drawables = NULL;
 
   if (fg_select->gui)
     gimp_tool_gui_hide (fg_select->gui);
@@ -1131,10 +1151,16 @@ gimp_foreground_select_tool_set_preview (GimpForegroundSelectTool *fg_select)
 static void
 gimp_foreground_select_tool_preview (GimpForegroundSelectTool *fg_select)
 {
-  GimpTool                    *tool     = GIMP_TOOL (fg_select);
+  GimpTool                    *tool      = GIMP_TOOL (fg_select);
   GimpForegroundSelectOptions *options;
-  GimpImage                   *image    = gimp_display_get_image (tool->display);
-  GimpDrawable                *drawable = gimp_image_get_active_drawable (image);
+  GimpImage                   *image     = gimp_display_get_image (tool->display);
+  GList                       *drawables = gimp_image_get_selected_drawables (image);
+  GimpDrawable                *drawable;
+
+  g_return_if_fail (g_list_length (drawables) == 1);
+
+  drawable = drawables->data;
+  g_list_free (drawables);
 
   options  = GIMP_FOREGROUND_SELECT_TOOL_GET_OPTIONS (tool);
 
diff --git a/app/tools/gimpgradienttool.c b/app/tools/gimpgradienttool.c
index ddae75a8b3..421ee40ca3 100644
--- a/app/tools/gimpgradienttool.c
+++ b/app/tools/gimpgradienttool.c
@@ -239,9 +239,9 @@ gimp_gradient_tool_initialize (GimpTool     *tool,
                                GError      **error)
 {
   GimpImage           *image     = gimp_display_get_image (display);
-  GList               *drawables = gimp_image_get_selected_drawables (image);
   GimpGradientOptions *options   = GIMP_GRADIENT_TOOL_GET_OPTIONS (tool);
   GimpGuiConfig       *config    = GIMP_GUI_CONFIG (display->gimp->config);
+  GList               *drawables;
   GimpDrawable        *drawable;
 
   if (! GIMP_TOOL_CLASS (parent_class)->initialize (tool, display, error))
@@ -249,6 +249,7 @@ gimp_gradient_tool_initialize (GimpTool     *tool,
       return FALSE;
     }
 
+  drawables = gimp_image_get_selected_drawables (image);
   if (g_list_length (drawables) != 1)
     {
       if (g_list_length (drawables) > 1)
@@ -482,8 +483,10 @@ gimp_gradient_tool_cursor_update (GimpTool         *tool,
                             gimp_tool_control_get_cursor (tool->control),
                             gimp_tool_control_get_tool_cursor (tool->control),
                             GIMP_CURSOR_MODIFIER_BAD);
+      g_list_free (drawables);
       return;
     }
+  g_list_free (drawables);
 
   GIMP_TOOL_CLASS (parent_class)->cursor_update (tool, coords, state, display);
 }
@@ -634,9 +637,9 @@ gimp_gradient_tool_start (GimpGradientTool *gradient_tool,
   if (options->instant_toggle)
     gtk_widget_set_sensitive (options->instant_toggle, FALSE);
 
-  tool->display  = display;
-  tool->drawable = drawables->data;
-  g_list_free (drawables);
+  tool->display   = display;
+  g_list_free (tool->drawables);
+  tool->drawables = drawables;
 
   gradient_tool->start_x = coords->x;
   gradient_tool->start_y = coords->y;
@@ -669,7 +672,7 @@ gimp_gradient_tool_start (GimpGradientTool *gradient_tool,
                             G_CALLBACK (gimp_gradient_tool_fg_bg_changed),
                             gradient_tool);
 
-  gimp_gradient_tool_create_filter (gradient_tool, tool->drawable);
+  gimp_gradient_tool_create_filter (gradient_tool, tool->drawables->data);
 
   /* Initially sync all of the properties */
   gimp_operation_config_sync_node (G_OBJECT (options),
@@ -742,8 +745,9 @@ gimp_gradient_tool_halt (GimpGradientTool *gradient_tool)
   gimp_draw_tool_set_widget (GIMP_DRAW_TOOL (tool), NULL);
   g_clear_object (&gradient_tool->widget);
 
-  tool->display  = NULL;
-  tool->drawable = NULL;
+  tool->display   = NULL;
+  g_list_free (tool->drawables);
+  tool->drawables = NULL;
 
   if (options->instant_toggle)
     gtk_widget_set_sensitive (options->instant_toggle, TRUE);
@@ -840,15 +844,17 @@ gimp_gradient_tool_precalc_shapeburst (GimpGradientTool *gradient_tool)
   GimpTool            *tool    = GIMP_TOOL (gradient_tool);
   gint                 x, y, width, height;
 
-  if (gradient_tool->dist_buffer || ! tool->drawable)
+  if (gradient_tool->dist_buffer || ! tool->drawables)
     return;
 
-  if (! gimp_item_mask_intersect (GIMP_ITEM (tool->drawable),
+  g_return_if_fail (g_list_length (tool->drawables) == 1);
+
+  if (! gimp_item_mask_intersect (GIMP_ITEM (tool->drawables->data),
                                   &x, &y, &width, &height))
     return;
 
   gradient_tool->dist_buffer =
-    gimp_drawable_gradient_shapeburst_distmap (tool->drawable,
+    gimp_drawable_gradient_shapeburst_distmap (tool->drawables->data,
                                                options->distance_metric,
                                                GEGL_RECTANGLE (x, y, width, height),
                                                GIMP_PROGRESS (gradient_tool));
@@ -924,7 +930,7 @@ gimp_gradient_tool_update_graph (GimpGradientTool *gradient_tool)
   GimpGradientOptions *options = GIMP_GRADIENT_TOOL_GET_OPTIONS (gradient_tool);
   gint                 off_x, off_y;
 
-  gimp_item_get_offset (GIMP_ITEM (tool->drawable), &off_x, &off_y);
+  gimp_item_get_offset (GIMP_ITEM (tool->drawables->data), &off_x, &off_y);
 
 #if 0
   if (gimp_gradient_tool_is_shapeburst (gradient_tool))
@@ -962,7 +968,7 @@ gimp_gradient_tool_update_graph (GimpGradientTool *gradient_tool)
       gdouble       start_x, start_y;
       gdouble       end_x,   end_y;
 
-      gimp_item_mask_intersect (GIMP_ITEM (tool->drawable),
+      gimp_item_mask_intersect (GIMP_ITEM (tool->drawables->data),
                                 &roi.x, &roi.y, &roi.width, &roi.height);
 
       start_x = gradient_tool->start_x - off_x;
@@ -970,7 +976,7 @@ gimp_gradient_tool_update_graph (GimpGradientTool *gradient_tool)
       end_x   = gradient_tool->end_x   - off_x;
       end_y   = gradient_tool->end_y   - off_y;
 
-      gimp_drawable_gradient_adjust_coords (tool->drawable,
+      gimp_drawable_gradient_adjust_coords (tool->drawables->data,
                                             options->gradient_type,
                                             &roi,
                                             &start_x, &start_y, &end_x, &end_y);
diff --git a/app/tools/gimplevelstool.c b/app/tools/gimplevelstool.c
index 2620cf37a6..dd29d74726 100644
--- a/app/tools/gimplevelstool.c
+++ b/app/tools/gimplevelstool.c
@@ -187,7 +187,8 @@ gimp_levels_tool_initialize (GimpTool     *tool,
   GimpFilterTool   *filter_tool = GIMP_FILTER_TOOL (tool);
   GimpLevelsTool   *l_tool      = GIMP_LEVELS_TOOL (tool);
   GimpImage        *image       = gimp_display_get_image (display);
-  GimpDrawable     *drawable    = gimp_image_get_active_drawable (image);
+  GList            *drawables;
+  GimpDrawable     *drawable;
   GimpLevelsConfig *config;
   gdouble           scale_factor;
   gdouble           step_increment;
@@ -199,6 +200,22 @@ gimp_levels_tool_initialize (GimpTool     *tool,
       return FALSE;
     }
 
+  drawables = gimp_image_get_selected_drawables (image);
+  if (g_list_length (drawables) != 1)
+    {
+      if (g_list_length (drawables) > 1)
+        gimp_tool_message_literal (tool, display,
+                                   _("Cannot modify multiple drawables. Select only one."));
+      else
+        gimp_tool_message_literal (tool, display, _("No selected drawables."));
+
+      g_list_free (drawables);
+      return FALSE;
+    }
+
+  drawable = drawables->data;
+  g_list_free (drawables);
+
   config = GIMP_LEVELS_CONFIG (filter_tool->config);
 
   g_clear_object (&l_tool->histogram);
@@ -679,7 +696,7 @@ gimp_levels_tool_config_notify (GimpFilterTool   *filter_tool,
       levels_tool->histogram = gimp_histogram_new (levels_config->trc);
 
       levels_tool->histogram_async = gimp_drawable_calculate_histogram_async
-        (GIMP_TOOL (filter_tool)->drawable, levels_tool->histogram, FALSE);
+        (GIMP_TOOL (filter_tool)->drawables->data, levels_tool->histogram, FALSE);
       gimp_histogram_view_set_histogram (GIMP_HISTOGRAM_VIEW (levels_tool->histogram_view),
                                          levels_tool->histogram);
     }
@@ -949,12 +966,14 @@ static gboolean
 levels_menu_sensitivity (gint      value,
                          gpointer  data)
 {
-  GimpDrawable         *drawable = GIMP_TOOL (data)->drawable;
+  GimpDrawable         *drawable;
   GimpHistogramChannel  channel  = value;
 
-  if (!drawable)
+  if (! GIMP_TOOL (data)->drawables)
     return FALSE;
 
+  drawable = GIMP_TOOL (data)->drawables->data;
+
   switch (channel)
     {
     case GIMP_HISTOGRAM_VALUE:
@@ -998,7 +1017,7 @@ levels_stretch_callback (GtkWidget      *widget,
     {
       gimp_levels_config_stretch (GIMP_LEVELS_CONFIG (filter_tool->config),
                                   levels_tool->histogram,
-                                  gimp_drawable_is_rgb (tool->drawable));
+                                  gimp_drawable_is_rgb (tool->drawables->data));
     }
 }
 
diff --git a/app/tools/gimpnpointdeformationtool.c b/app/tools/gimpnpointdeformationtool.c
index 0b653dee34..e44f4bad80 100644
--- a/app/tools/gimpnpointdeformationtool.c
+++ b/app/tools/gimpnpointdeformationtool.c
@@ -246,13 +246,16 @@ gimp_n_point_deformation_tool_start (GimpNPointDeformationTool *npd_tool,
 
   image = gimp_display_get_image (display);
 
-  tool->display  = display;
-  tool->drawable = gimp_image_get_active_drawable (image);
+  tool->display   = display;
+  g_list_free (tool->drawables);
+  tool->drawables = gimp_image_get_selected_drawables (image);
 
   npd_tool->active = TRUE;
 
+  g_return_if_fail (g_list_length (tool->drawables) == 1);
+
   /* create GEGL graph */
-  source_buffer  = gimp_drawable_get_buffer (tool->drawable);
+  source_buffer  = gimp_drawable_get_buffer (tool->drawables->data);
 
   preview_buffer = gegl_buffer_new (gegl_buffer_get_extent (source_buffer),
                                     babl_format ("cairo-ARGB32"));
@@ -293,7 +296,7 @@ gimp_n_point_deformation_tool_start (GimpNPointDeformationTool *npd_tool,
   npd_tool->lattice_points = g_new (GimpVector2,
                                     5 * model->hidden_model->num_of_bones);
 
-  gimp_item_get_offset (GIMP_ITEM (tool->drawable),
+  gimp_item_get_offset (GIMP_ITEM (tool->drawables->data),
                         &npd_tool->offset_x, &npd_tool->offset_y);
   gimp_npd_debug (("offset: %f %f\n", npd_tool->offset_x, npd_tool->offset_y));
 
@@ -302,7 +305,7 @@ gimp_n_point_deformation_tool_start (GimpNPointDeformationTool *npd_tool,
   gimp_n_point_deformation_tool_perform_deformation (npd_tool);
 
   /* hide original image */
-  gimp_item_set_visible (GIMP_ITEM (tool->drawable), FALSE, FALSE);
+  gimp_item_set_visible (GIMP_ITEM (tool->drawables->data), FALSE, FALSE);
   gimp_image_flush (image);
 
   /* create and start a deformation thread */
@@ -334,7 +337,7 @@ gimp_n_point_deformation_tool_commit (GimpNPointDeformationTool *npd_tool)
       gimp_tool_control_pop_preserve (tool->control);
 
       /* show original/deformed image */
-      gimp_item_set_visible (GIMP_ITEM (tool->drawable), TRUE, FALSE);
+      gimp_item_set_visible (GIMP_ITEM (tool->drawables->data), TRUE, FALSE);
       gimp_image_flush (gimp_display_get_image (tool->display));
 
       npd_tool->active = FALSE;
@@ -355,7 +358,7 @@ gimp_n_point_deformation_tool_halt (GimpNPointDeformationTool *npd_tool)
       gimp_n_point_deformation_tool_halt_threads (npd_tool);
 
       /* show original/deformed image */
-      gimp_item_set_visible (GIMP_ITEM (tool->drawable), TRUE, FALSE);
+      gimp_item_set_visible (GIMP_ITEM (tool->drawables->data), TRUE, FALSE);
       gimp_image_flush (gimp_display_get_image (tool->display));
 
       /* disable some options */
@@ -377,8 +380,9 @@ gimp_n_point_deformation_tool_halt (GimpNPointDeformationTool *npd_tool)
   g_clear_object (&npd_tool->preview_buffer);
   g_clear_pointer (&npd_tool->lattice_points, g_free);
 
-  tool->display  = NULL;
-  tool->drawable = NULL;
+  tool->display   = NULL;
+  g_list_free (tool->drawables);
+  tool->drawables = NULL;
 }
 
 static void
@@ -890,7 +894,7 @@ gimp_n_point_deformation_tool_motion (GimpTool         *tool,
 static gboolean
 gimp_n_point_deformation_tool_canvas_update_timeout (GimpNPointDeformationTool *npd_tool)
 {
-  if (! GIMP_TOOL (npd_tool)->drawable)
+  if (! GIMP_TOOL (npd_tool)->drawables->data)
     return FALSE;
 
   gimp_npd_debug (("canvas update thread\n"));
@@ -989,7 +993,7 @@ gimp_n_point_deformation_tool_apply_deformation (GimpNPointDeformationTool *npd_
   npd_options = GIMP_N_POINT_DEFORMATION_TOOL_GET_OPTIONS (npd_tool);
 
   image  = gimp_display_get_image (tool->display);
-  buffer = gimp_drawable_get_buffer (tool->drawable);
+  buffer = gimp_drawable_get_buffer (tool->drawables->data);
 
   width  = gegl_buffer_get_width  (buffer);
   height = gegl_buffer_get_height (buffer);
@@ -999,16 +1003,16 @@ gimp_n_point_deformation_tool_apply_deformation (GimpNPointDeformationTool *npd_
   gimp_n_point_deformation_tool_set_options (npd_tool, npd_options);
   npd_options->rigidity = prev;
 
-  gimp_drawable_push_undo (tool->drawable, _("N-Point Deformation"), NULL,
+  gimp_drawable_push_undo (tool->drawables->data, _("N-Point Deformation"), NULL,
                            0, 0, width, height);
 
 
   gimp_gegl_apply_operation (NULL, NULL, _("N-Point Deformation"),
                              npd_tool->npd_node,
-                             gimp_drawable_get_buffer (tool->drawable),
+                             gimp_drawable_get_buffer (tool->drawables->data),
                              NULL, FALSE);
 
-  gimp_drawable_update (tool->drawable,
+  gimp_drawable_update (tool->drawables->data,
                         0, 0, width, height);
 
   gimp_projection_flush (gimp_image_get_projection (image));
diff --git a/app/tools/gimpoffsettool.c b/app/tools/gimpoffsettool.c
index 7b9536a102..ce7f00309a 100644
--- a/app/tools/gimpoffsettool.c
+++ b/app/tools/gimpoffsettool.c
@@ -173,13 +173,27 @@ gimp_offset_tool_initialize (GimpTool     *tool,
   GimpOffsetTool *offset_tool = GIMP_OFFSET_TOOL (tool);
   GimpContext    *context     = GIMP_CONTEXT (GIMP_TOOL_GET_OPTIONS (tool));
   GimpImage      *image;
+  GimpDrawable   *drawable;
   gdouble         xres;
   gdouble         yres;
 
   if (! GIMP_TOOL_CLASS (parent_class)->initialize (tool, display, error))
     return FALSE;
 
-  image = gimp_item_get_image (GIMP_ITEM (tool->drawable));
+  if (g_list_length (tool->drawables) != 1)
+    {
+      if (g_list_length (tool->drawables) > 1)
+        gimp_tool_message_literal (tool, display,
+                                   _("Cannot modify multiple drawables. Select only one."));
+      else
+        gimp_tool_message_literal (tool, display, _("No selected drawables."));
+
+      return FALSE;
+    }
+
+  drawable = tool->drawables->data;
+
+  image = gimp_item_get_image (GIMP_ITEM (drawable));
 
   gimp_image_get_resolution (image, &xres, &yres);
 
@@ -194,17 +208,17 @@ gimp_offset_tool_initialize (GimpTool     *tool,
     GIMP_SIZE_ENTRY (offset_tool->offset_se), 1,
     yres, FALSE);
 
-  if (GIMP_IS_LAYER (tool->drawable))
+  if (GIMP_IS_LAYER (drawable))
     gimp_tool_gui_set_description (filter_tool->gui, _("Offset Layer"));
-  else if (GIMP_IS_LAYER_MASK (tool->drawable))
+  else if (GIMP_IS_LAYER_MASK (drawable))
     gimp_tool_gui_set_description (filter_tool->gui, _("Offset Layer Mask"));
-  else if (GIMP_IS_CHANNEL (tool->drawable))
+  else if (GIMP_IS_CHANNEL (drawable))
     gimp_tool_gui_set_description (filter_tool->gui, _("Offset Channel"));
   else
     g_warning ("%s: unexpected drawable type", G_STRFUNC);
 
   gtk_widget_set_sensitive (offset_tool->transparent_radio,
-                            gimp_drawable_has_alpha (tool->drawable));
+                            gimp_drawable_has_alpha (drawable));
 
   g_signal_handlers_unblock_by_func (offset_tool->offset_se,
                                      gimp_offset_tool_offset_changed,
@@ -403,7 +417,7 @@ gimp_offset_tool_oper_update (GimpTool         *tool,
                               gboolean          proximity,
                               GimpDisplay      *display)
 {
-  if (! tool->drawable ||
+  if (! tool->drawables ||
       gimp_filter_tool_on_guide (GIMP_FILTER_TOOL (tool),
                                  coords, display))
     {
@@ -425,7 +439,7 @@ gimp_offset_tool_cursor_update (GimpTool         *tool,
                                 GdkModifierType   state,
                                 GimpDisplay      *display)
 {
-  if (! tool->drawable ||
+  if (! tool->drawables ||
       gimp_filter_tool_on_guide (GIMP_FILTER_TOOL (tool),
                                  coords, display))
     {
@@ -708,8 +722,8 @@ gimp_offset_tool_update (GimpOffsetTool *offset_tool)
 
   type = orig_type;
 
-  if (tool->drawable                             &&
-      ! gimp_drawable_has_alpha (tool->drawable) &&
+  if (tool->drawables                            &&
+      ! gimp_drawable_has_alpha (tool->drawables->data) &&
       type == GIMP_OFFSET_TRANSPARENT)
     {
       type = GIMP_OFFSET_BACKGROUND;
diff --git a/app/tools/gimpoperationtool.c b/app/tools/gimpoperationtool.c
index d5894dc19f..ba7fd7c49b 100644
--- a/app/tools/gimpoperationtool.c
+++ b/app/tools/gimpoperationtool.c
@@ -292,7 +292,7 @@ gimp_operation_tool_reset (GimpFilterTool *filter_tool)
 
   GIMP_FILTER_TOOL_CLASS (parent_class)->reset (filter_tool);
 
-  if (filter_tool->config && GIMP_TOOL (op_tool)->drawable)
+  if (filter_tool->config && GIMP_TOOL (op_tool)->drawables)
     gimp_operation_tool_sync_op (op_tool, TRUE);
 
   gimp_operation_tool_relink_chains (op_tool);
@@ -308,7 +308,7 @@ gimp_operation_tool_set_config (GimpFilterTool *filter_tool,
 
   GIMP_FILTER_TOOL_CLASS (parent_class)->set_config (filter_tool, config);
 
-  if (filter_tool->config && GIMP_TOOL (op_tool)->drawable)
+  if (filter_tool->config && GIMP_TOOL (op_tool)->drawables)
     gimp_operation_tool_sync_op (op_tool, FALSE);
 
   gimp_operation_tool_relink_chains (op_tool);
@@ -857,7 +857,7 @@ gimp_operation_tool_set_operation (GimpOperationTool *op_tool,
 
   gimp_filter_tool_get_operation (filter_tool);
 
-  if (tool->drawable)
+  if (tool->drawables)
     gimp_operation_tool_sync_op (op_tool, TRUE);
 
   if (filter_tool->config && tool->display)
diff --git a/app/tools/gimppainttool.c b/app/tools/gimppainttool.c
index 011457604a..0aa2edc968 100644
--- a/app/tools/gimppainttool.c
+++ b/app/tools/gimppainttool.c
@@ -276,7 +276,8 @@ gimp_paint_tool_button_press (GimpTool            *tool,
   GimpGuiConfig    *config     = GIMP_GUI_CONFIG (display->gimp->config);
   GimpDisplayShell *shell      = gimp_display_get_shell (display);
   GimpImage        *image      = gimp_display_get_image (display);
-  GimpDrawable     *drawable   = gimp_image_get_active_drawable (image);
+  GList            *drawables;
+  GimpDrawable     *drawable;
   gboolean          constrain;
   GError           *error = NULL;
 
@@ -287,20 +288,28 @@ gimp_paint_tool_button_press (GimpTool            *tool,
       return;
     }
 
-  if (! drawable)
+  drawables  = gimp_image_get_selected_drawables (image);
+  if (g_list_length (drawables) != 1)
     {
-      if (g_list_length (gimp_image_get_selected_layers (image)) > 1)
+      if (g_list_length (drawables) > 1)
         gimp_tool_message_literal (tool, display,
-                                   _("Cannot paint on multiple layer. Select only one layer."));
+                                   _("Cannot paint on multiple layers. Select only one layer."));
       else
         gimp_tool_message_literal (tool, display,
-                                   _("No active drawable."));
+                                   _("No selected drawables."));
+
+      g_list_free (drawables);
       return;
     }
-  else if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
+
+  drawable = drawables->data;
+
+  if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
     {
       gimp_tool_message_literal (tool, display,
                                  _("Cannot paint on layer groups."));
+      g_list_free (drawables);
+
       return;
     }
 
@@ -309,6 +318,8 @@ gimp_paint_tool_button_press (GimpTool            *tool,
       gimp_tool_message_literal (tool, display,
                                  _("The active layer's pixels are locked."));
       gimp_tools_blink_lock_box (display->gimp, GIMP_ITEM (drawable));
+      g_list_free (drawables);
+
       return;
     }
 
@@ -327,6 +338,7 @@ gimp_paint_tool_button_press (GimpTool            *tool,
         gimp_widget_blink (mode_box);
 
       g_clear_error (&error);
+      g_list_free (drawables);
 
       return;
     }
@@ -336,6 +348,8 @@ gimp_paint_tool_button_press (GimpTool            *tool,
     {
       gimp_tool_message_literal (tool, display,
                                  _("The active layer is not visible."));
+      g_list_free (drawables);
+
       return;
     }
 
@@ -366,8 +380,8 @@ gimp_paint_tool_button_press (GimpTool            *tool,
       return;
     }
 
-  tool->display  = display;
-  tool->drawable = drawable;
+  tool->display   = display;
+  tool->drawables = drawables;
 
   /*  pause the current selection  */
   gimp_display_shell_selection_pause (shell);
@@ -517,13 +531,20 @@ gimp_paint_tool_cursor_update (GimpTool         *tool,
 
   if (! gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
     {
-      GimpImage    *image    = gimp_display_get_image (display);
-      GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+      GimpImage    *image     = gimp_display_get_image (display);
+      GList        *drawables = gimp_image_get_selected_drawables (image);
+      GimpDrawable *drawable  = NULL;
 
-      if (! drawable)
+      if (! drawables)
         return;
 
-      if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable))               ||
+      if (g_list_length (drawables) == 1)
+        drawable = drawables->data;
+
+      g_list_free (drawables);
+
+      if (! drawable                                                          ||
+          gimp_viewable_get_children (GIMP_VIEWABLE (drawable))               ||
           gimp_item_is_content_locked (GIMP_ITEM (drawable))                  ||
           ! gimp_paint_tool_check_alpha (paint_tool, drawable, display, NULL) ||
           ! (gimp_item_is_visible (GIMP_ITEM (drawable)) ||
@@ -574,7 +595,7 @@ gimp_paint_tool_oper_update (GimpTool         *tool,
   GimpPaintCore    *core          = paint_tool->core;
   GimpDisplayShell *shell         = gimp_display_get_shell (display);
   GimpImage        *image         = gimp_display_get_image (display);
-  GimpDrawable     *drawable      = gimp_image_get_active_drawable (image);
+  GList            *drawables;
 
   if (gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (tool)))
     {
@@ -604,7 +625,8 @@ gimp_paint_tool_oper_update (GimpTool         *tool,
       tool->display = display;
     }
 
-  if (drawable && proximity)
+  drawables = gimp_image_get_selected_drawables (image);
+  if (g_list_length (drawables) == 1 && proximity)
     {
       gchar    *status;
       gboolean  constrain_mask = gimp_get_constrain_behavior_mask ();
@@ -612,7 +634,7 @@ gimp_paint_tool_oper_update (GimpTool         *tool,
 
       core->cur_coords = *coords;
 
-      gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
+      gimp_item_get_offset (GIMP_ITEM (drawables->data), &off_x, &off_y);
 
       core->cur_coords.x -= off_x;
       core->cur_coords.y -= off_y;
@@ -691,6 +713,7 @@ gimp_paint_tool_oper_update (GimpTool         *tool,
                                                display);
 
   gimp_draw_tool_resume (draw_tool);
+  g_list_free (drawables);
 }
 
 static void
@@ -698,17 +721,22 @@ gimp_paint_tool_draw (GimpDrawTool *draw_tool)
 {
   GimpPaintTool *paint_tool = GIMP_PAINT_TOOL (draw_tool);
 
-
   if (paint_tool->active &&
       ! gimp_color_tool_is_enabled (GIMP_COLOR_TOOL (draw_tool)))
     {
       GimpPaintCore  *core       = paint_tool->core;
       GimpImage      *image      = gimp_display_get_image (draw_tool->display);
-      GimpDrawable   *drawable   = gimp_image_get_active_drawable (image);
       GimpCanvasItem *outline    = NULL;
       gboolean        line_drawn = FALSE;
       gdouble         cur_x, cur_y;
       gint            off_x, off_y;
+      GList          *drawables  = gimp_image_get_selected_drawables (image);
+      GimpDrawable   *drawable;
+
+      g_return_if_fail (g_list_length (drawables) == 1);
+
+      drawable = drawables->data;
+      g_list_free (drawables);
 
       gimp_item_get_offset (GIMP_ITEM (drawable), &off_x, &off_y);
 
diff --git a/app/tools/gimpperspectiveclonetool.c b/app/tools/gimpperspectiveclonetool.c
index 6630028060..b59d3a9869 100644
--- a/app/tools/gimpperspectiveclonetool.c
+++ b/app/tools/gimpperspectiveclonetool.c
@@ -209,20 +209,35 @@ gimp_perspective_clone_tool_initialize (GimpTool     *tool,
                                         GError      **error)
 {
   GimpPerspectiveCloneTool *clone_tool = GIMP_PERSPECTIVE_CLONE_TOOL (tool);
+  GimpImage                *image      = gimp_display_get_image (display);
+  GList                    *drawables;
 
   if (! GIMP_TOOL_CLASS (parent_class)->initialize (tool, display, error))
     {
       return FALSE;
     }
 
+  drawables = gimp_image_get_selected_drawables (image);
+  if (g_list_length (drawables) != 1)
+    {
+      if (g_list_length (drawables) > 1)
+        gimp_tool_message_literal (tool, display,
+                                   _("Cannot paint on multiple layers. Select only one layer."));
+      else
+        gimp_tool_message_literal (tool, display, _("No selected drawables."));
+
+      g_list_free (drawables);
+
+      return FALSE;
+    }
+
   if (display != tool->display)
     {
       GimpDisplayShell *shell = gimp_display_get_shell (display);
-      GimpImage        *image = gimp_display_get_image (display);
       gint              i;
 
-      tool->display  = display;
-      tool->drawable = gimp_image_get_active_drawable (image);
+      tool->display   = display;
+      tool->drawables = drawables;
 
       /*  Find the transform bounds initializing */
       gimp_perspective_clone_tool_bounds (clone_tool, display);
@@ -269,6 +284,10 @@ gimp_perspective_clone_tool_initialize (GimpTool     *tool,
       for (i = 0; i < TRANS_INFO_SIZE; i++)
         clone_tool->old_trans_info[i] = clone_tool->trans_info[i];
     }
+  else
+    {
+      g_list_free (drawables);
+    }
 
   return TRUE;
 }
@@ -777,8 +796,9 @@ gimp_perspective_clone_tool_halt (GimpPerspectiveCloneTool *clone_tool)
 
   g_clear_object (&clone_tool->widget);
 
-  tool->display  = NULL;
-  tool->drawable = NULL;
+  tool->display   = NULL;
+  g_list_free (tool->drawables);
+  tool->drawables = NULL;
 }
 
 static void
diff --git a/app/tools/gimpseamlessclonetool.c b/app/tools/gimpseamlessclonetool.c
index 79a97806d3..69beee0865 100644
--- a/app/tools/gimpseamlessclonetool.c
+++ b/app/tools/gimpseamlessclonetool.c
@@ -279,9 +279,15 @@ static void
 gimp_seamless_clone_tool_start (GimpSeamlessCloneTool *sc,
                                 GimpDisplay           *display)
 {
-  GimpTool     *tool     = GIMP_TOOL (sc);
-  GimpImage    *image    = gimp_display_get_image (display);
-  GimpDrawable *drawable = gimp_image_get_active_drawable (image);
+  GimpTool     *tool      = GIMP_TOOL (sc);
+  GimpImage    *image     = gimp_display_get_image (display);
+  GList        *drawables = gimp_image_get_selected_drawables (image);
+  GimpDrawable *drawable;
+
+  g_return_if_fail (g_list_length (drawables) == 1);
+
+  drawable = drawables->data;
+  g_list_free (drawables);
 
   /* First handle the paste - we need to make sure we have one in order
    * to do anything else.
@@ -718,7 +724,7 @@ gimp_seamless_clone_tool_render_node_update (GimpSeamlessCloneTool *sc)
   static gint rendered_yoff              = G_MAXINT;
 
   GimpSeamlessCloneOptions *options = GIMP_SEAMLESS_CLONE_TOOL_GET_OPTIONS (sc);
-  GimpDrawable *bg = GIMP_TOOL (sc)->drawable;
+  GimpDrawable *bg = GIMP_TOOL (sc)->drawables->data;
   gint          off_x, off_y;
 
   /* All properties stay the same. No need to update. */
@@ -775,7 +781,7 @@ gimp_seamless_clone_tool_filter_update (GimpSeamlessCloneTool *sc)
 {
   GimpTool         *tool  = GIMP_TOOL (sc);
   GimpDisplayShell *shell = gimp_display_get_shell (tool->display);
-  GimpItem         *item  = GIMP_ITEM (tool->drawable);
+  GimpItem         *item  = GIMP_ITEM (tool->drawables->data);
   gint              x, y;
   gint              w, h;
   gint              off_x, off_y;
diff --git a/app/tools/gimptexttool.c b/app/tools/gimptexttool.c
index 5398ab7d47..9fa6f5dd2c 100644
--- a/app/tools/gimptexttool.c
+++ b/app/tools/gimptexttool.c
@@ -1102,8 +1102,9 @@ gimp_text_tool_halt (GimpTextTool *text_tool)
   gimp_draw_tool_set_widget (GIMP_DRAW_TOOL (tool), NULL);
   g_clear_object (&text_tool->widget);
 
-  tool->display  = NULL;
-  tool->drawable = NULL;
+  tool->display   = NULL;
+  g_list_free (tool->drawables);
+  tool->drawables = NULL;
 }
 
 static void
@@ -2223,7 +2224,8 @@ gimp_text_tool_set_layer (GimpTextTool *text_tool,
               return FALSE;
             }
 
-          tool->drawable = GIMP_DRAWABLE (layer);
+          g_list_free (tool->drawables);
+          tool->drawables = g_list_prepend (NULL, GIMP_DRAWABLE (layer));
         }
     }
 
diff --git a/app/tools/gimpthresholdtool.c b/app/tools/gimpthresholdtool.c
index 826045d551..cdececd7b1 100644
--- a/app/tools/gimpthresholdtool.c
+++ b/app/tools/gimpthresholdtool.c
@@ -139,7 +139,8 @@ gimp_threshold_tool_initialize (GimpTool     *tool,
   GimpThresholdTool *t_tool      = GIMP_THRESHOLD_TOOL (tool);
   GimpFilterTool    *filter_tool = GIMP_FILTER_TOOL (tool);
   GimpImage         *image       = gimp_display_get_image (display);
-  GimpDrawable      *drawable    = gimp_image_get_active_drawable (image);
+  GList             *drawables;
+  GimpDrawable      *drawable;
   gdouble            low;
   gdouble            high;
   gint               n_bins;
@@ -149,6 +150,22 @@ gimp_threshold_tool_initialize (GimpTool     *tool,
       return FALSE;
     }
 
+  drawables = gimp_image_get_selected_drawables (image);
+  if (g_list_length (drawables) != 1)
+    {
+      if (g_list_length (drawables) > 1)
+        gimp_tool_message_literal (tool, display,
+                                   _("Cannot modify multiple drawables. Select only one."));
+      else
+        gimp_tool_message_literal (tool, display, _("No selected drawables."));
+
+      g_list_free (drawables);
+      return FALSE;
+    }
+
+  drawable = drawables->data;
+  g_list_free (drawables);
+
   g_clear_object (&t_tool->histogram_async);
 
   g_object_get (filter_tool->config,
@@ -338,12 +355,16 @@ static gboolean
 gimp_threshold_tool_channel_sensitive (gint     value,
                                        gpointer data)
 {
-  GimpDrawable         *drawable = GIMP_TOOL (data)->drawable;
-  GimpHistogramChannel  channel  = value;
+  GList                *drawables = GIMP_TOOL (data)->drawables;
+  GimpDrawable         *drawable;
+  GimpHistogramChannel  channel   = value;
 
-  if (!drawable)
+  if (!drawables)
     return FALSE;
 
+  g_return_val_if_fail (g_list_length (drawables) == 1, FALSE);
+  drawable = drawables->data;
+
   switch (channel)
     {
     case GIMP_HISTOGRAM_VALUE:
diff --git a/app/tools/gimptool.c b/app/tools/gimptool.c
index 99842ce542..0ad73e1ee1 100644
--- a/app/tools/gimptool.c
+++ b/app/tools/gimptool.c
@@ -197,7 +197,7 @@ gimp_tool_init (GimpTool *tool)
   tool->ID                    = global_tool_ID++;
   tool->control               = g_object_new (GIMP_TYPE_TOOL_CONTROL, NULL);
   tool->display               = NULL;
-  tool->drawable              = NULL;
+  tool->drawables             = NULL;
   tool->focus_display         = NULL;
   tool->modifier_state        = 0;
   tool->active_modifier_state = 0;
@@ -331,8 +331,9 @@ gimp_tool_real_control (GimpTool       *tool,
       break;
 
     case GIMP_TOOL_ACTION_HALT:
-      tool->display  = NULL;
-      tool->drawable = NULL;
+      tool->display   = NULL;
+      g_list_free (tool->drawables);
+      tool->drawables = NULL;
       break;
 
     case GIMP_TOOL_ACTION_COMMIT:
@@ -352,8 +353,9 @@ gimp_tool_real_button_press (GimpTool            *tool,
     {
       GimpImage *image = gimp_display_get_image (display);
 
-      tool->display  = display;
-      tool->drawable = gimp_image_get_active_drawable (image);
+      tool->display   = display;
+      g_list_free (tool->drawables);
+      tool->drawables = gimp_image_get_selected_drawables (image);
 
       gimp_tool_control_activate (tool->control);
     }
diff --git a/app/tools/gimptool.h b/app/tools/gimptool.h
index 171636338d..aeaef5163a 100644
--- a/app/tools/gimptool.h
+++ b/app/tools/gimptool.h
@@ -50,7 +50,7 @@ struct _GimpTool
   GimpToolControl *control;
 
   GimpDisplay     *display;     /*  pointer to currently active display    */
-  GimpDrawable    *drawable;    /*  pointer to the tool's current drawable */
+  GList           *drawables;   /*  list of the tool's current drawables   */
 
   /*  private state of gimp_tool_set_focus_display() and
    *  gimp_tool_set_[active_]modifier_state()
diff --git a/app/tools/gimptransformgridtool.c b/app/tools/gimptransformgridtool.c
index 8802850bb0..191c56dc4f 100644
--- a/app/tools/gimptransformgridtool.c
+++ b/app/tools/gimptransformgridtool.c
@@ -339,7 +339,7 @@ gimp_transform_grid_tool_initialize (GimpTool     *tool,
   GimpTransformGridTool    *tg_tool    = GIMP_TRANSFORM_GRID_TOOL (tool);
   GimpTransformGridOptions *tg_options = GIMP_TRANSFORM_GRID_TOOL_GET_OPTIONS (tool);
   GimpImage                *image      = gimp_display_get_image (display);
-  GimpDrawable             *drawable   = gimp_image_get_active_drawable (image);
+  GList                    *drawables;
   GimpObject               *object;
   UndoInfo                 *undo_info;
 
@@ -348,8 +348,21 @@ gimp_transform_grid_tool_initialize (GimpTool     *tool,
   if (! object)
     return FALSE;
 
+  drawables = gimp_image_get_selected_drawables (image);
+  if (g_list_length (drawables) != 1)
+    {
+      if (g_list_length (drawables) > 1)
+        gimp_tool_message_literal (tool, display,
+                                   _("Cannot modify multiple drawables. Select only one."));
+      else
+        gimp_tool_message_literal (tool, display, _("No active drawables."));
+
+      g_list_free (drawables);
+      return FALSE;
+    }
+
   tool->display   = display;
-  tool->drawable  = drawable;
+  tool->drawables = drawables;
 
   tr_tool->object = object;
 
@@ -762,7 +775,9 @@ gimp_transform_grid_tool_draw (GimpDrawTool *draw_tool)
         }
       else
         {
-          pickable = GIMP_PICKABLE (tool->drawable);
+          g_return_if_fail (g_list_length (tool->drawables) == 1);
+
+          pickable = GIMP_PICKABLE (tool->drawables->data);
         }
 
       tg_tool->preview =
@@ -1209,7 +1224,8 @@ gimp_transform_grid_tool_halt (GimpTransformGridTool *tg_tool)
     }
 
   tool->display   = NULL;
-  tool->drawable  = NULL;
+  g_list_free (tool->drawables);
+  tool->drawables = NULL;
 
   if (tr_tool->object)
     {
@@ -1720,7 +1736,7 @@ gimp_transform_grid_tool_update_preview (GimpTransformGridTool *tg_tool)
           g_object_set (
             tg_tool->preview,
             "transform", &tr_tool->transform,
-            "clip",      gimp_item_get_clip (GIMP_ITEM (tool->drawable),
+            "clip",      gimp_item_get_clip (GIMP_ITEM (tool->drawables->data),
                                              tr_options->clip),
             "opacity",   tg_options->preview_opacity,
             NULL);
@@ -1781,8 +1797,10 @@ gimp_transform_grid_tool_update_filters (GimpTransformGridTool *tg_tool)
   if (! tg_tool->filters)
     return;
 
+  g_return_if_fail (g_list_length (tool->drawables) == 1);
+
   if (options->preview_linked &&
-      gimp_item_get_linked (GIMP_ITEM (tool->drawable)))
+      gimp_item_get_linked (GIMP_ITEM (tool->drawables->data)))
     {
       GimpImage *image = gimp_display_get_image (tool->display);
 
@@ -1795,7 +1813,7 @@ gimp_transform_grid_tool_update_filters (GimpTransformGridTool *tg_tool)
     }
   else
     {
-      drawables = g_list_prepend (NULL, tool->drawable);
+      drawables = g_list_copy (tool->drawables);
     }
 
   new_drawables = g_hash_table_new (g_direct_hash, g_direct_equal);
diff --git a/app/tools/gimpwarptool.c b/app/tools/gimpwarptool.c
index 1ab17b95b0..de60c2debc 100644
--- a/app/tools/gimpwarptool.c
+++ b/app/tools/gimpwarptool.c
@@ -311,6 +311,8 @@ gimp_warp_tool_button_press (GimpTool            *tool,
   if (! gimp_warp_tool_can_stroke (wt, display, TRUE))
     return;
 
+  g_return_if_fail (g_list_length (tool->drawables) == 1);
+
   wt->current_stroke = gegl_path_new ();
 
   wt->last_pos.x = coords->x;
@@ -334,7 +336,7 @@ gimp_warp_tool_button_press (GimpTool            *tool,
   gimp_warp_tool_add_op (wt, new_op);
   g_object_unref (new_op);
 
-  gimp_item_get_offset (GIMP_ITEM (tool->drawable), &off_x, &off_y);
+  gimp_item_get_offset (GIMP_ITEM (tool->drawables->data), &off_x, &off_y);
 
   gimp_warp_tool_stroke_append (wt,
                                 'M', wt->last_pos.x - off_x,
@@ -447,7 +449,7 @@ gimp_warp_tool_motion (GimpTool         *tool,
               gimp_draw_tool_pause (GIMP_DRAW_TOOL (tool));
             }
 
-          gimp_item_get_offset (GIMP_ITEM (tool->drawable), &off_x, &off_y);
+          gimp_item_get_offset (GIMP_ITEM (tool->drawables->data), &off_x, &off_y);
 
           gimp_warp_tool_stroke_append (wt,
                                         'L', wt->last_pos.x - off_x,
@@ -755,27 +757,34 @@ gimp_warp_tool_can_stroke (GimpWarpTool *wt,
                            GimpDisplay  *display,
                            gboolean      show_message)
 {
-  GimpTool        *tool     = GIMP_TOOL (wt);
-  GimpWarpOptions *options  = GIMP_WARP_TOOL_GET_OPTIONS (wt);
-  GimpGuiConfig   *config   = GIMP_GUI_CONFIG (display->gimp->config);
-  GimpImage       *image    = gimp_display_get_image (display);
-  GimpDrawable    *drawable = gimp_image_get_active_drawable (image);
-
-  if (! drawable)
+  GimpTool        *tool      = GIMP_TOOL (wt);
+  GimpWarpOptions *options   = GIMP_WARP_TOOL_GET_OPTIONS (wt);
+  GimpGuiConfig   *config    = GIMP_GUI_CONFIG (display->gimp->config);
+  GimpImage       *image     = gimp_display_get_image (display);
+  GList           *drawables = gimp_image_get_selected_drawables (image);
+  GimpDrawable    *drawable;
+
+  if (g_list_length (drawables) != 1)
     {
       if (show_message)
         {
-          if (g_list_length (gimp_image_get_selected_layers (image)) > 1)
+          if (g_list_length (drawables) > 1)
             gimp_tool_message_literal (tool, display,
                                        _("Cannot warp multiple layers. Select only one layer."));
           else
             gimp_tool_message_literal (tool, display,
-                                       _("No active drawable."));
+                                       _("No active drawables."));
         }
 
+      g_list_free (drawables);
+
       return FALSE;
     }
-  else if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
+
+  drawable = drawables->data;
+  g_list_free (drawables);
+
+  if (gimp_viewable_get_children (GIMP_VIEWABLE (drawable)))
     {
       if (show_message)
         {
@@ -870,15 +879,18 @@ gimp_warp_tool_start (GimpWarpTool *wt,
   GimpTool        *tool     = GIMP_TOOL (wt);
   GimpWarpOptions *options  = GIMP_WARP_TOOL_GET_OPTIONS (wt);
   GimpImage       *image    = gimp_display_get_image (display);
-  GimpDrawable    *drawable = gimp_image_get_active_drawable (image);
+  GimpDrawable    *drawable;
   const Babl      *format;
   GeglRectangle    bbox;
 
   if (! gimp_warp_tool_can_stroke (wt, display, TRUE))
     return FALSE;
 
-  tool->display  = display;
-  tool->drawable = drawable;
+  tool->display   = display;
+  g_list_free (tool->drawables);
+  tool->drawables = gimp_image_get_selected_drawables (image);
+
+  drawable = tool->drawables->data;
 
   /* Create the coords buffer, with the size of the selection */
   format = babl_format_n (babl_type ("float"), 2);
@@ -935,8 +947,9 @@ gimp_warp_tool_halt (GimpWarpTool *wt)
       wt->redo_stack = NULL;
     }
 
-  tool->display  = NULL;
-  tool->drawable = NULL;
+  tool->display   = NULL;
+  g_list_free (tool->drawables);
+  tool->drawables = NULL;
 
   if (gimp_draw_tool_is_active (GIMP_DRAW_TOOL (wt)))
     gimp_draw_tool_stop (GIMP_DRAW_TOOL (wt));
@@ -1009,7 +1022,9 @@ gimp_warp_tool_stroke_timer (GimpWarpTool *wt)
   GimpTool *tool = GIMP_TOOL (wt);
   gint      off_x, off_y;
 
-  gimp_item_get_offset (GIMP_ITEM (tool->drawable), &off_x, &off_y);
+  g_return_val_if_fail (g_list_length (tool->drawables) == 1, FALSE);
+
+  gimp_item_get_offset (GIMP_ITEM (tool->drawables->data), &off_x, &off_y);
 
   gimp_warp_tool_stroke_append (wt,
                                 'L', wt->last_pos.x - off_x,
@@ -1401,6 +1416,8 @@ gimp_warp_tool_animate (GimpWarpTool *wt)
   GtkWidget       *widget;
   gint             i;
 
+  g_return_if_fail (g_list_length (tool->drawables) == 1);
+
   if (! gimp_warp_tool_can_undo (tool, tool->display))
     {
       gimp_tool_message_literal (tool, tool->display,
@@ -1420,17 +1437,17 @@ gimp_warp_tool_animate (GimpWarpTool *wt)
   gimp_progress_start (GIMP_PROGRESS (tool), FALSE,
                        _("Rendering Frame %d"), 1);
 
-  orig_image = gimp_item_get_image (GIMP_ITEM (tool->drawable));
+  orig_image = gimp_item_get_image (GIMP_ITEM (tool->drawables->data));
 
   image = gimp_create_image (orig_image->gimp,
-                             gimp_item_get_width  (GIMP_ITEM (tool->drawable)),
-                             gimp_item_get_height (GIMP_ITEM (tool->drawable)),
-                             gimp_drawable_get_base_type (tool->drawable),
-                             gimp_drawable_get_precision (tool->drawable),
+                             gimp_item_get_width  (GIMP_ITEM (tool->drawables->data)),
+                             gimp_item_get_height (GIMP_ITEM (tool->drawables->data)),
+                             gimp_drawable_get_base_type (tool->drawables->data),
+                             gimp_drawable_get_precision (tool->drawables->data),
                              TRUE);
 
   /*  the first frame is always the unwarped image  */
-  layer = GIMP_LAYER (gimp_item_convert (GIMP_ITEM (tool->drawable), image,
+  layer = GIMP_LAYER (gimp_item_convert (GIMP_ITEM (tool->drawables->data), image,
                                          GIMP_TYPE_LAYER));
   gimp_object_take_name (GIMP_OBJECT (layer),
                          g_strdup_printf (_("Frame %d"), 1));
@@ -1487,7 +1504,7 @@ gimp_warp_tool_animate (GimpWarpTool *wt)
   gimp_progress_end (GIMP_PROGRESS (tool));
 
   /*  recreate the image map  */
-  gimp_warp_tool_create_filter (wt, tool->drawable);
+  gimp_warp_tool_create_filter (wt, tool->drawables->data);
   gimp_warp_tool_update_stroke (wt, NULL);
 
   widget = GTK_WIDGET (gimp_display_get_shell (tool->display));
diff --git a/app/tools/tool_manager.c b/app/tools/tool_manager.c
index 296606a70e..5a9b815b90 100644
--- a/app/tools/tool_manager.c
+++ b/app/tools/tool_manager.c
@@ -266,7 +266,8 @@ tool_manager_initialize_active (Gimp        *gimp,
         {
           GimpImage *image = gimp_display_get_image (display);
 
-          tool->drawable = gimp_image_get_active_drawable (image);
+          g_list_free (tool->drawables);
+          tool->drawables = gimp_image_get_selected_drawables (image);
 
           return TRUE;
         }


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