[gimp] app: Implement canvas support for touchpad gesture rotation by pinch
- From: Jehan <jehanp src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gimp] app: Implement canvas support for touchpad gesture rotation by pinch
- Date: Wed, 6 Apr 2022 19:34:12 +0000 (UTC)
commit e8cf57f1579305cc77226e6c3dee6b5594a635bf
Author: Povilas Kanapickas <povilas radix lt>
Date: Wed Mar 16 23:59:20 2022 +0200
app: Implement canvas support for touchpad gesture rotation by pinch
app/display/gimpdisplayshell-tool-events.c | 64 ++++++++++++++++++++++++++++++
app/display/gimpdisplayshell-tool-events.h | 7 ++++
app/display/gimpdisplayshell.c | 12 ++++++
app/display/gimpdisplayshell.h | 5 +++
4 files changed, 88 insertions(+)
---
diff --git a/app/display/gimpdisplayshell-tool-events.c b/app/display/gimpdisplayshell-tool-events.c
index e28e7199f7..16df65ff58 100644
--- a/app/display/gimpdisplayshell-tool-events.c
+++ b/app/display/gimpdisplayshell-tool-events.c
@@ -21,6 +21,7 @@
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
+#include "libgimpmath/gimpmath.h"
#include "libgimpwidgets/gimpwidgets.h"
#include "display-types.h"
@@ -100,6 +101,10 @@ static void gimp_display_shell_handle_scrolling (GimpDisplayShell
gint x,
gint y);
+static void gimp_display_shell_rotate_gesture_maybe_get_state (GtkGestureRotate *gesture,
+ GdkEventSequence *sequence,
+ guint *maybe_out_state);
+
static void gimp_display_shell_space_pressed (GimpDisplayShell *shell,
const GdkEvent *event);
static void gimp_display_shell_released (GimpDisplayShell *shell,
@@ -1273,6 +1278,38 @@ gimp_display_shell_zoom_gesture_update (GtkGestureZoom *gesture,
GIMP_ZOOM_FOCUS_POINTER);
}
+void
+gimp_display_shell_rotate_gesture_begin (GtkGestureRotate *gesture,
+ GdkEventSequence *sequence,
+ GimpDisplayShell *shell)
+{
+
+ shell->initial_gesture_rotate_angle = shell->rotate_angle;
+ shell->last_gesture_rotate_state = 0;
+ gimp_display_shell_rotate_gesture_maybe_get_state (gesture, sequence,
+ &shell->last_gesture_rotate_state);
+}
+
+void
+gimp_display_shell_rotate_gesture_update (GtkGestureRotate *gesture,
+ GdkEventSequence *sequence,
+ GimpDisplayShell *shell)
+{
+ gdouble angle;
+ gboolean constrain;
+
+ gimp_display_shell_rotate_gesture_maybe_get_state (gesture, sequence,
+ &shell->last_gesture_rotate_state);
+
+ angle = shell->initial_gesture_rotate_angle +
+ 180.0 * gtk_gesture_rotate_get_angle_delta (gesture) / G_PI;
+
+ constrain = (shell->last_gesture_rotate_state & GDK_CONTROL_MASK) ? TRUE : FALSE;
+
+ gimp_display_shell_rotate_to (shell,
+ constrain ? RINT (angle / 15.0) * 15.0 : angle);
+}
+
void
gimp_display_shell_buffer_stroke (GimpMotionBuffer *buffer,
const GimpCoords *coords,
@@ -1671,6 +1708,33 @@ gimp_display_shell_handle_scrolling (GimpDisplayShell *shell,
shell->scroll_last_y = y;
}
+static void
+gimp_display_shell_rotate_gesture_maybe_get_state (GtkGestureRotate *gesture,
+ GdkEventSequence *sequence,
+ guint *maybe_out_state)
+{
+ /* The only way to get any access to any data about events handled by the
+ * GtkGestureRotate is through its last_event. The set of events handled by
+ * GtkGestureRotate is not fully defined so we can't guarantee that last_event
+ * will be of event type that has a state field (though touch and gesture
+ * events do have that).
+ *
+ * Usually this would not be a problem, but when handling a gesture we don't
+ * want to repeatedly switch between a valid state and its default value if
+ * last_event happens to not have it. Thus we store the last valid state
+ * and only update it if we get a valid state from last_event.
+ */
+ guint state = 0;
+ const GdkEvent *last_event;
+
+ last_event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), sequence);
+ if (last_event == NULL)
+ return;
+
+ if (gdk_event_get_state (last_event, &state))
+ *maybe_out_state = state;
+}
+
static void
gimp_display_shell_space_pressed (GimpDisplayShell *shell,
const GdkEvent *event)
diff --git a/app/display/gimpdisplayshell-tool-events.h b/app/display/gimpdisplayshell-tool-events.h
index 6539640c11..a491999d04 100644
--- a/app/display/gimpdisplayshell-tool-events.h
+++ b/app/display/gimpdisplayshell-tool-events.h
@@ -37,6 +37,13 @@ void gimp_display_shell_zoom_gesture_update (GtkGestureZoom *gesture
GdkEventSequence *sequence,
GimpDisplayShell *shell);
+void gimp_display_shell_rotate_gesture_begin (GtkGestureRotate *gesture,
+ GdkEventSequence *sequence,
+ GimpDisplayShell *shell);
+void gimp_display_shell_rotate_gesture_update (GtkGestureRotate *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 a87b940290..8ca3d1efa4 100644
--- a/app/display/gimpdisplayshell.c
+++ b/app/display/gimpdisplayshell.c
@@ -516,6 +516,10 @@ gimp_display_shell_constructed (GObject *object)
gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (shell->zoom_gesture),
GTK_PHASE_CAPTURE);
+ shell->rotate_gesture = gtk_gesture_rotate_new (GTK_WIDGET (shell->canvas));
+ gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (shell->rotate_gesture),
+ GTK_PHASE_CAPTURE);
+
/* the horizontal ruler */
shell->hrule = gimp_ruler_new (GTK_ORIENTATION_HORIZONTAL);
gtk_widget_set_events (GTK_WIDGET (shell->hrule),
@@ -608,6 +612,13 @@ gimp_display_shell_constructed (GObject *object)
g_signal_connect (shell->zoom_gesture, "update",
G_CALLBACK (gimp_display_shell_zoom_gesture_update),
shell);
+ g_signal_connect (shell->rotate_gesture, "begin",
+ G_CALLBACK (gimp_display_shell_rotate_gesture_begin),
+ shell);
+ g_signal_connect (shell->rotate_gesture, "update",
+ G_CALLBACK (gimp_display_shell_rotate_gesture_update),
+ shell);
+
/* the zoom button */
shell->zoom_button = g_object_new (GTK_TYPE_CHECK_BUTTON,
@@ -759,6 +770,7 @@ gimp_display_shell_dispose (GObject *object)
}
g_clear_object (&shell->zoom_gesture);
+ g_clear_object (&shell->rotate_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 f9bf6360f0..7a4a0a41f3 100644
--- a/app/display/gimpdisplayshell.h
+++ b/app/display/gimpdisplayshell.h
@@ -101,6 +101,7 @@ struct _GimpDisplayShell
GtkWidget *canvas; /* GimpCanvas widget */
GtkGesture *zoom_gesture; /* Zoom gesture handler for the canvas*/
+ GtkGesture *rotate_gesture; /* Rotation gesture handler */
GtkAdjustment *hsbdata; /* adjustments */
GtkAdjustment *vsbdata;
@@ -203,6 +204,10 @@ struct _GimpDisplayShell
/* the state of gimp_display_shell_zoom_gesture_*() */
gdouble last_zoom_scale;
+ /* the state of gimp_display_shell_rotate_gesture_*() */
+ guint last_gesture_rotate_state;
+ gdouble initial_gesture_rotate_angle;
+
/* 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
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]