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.
This commit is contained in:
Michael Natterer 2018-05-11 02:08:51 +02:00
parent e4d05a4758
commit 2dd2f1509b
17 changed files with 94 additions and 32 deletions

View File

@ -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

View File

@ -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 | \

View File

@ -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)

View File

@ -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;
}

View File

@ -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",

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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:

View File

@ -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);
};

View File

@ -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),

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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 +

View File

@ -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;

View File

@ -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);

View File

@ -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