summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorErnestas Kulik <ernestask@gnome.org>2018-03-11 09:48:19 +0200
committerErnestas Kulik <ernestask@gnome.org>2018-03-11 17:41:18 +0200
commit9a00c5fbed464a0fc1d2abeee279735f2e5d25a9 (patch)
tree9cee1daee70714637fc894796415ea5e4268ff4d
parentfdfd7a656f1c3d3df270be263029732212987179 (diff)
downloadlibgd-9a00c5fbed464a0fc1d2abeee279735f2e5d25a9.tar.gz
notification: use snapshot API for drawing
The applied style classes allow us to not draw the background and frame manually, and we can avoid using GdkWindow API for animating.
-rw-r--r--libgd/gd-notification.c106
1 files changed, 40 insertions, 66 deletions
diff --git a/libgd/gd-notification.c b/libgd/gd-notification.c
index a93b321..00df8bb 100644
--- a/libgd/gd-notification.c
+++ b/libgd/gd-notification.c
@@ -42,7 +42,7 @@
#define SHADOW_OFFSET_X 2
#define SHADOW_OFFSET_Y 3
#define ANIMATION_TIME 200 /* msec */
-#define ANIMATION_STEP 40 /* msec */
+#define ANIMATION_STEP 20 /* msec */
enum {
PROP_0,
@@ -56,7 +56,7 @@ struct _GdNotificationPrivate {
GdkWindow *bin_window;
- int animate_y; /* from 0 to allocation.height */
+ gdouble animate_y; /* ∈ [0.0; 1.0] */
gboolean waiting_for_viewable;
gboolean revealed;
gboolean dismissed;
@@ -74,8 +74,6 @@ enum {
static guint notification_signals[LAST_SIGNAL] = { 0 };
-static gboolean gd_notification_draw (GtkWidget *widget,
- cairo_t *cr);
static void gd_notification_get_preferred_width (GtkWidget *widget,
gint *minimum_size,
gint *natural_size);
@@ -125,7 +123,7 @@ gd_notification_init (GdNotification *notification)
GD_TYPE_NOTIFICATION,
GdNotificationPrivate);
- priv->animate_y = 0;
+ priv->animate_y = 0.0;
priv->close_button = gtk_button_new_from_icon_name ("window-close-symbolic");
gtk_widget_set_parent (priv->close_button, GTK_WIDGET (notification));
gtk_widget_show (priv->close_button);
@@ -247,18 +245,12 @@ gd_notification_unrealize (GtkWidget *widget)
GTK_WIDGET_CLASS (gd_notification_parent_class)->unrealize (widget);
}
-static int
+static gdouble
animation_target (GdNotification *notification)
{
GdNotificationPrivate *priv = notification->priv;
- GtkAllocation allocation;
- if (priv->revealed) {
- gtk_widget_get_allocation (GTK_WIDGET (notification), &allocation);
- return allocation.height;
- } else {
- return 0;
- }
+ return priv->revealed? 1.0 : 0.0;
}
static gboolean
@@ -267,30 +259,28 @@ animation_timeout_cb (gpointer user_data)
GdNotification *notification = GD_NOTIFICATION (user_data);
GdNotificationPrivate *priv = notification->priv;
GtkAllocation allocation;
- int target, delta;
+ gdouble target, delta;
target = animation_target (notification);
if (priv->animate_y != target) {
gtk_widget_get_allocation (GTK_WIDGET (notification), &allocation);
- delta = allocation.height * ANIMATION_STEP / ANIMATION_TIME;
+ delta = (gdouble) ANIMATION_STEP / (gdouble) ANIMATION_TIME;
if (priv->revealed)
priv->animate_y += delta;
else
priv->animate_y -= delta;
- priv->animate_y = CLAMP (priv->animate_y, 0, allocation.height);
+ priv->animate_y = CLAMP (priv->animate_y, 0.0, 1.0);
+
+ gtk_widget_queue_draw (GTK_WIDGET (notification));
- if (priv->bin_window != NULL)
- gdk_window_move (priv->bin_window,
- 0,
- -allocation.height + priv->animate_y);
return G_SOURCE_CONTINUE;
}
- if (priv->dismissed && priv->animate_y == 0)
+ if (priv->dismissed && priv->animate_y == 0.0)
gtk_widget_destroy (GTK_WIDGET (notification));
priv->animate_timeout = 0;
@@ -468,6 +458,32 @@ gd_notification_leave_notify (GtkWidget *widget,
}
return FALSE;
+
+static void
+gd_notification_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
+{
+ GdNotification *self;
+ GdNotificationPrivate *priv;
+ GtkAllocation allocation;
+ graphene_rect_t bounds;
+
+ self = GD_NOTIFICATION (widget);
+ priv = self->priv;
+
+ gtk_widget_get_allocation (widget, &allocation);
+
+ bounds = GRAPHENE_RECT_INIT (0, 0,
+ allocation.width, allocation.height);
+
+ gtk_snapshot_push_clip (snapshot, &bounds, "GdNotification Clip");
+ gtk_snapshot_offset (snapshot,
+ 0,
+ -allocation.height * (1.0 - priv->animate_y));
+
+ GTK_WIDGET_CLASS (gd_notification_parent_class)->snapshot (widget, snapshot);
+
+ gtk_snapshot_pop (snapshot);
}
static void
@@ -489,7 +505,7 @@ gd_notification_class_init (GdNotificationClass *klass)
widget_class->get_preferred_height = gd_notification_get_preferred_height;
widget_class->get_preferred_width_for_height = gd_notification_get_preferred_width_for_height;
widget_class->size_allocate = gd_notification_size_allocate;
- widget_class->draw = gd_notification_draw;
+ widget_class->snapshot = gd_notification_snapshot;
widget_class->realize = gd_notification_realize;
widget_class->unrealize = gd_notification_unrealize;
widget_class->visibility_notify_event = gd_notification_visibility_notify_event;
@@ -551,34 +567,6 @@ get_padding_and_border (GdNotification *notification,
border->left += tmp.left;
}
-static gboolean
-gd_notification_draw (GtkWidget *widget, cairo_t *cr)
-{
- GdNotification *notification = GD_NOTIFICATION (widget);
- GdNotificationPrivate *priv = notification->priv;
- GtkStyleContext *context;
-
- if (gtk_cairo_should_draw_window (cr, priv->bin_window))
- {
- context = gtk_widget_get_style_context (widget);
-
- gtk_render_background (context, cr,
- 0, 0,
- gtk_widget_get_allocated_width (widget),
- gtk_widget_get_allocated_height (widget));
- gtk_render_frame (context,cr,
- 0, 0,
- gtk_widget_get_allocated_width (widget),
- gtk_widget_get_allocated_height (widget));
-
-
- if (GTK_WIDGET_CLASS (gd_notification_parent_class)->draw)
- GTK_WIDGET_CLASS (gd_notification_parent_class)->draw(widget, cr);
- }
-
- return FALSE;
-}
-
static void
gd_notification_add (GtkContainer *container,
GtkWidget *child)
@@ -760,26 +748,12 @@ gd_notification_size_allocate (GtkWidget *widget,
/* If somehow the notification changes while not hidden
and we're not animating, immediately follow the resize */
- if (priv->animate_y > 0 &&
+ if (priv->animate_y > 0.0 &&
!priv->animate_timeout)
- priv->animate_y = allocation->height;
+ priv->animate_y = 1.0;
get_padding_and_border (notification, &padding);
- if (gtk_widget_get_realized (widget))
- {
- gdk_window_move_resize (gtk_widget_get_window (widget),
- allocation->x,
- allocation->y,
- allocation->width,
- allocation->height);
- gdk_window_move_resize (priv->bin_window,
- 0,
- -allocation->height + priv->animate_y,
- allocation->width,
- allocation->height);
- }
-
child_allocation.x = SHADOW_OFFSET_X + padding.left;
child_allocation.y = padding.top;