[gnome-builder/wip/chergert/three-finger-swipe] layout: stub out three-finger-swipe



commit 3ff60b5f50d83166aee98e07fbfe4450998c54e0
Author: Christian Hergert <chergert redhat com>
Date:   Fri Oct 13 01:15:24 2017 -0700

    layout: stub out three-finger-swipe
    
    This starts on plumbing to use three-finger-swipe to move
    IdeLayoutView left/right.
    
    Nothing reacts to the move yet, but it's sort of fun to play
    around with.

 src/libide/layout/ide-layout-stack.c  |  165 ++++++++++++++++++++++++-
 src/libide/layout/ide-layout-stack.ui |  211 +++++++++++++++++----------------
 2 files changed, 266 insertions(+), 110 deletions(-)
---
diff --git a/src/libide/layout/ide-layout-stack.c b/src/libide/layout/ide-layout-stack.c
index 75b2193..e7e67c2 100644
--- a/src/libide/layout/ide-layout-stack.c
+++ b/src/libide/layout/ide-layout-stack.c
@@ -54,12 +54,25 @@ typedef struct
   GPtrArray            *in_transition;
   PeasExtensionSet     *addins;
 
+  /*
+   * Our gestures are used to do interactive moves when the user
+   * does a three finger swipe. We create the dummy gesture to
+   * ensure things work, because it for some reason does not without
+   * the dummy gesture set.
+   *
+   * https://bugzilla.gnome.org/show_bug.cgi?id=788914
+   */
+  GtkGesture           *dummy;
+  GtkGesture           *pan;
+  DzlBoxTheatric       *pan_theatric;
+
   /* Template references */
   DzlBox               *empty_state;
   DzlEmptyState        *failed_state;
   IdeLayoutStackHeader *header;
   GtkStack             *stack;
   GtkStack             *top_stack;
+  GtkEventBox          *event_box;
 } IdeLayoutStackPrivate;
 
 typedef struct
@@ -91,6 +104,13 @@ G_DEFINE_TYPE_WITH_CODE (IdeLayoutStack, ide_layout_stack, GTK_TYPE_BOX,
 static GParamSpec *properties [N_PROPS];
 static guint signals [N_SIGNALS];
 
+static inline gboolean
+is_uninitialized (GtkAllocation *alloc)
+{
+  return (alloc->x == -1 && alloc->y == -1 &&
+          alloc->width == 1 && alloc->height == 1);
+}
+
 static void
 ide_layout_stack_view_failed (IdeLayoutStack *self,
                               GParamSpec     *pspec,
@@ -388,6 +408,110 @@ ide_layout_stack_addin_removed (PeasExtensionSet *set,
   ide_layout_stack_addin_unload (addin, self);
 }
 
+static gboolean
+ide_layout_stack_pan_begin (IdeLayoutStack   *self,
+                            GdkEventSequence *sequence,
+                            GtkGesturePan    *gesture)
+{
+  IdeLayoutStackPrivate *priv = ide_layout_stack_get_instance_private (self);
+  GtkAllocation alloc;
+  cairo_surface_t *surface = NULL;
+  IdeLayoutView *view;
+  GdkWindow *window;
+  GtkWidget *grid;
+  cairo_t *cr;
+  gdouble x, y;
+  gboolean enable_animations;
+
+  g_assert (IDE_IS_LAYOUT_STACK (self));
+  g_assert (GTK_IS_GESTURE_PAN (gesture));
+  g_assert (priv->pan_theatric == NULL);
+
+  view = ide_layout_stack_get_visible_child (self);
+
+  gtk_widget_get_allocation (GTK_WIDGET (view), &alloc);
+
+  g_object_get (gtk_settings_get_default (),
+                "gtk-enable-animations", &enable_animations,
+                NULL);
+
+  if (sequence != NULL ||
+      view == NULL ||
+      !enable_animations ||
+      is_uninitialized (&alloc) ||
+      NULL == (window = gtk_widget_get_window (GTK_WIDGET (view))) ||
+      NULL == (surface = gdk_window_create_similar_surface (window,
+                                                            CAIRO_CONTENT_COLOR,
+                                                            alloc.width,
+                                                            alloc.height)))
+    {
+      if (sequence != NULL)
+        gtk_gesture_set_state (GTK_GESTURE (gesture), GTK_EVENT_SEQUENCE_DENIED);
+      return FALSE;
+    }
+
+  gtk_gesture_drag_get_offset (GTK_GESTURE_DRAG (gesture), &x, &y);
+
+  cr = cairo_create (surface);
+  gtk_widget_draw (GTK_WIDGET (view), cr);
+  cairo_destroy (cr);
+
+  grid = gtk_widget_get_ancestor (GTK_WIDGET (self), IDE_TYPE_LAYOUT_GRID_COLUMN);
+  gtk_widget_translate_coordinates (GTK_WIDGET (priv->stack), grid, 0, 0,
+                                    &alloc.x, &alloc.y);
+
+  priv->pan_theatric = g_object_new (DZL_TYPE_BOX_THEATRIC,
+                                     "surface", surface,
+                                     "height", alloc.height,
+                                     "target", grid,
+                                     "width", alloc.width,
+                                     "x", (gint)(alloc.x + x),
+                                     "y", alloc.y,
+                                     NULL);
+
+  g_clear_pointer (&surface, cairo_surface_destroy);
+
+  return TRUE;
+}
+
+static void
+ide_layout_stack_pan_end (IdeLayoutStack   *self,
+                          GdkEventSequence *sequence,
+                          GtkGesturePan    *gesture)
+{
+  IdeLayoutStackPrivate *priv = ide_layout_stack_get_instance_private (self);
+
+  g_assert (IDE_IS_LAYOUT_STACK (self));
+  g_assert (GTK_IS_GESTURE_PAN (gesture));
+
+  g_clear_object (&priv->pan_theatric);
+  gtk_widget_queue_draw (gtk_widget_get_toplevel (GTK_WIDGET (self)));
+}
+
+static void
+ide_layout_stack_pan_update (IdeLayoutStack   *self,
+                             GdkEventSequence *sequence,
+                             GtkGestureSwipe  *gesture)
+{
+  IdeLayoutStackPrivate *priv = ide_layout_stack_get_instance_private (self);
+  IdeLayoutView *view;
+  GtkAllocation alloc;
+  gdouble x, y;
+
+  g_assert (IDE_IS_LAYOUT_STACK (self));
+  g_assert (GTK_IS_GESTURE_PAN (gesture));
+  g_assert (priv->pan_theatric != NULL);
+
+  gtk_gesture_drag_get_offset (GTK_GESTURE_DRAG (gesture), &x, &y);
+
+  view = ide_layout_stack_get_visible_child (self);
+  gtk_widget_get_allocation (GTK_WIDGET (view), &alloc);
+
+  g_object_set (priv->pan_theatric,
+                "x", (gint)(alloc.x + x),
+                NULL);
+}
+
 static void
 ide_layout_stack_constructed (GObject *object)
 {
@@ -415,6 +539,37 @@ ide_layout_stack_constructed (GObject *object)
   peas_extension_set_foreach (priv->addins,
                               ide_layout_stack_addin_added,
                               self);
+
+  gtk_widget_add_events (GTK_WIDGET (priv->event_box), GDK_TOUCH_MASK);
+  priv->pan = g_object_new (GTK_TYPE_GESTURE_PAN,
+                            "widget", priv->event_box,
+                            "orientation", GTK_ORIENTATION_HORIZONTAL,
+                            "n-points", 3,
+                            NULL);
+  g_signal_connect_swapped (priv->pan,
+                            "begin",
+                            G_CALLBACK (ide_layout_stack_pan_begin),
+                            self);
+  g_signal_connect_swapped (priv->pan,
+                            "update",
+                            G_CALLBACK (ide_layout_stack_pan_update),
+                            self);
+  g_signal_connect_swapped (priv->pan,
+                            "end",
+                            G_CALLBACK (ide_layout_stack_pan_end),
+                            self);
+  gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->pan),
+                                              GTK_PHASE_BUBBLE);
+
+  /*
+   * FIXME: Our priv->pan gesture does not activate unless we add another
+   *        dummy gesture. I currently have no idea why that is.
+   *
+   *        https://bugzilla.gnome.org/show_bug.cgi?id=788914
+   */
+  priv->dummy = gtk_gesture_rotate_new (GTK_WIDGET (priv->event_box));
+  gtk_event_controller_set_propagation_phase (GTK_EVENT_CONTROLLER (priv->dummy),
+                                              GTK_PHASE_BUBBLE);
 }
 
 static void
@@ -463,6 +618,8 @@ ide_layout_stack_destroy (GtkWidget *widget)
       g_clear_object (&priv->signals);
     }
 
+  g_clear_object (&priv->pan);
+
   GTK_WIDGET_CLASS (ide_layout_stack_parent_class)->destroy (widget);
 }
 
@@ -557,6 +714,7 @@ ide_layout_stack_class_init (IdeLayoutStackClass *klass)
   gtk_widget_class_bind_template_child_private (widget_class, IdeLayoutStack, header);
   gtk_widget_class_bind_template_child_private (widget_class, IdeLayoutStack, stack);
   gtk_widget_class_bind_template_child_private (widget_class, IdeLayoutStack, top_stack);
+  gtk_widget_class_bind_template_child_private (widget_class, IdeLayoutStack, event_box);
 
   g_type_ensure (IDE_TYPE_LAYOUT_STACK_HEADER);
   g_type_ensure (IDE_TYPE_SHORTCUT_LABEL);
@@ -880,13 +1038,6 @@ animation_state_complete (gpointer data)
   g_slice_free (AnimationState, state);
 }
 
-static inline gboolean
-is_uninitialized (GtkAllocation *alloc)
-{
-  return (alloc->x == -1 && alloc->y == -1 &&
-          alloc->width == 1 && alloc->height == 1);
-}
-
 void
 _ide_layout_stack_transfer (IdeLayoutStack *self,
                             IdeLayoutStack *dest,
diff --git a/src/libide/layout/ide-layout-stack.ui b/src/libide/layout/ide-layout-stack.ui
index cf15da7..be87e44 100644
--- a/src/libide/layout/ide-layout-stack.ui
+++ b/src/libide/layout/ide-layout-stack.ui
@@ -10,125 +10,130 @@
       </object>
     </child>
     <child>
-      <object class="GtkStack" id="top_stack">
-        <property name="expand">true</property>
-        <property name="homogeneous">false</property>
-        <property name="interpolate-size">false</property>
+      <object class="GtkEventBox" id="event_box">
         <property name="visible">true</property>
         <child>
-          <object class="DzlBox" id="empty_state">
-            <property name="expand">false</property>
-            <property name="halign">center</property>
-            <property name="orientation">vertical</property>
-            <property name="valign">center</property>
-            <property name="max-width-request">275</property>
-            <property name="margin">32</property>
-            <property name="spacing">6</property>
+          <object class="GtkStack" id="top_stack">
+            <property name="expand">true</property>
+            <property name="homogeneous">false</property>
+            <property name="interpolate-size">false</property>
             <property name="visible">true</property>
             <child>
-              <object class="GtkLabel">
-                <property name="label" translatable="yes">Open a File or Terminal</property>
-                <property name="margin-bottom">6</property>
-                <property name="visible">true</property>
-                <style>
-                  <class name="dim-label"/>
-                </style>
-                <attributes>
-                  <attribute name="weight" value="bold"/>
-                  <attribute name="scale" value="1.2"/>
-                </attributes>
-              </object>
-            </child>
-            <child>
-              <object class="GtkLabel">
-                <property name="label" translatable="yes">Use the page switcher above or use one of the 
following:</property>
-                <property name="justify">center</property>
-                <property name="margin-bottom">18</property>
-                <property name="visible">true</property>
-                <property name="wrap">true</property>
-                <style>
-                  <class name="dim-label"/>
-                </style>
-                <attributes>
-                  <attribute name="scale" value=".909"/>
-                </attributes>
-              </object>
-            </child>
-            <child>
-              <object class="IdeShortcutLabel">
-                <property name="title" translatable="yes">Search</property>
-                <property name="action">win.global-search</property>
-                <property name="visible">true</property>
-                <!-- Remove after auto accel tracking -->
-                <property name="accel">Ctrl+.</property>
-              </object>
-            </child>
-            <child>
-              <object class="IdeShortcutLabel">
-                <property name="title" translatable="yes">Project sidebar</property>
-                <property name="action">editor.sidebar</property>
-                <property name="visible">true</property>
-                <!-- Remove after auto accel tracking -->
-                <property name="accel">F9</property>
-              </object>
-            </child>
-            <child>
-              <object class="IdeShortcutLabel">
-                <property name="title" translatable="yes">File chooser</property>
-                <property name="action">editor.open-file</property>
-                <property name="visible">true</property>
-                <!-- Remove after auto accel tracking -->
-                <property name="accel">Ctrl+O</property>
-              </object>
-            </child>
-            <child>
-              <object class="IdeShortcutLabel">
-                <property name="title" translatable="yes">New terminal</property>
-                <property name="action">win.new-terminal</property>
-                <property name="visible">true</property>
-                <!-- Remove after auto accel tracking -->
-                <property name="accel">Ctrl+Shift+T</property>
-              </object>
-            </child>
-            <child>
-              <object class="GtkBox">
-                <property name="homogeneous">true</property>
-                <property name="margin-top">18</property>
+              <object class="DzlBox" id="empty_state">
+                <property name="expand">false</property>
+                <property name="halign">center</property>
+                <property name="orientation">vertical</property>
+                <property name="valign">center</property>
+                <property name="max-width-request">275</property>
+                <property name="margin">32</property>
                 <property name="spacing">6</property>
                 <property name="visible">true</property>
                 <child>
-                  <object class="GtkButton">
-                    <property name="action-name">editor.open-file</property>
-                    <property name="label" translatable="yes">Open File…</property>
+                  <object class="GtkLabel">
+                    <property name="label" translatable="yes">Open a File or Terminal</property>
+                    <property name="margin-bottom">6</property>
+                    <property name="visible">true</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                    <attributes>
+                      <attribute name="weight" value="bold"/>
+                      <attribute name="scale" value="1.2"/>
+                    </attributes>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="label" translatable="yes">Use the page switcher above or use one of the 
following:</property>
+                    <property name="justify">center</property>
+                    <property name="margin-bottom">18</property>
+                    <property name="visible">true</property>
+                    <property name="wrap">true</property>
+                    <style>
+                      <class name="dim-label"/>
+                    </style>
+                    <attributes>
+                      <attribute name="scale" value=".909"/>
+                    </attributes>
+                  </object>
+                </child>
+                <child>
+                  <object class="IdeShortcutLabel">
+                    <property name="title" translatable="yes">Search</property>
+                    <property name="action">win.global-search</property>
                     <property name="visible">true</property>
+                    <!-- Remove after auto accel tracking -->
+                    <property name="accel">Ctrl+.</property>
                   </object>
                 </child>
                 <child>
-                  <object class="GtkButton">
-                    <property name="action-name">win.new-terminal</property>
-                    <property name="label" translatable="yes">New Terminal</property>
+                  <object class="IdeShortcutLabel">
+                    <property name="title" translatable="yes">Project sidebar</property>
+                    <property name="action">editor.sidebar</property>
                     <property name="visible">true</property>
+                    <!-- Remove after auto accel tracking -->
+                    <property name="accel">F9</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="IdeShortcutLabel">
+                    <property name="title" translatable="yes">File chooser</property>
+                    <property name="action">editor.open-file</property>
+                    <property name="visible">true</property>
+                    <!-- Remove after auto accel tracking -->
+                    <property name="accel">Ctrl+O</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="IdeShortcutLabel">
+                    <property name="title" translatable="yes">New terminal</property>
+                    <property name="action">win.new-terminal</property>
+                    <property name="visible">true</property>
+                    <!-- Remove after auto accel tracking -->
+                    <property name="accel">Ctrl+Shift+T</property>
+                  </object>
+                </child>
+                <child>
+                  <object class="GtkBox">
+                    <property name="homogeneous">true</property>
+                    <property name="margin-top">18</property>
+                    <property name="spacing">6</property>
+                    <property name="visible">true</property>
+                    <child>
+                      <object class="GtkButton">
+                        <property name="action-name">editor.open-file</property>
+                        <property name="label" translatable="yes">Open File…</property>
+                        <property name="visible">true</property>
+                      </object>
+                    </child>
+                    <child>
+                      <object class="GtkButton">
+                        <property name="action-name">win.new-terminal</property>
+                        <property name="label" translatable="yes">New Terminal</property>
+                        <property name="visible">true</property>
+                      </object>
+                    </child>
                   </object>
                 </child>
               </object>
             </child>
-          </object>
-        </child>
-        <child>
-          <object class="DzlEmptyState" id="failed_state">
-            <property name="icon-name">computer-fail-symbolic</property>
-            <property name="pixel-size">160</property>
-            <property name="title" translatable="yes">Uh oh, something went wrong</property>
-            <property name="subtitle" translatable="yes">There was a failure while trying to perform the 
operation.</property>
-            <property name="visible">true</property>
-          </object>
-        </child>
-        <child>
-          <object class="GtkStack" id="stack">
-            <property name="expand">true</property>
-            <property name="homogeneous">false</property>
-            <property name="interpolate-size">false</property>
-            <property name="visible">true</property>
+            <child>
+              <object class="DzlEmptyState" id="failed_state">
+                <property name="icon-name">computer-fail-symbolic</property>
+                <property name="pixel-size">160</property>
+                <property name="title" translatable="yes">Uh oh, something went wrong</property>
+                <property name="subtitle" translatable="yes">There was a failure while trying to perform the 
operation.</property>
+                <property name="visible">true</property>
+              </object>
+            </child>
+            <child>
+              <object class="GtkStack" id="stack">
+                <property name="expand">true</property>
+                <property name="homogeneous">false</property>
+                <property name="interpolate-size">false</property>
+                <property name="visible">true</property>
+              </object>
+            </child>
           </object>
         </child>
       </object>


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