[gimp/wip/Jehan/issue-498-quick-brush-edit: 24/48] app: allow to change the brush size on alt-right click.




commit f734912399747b497d37f7af0633fbc83c9b356f
Author: Jehan <jehan girinstud io>
Date:   Tue Feb 15 00:10:34 2022 +0100

    app: allow to change the brush size on alt-right click.
    
    I started from mitch's patch (though code changed so it was not working,
    yet I ended up with quite a different direction).
    
    Modified from original proposition in #498:
    
    * Do not mix opacity and brush size in a same action, one on horizontal
      movement, the other on vertical. The problem is that it's hard to stay
      perfectly horizontal or vertical, so you nearly necessarily change one
      while changing the other and this would be frustrating.
    * Do not just use modifiers, but modifiers + right click. The logics is
      that left (or whatever is the first button) click is for the tool
      actions. The middle click for navigation (panning, rotation, and even
      layer navigation now). Right click for now is only for menu. With this
      change, let's use right click for various settings-related changes
      too. Also we already have people complaining with things like canvas
      rotation happening unexpectedly even though it requires button clicks.
      Imagine an action just made of modifiers! Many people would hit these
      by mistake all the time!
    * Focus on brush size only for now. Instead of just calling the action
      repetitively with the "SElECT_NEXT" action as proposed in the original
      patch by mitch, let's compute the actual size between the press and
      release. This would allow to have a real visual hint and also would
      make it a lot more useful and meaningful to be an on-canvas change.
      Say you want to reproduce a stroke size on canvas. You can click the
      center and expand to retrieve approximately the size without computing
      it in pixels.
    
    Limitations and future work:
    
    * This is a first draft and I still want to test if it works well with
      the "lock brush to view" and with scale factor > 1.
    * I want to associate this with work done for #7034 so that visual hint
      still appear even when we have no visual hint set.
    * I am not so fond of with the way we use enum actions which doesn't
      really make satisfying logics (I hacked a bit over it, but it's
      getting ugly). I'm considering creating int/double actions to really
      set some values with exact numbers through actions.
    * Right now we need to stop the right click first. I want to be able to
      stop the brush sizing with releasing Alt too.
    * It would be nice to make this all more customizable, which is why I
      called internal variable "mod1_setting". The goal will be to have
      other types of actions possibly. Also it could be deactivatable for
      people really not liking these or hitting these by mistake (while not
      needing these). Same for the navigation shorcuts.
    * Similarly the right-click menu could be deactivatable or switched to
      other actions conditionally (through Preferences). It is doubtful how
      useful it is (compared to using the same menus on top of the GUI)
      though I don't want to just delete the option because some people
      would clearly be used to it.
    * I think we should start breaking down the whole tool events code a bit
      more, in particular the function gimp_display_shell_canvas_tool_events().
    * For more settings, a small on-canvas GUI could be of interest where
      you could customize various values through sliders and buttons, and
      also where you could put your favorite brushes or dynamics or whatnot.
      It's not replacing the more complete dockable but could be a nice
      quick version for fast editing.

 app/actions/actions.c                      |  46 ++++++++++--
 app/actions/actions.h                      |   6 +-
 app/actions/context-commands.c             |  42 +++++------
 app/actions/layers-commands.c              |   4 +-
 app/actions/tools-commands.c               |  36 ++++-----
 app/actions/view-commands.c                |  10 +--
 app/display/gimpdisplayshell-tool-events.c | 116 +++++++++++++++++++++++++----
 app/display/gimpdisplayshell.h             |   2 +
 8 files changed, 194 insertions(+), 68 deletions(-)
---
diff --git a/app/actions/actions.c b/app/actions/actions.c
index caaedd8e4f..daa06ef9bb 100644
--- a/app/actions/actions.c
+++ b/app/actions/actions.c
@@ -492,6 +492,29 @@ action_data_sel_count (gpointer data)
     }
 }
 
+/* action_select_value:
+ * @select_type:
+ * @value:
+ * @min:
+ * max:
+ * def:
+ * small_inc:
+ * inc:
+ * skip_inc:
+ * delta_factor:
+ * wrap:
+ * set_to_value:
+ *
+ * For any valid enum @value (which are all negative), the corresponding
+ * action computes the semantic value (default, first, next, etc.).
+ * For a positive @value:
+ * - if @set_to_value is used, then @value is used as-is (possibly
+ *   wrapped if @wrap is set, clamped otherwise).
+ * - otherwise, @value is considered as a per-thousand value between the
+ *   @min and @max, allowing to compute the returned value.
+ *
+ * Returns: the computed value to use for the action.
+ */
 gdouble
 action_select_value (GimpActionSelectType  select_type,
                      gdouble               value,
@@ -502,7 +525,8 @@ action_select_value (GimpActionSelectType  select_type,
                      gdouble               inc,
                      gdouble               skip_inc,
                      gdouble               delta_factor,
-                     gboolean              wrap)
+                     gboolean              wrap,
+                     gboolean              set_to_value)
 {
   switch (select_type)
     {
@@ -554,9 +578,16 @@ action_select_value (GimpActionSelectType  select_type,
 
     default:
       if ((gint) select_type >= 0)
-        value = (gdouble) select_type * (max - min) / 1000.0 + min;
+        {
+          if (set_to_value)
+            value = (gdouble) select_type;
+          else
+            value = (gdouble) select_type * (max - min) / 1000.0 + min;
+        }
       else
-        g_return_val_if_reached (value);
+        {
+          g_return_val_if_reached (value);
+        }
       break;
     }
 
@@ -585,7 +616,8 @@ action_select_property (GimpActionSelectType  select_type,
                         gdouble               inc,
                         gdouble               skip_inc,
                         gdouble               delta_factor,
-                        gboolean              wrap)
+                        gboolean              wrap,
+                        gboolean              set_to_value)
 {
   GParamSpec *pspec;
 
@@ -607,7 +639,8 @@ action_select_property (GimpActionSelectType  select_type,
                                    G_PARAM_SPEC_DOUBLE (pspec)->minimum,
                                    G_PARAM_SPEC_DOUBLE (pspec)->maximum,
                                    G_PARAM_SPEC_DOUBLE (pspec)->default_value,
-                                   small_inc, inc, skip_inc, delta_factor, wrap);
+                                   small_inc, inc, skip_inc, delta_factor, wrap,
+                                   set_to_value);
 
       g_object_set (object, property_name, value, NULL);
 
@@ -633,7 +666,8 @@ action_select_property (GimpActionSelectType  select_type,
                                    G_PARAM_SPEC_INT (pspec)->minimum,
                                    G_PARAM_SPEC_INT (pspec)->maximum,
                                    G_PARAM_SPEC_INT (pspec)->default_value,
-                                   small_inc, inc, skip_inc, delta_factor, wrap);
+                                   small_inc, inc, skip_inc, delta_factor, wrap,
+                                   set_to_value);
 
       g_object_set (object, property_name, value, NULL);
 
diff --git a/app/actions/actions.h b/app/actions/actions.h
index b34636c828..b325f91864 100644
--- a/app/actions/actions.h
+++ b/app/actions/actions.h
@@ -42,7 +42,8 @@ gdouble            action_select_value     (GimpActionSelectType  select_type,
                                             gdouble               inc,
                                             gdouble               skip_inc,
                                             gdouble               delta_factor,
-                                            gboolean              wrap);
+                                            gboolean              wrap,
+                                            gboolean              set_to_value);
 void               action_select_property  (GimpActionSelectType  select_type,
                                             GimpDisplay          *display,
                                             GObject              *object,
@@ -51,7 +52,8 @@ void               action_select_property  (GimpActionSelectType  select_type,
                                             gdouble               inc,
                                             gdouble               skip_inc,
                                             gdouble               delta_factor,
-                                            gboolean              wrap);
+                                            gboolean              wrap,
+                                            gboolean              set_to_value);
 GimpObject       * action_select_object    (GimpActionSelectType  select_type,
                                             GimpContainer        *container,
                                             GimpObject           *current);
diff --git a/app/actions/context-commands.c b/app/actions/context-commands.c
index e6c20049b9..167bb2d67b 100644
--- a/app/actions/context-commands.c
+++ b/app/actions/context-commands.c
@@ -145,7 +145,7 @@ context_foreground_red_cmd_callback (GimpAction *action,
   color.r = action_select_value (select_type,
                                  color.r,
                                  0.0, 1.0, 1.0,
-                                 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
+                                 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE, FALSE);
   gimp_context_set_foreground (context, &color);
 }
 
@@ -165,7 +165,7 @@ context_foreground_green_cmd_callback (GimpAction *action,
   color.g = action_select_value (select_type,
                                  color.g,
                                  0.0, 1.0, 1.0,
-                                 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
+                                 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE, FALSE);
   gimp_context_set_foreground (context, &color);
 }
 
@@ -185,7 +185,7 @@ context_foreground_blue_cmd_callback (GimpAction *action,
   color.b = action_select_value (select_type,
                                  color.b,
                                  0.0, 1.0, 1.0,
-                                 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
+                                 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE, FALSE);
   gimp_context_set_foreground (context, &color);
 }
 
@@ -205,7 +205,7 @@ context_background_red_cmd_callback (GimpAction *action,
   color.r = action_select_value (select_type,
                                  color.r,
                                  0.0, 1.0, 1.0,
-                                 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
+                                 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE, FALSE);
   gimp_context_set_background (context, &color);
 }
 
@@ -225,7 +225,7 @@ context_background_green_cmd_callback (GimpAction *action,
   color.g = action_select_value (select_type,
                                  color.g,
                                  0.0, 1.0, 1.0,
-                                 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
+                                 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE, FALSE);
   gimp_context_set_background (context, &color);
 }
 
@@ -245,7 +245,7 @@ context_background_blue_cmd_callback (GimpAction *action,
   color.b = action_select_value (select_type,
                                  color.b,
                                  0.0, 1.0, 1.0,
-                                 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
+                                 1.0 / 255.0, 0.01, 0.1, 0.0, FALSE, FALSE);
   gimp_context_set_background (context, &color);
 }
 
@@ -267,7 +267,7 @@ context_foreground_hue_cmd_callback (GimpAction *action,
   hsv.h = action_select_value (select_type,
                                hsv.h,
                                0.0, 1.0, 1.0,
-                               1.0 / 360.0, 0.01, 0.1, 0.0, FALSE);
+                               1.0 / 360.0, 0.01, 0.1, 0.0, FALSE, FALSE);
   gimp_hsv_to_rgb (&hsv, &color);
   gimp_context_set_foreground (context, &color);
 }
@@ -290,7 +290,7 @@ context_foreground_saturation_cmd_callback (GimpAction *action,
   hsv.s = action_select_value (select_type,
                                hsv.s,
                                0.0, 1.0, 1.0,
-                               0.01, 0.01, 0.1, 0.0, FALSE);
+                               0.01, 0.01, 0.1, 0.0, FALSE, FALSE);
   gimp_hsv_to_rgb (&hsv, &color);
   gimp_context_set_foreground (context, &color);
 }
@@ -313,7 +313,7 @@ context_foreground_value_cmd_callback (GimpAction *action,
   hsv.v = action_select_value (select_type,
                                hsv.v,
                                0.0, 1.0, 1.0,
-                               0.01, 0.01, 0.1, 0.0, FALSE);
+                               0.01, 0.01, 0.1, 0.0, FALSE, FALSE);
   gimp_hsv_to_rgb (&hsv, &color);
   gimp_context_set_foreground (context, &color);
 }
@@ -336,7 +336,7 @@ context_background_hue_cmd_callback (GimpAction *action,
   hsv.h = action_select_value (select_type,
                                hsv.h,
                                0.0, 1.0, 1.0,
-                               1.0 / 360.0, 0.01, 0.1, 0.0, FALSE);
+                               1.0 / 360.0, 0.01, 0.1, 0.0, FALSE, FALSE);
   gimp_hsv_to_rgb (&hsv, &color);
   gimp_context_set_background (context, &color);
 }
@@ -359,7 +359,7 @@ context_background_saturation_cmd_callback (GimpAction *action,
   hsv.s = action_select_value (select_type,
                                hsv.s,
                                0.0, 1.0, 1.0,
-                               0.01, 0.01, 0.1, 0.0, FALSE);
+                               0.01, 0.01, 0.1, 0.0, FALSE, FALSE);
   gimp_hsv_to_rgb (&hsv, &color);
   gimp_context_set_background (context, &color);
 }
@@ -382,7 +382,7 @@ context_background_value_cmd_callback (GimpAction *action,
   hsv.v = action_select_value (select_type,
                                hsv.v,
                                0.0, 1.0, 1.0,
-                               0.01, 0.01, 0.1, 0.0, FALSE);
+                               0.01, 0.01, 0.1, 0.0, FALSE, FALSE);
   gimp_hsv_to_rgb (&hsv, &color);
   gimp_context_set_background (context, &color);
 }
@@ -407,7 +407,7 @@ context_opacity_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "opacity",
-                              1.0 / 255.0, 0.01, 0.1, 0.1, FALSE);
+                              1.0 / 255.0, 0.01, 0.1, 0.1, FALSE, FALSE);
     }
 }
 
@@ -435,7 +435,7 @@ context_paint_mode_cmd_callback (GimpAction *action,
   index = context_paint_mode_index (paint_mode, modes, n_modes);
   index = action_select_value (select_type,
                                index, 0, n_modes - 1, 0,
-                               0.0, 1.0, 1.0, 0.0, FALSE);
+                               0.0, 1.0, 1.0, 0.0, FALSE, FALSE);
   paint_mode = modes[index];
   g_free (modes);
 
@@ -576,7 +576,7 @@ context_brush_spacing_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (brush),
                               "spacing",
-                              1.0, 5.0, 20.0, 0.1, FALSE);
+                              1.0, 5.0, 20.0, 0.1, FALSE, FALSE);
     }
 }
 
@@ -665,7 +665,7 @@ context_brush_radius_cmd_callback (GimpAction *action,
       radius = action_select_value (select_type,
                                     radius,
                                     min_radius, 4000.0, min_radius,
-                                    0.1, 1.0, 10.0, 0.05, FALSE);
+                                    0.1, 1.0, 10.0, 0.05, FALSE, FALSE);
       gimp_brush_generated_set_radius (generated, radius);
 
       display = action_data_get_display (data);
@@ -699,7 +699,7 @@ context_brush_spikes_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (brush),
                               "spikes",
-                              0.0, 1.0, 4.0, 0.1, FALSE);
+                              0.0, 1.0, 4.0, 0.1, FALSE, FALSE);
     }
 }
 
@@ -724,7 +724,7 @@ context_brush_hardness_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (brush),
                               "hardness",
-                              0.001, 0.01, 0.1, 0.1, FALSE);
+                              0.001, 0.01, 0.1, 0.1, FALSE, FALSE);
     }
 }
 
@@ -749,7 +749,7 @@ context_brush_aspect_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (brush),
                               "aspect-ratio",
-                              0.1, 1.0, 4.0, 0.1, FALSE);
+                              0.1, 1.0, 4.0, 0.1, FALSE, FALSE);
     }
 }
 
@@ -784,7 +784,7 @@ context_brush_angle_cmd_callback (GimpAction *action,
         angle = action_select_value (select_type,
                                      angle,
                                      0.0, 180.0, 0.0,
-                                     0.1, 1.0, 15.0, 0.1, TRUE);
+                                     0.1, 1.0, 15.0, 0.1, TRUE, FALSE);
 
       gimp_brush_generated_set_angle (generated, angle);
 
@@ -881,7 +881,7 @@ context_select_color (GimpActionSelectType  select_type,
   index = action_select_value (select_type,
                                index,
                                0, max, 0,
-                               0, 1, 4, 0, FALSE);
+                               0, 1, 4, 0, FALSE, FALSE);
 
   context_set_color_index (index, use_colormap, use_palette, color);
 }
diff --git a/app/actions/layers-commands.c b/app/actions/layers-commands.c
index 262fb4f297..9c16fa382b 100644
--- a/app/actions/layers-commands.c
+++ b/app/actions/layers-commands.c
@@ -1788,7 +1788,7 @@ layers_opacity_cmd_callback (GimpAction *action,
       opacity = action_select_value (select_type,
                                      gimp_layer_get_opacity (iter->data),
                                      0.0, 1.0, 1.0,
-                                     1.0 / 255.0, 0.01, 0.1, 0.0, FALSE);
+                                     1.0 / 255.0, 0.01, 0.1, 0.0, FALSE, FALSE);
       gimp_layer_set_opacity (iter->data, opacity, push_undo);
     }
 
@@ -1842,7 +1842,7 @@ layers_mode_cmd_callback (GimpAction *action,
       index = layers_mode_index (layer_mode, modes, n_modes);
       index = action_select_value (select_type,
                                    index, 0, n_modes - 1, 0,
-                                   0.0, 1.0, 1.0, 0.0, FALSE);
+                                   0.0, 1.0, 1.0, 0.0, FALSE, FALSE);
       layer_mode = modes[index];
       g_free (modes);
 
diff --git a/app/actions/tools-commands.c b/app/actions/tools-commands.c
index 7e84c5397e..9562c301c6 100644
--- a/app/actions/tools-commands.c
+++ b/app/actions/tools-commands.c
@@ -171,7 +171,7 @@ tools_color_average_radius_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "average-radius",
-                              1.0, 1.0, 10.0, 0.1, FALSE);
+                              1.0, 1.0, 10.0, 0.1, FALSE, FALSE);
     }
 }
 
@@ -195,7 +195,7 @@ tools_paintbrush_size_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "brush-size",
-                              0.1, 1.0, 10.0, 1.0, FALSE);
+                              0.1, 1.0, 10.0, 1.0, FALSE, TRUE);
     }
 }
 
@@ -219,7 +219,7 @@ tools_paintbrush_angle_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "brush-angle",
-                              0.1, 1.0, 15.0, 0.1, TRUE);
+                              0.1, 1.0, 15.0, 0.1, TRUE, FALSE);
     }
 }
 
@@ -243,7 +243,7 @@ tools_paintbrush_aspect_ratio_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "brush-aspect-ratio",
-                              0.01, 0.1, 1.0, 0.1, TRUE);
+                              0.01, 0.1, 1.0, 0.1, TRUE, FALSE);
     }
 }
 
@@ -267,7 +267,7 @@ tools_paintbrush_spacing_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "brush-spacing",
-                              0.001, 0.01, 0.1, 0.1, FALSE);
+                              0.001, 0.01, 0.1, 0.1, FALSE, FALSE);
     }
 }
 
@@ -291,7 +291,7 @@ tools_paintbrush_hardness_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "brush-hardness",
-                              0.001, 0.01, 0.1, 0.1, FALSE);
+                              0.001, 0.01, 0.1, 0.1, FALSE, FALSE);
     }
 }
 
@@ -315,7 +315,7 @@ tools_paintbrush_force_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "brush-force",
-                              0.001, 0.01, 0.1, 0.1, FALSE);
+                              0.001, 0.01, 0.1, 0.1, FALSE, FALSE);
     }
 }
 
@@ -339,7 +339,7 @@ tools_ink_blob_size_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "size",
-                              0.1, 1.0, 10.0, 0.1, FALSE);
+                              0.1, 1.0, 10.0, 0.1, FALSE, FALSE);
     }
 }
 
@@ -363,7 +363,7 @@ tools_ink_blob_aspect_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "blob-aspect",
-                              1.0, 0.1, 1.0, 0.1, FALSE);
+                              1.0, 0.1, 1.0, 0.1, FALSE, FALSE);
     }
 }
 
@@ -390,7 +390,7 @@ tools_ink_blob_angle_cmd_callback (GimpAction *action,
                               gimp_deg_to_rad (0.1),
                               gimp_deg_to_rad (1.0),
                               gimp_deg_to_rad (15.0),
-                              0.1, TRUE);
+                              0.1, TRUE, FALSE);
     }
 }
 
@@ -414,7 +414,7 @@ tools_airbrush_rate_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "rate",
-                              0.1, 1.0, 10.0, 0.1, FALSE);
+                              0.1, 1.0, 10.0, 0.1, FALSE, FALSE);
     }
 }
 
@@ -438,7 +438,7 @@ tools_airbrush_flow_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "flow",
-                              0.1, 1.0, 10.0, 0.1, FALSE);
+                              0.1, 1.0, 10.0, 0.1, FALSE, FALSE);
     }
 }
 
@@ -462,7 +462,7 @@ tools_mybrush_radius_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "radius",
-                              0.1, 0.1, 0.5, 1.0, FALSE);
+                              0.1, 0.1, 0.5, 1.0, FALSE, FALSE);
     }
 }
 
@@ -486,7 +486,7 @@ tools_mybrush_hardness_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "hardness",
-                              0.001, 0.01, 0.1, 1.0, FALSE);
+                              0.001, 0.01, 0.1, 1.0, FALSE, FALSE);
     }
 }
 
@@ -510,7 +510,7 @@ tools_fg_select_brush_size_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "stroke-width",
-                              1.0, 4.0, 16.0, 0.1, FALSE);
+                              1.0, 4.0, 16.0, 0.1, FALSE, FALSE);
     }
 }
 
@@ -534,7 +534,7 @@ tools_transform_preview_opacity_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "preview-opacity",
-                              0.01, 0.1, 0.5, 0.1, FALSE);
+                              0.01, 0.1, 0.5, 0.1, FALSE, FALSE);
     }
 }
 
@@ -558,7 +558,7 @@ tools_warp_effect_size_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "effect-size",
-                              1.0, 4.0, 16.0, 0.1, FALSE);
+                              1.0, 4.0, 16.0, 0.1, FALSE, FALSE);
     }
 }
 
@@ -582,7 +582,7 @@ tools_warp_effect_hardness_cmd_callback (GimpAction *action,
                               action_data_get_display (data),
                               G_OBJECT (tool_info->tool_options),
                               "effect-hardness",
-                              0.001, 0.01, 0.1, 0.1, FALSE);
+                              0.001, 0.01, 0.1, 0.1, FALSE, FALSE);
     }
 }
 
diff --git a/app/actions/view-commands.c b/app/actions/view-commands.c
index ecb0f4a129..8e70eaf4c1 100644
--- a/app/actions/view-commands.c
+++ b/app/actions/view-commands.c
@@ -247,7 +247,7 @@ view_zoom_cmd_callback (GimpAction *action,
                                      scale,
                                      0.0, 512.0, 1.0,
                                      1.0 / 8.0, 1.0, 16.0, 0.0,
-                                     FALSE);
+                                     FALSE, FALSE);
 
         /* min = 1.0 / 256,  max = 256.0                */
         /* scale = min *  (max / min)**(i/n), i = 0..n  */
@@ -435,7 +435,7 @@ view_rotate_absolute_cmd_callback (GimpAction *action,
                                0.0,
                                -180.0, 180.0, 0.0,
                                1.0, 15.0, 90.0, 0.0,
-                               TRUE);
+                               TRUE, FALSE);
 
   gimp_display_shell_rotate_to (shell, angle);
 }
@@ -459,7 +459,7 @@ view_rotate_relative_cmd_callback (GimpAction *action,
                                0.0,
                                -180.0, 180.0, 0.0,
                                1.0, 15.0, 90.0, 0.0,
-                               TRUE);
+                               TRUE, FALSE);
 
   gimp_display_shell_rotate (shell, delta);
 }
@@ -518,7 +518,7 @@ view_scroll_horizontal_cmd_callback (GimpAction *action,
                                 gtk_adjustment_get_step_increment (adj),
                                 gtk_adjustment_get_page_increment (adj),
                                 0,
-                                FALSE);
+                                FALSE, FALSE);
 
   gtk_adjustment_set_value (shell->hsbdata, offset);
 }
@@ -548,7 +548,7 @@ view_scroll_vertical_cmd_callback (GimpAction *action,
                                 gtk_adjustment_get_step_increment (adj),
                                 gtk_adjustment_get_page_increment (adj),
                                 0,
-                                FALSE);
+                                FALSE, FALSE);
 
   gtk_adjustment_set_value (shell->vsbdata, offset);
 }
diff --git a/app/display/gimpdisplayshell-tool-events.c b/app/display/gimpdisplayshell-tool-events.c
index ca6000b712..4d1f205d2c 100644
--- a/app/display/gimpdisplayshell-tool-events.c
+++ b/app/display/gimpdisplayshell-tool-events.c
@@ -17,6 +17,8 @@
 
 #include "config.h"
 
+#include <math.h>
+
 #include <gegl.h>
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
@@ -36,6 +38,7 @@
 #include "core/gimpimage-pick-item.h"
 #include "core/gimpitem.h"
 
+#include "widgets/gimpaction.h"
 #include "widgets/gimpcontrollers.h"
 #include "widgets/gimpcontrollerkeyboard.h"
 #include "widgets/gimpcontrollermouse.h"
@@ -45,6 +48,7 @@
 #include "widgets/gimpdevicemanager.h"
 #include "widgets/gimpdevices.h"
 #include "widgets/gimpdialogfactory.h"
+#include "widgets/gimpenumaction.h"
 #include "widgets/gimpuimanager.h"
 #include "widgets/gimpwidgets-utils.h"
 
@@ -138,6 +142,10 @@ static void       gimp_display_shell_untransform_event_coords (GimpDisplayShell
                                                                GimpCoords        *image_coords,
                                                                gboolean          *update_software_cursor);
 
+static void       gimp_display_shell_activate_enum_action     (GimpUIManager     *manager,
+                                                               const gchar       *action_desc,
+                                                               gint               value);
+
 
 /*  public functions  */
 
@@ -508,22 +516,35 @@ gimp_display_shell_canvas_tool_events (GtkWidget        *canvas,
 
         if (gdk_event_triggers_context_menu (event))
           {
-            GimpUIManager *ui_manager;
-            const gchar   *ui_path;
+            GimpUIManager   *ui_manager;
+            const gchar     *ui_path;
+            GdkModifierType  mod_state;
 
-            ui_manager = tool_manager_get_popup_active (gimp,
-                                                        &image_coords, state,
-                                                        display,
-                                                        &ui_path);
+            mod_state = state & gimp_get_all_modifiers_mask ();
 
-            if (! ui_manager)
+            /* Menu only with a right-click and no modifiers. */
+            if (mod_state == 0)
               {
-                ui_manager = shell->popup_manager;
-                ui_path    = "/dummy-menubar/image-popup";
-              }
+                ui_manager = tool_manager_get_popup_active (gimp,
+                                                            &image_coords, state,
+                                                            display,
+                                                            &ui_path);
 
-            gimp_ui_manager_ui_popup_at_pointer (ui_manager, ui_path, event,
-                                                 NULL, NULL);
+                if (! ui_manager)
+                  {
+                    ui_manager = shell->popup_manager;
+                    ui_path    = "/dummy-menubar/image-popup";
+                  }
+
+                gimp_ui_manager_ui_popup_at_pointer (ui_manager, ui_path, event,
+                                                     NULL, NULL);
+              }
+            else if (mod_state == GDK_MOD1_MASK)
+              {
+                shell->mod1_settings = TRUE;
+                gimp_display_shell_start_scrolling (shell, event, state,
+                                                    bevent->x, bevent->y);
+              }
           }
         else if (bevent->button == 1)
           {
@@ -703,7 +724,8 @@ gimp_display_shell_canvas_tool_events (GtkWidget        *canvas,
           }
         else if (bevent->button == 3)
           {
-            /* nop */
+            if (shell->mod1_settings)
+              gimp_display_shell_stop_scrolling (shell, event);
           }
         else
           {
@@ -1624,7 +1646,8 @@ gimp_display_shell_start_scrolling (GimpDisplayShell *shell,
   shell->rotating          = (state & gimp_get_extend_selection_mask ()) ? TRUE : FALSE;
   shell->rotate_drag_angle = shell->rotate_angle;
   shell->scaling           = (state & gimp_get_toggle_behavior_mask ()) ? TRUE : FALSE;
-  shell->layer_picking     = (state & GDK_MOD1_MASK) ? TRUE : FALSE;
+  shell->layer_picking     = ! gdk_event_triggers_context_menu (event) && (state & GDK_MOD1_MASK) ? TRUE : 
FALSE;
+  shell->mod1_settings     = gdk_event_triggers_context_menu (event) && (state & GDK_MOD1_MASK) ? TRUE : 
FALSE;
 
   if (shell->rotating)
     {
@@ -1679,6 +1702,10 @@ gimp_display_shell_start_scrolling (GimpDisplayShell *shell,
           shell->picked_layer = layer;
         }
     }
+  else if (shell->mod1_settings == TRUE)
+    {
+      /* no-op. */
+    }
   else
     gimp_display_shell_set_override_cursor (shell,
                                             (GimpCursorType) GDK_FLEUR);
@@ -1701,6 +1728,7 @@ gimp_display_shell_stop_scrolling (GimpDisplayShell *shell,
   shell->rotate_drag_angle = 0.0;
   shell->scaling           = FALSE;
   shell->layer_picking     = FALSE;
+  shell->mod1_settings     = FALSE;
 
   /* We may have ungrabbed the pointer when space was released while
    * mouse was down, to be able to catch a GDK_BUTTON_RELEASE event.
@@ -1740,6 +1768,36 @@ gimp_display_shell_handle_scrolling (GimpDisplayShell *shell,
     {
       /* Do nothing. We only pick the layer on click. */
     }
+  else if (shell->mod1_settings == TRUE)
+    {
+      GimpDisplay *display     = shell->display;
+      Gimp        *gimp        = gimp_display_get_gimp (display);
+      GimpTool    *active_tool = tool_manager_get_active (gimp);
+      const gchar *action;
+      gint         size;
+
+      /* Size in image pixels: distance between start and current
+       * position.
+       */
+      size = (gint) (sqrt (pow ((x - shell->scroll_start_x) / shell->scale_x, 2) +
+                           pow ((y - shell->scroll_start_y) / shell->scale_y, 2)) * 2.0);
+
+      /* TODO: different logics with "lock brush to view". */
+      /* TODO 2: scale aware? */
+      action = gimp_tool_control_get_action_size (active_tool->control);
+
+      if (action)
+        {
+          GimpImageWindow *window  = gimp_display_shell_get_window (shell);
+          GimpUIManager   *manager = gimp_image_window_get_ui_manager (window);
+
+          /* Special trick with these enum actions. If using any
+           * positive value, we get the GIMP_ACTION_SELECT_SET behavior
+           * which sets to the given value.
+           */
+          gimp_display_shell_activate_enum_action (manager, action, size);
+        }
+    }
   else
     {
       gimp_display_shell_scroll (shell,
@@ -2176,3 +2234,33 @@ gimp_display_shell_untransform_event_coords (GimpDisplayShell *shell,
         }
     }
 }
+
+static void
+gimp_display_shell_activate_enum_action (GimpUIManager *manager,
+                                         const gchar   *action_desc,
+                                         gint           value)
+{
+  gchar *group_name;
+  gchar *action_name;
+
+  group_name  = g_strdup (action_desc);
+  action_name = strchr (group_name, '/');
+
+  if (action_name)
+    {
+      GimpAction *action;
+
+      *action_name++ = '\0';
+
+      action = gimp_ui_manager_find_action (manager, group_name, action_name);
+
+      if (GIMP_IS_ENUM_ACTION (action) &&
+          GIMP_ENUM_ACTION (action)->value_variable)
+        {
+          gimp_action_emit_activate (action,
+                                     g_variant_new_int32 (value));
+        }
+    }
+
+  g_free (group_name);
+}
diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h
index 395364b863..fb1b04aff8 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -227,6 +227,8 @@ struct _GimpDisplayShell
   gboolean           layer_picking;
   GimpLayer         *picked_layer;
 
+  gboolean           mod1_settings;
+
   GeglBuffer        *mask;
   gint               mask_offset_x;
   gint               mask_offset_y;


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