[totem] Use new GTK+ 3.x drawing APIs in glow button
- From: Bastien Nocera <hadess src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [totem] Use new GTK+ 3.x drawing APIs in glow button
- Date: Thu, 7 Oct 2010 13:30:16 +0000 (UTC)
commit 735a32a984262336bc148fad37dc3be95a8738db
Author: Bastien Nocera <hadess hadess net>
Date: Thu Oct 7 14:28:08 2010 +0100
Use new GTK+ 3.x drawing APIs in glow button
With help from Benjamin Otte's work on the panel tasklist:
http://git.gnome.org/browse/libwnck/commit/?h=gtk3&id=211a61d40b3cbac8ac38d3efe17e885b00e85f0e
http://git.gnome.org/browse/libwnck/commit/?h=gtk3&id=1857f00faa225c41a3d5d1ca5bce0c10e1c7deb6
browser-plugin/totem-glow-button.c | 218 ++++++++---------------------------
1 files changed, 50 insertions(+), 168 deletions(-)
---
diff --git a/browser-plugin/totem-glow-button.c b/browser-plugin/totem-glow-button.c
index ffb65a1..76c5002 100644
--- a/browser-plugin/totem-glow-button.c
+++ b/browser-plugin/totem-glow-button.c
@@ -38,10 +38,8 @@
struct _TotemGlowButton {
GtkButton parent;
- GdkPixmap *screenshot;
- GdkPixmap *screenshot_faded;
-
gdouble glow_start_time;
+ gdouble glow_factor;
guint button_glow;
@@ -51,63 +49,29 @@ struct _TotemGlowButton {
/* Set when we don't want to play animation
* anymore in pointer entered mode */
guint anim_finished :1;
-
- guint in_expose : 1;
};
-static void totem_glow_button_set_timeout (TotemGlowButton *button,
- gboolean set_timeout);
+static void totem_glow_button_set_timeout (TotemGlowButton *button, gboolean set_timeout);
static GtkButtonClass *parent_class;
G_DEFINE_TYPE (TotemGlowButton, totem_glow_button, GTK_TYPE_BUTTON);
-static void
-totem_glow_button_do_expose (TotemGlowButton *button)
-{
- GdkRectangle area;
- GtkWidget *buttonw;
- GtkAllocation allocation;
-
- buttonw = GTK_WIDGET (button);
- if (gtk_widget_get_window (buttonw) == NULL)
- return;
-
- gtk_widget_get_allocation (buttonw, &allocation);
- area.x = allocation.x;
- area.y = allocation.y;
- area.width = allocation.width;
- area.height = allocation.height;
-
- /* Send a fake expose event */
- gdk_window_invalidate_rect (gtk_widget_get_window (buttonw), &area, TRUE);
- gdk_window_process_updates (gtk_widget_get_window (buttonw), TRUE);
-}
-
static gboolean
totem_glow_button_glow (TotemGlowButton *button)
-{
+{
GtkWidget *buttonw;
- GtkAllocation allocation;
GTimeVal tv;
- gdouble glow_factor, now;
+ gdouble now;
gfloat fade_opacity, loop_time;
- cairo_t *cr;
buttonw = GTK_WIDGET (button);
if (gtk_widget_get_realized (buttonw) == FALSE)
return TRUE;
- if (button->screenshot == NULL) {
- /* Send a fake expose event to get a screenshot */
- totem_glow_button_do_expose (button);
- if (button->screenshot == NULL)
- return TRUE;
- }
-
if (button->anim_enabled != FALSE) {
- g_get_current_time (&tv);
+ g_get_current_time (&tv);
now = (tv.tv_sec * (1.0 * G_USEC_PER_SEC) +
tv.tv_usec) / G_USEC_PER_SEC;
@@ -136,38 +100,15 @@ totem_glow_button_glow (TotemGlowButton *button)
}
if ((now - button->glow_start_time) > loop_time * FADE_MAX_LOOPS) {
button->anim_finished = TRUE;
- glow_factor = FADE_OPACITY_DEFAULT * 0.5;
+ button->glow_factor = FADE_OPACITY_DEFAULT * 0.5;
} else {
- glow_factor = fade_opacity * (0.5 - 0.5 * cos ((now - button->glow_start_time) * M_PI * 2.0 / loop_time));
+ button->glow_factor = fade_opacity * (0.5 - 0.5 * cos ((now - button->glow_start_time) * M_PI * 2.0 / loop_time));
}
} else {
- glow_factor = FADE_OPACITY_DEFAULT * 0.5;
+ button->glow_factor = FADE_OPACITY_DEFAULT * 0.5;
}
- gtk_widget_get_allocation (buttonw, &allocation);
- gdk_window_begin_paint_rect (gtk_widget_get_window (buttonw),
- &allocation);
-
- cr = gdk_cairo_create (gtk_widget_get_window (buttonw));
- gdk_cairo_rectangle (cr, &allocation);
- cairo_translate (cr, allocation.x, allocation.y);
- cairo_clip (cr);
-
- cairo_save (cr);
-
- gdk_cairo_set_source_pixmap (cr, button->screenshot, 0., 0.);
- cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
- cairo_paint (cr);
-
- cairo_restore (cr);
-
- gdk_cairo_set_source_pixmap (cr, button->screenshot_faded, 0., 0.);
- cairo_set_operator (cr, CAIRO_OPERATOR_OVER);
- cairo_paint_with_alpha (cr, glow_factor);
-
- cairo_destroy (cr);
-
- gdk_window_end_paint (gtk_widget_get_window (buttonw));
+ gtk_widget_queue_draw (GTK_WIDGET (button));
if (button->anim_finished != FALSE)
totem_glow_button_set_timeout (button, FALSE);
@@ -177,114 +118,54 @@ totem_glow_button_glow (TotemGlowButton *button)
static void
totem_glow_button_clear_glow_start_timeout_id (TotemGlowButton *button)
-{
+{
button->button_glow = 0;
}
-static void
-cleanup_screenshots (TotemGlowButton *button)
+static gboolean
+totem_glow_button_draw (GtkWidget *widget,
+ cairo_t *cr,
+ gpointer user_data)
{
- if (button->screenshot != NULL) {
- g_object_unref (button->screenshot);
- button->screenshot = NULL;
- }
- if (button->screenshot_faded != NULL) {
- g_object_unref (button->screenshot_faded);
- button->screenshot_faded = NULL;
- }
-}
+ TotemGlowButton *button;
+ GtkStyle *style;
+ GtkAllocation allocation, child_allocation;
+ gint width, height;
+ GtkWidget *child;
-static void
-fake_expose_widget (GtkWidget *widget,
- GdkPixmap *pixmap,
- gint x,
- gint y)
-{
- GtkAllocation allocation;
- GdkWindow *tmp_window;
- GdkEventExpose event;
-
- event.type = GDK_EXPOSE;
- event.window = pixmap;
- event.send_event = FALSE;
- event.region = NULL;
- event.count = 0;
-
- tmp_window = gtk_widget_get_window (widget);
- gtk_widget_set_window (widget, pixmap);
- gtk_widget_get_allocation (widget, &allocation);
- allocation.x += x;
- allocation.y += y;
- gtk_widget_set_allocation (widget, &allocation);
+ button = TOTEM_GLOW_BUTTON (widget);
- event.area = allocation;
+ if (button->glow_factor == 0.0)
+ return FALSE;
- gtk_widget_send_expose (widget, (GdkEvent *) &event);
+ /* push a translucent overlay to paint to, so we can blend later */
+ cairo_push_group_with_content (cr, CAIRO_CONTENT_COLOR_ALPHA);
- gtk_widget_set_window (widget, tmp_window);
gtk_widget_get_allocation (widget, &allocation);
- allocation.x -= x;
- allocation.y -= y;
- gtk_widget_set_allocation (widget, &allocation);
-}
-
-static GdkPixmap *
-take_screenshot (TotemGlowButton *button)
-{
- GtkWidget *buttonw;
- GtkAllocation allocation;
- GtkStyle *style;
- GdkPixmap *pixmap;
- gint width, height;
- cairo_t *cr;
-
- buttonw = GTK_WIDGET (button);
- gtk_widget_get_allocation (buttonw, &allocation);
width = allocation.width;
height = allocation.height;
- pixmap = gdk_pixmap_new (gtk_widget_get_window (buttonw),
- width, height, -1);
- cr = gdk_cairo_create (pixmap);
-
/* Draw a rectangle with bg[SELECTED] */
- style = gtk_widget_get_style (buttonw);
+ style = gtk_widget_get_style (widget);
gdk_cairo_set_source_color (cr, &(style->bg[GTK_STATE_SELECTED]));
- cairo_rectangle (cr, 0.0, 0.0, width + 1.0, height + 1.0);
- cairo_fill (cr);
+ gtk_paint_box (style, cr, GTK_STATE_SELECTED,
+ GTK_SHADOW_OUT, widget, "button",
+ 0, 0, height, width);
/* then the image */
- fake_expose_widget (gtk_button_get_image (GTK_BUTTON (button)), pixmap,
- -allocation.x, -allocation.y);
-
- cairo_destroy (cr);
-
- return pixmap;
-}
-
-static gboolean
-totem_glow_button_expose (GtkWidget *buttonw,
- GdkEventExpose *event)
-{
- TotemGlowButton *button;
-
- button = TOTEM_GLOW_BUTTON (buttonw);
-
- (* GTK_WIDGET_CLASS (parent_class)->expose_event) (buttonw, event);
-
- if (button->glow != FALSE && button->screenshot == NULL && button->in_expose == FALSE &&
- /* Don't take screenshots if we finished playing animation after
- pointer entered, or if we're already in an expose event. */
- (button->pointer_entered != FALSE &&
- button->anim_finished != FALSE) == FALSE) {
- button->in_expose = TRUE;
-
- button->screenshot = gtk_widget_get_snapshot (buttonw, NULL);;
- button->screenshot_faded = take_screenshot (button);
+ cairo_save (cr);
+ child = gtk_bin_get_child (GTK_BIN (button));
+ gtk_widget_get_allocation (child, &child_allocation);
+ cairo_translate (cr,
+ child_allocation.x - allocation.x,
+ child_allocation.y - allocation.y);
+ gtk_widget_draw (gtk_bin_get_child (GTK_BIN (button)), cr);
+ cairo_restore (cr);
- button->in_expose = FALSE;
- }
+ /* finally blend it */
+ cairo_pop_group_to_source (cr);
+ cairo_paint_with_alpha (cr, button->glow_factor);
return FALSE;
}
@@ -315,8 +196,6 @@ totem_glow_button_unmap (GtkWidget *buttonw)
button->button_glow = 0;
}
- cleanup_screenshots (button);
-
(* GTK_WIDGET_CLASS (parent_class)->unmap) (buttonw);
}
@@ -328,7 +207,7 @@ totem_glow_button_enter (GtkButton *buttonw)
button = TOTEM_GLOW_BUTTON (buttonw);
(* GTK_BUTTON_CLASS (parent_class)->enter) (buttonw);
-
+
button->pointer_entered = TRUE;
button->anim_finished = FALSE;
button->glow_start_time = G_MINDOUBLE;
@@ -356,7 +235,6 @@ totem_glow_button_finalize (GObject *object)
TotemGlowButton *button = TOTEM_GLOW_BUTTON (object);
totem_glow_button_set_glow (button, FALSE);
- cleanup_screenshots (button);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@@ -371,7 +249,8 @@ totem_glow_button_class_init (TotemGlowButtonClass *klass)
parent_class = g_type_class_peek_parent (klass);
object_class->finalize = totem_glow_button_finalize;
- widget_class->expose_event = totem_glow_button_expose;
+ /* Note that we don't use a draw here because we
+ * want to modify what the button will draw by itself */
widget_class->map = totem_glow_button_map;
widget_class->unmap = totem_glow_button_unmap;
button_class->enter = totem_glow_button_enter;
@@ -383,8 +262,12 @@ totem_glow_button_init (TotemGlowButton *button)
{
button->glow_start_time = 0.0;
button->button_glow = 0;
- button->screenshot = NULL;
- button->screenshot_faded = NULL;
+ button->glow_factor = 0.0;
+
+ g_signal_connect_object (button, "draw",
+ G_CALLBACK (totem_glow_button_draw),
+ G_OBJECT (button),
+ G_CONNECT_AFTER);
}
GtkWidget *
@@ -400,7 +283,7 @@ totem_glow_button_set_timeout (TotemGlowButton *button, gboolean set_timeout)
button->glow_start_time = 0.0;
/* The animation doesn't speed up or slow down based on the
- * timeout value, but instead will just appear smoother or
+ * timeout value, but instead will just appear smoother or
* choppier.
*/
button->button_glow =
@@ -413,8 +296,7 @@ totem_glow_button_set_timeout (TotemGlowButton *button, gboolean set_timeout)
g_source_remove (button->button_glow);
button->button_glow = 0;
}
- cleanup_screenshots (button);
- totem_glow_button_do_expose (button);
+ button->glow_factor = 0.0;
}
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]