[gtk+] css: Support opacity



commit 366b4db791b03b39275c6767dede2c2089f40506
Author: Alexander Larsson <alexl redhat com>
Date:   Wed Feb 6 14:29:22 2013 +0100

    css: Support opacity
    
    https://bugzilla.gnome.org/show_bug.cgi?id=687842

 gtk/gtkcssstylepropertyimpl.c |   16 +++++++
 gtk/gtkcsstypesprivate.h      |    1 +
 gtk/gtkwidget.c               |  101 +++++++++++++++++++++++++++--------------
 3 files changed, 83 insertions(+), 35 deletions(-)
---
diff --git a/gtk/gtkcssstylepropertyimpl.c b/gtk/gtkcssstylepropertyimpl.c
index c58edd8..26726d7 100644
--- a/gtk/gtkcssstylepropertyimpl.c
+++ b/gtk/gtkcssstylepropertyimpl.c
@@ -421,6 +421,14 @@ parse_css_direction (GtkCssStyleProperty *property,
 }
 
 static GtkCssValue *
+opacity_parse (GtkCssStyleProperty *property,
+	       GtkCssParser        *parser)
+{
+  return _gtk_css_number_value_parse (parser, GTK_CSS_PARSE_NUMBER);
+}
+
+
+static GtkCssValue *
 parse_one_css_play_state (GtkCssParser *parser)
 {
   GtkCssValue *value = _gtk_css_play_state_value_try_parse (parser);
@@ -1382,6 +1390,14 @@ _gtk_css_style_property_init_properties (void)
                                           NULL,
                                           NULL,
                                           _gtk_css_array_value_new (_gtk_css_fill_mode_value_new (GTK_CSS_FILL_NONE)));
+  gtk_css_style_property_register        ("opacity",
+                                          GTK_CSS_PROPERTY_OPACITY,
+                                          G_TYPE_NONE,
+                                          GTK_STYLE_PROPERTY_ANIMATED | GTK_STYLE_PROPERTY_NO_RESIZE,
+                                          opacity_parse,
+                                          NULL,
+                                          NULL,
+                                          _gtk_css_number_value_new (1, GTK_CSS_NUMBER));
 
   gtk_css_style_property_register        ("engine",
                                           GTK_CSS_PROPERTY_ENGINE,
diff --git a/gtk/gtkcsstypesprivate.h b/gtk/gtkcsstypesprivate.h
index 9c1f92b..b2881fe 100644
--- a/gtk/gtkcsstypesprivate.h
+++ b/gtk/gtkcsstypesprivate.h
@@ -132,6 +132,7 @@ enum { /*< skip >*/
   GTK_CSS_PROPERTY_ANIMATION_PLAY_STATE,
   GTK_CSS_PROPERTY_ANIMATION_DELAY,
   GTK_CSS_PROPERTY_ANIMATION_FILL_MODE,
+  GTK_CSS_PROPERTY_OPACITY,
   GTK_CSS_PROPERTY_ENGINE,
   GTK_CSS_PROPERTY_GTK_KEY_BINDINGS,
   /* add more */
diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c
index a2faff5..d99ee55 100644
--- a/gtk/gtkwidget.c
+++ b/gtk/gtkwidget.c
@@ -37,6 +37,7 @@
 #include "gtkaccelmapprivate.h"
 #include "gtkclipboard.h"
 #include "gtkcssstylepropertyprivate.h"
+#include "gtkcssnumbervalueprivate.h"
 #include "gtkiconfactory.h"
 #include "gtkintl.h"
 #include "gtkmarshalers.h"
@@ -362,6 +363,7 @@ struct _GtkWidgetPrivate
   guint norender              : 1; /* Don't expose windows, instead recurse via draw */
 
   guint8 alpha;
+  guint8 user_alpha;
 
   /* The widget's name. If the widget does not have a name
    * (the name is NULL), then its name (as returned by
@@ -610,7 +612,8 @@ static PangoContext*	gtk_widget_peek_pango_context		(GtkWidget	  *widget);
 static void     	gtk_widget_update_pango_context		(GtkWidget	  *widget);
 static void		gtk_widget_propagate_state		(GtkWidget	  *widget,
 								 GtkStateData 	  *data);
-;
+static void             gtk_widget_update_alpha                 (GtkWidget        *widget);
+
 static gint		gtk_widget_event_internal		(GtkWidget	  *widget,
 								 GdkEvent	  *event);
 static gboolean		gtk_widget_real_mnemonic_activate	(GtkWidget	  *widget,
@@ -3743,6 +3746,7 @@ gtk_widget_init (GtkWidget *widget)
   priv->allocation.y = -1;
   priv->allocation.width = 1;
   priv->allocation.height = 1;
+  priv->user_alpha = 255;
   priv->alpha = 255;
   priv->window = NULL;
   priv->parent = NULL;
@@ -6801,6 +6805,7 @@ gtk_widget_real_style_updated (GtkWidget *widget)
   GtkWidgetPrivate *priv = widget->priv;
 
   gtk_widget_update_pango_context (widget);
+  gtk_widget_update_alpha (widget);
 
   if (priv->style != NULL &&
       priv->style != gtk_widget_get_default_style ())
@@ -13927,55 +13932,37 @@ gtk_widget_update_norender (GtkWidget *widget)
     propagate_norender_non_window (widget, norender | widget->priv->norender_children);
 }
 
-/**
- * gtk_widget_set_opacity:
- * @widget: a #GtkWidget
- * @opacity: desired opacity, between 0 and 1
- *
- * Request the @widget to be rendered partially transparent,
- * with opacity 0 being fully transparent and 1 fully opaque. (Opacity values
- * are clamped to the [0,1] range.).
- * This works on both toplevel widget, and child widgets, although there
- * are some limitations:
- *
- * For toplevel widgets this depends on the capabilities of the windowing
- * system. On X11 this has any effect only on X screens with a compositing manager
- * running. See gtk_widget_is_composited(). On Windows it should work
- * always, although setting a window's opacity after the window has been
- * shown causes it to flicker once on Windows.
- *
- * For child widgets it doesn't work if any affected widget has a native window, or
- * disables double buffering.
- *
- * Since: 3.8
- **/
-void
-gtk_widget_set_opacity  (GtkWidget *widget,
-			 gdouble    opacity)
+static void
+gtk_widget_update_alpha (GtkWidget *widget)
 {
   GtkWidgetPrivate *priv;
+  double opacity;
   guint8 alpha;
 
-  g_return_if_fail (GTK_IS_WIDGET (widget));
-
   priv = widget->priv;
 
-  if (opacity < 0.0)
-    opacity = 0.0;
-  else if (opacity > 1.0)
-    opacity = 1.0;
+  alpha = priv->user_alpha;
+
+  if (priv->context)
+    {
+      opacity =
+	_gtk_css_number_value_get (_gtk_style_context_peek_property (priv->context,
+								     GTK_CSS_PROPERTY_OPACITY),
+				   100);
+      opacity = CLAMP (opacity, 0.0, 1.0);
+      alpha = round (priv->user_alpha * opacity);
+    }
 
-  alpha = round (opacity * 255);
   if (alpha == priv->alpha)
     return;
 
   priv->alpha = alpha;
 
-  if (gtk_widget_get_has_window (widget))
+    if (gtk_widget_get_has_window (widget))
     {
       if (priv->window != NULL)
 	gdk_window_set_opacity (priv->window,
-				priv->norender ? 0 : opacity);
+				priv->norender ? 0 : priv->alpha / 255.0);
     }
   else
     {
@@ -14005,6 +13992,50 @@ gtk_widget_set_opacity  (GtkWidget *widget,
 }
 
 /**
+ * gtk_widget_set_opacity:
+ * @widget: a #GtkWidget
+ * @opacity: desired opacity, between 0 and 1
+ *
+ * Request the @widget to be rendered partially transparent,
+ * with opacity 0 being fully transparent and 1 fully opaque. (Opacity values
+ * are clamped to the [0,1] range.).
+ * This works on both toplevel widget, and child widgets, although there
+ * are some limitations:
+ *
+ * For toplevel widgets this depends on the capabilities of the windowing
+ * system. On X11 this has any effect only on X screens with a compositing manager
+ * running. See gtk_widget_is_composited(). On Windows it should work
+ * always, although setting a window's opacity after the window has been
+ * shown causes it to flicker once on Windows.
+ *
+ * For child widgets it doesn't work if any affected widget has a native window, or
+ * disables double buffering.
+ *
+ * Since: 3.8
+ **/
+void
+gtk_widget_set_opacity  (GtkWidget *widget,
+			 gdouble    opacity)
+{
+  GtkWidgetPrivate *priv;
+  guint8 alpha;
+
+  g_return_if_fail (GTK_IS_WIDGET (widget));
+
+  priv = widget->priv;
+
+  opacity = CLAMP (opacity, 0.0, 1.0);
+
+  alpha = round (opacity * 255);
+  if (alpha == priv->user_alpha)
+    return;
+
+  priv->user_alpha = alpha;
+
+  gtk_widget_update_alpha (widget);
+}
+
+/**
  * gtk_widget_get_opacity:
  * @widget: a #GtkWidget
  *


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