[gimp/gtk3-port: 412/460] Enable and fix smooth scrolling and zooming



commit 02386e5c795cfb2c52399412547f261789226c50
Author: Michael Natterer <mitch gimp org>
Date:   Fri May 11 02:08:51 2018 +0200

    Enable and fix smooth scrolling and zooming
    
    - Fix gimp_scroll_adjustment_values() for smooth scroll events
    - Set GDK_SMOOTH_SCROLL_MASK on all widgets where we set GDK_SCROLL_MASK
    - Add GIMP_ZOOM_SMOOTH to enum GimpZoomType
    - Add "gdouble delta" to gimp_zoom_model_step()
    - Change the meaning of the "scale" parameter to "scale or delta" in
      all functions that take GimpZoomType and a scale factor.

 app/core/gimpmarshal.list                  |    1 +
 app/display/gimpcanvas.h                   |    1 +
 app/display/gimpdisplayshell-scale.c       |   10 ++++++--
 app/display/gimpdisplayshell-tool-events.c |   10 ++++++++
 app/display/gimpdisplayshell.c             |    3 +-
 app/display/gimpnavigationeditor.c         |    4 ++-
 app/widgets/gimpgradienteditor.c           |    4 ++-
 app/widgets/gimpnavigationview.c           |   19 +++++++++++----
 app/widgets/gimpnavigationview.h           |    3 +-
 app/widgets/gimpsearchpopup.c              |    3 +-
 app/widgets/gimptagpopup.c                 |    3 +-
 libgimp/gimpzoompreview.c                  |    6 +++++
 libgimpwidgets/gimppreview.c               |    1 +
 libgimpwidgets/gimpscrolledpreview.c       |   18 ++++++++------
 libgimpwidgets/gimpwidgetsenums.h          |    4 ++-
 libgimpwidgets/gimpzoommodel.c             |   33 +++++++++++++++++++++------
 libgimpwidgets/gimpzoommodel.h             |    3 +-
 17 files changed, 94 insertions(+), 32 deletions(-)
---
diff --git a/app/core/gimpmarshal.list b/app/core/gimpmarshal.list
index a79ef9b..4232c47 100644
--- a/app/core/gimpmarshal.list
+++ b/app/core/gimpmarshal.list
@@ -42,6 +42,7 @@ VOID: DOUBLE
 VOID: DOUBLE, DOUBLE
 VOID: DOUBLE, DOUBLE, DOUBLE, DOUBLE
 VOID: ENUM
+VOID: ENUM, DOUBLE
 VOID: ENUM, INT
 VOID: ENUM, INT, BOOLEAN
 VOID: ENUM, OBJECT
diff --git a/app/display/gimpcanvas.h b/app/display/gimpcanvas.h
index a4f02e8..e49bdfc 100644
--- a/app/display/gimpcanvas.h
+++ b/app/display/gimpcanvas.h
@@ -27,6 +27,7 @@
                                 GDK_BUTTON_PRESS_MASK        | \
                                 GDK_BUTTON_RELEASE_MASK      | \
                                 GDK_SCROLL_MASK              | \
+                                GDK_SMOOTH_SCROLL_MASK       | \
                                 GDK_STRUCTURE_MASK           | \
                                 GDK_ENTER_NOTIFY_MASK        | \
                                 GDK_LEAVE_NOTIFY_MASK        | \
diff --git a/app/display/gimpdisplayshell-scale.c b/app/display/gimpdisplayshell-scale.c
index 526f93f..a9f8753 100644
--- a/app/display/gimpdisplayshell-scale.c
+++ b/app/display/gimpdisplayshell-scale.c
@@ -353,6 +353,7 @@ gimp_display_shell_scale (GimpDisplayShell *shell,
 {
   GimpDisplayConfig *config;
   gdouble            current_scale;
+  gdouble            delta;
   gboolean           resize_window;
 
   g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
@@ -360,8 +361,11 @@ gimp_display_shell_scale (GimpDisplayShell *shell,
 
   current_scale = gimp_zoom_model_get_factor (shell->zoom);
 
+  if (zoom_type == GIMP_ZOOM_SMOOTH)
+    delta = new_scale;
+
   if (zoom_type != GIMP_ZOOM_TO)
-    new_scale = gimp_zoom_model_zoom_step (zoom_type, current_scale);
+    new_scale = gimp_zoom_model_zoom_step (zoom_type, current_scale, delta);
 
   if (SCALE_EQUALS (new_scale, current_scale))
     return;
@@ -760,14 +764,14 @@ gimp_display_shell_set_initial_scale (GimpDisplayShell *shell,
           new_scale = current * MIN (((gdouble) monitor_height) / shell_height,
                                      ((gdouble) monitor_width)  / shell_width);
 
-          new_scale = gimp_zoom_model_zoom_step (GIMP_ZOOM_OUT, new_scale);
+          new_scale = gimp_zoom_model_zoom_step (GIMP_ZOOM_OUT, new_scale, 0.0);
 
           /*  Since zooming out might skip a zoom step we zoom in
            *  again and test if we are small enough.
            */
           gimp_zoom_model_zoom (shell->zoom, GIMP_ZOOM_TO,
                                 gimp_zoom_model_zoom_step (GIMP_ZOOM_IN,
-                                                           new_scale));
+                                                           new_scale, 0.0));
 
           if (SCALEX (shell, image_width)  > monitor_width ||
               SCALEY (shell, image_height) > monitor_height)
diff --git a/app/display/gimpdisplayshell-tool-events.c b/app/display/gimpdisplayshell-tool-events.c
index 7a9fd53..dc7c11b 100644
--- a/app/display/gimpdisplayshell-tool-events.c
+++ b/app/display/gimpdisplayshell-tool-events.c
@@ -732,6 +732,8 @@ gimp_display_shell_canvas_tool_events (GtkWidget        *canvas,
           {
             if (state & gimp_get_toggle_behavior_mask ())
               {
+                gdouble delta;
+
                 switch (sevent->direction)
                   {
                   case GDK_SCROLL_UP:
@@ -748,6 +750,14 @@ gimp_display_shell_canvas_tool_events (GtkWidget        *canvas,
                                               GIMP_ZOOM_FOCUS_POINTER);
                     break;
 
+                  case GDK_SCROLL_SMOOTH:
+                    gdk_event_get_scroll_deltas (event, NULL, &delta);
+                    gimp_display_shell_scale (shell,
+                                              GIMP_ZOOM_SMOOTH,
+                                              delta,
+                                              GIMP_ZOOM_FOCUS_POINTER);
+                    break;
+
                   default:
                     break;
                   }
diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c
index 64f7cd6..ce6d39a 100644
--- a/app/display/gimpdisplayshell.c
+++ b/app/display/gimpdisplayshell.c
@@ -334,7 +334,8 @@ gimp_display_shell_init (GimpDisplayShell *shell)
                                               GDK_KEY_RELEASE_MASK       |
                                               GDK_FOCUS_CHANGE_MASK      |
                                               GDK_VISIBILITY_NOTIFY_MASK |
-                                              GDK_SCROLL_MASK));
+                                              GDK_SCROLL_MASK            |
+                                              GDK_SMOOTH_SCROLL_MASK));
 
   /*  zoom model callback  */
   g_signal_connect_swapped (shell->zoom, "zoomed",
diff --git a/app/display/gimpnavigationeditor.c b/app/display/gimpnavigationeditor.c
index 31e8b7d..479a6e5 100644
--- a/app/display/gimpnavigationeditor.c
+++ b/app/display/gimpnavigationeditor.c
@@ -80,6 +80,7 @@ static void        gimp_navigation_editor_marker_changed    (GimpNavigationView
                                                              GimpNavigationEditor *editor);
 static void        gimp_navigation_editor_zoom              (GimpNavigationView   *view,
                                                              GimpZoomType          direction,
+                                                             gdouble               delta,
                                                              GimpNavigationEditor *editor);
 static void        gimp_navigation_editor_scroll            (GimpNavigationView   *view,
                                                              GdkEventScroll       *sevent,
@@ -553,6 +554,7 @@ gimp_navigation_editor_marker_changed (GimpNavigationView   *view,
 static void
 gimp_navigation_editor_zoom (GimpNavigationView   *view,
                              GimpZoomType          direction,
+                             gdouble               delta,
                              GimpNavigationEditor *editor)
 {
   g_return_if_fail (direction != GIMP_ZOOM_TO);
@@ -562,7 +564,7 @@ gimp_navigation_editor_zoom (GimpNavigationView   *view,
       if (gimp_display_get_image (editor->shell->display))
         gimp_display_shell_scale (editor->shell,
                                   direction,
-                                  0.0,
+                                  delta,
                                   GIMP_ZOOM_FOCUS_BEST_GUESS);
     }
 }
diff --git a/app/widgets/gimpgradienteditor.c b/app/widgets/gimpgradienteditor.c
index d85f6fd..14e93e0 100644
--- a/app/widgets/gimpgradienteditor.c
+++ b/app/widgets/gimpgradienteditor.c
@@ -92,7 +92,8 @@
                               GDK_POINTER_MOTION_HINT_MASK | \
                               GDK_BUTTON_PRESS_MASK        | \
                               GDK_BUTTON_RELEASE_MASK      | \
-                              GDK_SCROLL_MASK)
+                              GDK_SCROLL_MASK              | \
+                              GDK_SMOOTH_SCROLL_MASK)
 
 #define GRAD_CONTROL_EVENT_MASK (GDK_EXPOSURE_MASK            | \
                                  GDK_LEAVE_NOTIFY_MASK        | \
@@ -101,6 +102,7 @@
                                  GDK_BUTTON_PRESS_MASK        | \
                                  GDK_BUTTON_RELEASE_MASK      | \
                                  GDK_SCROLL_MASK              | \
+                                 GDK_SMOOTH_SCROLL_MASK       | \
                                  GDK_BUTTON1_MOTION_MASK)
 
 
diff --git a/app/widgets/gimpnavigationview.c b/app/widgets/gimpnavigationview.c
index 627f647..982479a 100644
--- a/app/widgets/gimpnavigationview.c
+++ b/app/widgets/gimpnavigationview.c
@@ -138,9 +138,10 @@ gimp_navigation_view_class_init (GimpNavigationViewClass *klass)
                   G_SIGNAL_RUN_FIRST,
                   G_STRUCT_OFFSET (GimpNavigationViewClass, zoom),
                   NULL, NULL,
-                  gimp_marshal_VOID__ENUM,
-                  G_TYPE_NONE, 1,
-                  GIMP_TYPE_ZOOM_TYPE);
+                  gimp_marshal_VOID__ENUM_DOUBLE,
+                  G_TYPE_NONE, 2,
+                  GIMP_TYPE_ZOOM_TYPE,
+                  G_TYPE_DOUBLE);
 
   view_signals[SCROLL] =
     g_signal_new ("scroll",
@@ -167,6 +168,7 @@ gimp_navigation_view_init (GimpNavigationView *view)
   gtk_widget_set_can_focus (GTK_WIDGET (view), TRUE);
   gtk_widget_add_events (GTK_WIDGET (view),
                          GDK_SCROLL_MASK         |
+                         GDK_SMOOTH_SCROLL_MASK  |
                          GDK_POINTER_MOTION_MASK |
                          GDK_KEY_PRESS_MASK);
 
@@ -297,14 +299,21 @@ gimp_navigation_view_scroll (GtkWidget      *widget,
 {
   if (sevent->state & gimp_get_toggle_behavior_mask ())
     {
+      gdouble delta;
+
       switch (sevent->direction)
         {
         case GDK_SCROLL_UP:
-          g_signal_emit (widget, view_signals[ZOOM], 0, GIMP_ZOOM_IN);
+          g_signal_emit (widget, view_signals[ZOOM], 0, GIMP_ZOOM_IN, 0.0);
           break;
 
         case GDK_SCROLL_DOWN:
-          g_signal_emit (widget, view_signals[ZOOM], 0, GIMP_ZOOM_OUT);
+          g_signal_emit (widget, view_signals[ZOOM], 0, GIMP_ZOOM_OUT, 0.0);
+          break;
+
+        case GDK_SCROLL_SMOOTH:
+          gdk_event_get_scroll_deltas ((GdkEvent *) sevent, NULL, &delta);
+          g_signal_emit (widget, view_signals[ZOOM], 0, GIMP_ZOOM_SMOOTH, delta);
           break;
 
         default:
diff --git a/app/widgets/gimpnavigationview.h b/app/widgets/gimpnavigationview.h
index 22d7113..2a0545d 100644
--- a/app/widgets/gimpnavigationview.h
+++ b/app/widgets/gimpnavigationview.h
@@ -47,7 +47,8 @@ struct _GimpNavigationViewClass
                            gdouble             width,
                            gdouble             height);
   void (* zoom)           (GimpNavigationView *view,
-                           GimpZoomType        direction);
+                           GimpZoomType        direction,
+                           gdouble             delta);
   void (* scroll)         (GimpNavigationView *view,
                            GdkEventScroll     *sevent);
 };
diff --git a/app/widgets/gimpsearchpopup.c b/app/widgets/gimpsearchpopup.c
index 490afe7..e94f0dc 100644
--- a/app/widgets/gimpsearchpopup.c
+++ b/app/widgets/gimpsearchpopup.c
@@ -370,7 +370,8 @@ gimp_search_popup_constructed (GObject *object)
                          GDK_KEY_RELEASE_MASK  |
                          GDK_KEY_PRESS_MASK    |
                          GDK_BUTTON_PRESS_MASK |
-                         GDK_SCROLL_MASK);
+                         GDK_SCROLL_MASK       |
+                         GDK_SMOOTH_SCROLL_MASK);
 
   g_signal_connect (popup->priv->keyword_entry, "key-press-event",
                     G_CALLBACK (keyword_entry_key_press_event),
diff --git a/app/widgets/gimptagpopup.c b/app/widgets/gimptagpopup.c
index 38e89f9..be9d49b 100644
--- a/app/widgets/gimptagpopup.c
+++ b/app/widgets/gimptagpopup.c
@@ -162,7 +162,8 @@ gimp_tag_popup_init (GimpTagPopup *popup)
                          GDK_BUTTON_RELEASE_MASK |
                          GDK_POINTER_MOTION_MASK |
                          GDK_KEY_RELEASE_MASK    |
-                         GDK_SCROLL_MASK);
+                         GDK_SCROLL_MASK         |
+                         GDK_SMOOTH_SCROLL_MASK);
 
   gtk_style_context_add_class (gtk_widget_get_style_context (GTK_WIDGET (popup)),
                                GTK_STYLE_CLASS_MENU);
diff --git a/libgimp/gimpzoompreview.c b/libgimp/gimpzoompreview.c
index 7c02ec6..8190339 100644
--- a/libgimp/gimpzoompreview.c
+++ b/libgimp/gimpzoompreview.c
@@ -435,6 +435,7 @@ gimp_zoom_preview_scroll_event (GtkWidget       *widget,
   if (event->state & GDK_CONTROL_MASK)
     {
       GimpZoomPreviewPrivate *priv = GET_PRIVATE (preview);
+      gdouble                 delta;
 
       gimp_scrolled_preview_freeze (GIMP_SCROLLED_PREVIEW (preview));
 
@@ -448,6 +449,11 @@ gimp_zoom_preview_scroll_event (GtkWidget       *widget,
           gimp_zoom_model_zoom (priv->model, GIMP_ZOOM_OUT, 0.0);
           break;
 
+        case GDK_SCROLL_SMOOTH:
+          gdk_event_get_scroll_deltas ((GdkEvent *) event, NULL, &delta);
+          gimp_zoom_model_zoom (priv->model, GIMP_ZOOM_SMOOTH, delta);
+          break;
+
         default:
           break;
         }
diff --git a/libgimpwidgets/gimppreview.c b/libgimpwidgets/gimppreview.c
index d76a875..c066c1b 100644
--- a/libgimpwidgets/gimppreview.c
+++ b/libgimpwidgets/gimppreview.c
@@ -281,6 +281,7 @@ gimp_preview_init (GimpPreview *preview)
                          GDK_BUTTON_PRESS_MASK        |
                          GDK_BUTTON_RELEASE_MASK      |
                          GDK_SCROLL_MASK              |
+                         GDK_SMOOTH_SCROLL_MASK       |
                          GDK_POINTER_MOTION_HINT_MASK |
                          GDK_BUTTON_MOTION_MASK);
 
diff --git a/libgimpwidgets/gimpscrolledpreview.c b/libgimpwidgets/gimpscrolledpreview.c
index a7c73b3..ae375db 100644
--- a/libgimpwidgets/gimpscrolledpreview.c
+++ b/libgimpwidgets/gimpscrolledpreview.c
@@ -963,8 +963,8 @@ gimp_scroll_adjustment_values (GdkEventScroll *sevent,
 {
   GtkAdjustment *adj_x;
   GtkAdjustment *adj_y;
-  gdouble        page_size_x;
-  gdouble        page_size_y;
+  gdouble        scroll_unit_x;
+  gdouble        scroll_unit_y;
   gdouble        value_x = 0.0;
   gdouble        value_y = 0.0;
 
@@ -983,29 +983,31 @@ gimp_scroll_adjustment_values (GdkEventScroll *sevent,
       adj_y = vadj;
     }
 
-  page_size_x = gtk_adjustment_get_page_size (adj_x);
-  page_size_y = gtk_adjustment_get_page_size (adj_y);
+  scroll_unit_x = pow (gtk_adjustment_get_page_size (adj_x), 2.0 / 3.0);
+  scroll_unit_y = pow (gtk_adjustment_get_page_size (adj_y), 2.0 / 3.0);
 
   switch (sevent->direction)
     {
     case GDK_SCROLL_LEFT:
-      value_x = -pow (page_size_x, 2.0 / 3.0);
+      value_x = -scroll_unit_x;
       break;
 
     case GDK_SCROLL_RIGHT:
-      value_x = pow (page_size_x, 2.0 / 3.0);
+      value_x = scroll_unit_x;
       break;
 
     case GDK_SCROLL_UP:
-      value_y = -pow (page_size_y, 2.0 / 3.0);
+      value_y = -scroll_unit_y;
       break;
 
     case GDK_SCROLL_DOWN:
-      value_y = pow (page_size_y, 2.0 / 3.0);
+      value_y = scroll_unit_y;
       break;
 
     case GDK_SCROLL_SMOOTH:
       gdk_event_get_scroll_deltas ((GdkEvent *) sevent, &value_x, &value_y);
+      value_x *= scroll_unit_x;
+      value_y *= scroll_unit_y;
     }
 
   value_x = CLAMP (value_x +
diff --git a/libgimpwidgets/gimpwidgetsenums.h b/libgimpwidgets/gimpwidgetsenums.h
index 676d11f..77709cf 100644
--- a/libgimpwidgets/gimpwidgetsenums.h
+++ b/libgimpwidgets/gimpwidgetsenums.h
@@ -192,6 +192,7 @@ typedef enum
  * @GIMP_ZOOM_IN_MAX:   zoom in as far as possible
  * @GIMP_ZOOM_OUT_MAX:  zoom out as far as possible
  * @GIMP_ZOOM_TO:       zoom to a specific zoom factor
+ * @GIMP_ZOOM_SMOOTH:   zoom smoothly from a smooth scroll event
  *
  * the zoom types for #GimpZoomModel.
  **/
@@ -207,7 +208,8 @@ typedef enum
   GIMP_ZOOM_OUT_MORE,  /*< skip >*/
   GIMP_ZOOM_IN_MAX,    /*< skip >*/
   GIMP_ZOOM_OUT_MAX,   /*< skip >*/
-  GIMP_ZOOM_TO         /*< skip >*/
+  GIMP_ZOOM_TO,        /*< skip >*/
+  GIMP_ZOOM_SMOOTH     /*< skip >*/
 } GimpZoomType;
 
 
diff --git a/libgimpwidgets/gimpzoommodel.c b/libgimpwidgets/gimpzoommodel.c
index 805a039..2fe834f 100644
--- a/libgimpwidgets/gimpzoommodel.c
+++ b/libgimpwidgets/gimpzoommodel.c
@@ -371,13 +371,18 @@ gimp_zoom_model_zoom (GimpZoomModel *model,
                       GimpZoomType   zoom_type,
                       gdouble        scale)
 {
+  gdouble delta = 0.0;
+
   g_return_if_fail (GIMP_IS_ZOOM_MODEL (model));
 
+  if (zoom_type == GIMP_ZOOM_SMOOTH)
+    delta = scale;
+
   if (zoom_type != GIMP_ZOOM_TO)
     scale = gimp_zoom_model_get_factor (model);
 
   g_object_set (model,
-                "value", gimp_zoom_model_zoom_step (zoom_type, scale),
+                "value", gimp_zoom_model_zoom_step (zoom_type, scale, delta),
                 NULL);
 }
 
@@ -605,6 +610,7 @@ gimp_zoom_button_new (GimpZoomModel *model,
  * gimp_zoom_model_zoom_step:
  * @zoom_type: the zoom type
  * @scale:     ignored unless @zoom_type == %GIMP_ZOOM_TO
+ * @delta:     the delta from a smooth zoom event
  *
  * Utility function to calculate a new scale factor.
  *
@@ -614,7 +620,8 @@ gimp_zoom_button_new (GimpZoomModel *model,
  **/
 gdouble
 gimp_zoom_model_zoom_step (GimpZoomType zoom_type,
-                           gdouble      scale)
+                           gdouble      scale,
+                           gdouble      delta)
 {
   gint    i, n_presets;
   gdouble new_scale = 1.0;
@@ -669,16 +676,16 @@ gimp_zoom_model_zoom_step (GimpZoomType zoom_type,
       break;
 
     case GIMP_ZOOM_IN_MORE:
-      scale = gimp_zoom_model_zoom_step (GIMP_ZOOM_IN, scale);
-      scale = gimp_zoom_model_zoom_step (GIMP_ZOOM_IN, scale);
-      scale = gimp_zoom_model_zoom_step (GIMP_ZOOM_IN, scale);
+      scale = gimp_zoom_model_zoom_step (GIMP_ZOOM_IN, scale, 0.0);
+      scale = gimp_zoom_model_zoom_step (GIMP_ZOOM_IN, scale, 0.0);
+      scale = gimp_zoom_model_zoom_step (GIMP_ZOOM_IN, scale, 0.0);
       new_scale = scale;
       break;
 
     case GIMP_ZOOM_OUT_MORE:
-      scale = gimp_zoom_model_zoom_step (GIMP_ZOOM_OUT, scale);
-      scale = gimp_zoom_model_zoom_step (GIMP_ZOOM_OUT, scale);
-      scale = gimp_zoom_model_zoom_step (GIMP_ZOOM_OUT, scale);
+      scale = gimp_zoom_model_zoom_step (GIMP_ZOOM_OUT, scale, 0.0);
+      scale = gimp_zoom_model_zoom_step (GIMP_ZOOM_OUT, scale, 0.0);
+      scale = gimp_zoom_model_zoom_step (GIMP_ZOOM_OUT, scale, 0.0);
       new_scale = scale;
       break;
 
@@ -693,6 +700,16 @@ gimp_zoom_model_zoom_step (GimpZoomType zoom_type,
     case GIMP_ZOOM_TO:
       new_scale = scale;
       break;
+
+    case GIMP_ZOOM_SMOOTH:
+      if (delta > 0.0)
+        new_scale = scale * (1.0 + 0.1 * delta);
+      else if (delta < 0.0)
+        new_scale = scale / (1.0 + 0.1 * -delta);
+      else
+        new_scale = scale;
+      break;
+
     }
 
   return CLAMP (new_scale, ZOOM_MIN, ZOOM_MAX);
diff --git a/libgimpwidgets/gimpzoommodel.h b/libgimpwidgets/gimpzoommodel.h
index 50f6052..e36724e 100644
--- a/libgimpwidgets/gimpzoommodel.h
+++ b/libgimpwidgets/gimpzoommodel.h
@@ -86,7 +86,8 @@ GtkWidget     * gimp_zoom_button_new         (GimpZoomModel      *model,
                                               GtkIconSize         icon_size);
 
 gdouble         gimp_zoom_model_zoom_step    (GimpZoomType        zoom_type,
-                                              gdouble             scale);
+                                              gdouble             scale,
+                                              gdouble             delta);
 
 G_END_DECLS
 


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