[gnome-shell] ScreenShield: add a drop shadow to the animated arrows
- From: Giovanni Campagna <gcampagna src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] ScreenShield: add a drop shadow to the animated arrows
- Date: Sat, 1 Sep 2012 14:50:34 +0000 (UTC)
commit a76cc79f88fc23b5308ef130bbc77bab2fc88f32
Author: Giovanni Campagna <gcampagna src gnome org>
Date: Tue Aug 21 21:13:33 2012 +0200
ScreenShield: add a drop shadow to the animated arrows
Introduce a StShadowHelper to manage drop shadows from JS (which
cannot use Cogl directly), and use it in a new StWidget-derived
JS class to draw the arrow.
https://bugzilla.gnome.org/show_bug.cgi?id=682285
data/theme/gnome-shell.css | 3 +-
js/ui/screenShield.js | 76 +++++++++++++++++++------
src/st/st-shadow.c | 132 +++++++++++++++++++++++++++++++++++++++++---
src/st/st-shadow.h | 17 ++++++
4 files changed, 199 insertions(+), 29 deletions(-)
---
diff --git a/data/theme/gnome-shell.css b/data/theme/gnome-shell.css
index 3be3db9..968b2cd 100644
--- a/data/theme/gnome-shell.css
+++ b/data/theme/gnome-shell.css
@@ -2208,11 +2208,12 @@ StButton.popup-menu-item:insensitive {
padding-bottom: 3em;
}
-.screen-shield-arrows > StDrawingArea {
+.screen-shield-arrows Gjs_Arrow {
color: white;
width: 80px;
height: 48px;
-arrow-thickness: 12px;
+ -arrow-shadow: 0 1px 1px rgba(0,0,0,0.4);
}
.screen-shield-clock {
diff --git a/js/ui/screenShield.js b/js/ui/screenShield.js
index 32ea2da..ad8ecae 100644
--- a/js/ui/screenShield.js
+++ b/js/ui/screenShield.js
@@ -274,6 +274,62 @@ const NotificationsBox = new Lang.Class({
},
});
+const Arrow = new Lang.Class({
+ Name: 'Arrow',
+ Extends: St.Bin,
+
+ _init: function(params) {
+ this.parent(params);
+ this.x_fill = this.y_fill = true;
+ this.set_offscreen_redirect(Clutter.OffscreenRedirect.ALWAYS);
+
+ this._drawingArea = new St.DrawingArea();
+ this._drawingArea.connect('repaint', Lang.bind(this, this._drawArrow));
+ this.child = this._drawingArea;
+
+ this._shadowHelper = null;
+ this._shadowWidth = this._shadowHeight = 0;
+ },
+
+ _drawArrow: function(arrow) {
+ let cr = arrow.get_context();
+ let [w, h] = arrow.get_surface_size();
+ let node = this.get_theme_node();
+ let thickness = node.get_length('-arrow-thickness');
+
+ Clutter.cairo_set_source_color(cr, node.get_foreground_color());
+
+ cr.setLineCap(Cairo.LineCap.ROUND);
+ cr.setLineWidth(thickness);
+
+ cr.moveTo(thickness / 2, h - thickness / 2);
+ cr.lineTo(w/2, thickness);
+ cr.lineTo(w - thickness / 2, h - thickness / 2);
+ cr.stroke();
+ },
+
+ vfunc_style_changed: function() {
+ let node = this.get_theme_node();
+ this._shadow = node.get_shadow('-arrow-shadow');
+ if (this._shadow)
+ this._shadowHelper = St.ShadowHelper.new(this._shadow);
+ else
+ this._shadowHelper = null;
+ },
+
+ vfunc_paint: function() {
+ if (this._shadowHelper) {
+ this._shadowHelper.update(this._drawingArea);
+
+ let allocation = this._drawingArea.get_allocation_box();
+ let paintOpacity = this._drawingArea.get_paint_opacity();
+ this._shadowHelper.paint(allocation, paintOpacity);
+ }
+
+ this._drawingArea.paint();
+ }
+});
+
/**
* To test screen shield, make sure to kill gnome-screensaver.
*
@@ -318,8 +374,7 @@ const ScreenShield = new Lang.Class({
y_expand: true });
for (let i = 0; i < N_ARROWS; i++) {
- let arrow = new St.DrawingArea({ opacity: 0 });
- arrow.connect('repaint', Lang.bind(this, this._drawArrow));
+ let arrow = new Arrow({ opacity: 0 });
this._arrowContainer.add_actor(arrow);
}
this._lockScreenContents.add_actor(this._arrowContainer);
@@ -384,23 +439,6 @@ const ScreenShield = new Lang.Class({
return true;
},
- _drawArrow: function(arrow) {
- let cr = arrow.get_context();
- let [w, h] = arrow.get_surface_size();
- let node = arrow.get_theme_node();
- let thickness = node.get_length('-arrow-thickness');
-
- Clutter.cairo_set_source_color(cr, node.get_foreground_color());
-
- cr.setLineCap(Cairo.LineCap.ROUND);
- cr.setLineWidth(thickness);
-
- cr.moveTo(thickness / 2, h - thickness / 2);
- cr.lineTo(w/2, thickness);
- cr.lineTo(w - thickness / 2, h - thickness / 2);
- cr.stroke();
- },
-
_animateArrows: function() {
let arrows = this._arrowContainer.get_children();
let unitaryDelay = ARROW_ANIMATION_TIME / (arrows.length + 1);
diff --git a/src/st/st-shadow.c b/src/st/st-shadow.c
index 9c3784a..df1787f 100644
--- a/src/st/st-shadow.c
+++ b/src/st/st-shadow.c
@@ -21,6 +21,10 @@
#include "config.h"
#include "st-shadow.h"
+#include "st-private.h"
+
+G_DEFINE_BOXED_TYPE (StShadow, st_shadow, st_shadow_ref, st_shadow_unref)
+G_DEFINE_BOXED_TYPE (StShadowHelper, st_shadow_helper, st_shadow_helper_copy, st_shadow_helper_free)
/**
* SECTION: st-shadow
@@ -175,16 +179,126 @@ st_shadow_get_box (StShadow *shadow,
+ shadow->blur + shadow->spread;
}
-GType
-st_shadow_get_type (void)
+/**
+ * SECTION:st-shadow-helper:
+ *
+ * An helper for implementing a drop shadow on a actor.
+ * The actor is expected to recreate the helper whenever its contents
+ * or size change. Then, it would call st_shadow_helper_paint() inside
+ * its paint() virtual function.
+ */
+
+struct _StShadowHelper {
+ StShadow *shadow;
+ CoglMaterial *material;
+
+ gfloat width;
+ gfloat height;
+};
+
+/**
+ * st_shadow_helper_new:
+ * @shadow: a #StShadow representing the shadow properties
+ *
+ * Builds a #StShadowHelper that will build a drop shadow
+ * using @source as the mask.
+ *
+ * Returns: (transfer full): a new #StShadowHelper
+ */
+StShadowHelper *
+st_shadow_helper_new (StShadow *shadow)
+{
+ StShadowHelper *helper;
+
+ helper = g_slice_new0 (StShadowHelper);
+ helper->shadow = st_shadow_ref (shadow);
+
+ return helper;
+}
+
+void
+st_shadow_helper_update (StShadowHelper *helper,
+ ClutterActor *source)
+{
+ gfloat width, height;
+
+ clutter_actor_get_size (source, &width, &height);
+
+ if (helper->material == NULL ||
+ helper->width != width ||
+ helper->height != height)
+ {
+ if (helper->material)
+ cogl_object_unref (helper->material);
+
+ helper->material = _st_create_shadow_material_from_actor (helper->shadow, source);
+ helper->width = width;
+ helper->height = height;
+ }
+}
+
+/**
+ * st_shadow_helper_copy:
+ * @helper: the #StShadowHelper to copy
+ *
+ * Returns: (transfer full): a copy of @helper
+ */
+StShadowHelper *
+st_shadow_helper_copy (StShadowHelper *helper)
{
- static GType _st_shadow_type = 0;
+ StShadowHelper *copy;
+
+ copy = g_slice_new (StShadowHelper);
+ *copy = *helper;
+ if (copy->material)
+ cogl_object_ref (copy->material);
+ st_shadow_ref (copy->shadow);
+
+ return copy;
+}
+
+/**
+ * st_shadow_helper_free:
+ * @helper: a #StShadowHelper
+ *
+ * Free resources associated with @helper.
+ */
+void
+st_shadow_helper_free (StShadowHelper *helper)
+{
+ if (helper->material)
+ cogl_object_unref (helper->material);
+ st_shadow_unref (helper->shadow);
+
+ g_slice_free (StShadowHelper, helper);
+}
+
+/**
+ * st_shadow_helper_paint:
+ * @helper: a #StShadowHelper
+ * @actor_box: the bounding box of the shadow
+ * @paint_opacity: the opacity at which the shadow is painted
+ *
+ * Paints the shadow associated with @helper This must only
+ * be called from the implementation of ClutterActor::paint().
+ */
+void
+st_shadow_helper_paint (StShadowHelper *helper,
+ ClutterActorBox *actor_box,
+ guint8 paint_opacity)
+{
+ ClutterActorBox allocation;
+ float width, height;
+
+ clutter_actor_box_get_size (actor_box, &width, &height);
- if (G_UNLIKELY (_st_shadow_type == 0))
- _st_shadow_type =
- g_boxed_type_register_static ("StShadow",
- (GBoxedCopyFunc) st_shadow_ref,
- (GBoxedFreeFunc) st_shadow_unref);
+ allocation.x1 = (width - helper->width) / 2;
+ allocation.y1 = (height - helper->height) / 2;
+ allocation.x2 = allocation.x1 + helper->width;
+ allocation.y2 = allocation.y1 + helper->height;
- return _st_shadow_type;
+ _st_paint_shadow_with_opacity (helper->shadow,
+ helper->material,
+ &allocation,
+ paint_opacity);
}
diff --git a/src/st/st-shadow.h b/src/st/st-shadow.h
index 3523cdd..40c2149 100644
--- a/src/st/st-shadow.h
+++ b/src/st/st-shadow.h
@@ -26,8 +26,10 @@
G_BEGIN_DECLS
#define ST_TYPE_SHADOW (st_shadow_get_type ())
+#define ST_TYPE_SHADOW_HELPER (st_shadow_get_type ())
typedef struct _StShadow StShadow;
+typedef struct _StShadowHelper StShadowHelper;
/**
* StShadow:
@@ -70,6 +72,21 @@ void st_shadow_get_box (StShadow *shadow,
const ClutterActorBox *actor_box,
ClutterActorBox *shadow_box);
+
+GType st_shadow_helper_get_type (void) G_GNUC_CONST;
+
+StShadowHelper *st_shadow_helper_new (StShadow *shadow);
+
+StShadowHelper *st_shadow_helper_copy (StShadowHelper *helper);
+void st_shadow_helper_free (StShadowHelper *helper);
+
+void st_shadow_helper_update (StShadowHelper *helper,
+ ClutterActor *source);
+
+void st_shadow_helper_paint (StShadowHelper *helper,
+ ClutterActorBox *actor_box,
+ guint8 paint_opacity);
+
G_END_DECLS
#endif /* __ST_SHADOW__ */
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]