diff options
author | Ernestas Kulik <ernestask@gnome.org> | 2018-03-11 09:48:19 +0200 |
---|---|---|
committer | Ernestas Kulik <ernestask@gnome.org> | 2018-03-11 17:41:18 +0200 |
commit | 9a00c5fbed464a0fc1d2abeee279735f2e5d25a9 (patch) | |
tree | 9cee1daee70714637fc894796415ea5e4268ff4d | |
parent | fdfd7a656f1c3d3df270be263029732212987179 (diff) | |
download | libgd-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.c | 106 |
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; |