[gnome-builder] pnl: import recent snapshot of panel-gtk
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] pnl: import recent snapshot of panel-gtk
- Date: Mon, 17 Apr 2017 20:21:57 +0000 (UTC)
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]