[gnome-builder] pnl: import recent snapshot of panel-gtk



commit 8e4f3939d77e1ceebb5bbff730cb7bdd4d29bb34
Author: Christian Hergert <chergert redhat com>
Date:   Sun Apr 16 22:59:16 2017 -0700

    pnl: import recent snapshot of panel-gtk

 contrib/pnl/pnl-animation.c     |   71 ++++++++++++-
 contrib/pnl/pnl-animation.h     |    4 +
 contrib/pnl/pnl-dock-overlay.c  |  222 +++++++++++++++++++++++++++++++++++----
 contrib/pnl/pnl-dock-revealer.c |   28 ++++--
 contrib/pnl/pnl-dock-stack.c    |    2 +-
 contrib/pnl/pnl-dock-widget.c   |    4 +-
 contrib/pnl/pnl-tab.c           |   20 +---
 contrib/pnl/pnl.h               |    1 +
 8 files changed, 304 insertions(+), 48 deletions(-)
---
diff --git a/contrib/pnl/pnl-animation.c b/contrib/pnl/pnl-animation.c
index 4ea57d3..d8d0ab1 100644
--- a/contrib/pnl/pnl-animation.c
+++ b/contrib/pnl/pnl-animation.c
@@ -594,9 +594,14 @@ pnl_animation_start (PnlAnimation *animation)
   g_object_ref_sink (animation);
   pnl_animation_load_begin_values (animation);
 
+  /*
+   * We want the real current time instead of the GdkFrameClocks current time
+   * because if the clock was asleep, it could be innaccurate.
+   */
+  animation->begin_msec = g_get_monotonic_time () / 1000UL;
+
   if (animation->frame_clock)
     {
-      animation->begin_msec = gdk_frame_clock_get_frame_time (animation->frame_clock) / 1000UL;
       animation->tween_handler =
         g_signal_connect (animation->frame_clock,
                           "update",
@@ -606,7 +611,6 @@ pnl_animation_start (PnlAnimation *animation)
     }
   else
     {
-      animation->begin_msec = g_get_monotonic_time () / 1000UL;
       animation->tween_handler = pnl_frame_source_add (FALLBACK_FRAME_RATE,
                                                        pnl_animation_timeout_cb,
                                                        animation);
@@ -1162,3 +1166,66 @@ pnl_object_animate_full (gpointer        object,
 
   return animation;
 }
+
+guint
+pnl_animation_calculate_duration (GdkMonitor *monitor,
+                                  gdouble     from_value,
+                                  gdouble     to_value)
+{
+  GdkRectangle geom;
+  gdouble distance_units;
+  gdouble distance_mm;
+  gdouble mm_per_frame;
+  gint height_mm;
+  gint refresh_rate;
+  gint n_frames;
+  guint ret;
+
+#define MM_PER_SECOND       (100.0)
+#define MIN_FRAMES_PER_ANIM (5)
+#define MAX_FRAMES_PER_ANIM (500)
+
+  g_assert (GDK_IS_MONITOR (monitor));
+  g_assert (from_value >= 0.0);
+  g_assert (to_value >= 0.0);
+
+  /*
+   * Get various monitor information we'll need to calculate the duration of
+   * the animation. We need the physical space of the monitor, the refresh
+   * rate, and geometry so that we can limit how many device units we will
+   * traverse per-frame of the animation. Failure to deal with the physical
+   * space results in jittery animations to the user.
+   *
+   * It would also be nice to take into account the acceleration curve so that
+   * we know the max amount of jump per frame, but that is getting into
+   * diminishing returns since we can just average it out.
+   */
+  height_mm = gdk_monitor_get_height_mm (monitor);
+  gdk_monitor_get_geometry (monitor, &geom);
+  refresh_rate = gdk_monitor_get_refresh_rate (monitor);
+  if (refresh_rate == 0)
+    refresh_rate = 60000;
+
+  /*
+   * The goal here is to determine the number of millimeters that we need to
+   * animate given a transition of distance_unit pixels. Since we are dealing
+   * with physical units (mm), we don't need to take into account the device
+   * scale underneath the widget. The equation comes out the same.
+   */
+
+  distance_units = ABS (from_value - to_value);
+  distance_mm = distance_units / (gdouble)geom.height * height_mm;
+  mm_per_frame = MM_PER_SECOND / (refresh_rate / 1000.0);
+  n_frames = (distance_mm / mm_per_frame) + 1;
+
+  ret = n_frames * (1000.0 / (refresh_rate / 1000.0));
+  ret = CLAMP (ret,
+               MIN_FRAMES_PER_ANIM * (1000000.0 / refresh_rate),
+               MAX_FRAMES_PER_ANIM * (1000000.0 / refresh_rate));
+
+  return ret;
+
+#undef MM_PER_SECOND
+#undef MIN_FRAMES_PER_ANIM
+#undef MAX_FRAMES_PER_ANIM
+}
diff --git a/contrib/pnl/pnl-animation.h b/contrib/pnl/pnl-animation.h
index 73117b0..98e67f3 100644
--- a/contrib/pnl/pnl-animation.h
+++ b/contrib/pnl/pnl-animation.h
@@ -73,6 +73,10 @@ PnlAnimation* pnl_object_animate_full     (gpointer          object,
                                            const gchar      *first_property,
                                            ...) G_GNUC_NULL_TERMINATED;
 
+guint pnl_animation_calculate_duration (GdkMonitor *monitor,
+                                        gdouble     from_value,
+                                        gdouble     to_value);
+
 G_END_DECLS
 
 #endif /* PNL_ANIMATION_H */
diff --git a/contrib/pnl/pnl-dock-overlay.c b/contrib/pnl/pnl-dock-overlay.c
index 05d2e2d..88ea7b7 100644
--- a/contrib/pnl/pnl-dock-overlay.c
+++ b/contrib/pnl/pnl-dock-overlay.c
@@ -24,7 +24,6 @@
 #include "pnl-tab-strip.h"
 #include "pnl-util-private.h"
 
-#define REVEAL_DURATION 300
 #define MNEMONIC_REVEAL_DURATION 200
 
 typedef struct
@@ -33,8 +32,10 @@ typedef struct
   PnlDockOverlayEdge *edges [4];
   GtkAdjustment      *edge_adj [4];
   GtkAdjustment      *edge_handle_adj [4];
+  GtkAllocation       hover_borders [4];
   guint               child_reveal : 4;
   guint               child_revealed : 4;
+  guint               child_transient : 4;
 } PnlDockOverlayPrivate;
 
 static void pnl_dock_overlay_init_dock_iface      (PnlDockInterface     *iface);
@@ -250,7 +251,7 @@ pnl_dock_overlay_toplevel_mnemonics (PnlDockOverlay *self,
       pnl_object_animate (handle_adj,
                           PNL_ANIMATION_EASE_IN_OUT_CUBIC,
                           MNEMONIC_REVEAL_DURATION,
-                          gtk_widget_get_frame_clock (GTK_WIDGET (edge)),
+                          gtk_widget_get_frame_clock (GTK_WIDGET (self)),
                           "value", (gdouble)overlap,
                           NULL);
     }
@@ -312,11 +313,7 @@ pnl_overlay_container_forall_cb (GtkWidget *widget,
       gtk_widget_is_visible (widget) &&
       state->current_grab == widget &&
       pnl_overlay_dock_widget_is_ancestor (widget, GTK_WIDGET (state->edge)))
-    {
-      state->result = TRUE;
-    }
-  else
-    return;
+    state->result = TRUE;
 }
 
 static gboolean
@@ -511,7 +508,8 @@ typedef struct
 {
   PnlDockOverlay  *self;
   GtkWidget       *child;
-  GtkPositionType  edge;
+  GtkPositionType  edge : 2;
+  guint            revealing : 1;
 } ChildRevealState;
 
 static void
@@ -531,14 +529,11 @@ pnl_dock_overlay_child_reveal_done (gpointer user_data)
   ChildRevealState *state = (ChildRevealState *)user_data;
   PnlDockOverlay *self = state->self;
   PnlDockOverlayPrivate *priv = pnl_dock_overlay_get_instance_private (self);
-  gboolean revealed;
 
   g_assert (PNL_IS_DOCK_OVERLAY (self));
   g_assert (GTK_IS_WIDGET (state->child));
 
-  revealed = !!(priv->child_reveal & (1 << state->edge));
-
-  if (revealed)
+  if (state->revealing)
     priv->child_revealed = priv->child_revealed | (1 << state->edge);
   else
     priv->child_revealed = priv->child_revealed & ~(1 << state->edge);
@@ -575,16 +570,45 @@ pnl_dock_overlay_set_child_reveal (PnlDockOverlay *self,
 
   if (priv->child_reveal != child_reveal)
     {
+      GtkAllocation alloc;
+      GdkMonitor *monitor;
+      GdkWindow *window;
+      guint duration = 0;
+
       state = g_slice_new0 (ChildRevealState);
       state->self = g_object_ref (self);
       state->child = g_object_ref (child);
       state->edge = edge;
+      state->revealing = !!reveal;
 
       priv->child_reveal = child_reveal;
 
+      window = gtk_widget_get_window (GTK_WIDGET (self));
+
+      if (window != NULL)
+        {
+          GdkDisplay *display = gtk_widget_get_display (child);
+
+          monitor = gdk_display_get_monitor_at_window (display, window);
+
+          gtk_widget_get_allocation (child, &alloc);
+
+          if (edge == GTK_POS_LEFT || edge == GTK_POS_RIGHT)
+            duration = pnl_animation_calculate_duration (monitor, 0, alloc.width);
+          else
+            duration = pnl_animation_calculate_duration (monitor, 0, alloc.height);
+        }
+
+#if 0
+      g_print ("Animating %s %d msec (currently at value=%lf)\n",
+               reveal ? "in" : "out",
+               duration,
+               gtk_adjustment_get_value (priv->edge_adj [edge]));
+#endif
+
       pnl_object_animate_full (priv->edge_adj [edge],
                                PNL_ANIMATION_EASE_IN_OUT_CUBIC,
-                               REVEAL_DURATION,
+                               duration,
                                gtk_widget_get_frame_clock (child),
                                pnl_dock_overlay_child_reveal_done,
                                state,
@@ -597,6 +621,156 @@ pnl_dock_overlay_set_child_reveal (PnlDockOverlay *self,
     }
 }
 
+static gboolean
+widget_descendant_contains_focus (GtkWidget *widget)
+{
+  GtkWidget *toplevel;
+
+  g_assert (GTK_IS_WIDGET (widget));
+
+  toplevel = gtk_widget_get_toplevel (widget);
+
+  if (GTK_IS_WINDOW (toplevel))
+    {
+      GtkWidget *focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
+
+      if (focus != NULL)
+        return gtk_widget_is_ancestor (focus, widget);
+    }
+
+  return FALSE;
+}
+
+static inline gboolean
+rectangle_contains_point (const GdkRectangle *a, gint x, gint y)
+{
+  return x >= a->x &&
+         x <= (a->x + a->width) &&
+         y >= a->y &&
+         y <= (a->y + a->height);
+}
+
+static gboolean
+pnl_dock_overlay_motion_notify_event (GtkWidget      *widget,
+                                      GdkEventMotion *event)
+{
+  PnlDockOverlay *self = (PnlDockOverlay *)widget;
+  PnlDockOverlayPrivate *priv = pnl_dock_overlay_get_instance_private (self);
+  GdkWindow *iter;
+  GdkWindow *window;
+  gdouble x, y;
+  guint i;
+
+  g_assert (PNL_IS_DOCK_OVERLAY (self));
+  g_assert (event != NULL);
+
+  window = gtk_widget_get_window (widget);
+
+  x = event->x;
+  y = event->y;
+
+  for (iter = event->window; iter != window; iter = gdk_window_get_parent (iter))
+    gdk_window_coords_to_parent (iter, x, y, &x, &y);
+
+  for (i = 0; i < G_N_ELEMENTS (priv->hover_borders); i++)
+    {
+      PnlDockOverlayEdge *edge = priv->edges [i];
+      GtkPositionType edge_type = pnl_dock_overlay_edge_get_position (edge);
+      GtkAllocation *hover_border = &priv->hover_borders [i];
+      guint mask = 1 << edge_type;
+
+      if (rectangle_contains_point (hover_border, x, y))
+        {
+          /* Ignore this edge if it is already revealing */
+          if (pnl_dock_overlay_get_child_reveal (self, GTK_WIDGET (edge)) ||
+              pnl_dock_overlay_get_child_revealed (self, GTK_WIDGET (edge)))
+            continue;
+
+          pnl_dock_overlay_set_child_reveal (self, GTK_WIDGET (edge), TRUE);
+
+          priv->child_transient |= mask;
+        }
+      else if ((priv->child_transient & mask) != 0)
+        {
+          GtkWidget *event_widget = NULL;
+          GtkAllocation alloc;
+          gint rel_x;
+          gint rel_y;
+
+          gdk_window_get_user_data (event->window, (gpointer *)&event_widget);
+          gtk_widget_get_allocation (GTK_WIDGET (edge), &alloc);
+          gtk_widget_translate_coordinates (event_widget,
+                                            GTK_WIDGET (edge),
+                                            event->x,
+                                            event->y,
+                                            &rel_x,
+                                            &rel_y);
+
+          /*
+           * If this edge is transient, and the event window is not a
+           * descendant of the edges window, then we should dismiss the
+           * transient state.
+           */
+          if (pnl_dock_overlay_get_child_revealed (self, GTK_WIDGET (edge)) &&
+              !rectangle_contains_point (&alloc, rel_x, rel_y) &&
+              !widget_descendant_contains_focus (GTK_WIDGET (edge)))
+            {
+              pnl_dock_overlay_set_child_reveal (self, GTK_WIDGET (edge), FALSE);
+              priv->child_transient &= ~mask;
+            }
+        }
+    }
+
+  return GTK_WIDGET_CLASS (pnl_dock_overlay_parent_class)->motion_notify_event (widget, event);
+}
+
+static void
+pnl_dock_overlay_size_allocate (GtkWidget     *widget,
+                                GtkAllocation *alloc)
+{
+  PnlDockOverlay *self = (PnlDockOverlay *)widget;
+  PnlDockOverlayPrivate *priv = pnl_dock_overlay_get_instance_private (self);
+  GtkAllocation copy;
+  GtkAllocation *edge;
+
+  g_assert (PNL_IS_DOCK_OVERLAY (self));
+  g_assert (alloc != NULL);
+
+  copy = *alloc;
+  copy.x = 0;
+  copy.y = 0;
+
+#define GRAB_AREA 15
+
+  edge = &priv->hover_borders [GTK_POS_TOP];
+  edge->x = copy.x;
+  edge->y = copy.y;
+  edge->width = copy.width;
+  edge->height = GRAB_AREA;
+
+  edge = &priv->hover_borders [GTK_POS_LEFT];
+  edge->x = copy.x;
+  edge->y = copy.y;
+  edge->width = GRAB_AREA;
+  edge->height = copy.height;
+
+  edge = &priv->hover_borders [GTK_POS_RIGHT];
+  edge->x = copy.x + copy.width - GRAB_AREA;
+  edge->y = copy.y;
+  edge->width = GRAB_AREA;
+  edge->height = copy.height;
+
+  edge = &priv->hover_borders [GTK_POS_BOTTOM];
+  edge->x = copy.x;
+  edge->y = copy.y + copy.height - GRAB_AREA;
+  edge->width = copy.width;
+  edge->height = GRAB_AREA;
+
+#undef GRAB_AREA
+
+  GTK_WIDGET_CLASS (pnl_dock_overlay_parent_class)->size_allocate (widget, alloc);
+}
+
 static void
 pnl_dock_overlay_get_property (GObject    *object,
                                guint       prop_id,
@@ -692,6 +866,8 @@ pnl_dock_overlay_class_init (PnlDockOverlayClass *klass)
 
   widget_class->destroy = pnl_dock_overlay_destroy;
   widget_class->hierarchy_changed = pnl_dock_overlay_hierarchy_changed;
+  widget_class->motion_notify_event = pnl_dock_overlay_motion_notify_event;
+  widget_class->size_allocate = pnl_dock_overlay_size_allocate;
 
   container_class->add = pnl_dock_overlay_add;
   container_class->get_child_property = pnl_dock_overlay_get_child_property;
@@ -749,6 +925,8 @@ pnl_dock_overlay_init (PnlDockOverlay *self)
   PnlDockOverlayPrivate *priv = pnl_dock_overlay_get_instance_private (self);
   guint i;
 
+  gtk_widget_add_events (GTK_WIDGET (self), GDK_POINTER_MOTION_MASK);
+
   priv->overlay = g_object_new (GTK_TYPE_OVERLAY,
                                 "visible", TRUE,
                                 NULL);
@@ -777,17 +955,19 @@ pnl_dock_overlay_init (PnlDockOverlay *self)
 
       priv->edge_adj [i] = gtk_adjustment_new (1, 0, 1, 0, 0, 0);
 
-      g_signal_connect_swapped (priv->edge_adj [i],
-                                "value-changed",
-                                G_CALLBACK (gtk_widget_queue_allocate),
-                                priv->overlay);
+      g_signal_connect_object (priv->edge_adj [i],
+                               "value-changed",
+                               G_CALLBACK (gtk_widget_queue_allocate),
+                               priv->overlay,
+                               G_CONNECT_SWAPPED);
 
       priv->edge_handle_adj [i] = gtk_adjustment_new (0, 0, 1000, 0, 0, 0);
 
-      g_signal_connect_swapped (priv->edge_handle_adj [i],
-                                "value-changed",
-                                G_CALLBACK (gtk_widget_queue_allocate),
-                                priv->overlay);
+      g_signal_connect_object (priv->edge_handle_adj [i],
+                               "value-changed",
+                               G_CALLBACK (gtk_widget_queue_allocate),
+                               priv->overlay,
+                               G_CONNECT_SWAPPED);
     }
 }
 
diff --git a/contrib/pnl/pnl-dock-revealer.c b/contrib/pnl/pnl-dock-revealer.c
index b07bd5f..ee994b0 100644
--- a/contrib/pnl/pnl-dock-revealer.c
+++ b/contrib/pnl/pnl-dock-revealer.c
@@ -178,8 +178,14 @@ pnl_dock_revealer_animation_done (gpointer user_data)
 }
 
 static guint
-size_to_duration (gint size)
+size_to_duration (GdkMonitor *monitor,
+                  gint        size)
 {
+  g_assert (!monitor || GDK_IS_MONITOR (monitor));
+
+  if (monitor != NULL)
+    return pnl_animation_calculate_duration (monitor, 0, size);
+
   return MAX (150, size * 1.2);
 }
 
@@ -188,6 +194,9 @@ pnl_dock_revealer_calculate_duration (PnlDockRevealer *self)
 {
   PnlDockRevealerPrivate *priv = pnl_dock_revealer_get_instance_private (self);
   GtkWidget *child;
+  GdkWindow *window;
+  GdkMonitor *monitor = NULL;
+  GdkDisplay *display;
   GtkRequisition min_size;
   GtkRequisition nat_size;
 
@@ -206,27 +215,32 @@ pnl_dock_revealer_calculate_duration (PnlDockRevealer *self)
 
   gtk_widget_get_preferred_size (child, &min_size, &nat_size);
 
+  display = gtk_widget_get_display (GTK_WIDGET (self));
+  window = gtk_widget_get_window (GTK_WIDGET (self));
+  if (window != NULL)
+    monitor = gdk_display_get_monitor_at_window (display, window);
+
   if (IS_HORIZONTAL (priv->transition_type))
     {
       if (priv->position_set)
         {
           if (priv->position_set && priv->position > min_size.width)
-            return size_to_duration (priv->position);
-          return size_to_duration (min_size.width);
+            return size_to_duration (monitor, priv->position);
+          return size_to_duration (monitor, min_size.width);
         }
 
-      return size_to_duration (nat_size.width);
+      return size_to_duration (monitor, nat_size.width);
     }
   else
     {
       if (priv->position_set)
         {
           if (priv->position_set && priv->position > min_size.height)
-            return size_to_duration (priv->position);
-          return size_to_duration (min_size.height);
+            return size_to_duration (monitor, priv->position);
+          return size_to_duration (monitor, min_size.height);
         }
 
-      return size_to_duration (nat_size.height);
+      return size_to_duration (monitor, nat_size.height);
     }
 }
 
diff --git a/contrib/pnl/pnl-dock-stack.c b/contrib/pnl/pnl-dock-stack.c
index 97cf410..6f9f64b 100644
--- a/contrib/pnl/pnl-dock-stack.c
+++ b/contrib/pnl/pnl-dock-stack.c
@@ -156,7 +156,7 @@ pnl_dock_stack_init (PnlDockStack *self)
   priv->edge = GTK_POS_TOP;
 
   priv->stack = g_object_new (GTK_TYPE_STACK,
-                              "homogeneous", FALSE,
+                              "homogeneous", TRUE,
                               "visible", TRUE,
                               NULL);
 
diff --git a/contrib/pnl/pnl-dock-widget.c b/contrib/pnl/pnl-dock-widget.c
index 738618b..0b54845 100644
--- a/contrib/pnl/pnl-dock-widget.c
+++ b/contrib/pnl/pnl-dock-widget.c
@@ -50,8 +50,8 @@ pnl_dock_widget_grab_focus (GtkWidget *widget)
 
   child = gtk_bin_get_child (GTK_BIN (self));
 
-  if (child != NULL)
-    gtk_widget_child_focus (child, GTK_DIR_TAB_FORWARD);
+  if (child == NULL || !gtk_widget_child_focus (child, GTK_DIR_TAB_FORWARD))
+    GTK_WIDGET_CLASS (pnl_dock_widget_parent_class)->grab_focus (GTK_WIDGET (self));
 }
 
 static void
diff --git a/contrib/pnl/pnl-tab.c b/contrib/pnl/pnl-tab.c
index 9758520..5199cf0 100644
--- a/contrib/pnl/pnl-tab.c
+++ b/contrib/pnl/pnl-tab.c
@@ -17,7 +17,10 @@
  * Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
+#define G_LOG_DOMAIN "pnl-tab"
+
 #include "pnl-tab.h"
+#include "pnl-util-private.h"
 
 struct _PnlTab
 {
@@ -44,11 +47,7 @@ pnl_tab_destroy (GtkWidget *widget)
 {
   PnlTab *self = (PnlTab *)widget;
 
-  if (self->widget)
-    {
-      g_object_remove_weak_pointer (G_OBJECT (self->widget), (gpointer *)&self->widget);
-      self->widget = NULL;
-    }
+  pnl_clear_weak_pointer (&self->widget);
 
   GTK_WIDGET_CLASS (pnl_tab_parent_class)->destroy (widget);
 }
@@ -258,18 +257,9 @@ pnl_tab_set_widget (PnlTab    *self,
 {
   g_return_if_fail (PNL_IS_TAB (self));
 
-  if (self->widget != widget)
+  if (pnl_set_weak_pointer (&self->widget, widget))
     {
-      if (self->widget)
-        g_object_remove_weak_pointer (G_OBJECT (self->widget), (gpointer *)&self->widget);
-
-      self->widget = widget;
-
-      if (widget)
-        g_object_add_weak_pointer (G_OBJECT (self->widget), (gpointer *)&self->widget);
-
       gtk_label_set_mnemonic_widget (self->title, widget);
-
       g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_WIDGET]);
     }
 }
diff --git a/contrib/pnl/pnl.h b/contrib/pnl/pnl.h
index 25ee5ef..500e654 100644
--- a/contrib/pnl/pnl.h
+++ b/contrib/pnl/pnl.h
@@ -31,6 +31,7 @@ G_BEGIN_DECLS
 #include "pnl-dock-item.h"
 #include "pnl-dock-manager.h"
 #include "pnl-dock-overlay.h"
+#include "pnl-dock-overlay-edge.h"
 #include "pnl-dock-paned.h"
 #include "pnl-dock-revealer.h"
 #include "pnl-dock-stack.h"


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