[gnome-shell] Fix app icon fading
- From: Colin Walters <walters src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-shell] Fix app icon fading
- Date: Sat, 13 Mar 2010 17:51:00 +0000 (UTC)
commit 3aea09b614035ba3d80c5d8dbdda0df8d17177be
Author: Colin Walters <walters verbum org>
Date: Fri Mar 12 15:57:01 2010 -0500
Fix app icon fading
The way we were loading data into a CoglTexture, then pulling it out
and manipulating it on the CPU, then loading it back into a texture
was a bit lame.
Clean things up a bit here by loading directly into the CPU, doing
the fading, then creating a texture.
Also cache the faded data in StTextureCache.
https://bugzilla.gnome.org/show_bug.cgi?id=612759
js/ui/panel.js | 20 +------
src/shell-app-system.c | 26 ++++++++-
src/shell-app-system.h | 4 +
src/shell-app.c | 144 ++++++++++++++++++++++++++++++++++++++++++++++++
src/shell-app.h | 1 +
src/shell-drawing.c | 64 ---------------------
src/shell-drawing.h | 2 -
7 files changed, 177 insertions(+), 84 deletions(-)
---
diff --git a/js/ui/panel.js b/js/ui/panel.js
index 6cce4c6..7046bec 100644
--- a/js/ui/panel.js
+++ b/js/ui/panel.js
@@ -158,7 +158,7 @@ AppPanelMenu.prototype = {
this._container.connect('get-preferred-width', Lang.bind(this, this._getPreferredWidth));
this._container.connect('get-preferred-height', Lang.bind(this, this._getPreferredHeight));
this._container.connect('allocate', Lang.bind(this, this._allocate));
- this._sourceIcon = null;
+
this._iconBox = new Shell.Slicer({ name: 'appMenuIcon' });
this._container.add_actor(this._iconBox);
this._label = new TextShadower();
@@ -271,7 +271,7 @@ AppPanelMenu.prototype = {
this._label.setText('');
let icon;
if (this._focusedApp != null) {
- icon = this._focusedApp.create_icon_texture(AppDisplay.APPICON_SIZE);
+ icon = this._focusedApp.get_faded_icon(AppDisplay.APPICON_SIZE);
this._label.setText(this._focusedApp.get_name());
} else if (this._activeSequence != null) {
icon = this._activeSequence.create_icon(AppDisplay.APPICON_SIZE);
@@ -281,21 +281,7 @@ AppPanelMenu.prototype = {
}
if (icon != null) {
- if (this._sourceIcon != null)
- this._sourceIcon.destroy();
- this._sourceIcon = icon;
- let faded = Shell.fade_app_icon(icon);
- // Because loading the texture is async, we may not have it yet.
- // If we don't, just create an empty one for now.
- if (faded == null)
- faded = new Clutter.Texture({ width: this._sourceIcon.width,
- height: this._sourceIcon.height });
- this._sourceIcon.connect('notify::cogl-texture', Lang.bind(this, function () {
- // TODO should be caching this
- faded = Shell.fade_app_icon(icon);
- this._iconBox.set_child(faded);
- }));
- this._iconBox.set_child(faded);
+ this._iconBox.set_child(icon);
this._iconBox.show();
}
diff --git a/src/shell-app-system.c b/src/shell-app-system.c
index be07df7..2d0d3db 100644
--- a/src/shell-app-system.c
+++ b/src/shell-app-system.c
@@ -1021,7 +1021,16 @@ themed_icon_from_name (const char *iconname)
return icon;
}
-static GIcon *
+/**
+ * shell_app_info_get_icon:
+ * @info: A #ShellAppInfo
+ *
+ * Get the #GIcon associated with this app; for apps "faked" from a #MetaWindow,
+ * return %NULL.
+ *
+ * Returns: (transfer full): The icon for @info, or %NULL
+ */
+GIcon *
shell_app_info_get_icon (ShellAppInfo *info)
{
char *iconname = NULL;
@@ -1121,6 +1130,21 @@ shell_app_info_create_icon_texture (ShellAppInfo *info, float size)
}
/**
+ * shell_app_info_get_source_window:
+ * @info: A #ShellAppInfo
+ *
+ * If @info is tracking a #MetaWindow, return that window.
+ * Otherwise, return %NULL.
+ */
+MetaWindow *
+shell_app_info_get_source_window (ShellAppInfo *info)
+{
+ if (info->type == SHELL_APP_INFO_TYPE_WINDOW)
+ return info->window;
+ return NULL;
+}
+
+/**
* shell_app_info_launch_full:
* @timestamp: Event timestamp, or 0 for current event timestamp
* @uris: List of uris to pass to application
diff --git a/src/shell-app-system.h b/src/shell-app-system.h
index a02cfb7..be7efeb 100644
--- a/src/shell-app-system.h
+++ b/src/shell-app-system.h
@@ -50,10 +50,14 @@ char *shell_app_info_get_name (ShellAppInfo *info);
char *shell_app_info_get_description (ShellAppInfo *info);
char *shell_app_info_get_executable (ShellAppInfo *info);
char *shell_app_info_get_desktop_file_path (ShellAppInfo *info);
+GIcon *shell_app_info_get_icon (ShellAppInfo *info);
ClutterActor *shell_app_info_create_icon_texture (ShellAppInfo *info, float size);
GSList *shell_app_info_get_categories (ShellAppInfo *info);
gboolean shell_app_info_get_is_nodisplay (ShellAppInfo *info);
gboolean shell_app_info_is_transient (ShellAppInfo *info);
+
+MetaWindow *shell_app_info_get_source_window (ShellAppInfo *info);
+
gboolean shell_app_info_launch_full (ShellAppInfo *info,
guint timestamp,
GList *uris,
diff --git a/src/shell-app.c b/src/shell-app.c
index 7630cd0..08e80c2 100644
--- a/src/shell-app.c
+++ b/src/shell-app.c
@@ -4,6 +4,9 @@
#include "shell-app-private.h"
#include "shell-global.h"
+#include "st.h"
+
+#include <string.h>
/**
* SECTION:shell-app
@@ -22,6 +25,7 @@ struct _ShellApp
gboolean window_sort_stale;
GSList *windows;
+
};
G_DEFINE_TYPE (ShellApp, shell_app, G_TYPE_OBJECT);
@@ -53,6 +57,146 @@ shell_app_create_icon_texture (ShellApp *app,
{
return shell_app_info_create_icon_texture (app->info, size);
}
+typedef struct {
+ ShellApp *app;
+ int size;
+} CreateFadedIconData;
+
+static CoglHandle
+shell_app_create_faded_icon_cpu (StTextureCache *cache,
+ const char *key,
+ void *datap,
+ GError **error)
+{
+ CreateFadedIconData *data = datap;
+ ShellApp *app;
+ GdkPixbuf *pixbuf;
+ int size;
+ CoglHandle texture;
+ gint width, height, rowstride;
+ guint8 n_channels;
+ gint fade_start;
+ gint fade_range;
+ guint i, j;
+ guint pixbuf_byte_size;
+ guint8 *orig_pixels;
+ guint8 *pixels;
+ GIcon *icon;
+ GtkIconInfo *info;
+
+ app = data->app;
+ size = data->size;
+
+ icon = shell_app_info_get_icon (app->info);
+ if (icon == NULL)
+ return COGL_INVALID_HANDLE;
+
+ info = gtk_icon_theme_lookup_by_gicon (gtk_icon_theme_get_default (),
+ icon, (int) (size + 0.5),
+ GTK_ICON_LOOKUP_FORCE_SIZE);
+ g_object_unref (icon);
+ if (info == NULL)
+ return COGL_INVALID_HANDLE;
+
+ pixbuf = gtk_icon_info_load_icon (info, NULL);
+ gtk_icon_info_free (info);
+
+ if (pixbuf == NULL)
+ return COGL_INVALID_HANDLE;
+
+ width = gdk_pixbuf_get_width (pixbuf);
+ height = gdk_pixbuf_get_height (pixbuf);
+ rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+ n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+ orig_pixels = gdk_pixbuf_get_pixels (pixbuf);
+
+ pixbuf_byte_size = (height - 1) * rowstride +
+ + width * ((n_channels * gdk_pixbuf_get_bits_per_sample (pixbuf) + 7) / 8);
+
+ pixels = g_malloc0 (rowstride * height);
+ memcpy (pixels, orig_pixels, pixbuf_byte_size);
+
+ fade_start = width / 2;
+ fade_range = width - fade_start;
+ for (i = fade_start; i < width; i++)
+ {
+ for (j = 0; j < height; j++)
+ {
+ guchar *pixel = &pixels[j * rowstride + i * n_channels];
+ float fade = 1.0 - ((float) i - fade_start) / fade_range;
+ pixel[0] = 0.5 + pixel[0] * fade;
+ pixel[1] = 0.5 + pixel[1] * fade;
+ pixel[2] = 0.5 + pixel[2] * fade;
+ pixel[3] = 0.5 + pixel[3] * fade;
+ }
+ }
+
+ texture = cogl_texture_new_from_data (width,
+ height,
+ COGL_TEXTURE_NONE,
+ gdk_pixbuf_get_has_alpha (pixbuf) ? COGL_PIXEL_FORMAT_RGBA_8888 : COGL_PIXEL_FORMAT_RGB_888,
+ COGL_PIXEL_FORMAT_ANY,
+ rowstride,
+ pixels);
+ g_free (pixels);
+ g_object_unref (pixbuf);
+
+ return texture;
+}
+
+/**
+ * shell_app_get_faded_icon:
+ * @app: A #ShellApp
+ * @size: Size in pixels
+ *
+ * Return an actor with a horizontally faded look.
+ *
+ * Return value: (transfer none): A floating #ClutterActor, or %NULL if no icon
+ */
+ClutterActor *
+shell_app_get_faded_icon (ShellApp *app, float size)
+{
+ MetaWindow *window;
+ CoglHandle texture;
+ ClutterActor *result;
+ char *cache_key;
+ CreateFadedIconData data;
+
+ /* Punt for WINDOW types for now...easier to reuse the property tracking bits,
+ * and this helps us visually distinguish app-tracked from not.
+ */
+ window = shell_app_info_get_source_window (app->info);
+ if (window)
+ {
+ return st_texture_cache_bind_pixbuf_property (st_texture_cache_get_default (),
+ G_OBJECT (window),
+ "icon");
+ }
+
+ cache_key = g_strdup_printf ("faded-icon:%s,size=%f", shell_app_get_id (app), size);
+ data.app = app;
+ data.size = (int) (0.5 + size);
+ texture = st_texture_cache_load (st_texture_cache_get_default (),
+ cache_key,
+ ST_TEXTURE_CACHE_POLICY_FOREVER,
+ shell_app_create_faded_icon_cpu,
+ &data,
+ NULL);
+ g_free (cache_key);
+
+ if (texture != COGL_INVALID_HANDLE)
+ {
+ result = clutter_texture_new ();
+ clutter_texture_set_cogl_texture (CLUTTER_TEXTURE (result), texture);
+ }
+ else
+ {
+ result = clutter_texture_new ();
+ g_object_set (result, "opacity", 0, "width", size, "height", size, NULL);
+
+ }
+ return result;
+}
char *
shell_app_get_name (ShellApp *app)
diff --git a/src/shell-app.h b/src/shell-app.h
index f6e2f71..0e25161 100644
--- a/src/shell-app.h
+++ b/src/shell-app.h
@@ -30,6 +30,7 @@ GType shell_app_get_type (void) G_GNUC_CONST;
const char *shell_app_get_id (ShellApp *app);
ClutterActor *shell_app_create_icon_texture (ShellApp *app, float size);
+ClutterActor *shell_app_get_faded_icon (ShellApp *app, float size);
char *shell_app_get_name (ShellApp *app);
char *shell_app_get_description (ShellApp *app);
gboolean shell_app_is_transient (ShellApp *app);
diff --git a/src/shell-drawing.c b/src/shell-drawing.c
index 01055c9..616c800 100644
--- a/src/shell-drawing.c
+++ b/src/shell-drawing.c
@@ -49,70 +49,6 @@ shell_draw_clock (StDrawingArea *area,
cairo_stroke (cr);
}
-/**
- * shell_fade_app_icon:
- * @source: Source #ClutterTexture
- *
- * Create a new texture by modifying the alpha channel of the
- * source texture, adding a horizontal gradient fade.
- *
- * Returns: (transfer none): A new #ClutterTexture
- */
-ClutterTexture *
-shell_fade_app_icon (ClutterTexture *source)
-{
- CoglHandle texture;
- guchar *pixels;
- gint width, height, rowstride;
- gint fade_start;
- gint fade_range;
- guint i, j;
- ClutterTexture *result;
-
- texture = clutter_texture_get_cogl_texture (source);
- if (texture == COGL_INVALID_HANDLE)
- return NULL;
-
- width = cogl_texture_get_width (texture);
- height = cogl_texture_get_height (texture);
- rowstride = (width * 4 + 3) & ~3;
-
- pixels = g_malloc0 (rowstride * height);
-
- cogl_texture_get_data (texture, COGL_PIXEL_FORMAT_RGBA_8888_PRE,
- rowstride, pixels);
-
- fade_start = width / 2;
- fade_range = width - fade_start;
- for (i = fade_start; i < width; i++)
- {
- for (j = 0; j < height; j++)
- {
- guchar *pixel = &pixels[j * rowstride + i * 4];
- float fade = 1.0 - ((float) i - fade_start) / fade_range;
- pixel[0] = 0.5 + pixel[0] * fade;
- pixel[1] = 0.5 + pixel[1] * fade;
- pixel[2] = 0.5 + pixel[2] * fade;
- pixel[3] = 0.5 + pixel[3] * fade;
- }
- }
-
- texture = cogl_texture_new_from_data (width,
- height,
- COGL_TEXTURE_NONE,
- COGL_PIXEL_FORMAT_RGBA_8888_PRE,
- COGL_PIXEL_FORMAT_ANY,
- rowstride,
- pixels);
- g_free (pixels);
-
- result = (ClutterTexture*)clutter_texture_new ();
- clutter_texture_set_cogl_texture (result, texture);
- cogl_handle_unref (texture);
-
- return result;
-}
-
void
shell_draw_box_pointer (StDrawingArea *area,
ShellPointerDirection direction,
diff --git a/src/shell-drawing.h b/src/shell-drawing.h
index ac6edf9..feaa580 100644
--- a/src/shell-drawing.h
+++ b/src/shell-drawing.h
@@ -24,8 +24,6 @@ void shell_draw_clock (StDrawingArea *area,
int hour,
int minute);
-ClutterTexture * shell_fade_app_icon (ClutterTexture *source);
-
guint shell_add_hook_paint_red_border (ClutterActor *actor);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]