diff --git a/app/display/gimpcanvas.h b/app/display/gimpcanvas.h index cb81f71897d2965687e8d4d5f36662abf24ce91c..0844b0a3444df77d6e0bda35e96bce22cbf40c98 100644 --- a/app/display/gimpcanvas.h +++ b/app/display/gimpcanvas.h @@ -28,6 +28,7 @@ GDK_BUTTON_RELEASE_MASK | \ GDK_SCROLL_MASK | \ GDK_SMOOTH_SCROLL_MASK | \ + GDK_TOUCHPAD_GESTURE_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 8e61eb47aef1bcaacc9c99af14a0e1841239d149..26afbbbf226017874c9fa1fab1dc1ac71a6de433 100644 --- a/app/display/gimpdisplayshell-scale.c +++ b/app/display/gimpdisplayshell-scale.c @@ -516,6 +516,9 @@ gimp_display_shell_scale (GimpDisplayShell *shell, if (zoom_type == GIMP_ZOOM_SMOOTH) delta = -new_scale; + if (zoom_type == GIMP_ZOOM_PINCH) + delta = new_scale; + if (zoom_type != GIMP_ZOOM_TO) new_scale = gimp_zoom_model_zoom_step (zoom_type, current_scale, delta); diff --git a/app/display/gimpdisplayshell-tool-events.c b/app/display/gimpdisplayshell-tool-events.c index 917b16845aab29e8f594497b9b20a46017763602..487a95a15826be36420ebccf0ea2ce79fac14f89 100644 --- a/app/display/gimpdisplayshell-tool-events.c +++ b/app/display/gimpdisplayshell-tool-events.c @@ -1247,6 +1247,29 @@ gimp_display_shell_canvas_grab_notify (GtkWidget *canvas, } } +void +gimp_display_shell_zoom_gesture_begin (GtkGestureZoom *gesture, + GdkEventSequence *sequence, + GimpDisplayShell *shell) +{ + shell->last_zoom_scale = gtk_gesture_zoom_get_scale_delta (gesture); +} + +void +gimp_display_shell_zoom_gesture_update (GtkGestureZoom *gesture, + GdkEventSequence *sequence, + GimpDisplayShell *shell) +{ + gdouble current_scale = gtk_gesture_zoom_get_scale_delta (gesture); + gdouble delta = (current_scale - shell->last_zoom_scale) / shell->last_zoom_scale; + shell->last_zoom_scale = current_scale; + + gimp_display_shell_scale (shell, + GIMP_ZOOM_PINCH, + delta, + GIMP_ZOOM_FOCUS_POINTER); +} + void gimp_display_shell_buffer_stroke (GimpMotionBuffer *buffer, const GimpCoords *coords, diff --git a/app/display/gimpdisplayshell-tool-events.h b/app/display/gimpdisplayshell-tool-events.h index 4458a926acfec444f2d93b91f3200aa18b8112c5..6539640c11ba74c0ad2d44451e867a77e089e9a9 100644 --- a/app/display/gimpdisplayshell-tool-events.h +++ b/app/display/gimpdisplayshell-tool-events.h @@ -30,6 +30,13 @@ void gimp_display_shell_canvas_grab_notify (GtkWidget *widget, gboolean was_grabbed, GimpDisplayShell *shell); +void gimp_display_shell_zoom_gesture_begin (GtkGestureZoom *gesture, + GdkEventSequence *sequence, + GimpDisplayShell *shell); +void gimp_display_shell_zoom_gesture_update (GtkGestureZoom *gesture, + GdkEventSequence *sequence, + GimpDisplayShell *shell); + void gimp_display_shell_buffer_stroke (GimpMotionBuffer *buffer, const GimpCoords *coords, guint32 time, diff --git a/app/display/gimpdisplayshell.c b/app/display/gimpdisplayshell.c index 2ca4039a40b868c9827bdaab285e6f393b30bcb3..957dea8f51f8d10ab5693cce864ec6cffc0c7cc5 100644 --- a/app/display/gimpdisplayshell.c +++ b/app/display/gimpdisplayshell.c @@ -521,6 +521,10 @@ gimp_display_shell_constructed (GObject *object) gimp_display_shell_dnd_init (shell); gimp_display_shell_selection_init (shell); + shell->zoom_gesture = gtk_gesture_zoom_new (GTK_WIDGET (shell->canvas)); + gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (shell->zoom_gesture), + GTK_PHASE_CAPTURE); + /* the horizontal ruler */ shell->hrule = gimp_ruler_new (GTK_ORIENTATION_HORIZONTAL); gtk_widget_set_events (GTK_WIDGET (shell->hrule), @@ -607,6 +611,12 @@ gimp_display_shell_constructed (GObject *object) g_signal_connect (shell->canvas, "key-release-event", G_CALLBACK (gimp_display_shell_canvas_tool_events), shell); + g_signal_connect (shell->zoom_gesture, "begin", + G_CALLBACK (gimp_display_shell_zoom_gesture_begin), + shell); + g_signal_connect (shell->zoom_gesture, "update", + G_CALLBACK (gimp_display_shell_zoom_gesture_update), + shell); /* the zoom button */ shell->zoom_button = g_object_new (GTK_TYPE_CHECK_BUTTON, @@ -757,6 +767,8 @@ gimp_display_shell_dispose (GObject *object) shell->filter_idle_id = 0; } + g_clear_object (&shell->zoom_gesture); + g_clear_pointer (&shell->render_cache, cairo_surface_destroy); g_clear_pointer (&shell->render_cache_valid, cairo_region_destroy); diff --git a/app/display/gimpdisplayshell.h b/app/display/gimpdisplayshell.h index 389370b464e47919f624575b98e24f56a1dbd688..8815b7e7b4ed15759dca93494b02fa3bda72f32a 100644 --- a/app/display/gimpdisplayshell.h +++ b/app/display/gimpdisplayshell.h @@ -99,6 +99,7 @@ struct _GimpDisplayShell GList *children; GtkWidget *canvas; /* GimpCanvas widget */ + GtkGesture *zoom_gesture; /* Zoom gesture handler for the canvas*/ GtkAdjustment *hsbdata; /* adjustments */ GtkAdjustment *vsbdata; @@ -203,6 +204,9 @@ struct _GimpDisplayShell GdkDevice *grab_keyboard_source; guint32 grab_keyboard_time; + /* the state of gimp_display_shell_zoom_gesture_*() */ + gdouble last_zoom_scale; + /* Two states are possible when the shell is grabbed: it can be * grabbed with space (or space+button1 which is the same state), * then if space is released but button1 was still pressed, we wait diff --git a/app/widgets/gimppaletteeditor.c b/app/widgets/gimppaletteeditor.c index a5b039566e1211303df4f8bc248f2c905378a1ad..6abee86f45912f020d9f719904f9998a41ae21fc 100644 --- a/app/widgets/gimppaletteeditor.c +++ b/app/widgets/gimppaletteeditor.c @@ -610,7 +610,8 @@ gimp_palette_editor_zoom (GimpPaletteEditor *editor, } break; - case GIMP_ZOOM_SMOOTH: /* can't happen */ + case GIMP_ZOOM_SMOOTH: + case GIMP_ZOOM_PINCH: /* can't happen */ g_return_if_reached (); } diff --git a/libgimpwidgets/gimpwidgetsenums.h b/libgimpwidgets/gimpwidgetsenums.h index 3544afc6a31d1eb76c547483564ef819ab908b83..ef6d93560764effb300b73e4dd79a4b620011c8f 100644 --- a/libgimpwidgets/gimpwidgetsenums.h +++ b/libgimpwidgets/gimpwidgetsenums.h @@ -216,6 +216,7 @@ typedef enum * @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 + * @GIMP_ZOOM_PINCH: zoom smoothly from a touchpad pinch gesture * * the zoom types for #GimpZoomModel. **/ @@ -232,7 +233,8 @@ typedef enum GIMP_ZOOM_IN_MAX, /*< skip >*/ GIMP_ZOOM_OUT_MAX, /*< skip >*/ GIMP_ZOOM_TO, /*< skip >*/ - GIMP_ZOOM_SMOOTH /*< skip >*/ + GIMP_ZOOM_SMOOTH, /*< skip >*/ + GIMP_ZOOM_PINCH, /*< skip >*/ } GimpZoomType; diff --git a/libgimpwidgets/gimpzoommodel.c b/libgimpwidgets/gimpzoommodel.c index 6d12aba7c01a788ed68d5164dd965b57e911a057..e4b772eacc609a04d26b235f2ed45f3227d063bc 100644 --- a/libgimpwidgets/gimpzoommodel.c +++ b/libgimpwidgets/gimpzoommodel.c @@ -705,6 +705,14 @@ gimp_zoom_model_zoom_step (GimpZoomType zoom_type, new_scale = scale; break; + case GIMP_ZOOM_PINCH: + if (delta > 0.0) + new_scale = scale * (1.0 + delta); + else if (delta < 0.0) + new_scale = scale / (1.0 + -delta); + else + new_scale = scale; + break; } return CLAMP (new_scale, ZOOM_MIN, ZOOM_MAX);