[gnome-flashback] notifications: store icon as GIcon



commit d8e8d704f68c5f7a00dcfd96cd4d125c4148d58e
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Thu Jan 2 22:39:31 2020 +0200

    notifications: store icon as GIcon

 gnome-flashback/libnotifications/gf-bubble.c       |  70 +----
 .../libnotifications/nd-notification-box.c         |  11 +-
 gnome-flashback/libnotifications/nd-notification.c | 310 ++++++++-------------
 gnome-flashback/libnotifications/nd-notification.h |   4 +-
 4 files changed, 135 insertions(+), 260 deletions(-)
---
diff --git a/gnome-flashback/libnotifications/gf-bubble.c b/gnome-flashback/libnotifications/gf-bubble.c
index 9f85082..289fc2a 100644
--- a/gnome-flashback/libnotifications/gf-bubble.c
+++ b/gnome-flashback/libnotifications/gf-bubble.c
@@ -196,43 +196,6 @@ add_notification_action (GfBubble    *bubble,
   gtk_widget_show (priv->actions_box);
 }
 
-static GdkPixbuf *
-scale_pixbuf (GdkPixbuf *pixbuf,
-              gint       max_width,
-              gint       max_height)
-{
-  gint pw;
-  gint ph;
-  gfloat scale_factor_x;
-  gfloat scale_factor_y;
-  gfloat scale_factor;
-
-  pw = gdk_pixbuf_get_width (pixbuf);
-  ph = gdk_pixbuf_get_height (pixbuf);
-
-  /* Determine which dimension requires the smallest scale. */
-  scale_factor_x = (gfloat) max_width / (gfloat) pw;
-  scale_factor_y = (gfloat) max_height / (gfloat) ph;
-
-  scale_factor = scale_factor_x;
-  if (scale_factor_x > scale_factor_y)
-    scale_factor = scale_factor_y;
-
-  if (scale_factor < 1.0f)
-    {
-      gint scale_x;
-      gint scale_y;
-
-      scale_x = (gint) (pw * scale_factor);
-      scale_y = (gint) (ph * scale_factor);
-
-      return gdk_pixbuf_scale_simple (pixbuf, scale_x, scale_y,
-                                      GDK_INTERP_BILINEAR);
-    }
-
-  return g_object_ref (pixbuf);
-}
-
 static gboolean
 timeout_bubble (gpointer user_data)
 {
@@ -292,7 +255,7 @@ update_bubble (GfBubble *bubble)
   gchar **actions;
   gint i;
   gboolean have_actions;
-  GdkPixbuf *pixbuf;
+  GIcon *icon;
   gboolean have_icon;
 
   priv = gf_bubble_get_instance_private (bubble);
@@ -361,36 +324,17 @@ update_bubble (GfBubble *bubble)
 
   /* Icon */
 
-  pixbuf = nd_notification_load_image (priv->notification, IMAGE_SIZE);
+  icon = nd_notification_get_icon (priv->notification);
   have_icon = FALSE;
 
-  if (pixbuf != NULL)
+  if (icon != NULL)
     {
-      GdkPixbuf *scaled;
-
-      scaled = scale_pixbuf (pixbuf, IMAGE_SIZE, IMAGE_SIZE);
-      g_object_unref (pixbuf);
+      gtk_image_set_from_gicon (GTK_IMAGE (priv->icon), icon, GTK_ICON_SIZE_DIALOG);
+      gtk_image_set_pixel_size (GTK_IMAGE (priv->icon), IMAGE_SIZE);
 
-      gtk_image_set_from_pixbuf (GTK_IMAGE (priv->icon), scaled);
-
-      have_icon = scaled != NULL;
+      have_icon = TRUE;
       gtk_widget_set_visible (priv->icon, have_icon);
-
-      if (scaled != NULL)
-        {
-          gint width;
-
-          width = gdk_pixbuf_get_width (scaled);
-          g_object_unref (scaled);
-
-          width = MAX (BODY_X_OFFSET, width);
-
-          gtk_widget_set_size_request (priv->icon, width, -1);
-        }
-      else
-        {
-          gtk_widget_set_size_request (priv->icon, BODY_X_OFFSET, -1);
-        }
+      gtk_widget_set_size_request (priv->icon, BODY_X_OFFSET, -1);
     }
 
   if (have_body || have_actions || have_icon)
diff --git a/gnome-flashback/libnotifications/nd-notification-box.c 
b/gnome-flashback/libnotifications/nd-notification-box.c
index e250d63..d86daed 100644
--- a/gnome-flashback/libnotifications/nd-notification-box.c
+++ b/gnome-flashback/libnotifications/nd-notification-box.c
@@ -172,7 +172,7 @@ update_notification_box (NdNotificationBox *notification_box)
         gboolean       have_body;
         const char    *body;
         gboolean       have_actions;
-        GdkPixbuf     *pixbuf;
+        GIcon         *icon;
         char         **actions;
         int            i;
         char          *str;
@@ -187,11 +187,10 @@ update_notification_box (NdNotificationBox *notification_box)
         have_actions = FALSE;
 
         /* image */
-        pixbuf = nd_notification_load_image (notification_box->priv->notification, IMAGE_SIZE);
-        if (pixbuf != NULL) {
-                gtk_image_set_from_pixbuf (GTK_IMAGE (notification_box->priv->icon), pixbuf);
-
-                g_object_unref (G_OBJECT (pixbuf));
+        icon = nd_notification_get_icon (notification_box->priv->notification);
+        if (icon != NULL) {
+                gtk_image_set_from_gicon (GTK_IMAGE (notification_box->priv->icon), icon, 
GTK_ICON_SIZE_DIALOG);
+                gtk_image_set_pixel_size (GTK_IMAGE (notification_box->priv->icon), IMAGE_SIZE);
                 have_icon = TRUE;
         }
 
diff --git a/gnome-flashback/libnotifications/nd-notification.c 
b/gnome-flashback/libnotifications/nd-notification.c
index bbf3e1f..3a8daa2 100644
--- a/gnome-flashback/libnotifications/nd-notification.c
+++ b/gnome-flashback/libnotifications/nd-notification.c
@@ -45,7 +45,7 @@ struct _NdNotification {
         char         *sender;
         guint32       id;
         char         *app_name;
-        char         *app_icon;
+        GIcon        *icon;
         char         *summary;
         char         *body;
         char        **actions;
@@ -193,6 +193,120 @@ parse_markup (const gchar  *text,
   return TRUE;
 }
 
+static void
+free_pixels (guchar   *pixels,
+             gpointer  user_data)
+{
+        g_free (pixels);
+}
+
+static GIcon *
+icon_from_data (GVariant *icon_data)
+{
+        gboolean        has_alpha;
+        int             bits_per_sample;
+        int             width;
+        int             height;
+        int             rowstride;
+        int             n_channels;
+        GVariant       *data_variant;
+        gsize           expected_len;
+        guchar         *data;
+        GdkPixbuf      *pixbuf;
+
+        g_variant_get (icon_data,
+                       "(iiibii@ay)",
+                       &width,
+                       &height,
+                       &rowstride,
+                       &has_alpha,
+                       &bits_per_sample,
+                       &n_channels,
+                       &data_variant);
+
+        expected_len = (height - 1) * rowstride + width
+                * ((n_channels * bits_per_sample + 7) / 8);
+
+        if (expected_len != g_variant_get_size (data_variant)) {
+                g_warning ("Expected image data to be of length %" G_GSIZE_FORMAT
+                           " but got a " "length of %" G_GSIZE_FORMAT,
+                           expected_len,
+                           g_variant_get_size (data_variant));
+                return NULL;
+        }
+
+        data = (guchar *) g_memdup (g_variant_get_data (data_variant),
+                                    g_variant_get_size (data_variant));
+
+        pixbuf = gdk_pixbuf_new_from_data (data,
+                                           GDK_COLORSPACE_RGB,
+                                           has_alpha,
+                                           bits_per_sample,
+                                           width,
+                                           height,
+                                           rowstride,
+                                           free_pixels,
+                                           NULL);
+
+        return G_ICON (pixbuf);
+}
+
+static GIcon *
+icon_from_path (const char *path)
+{
+        GFile *file;
+        GIcon *icon;
+
+        if (path == NULL || *path == '\0')
+                return NULL;
+
+        if (g_str_has_prefix (path, "file://"))
+                file = g_file_new_for_uri (path);
+        else if (*path == '/')
+                file = g_file_new_for_path (path);
+        else
+                file = NULL;
+
+        if (file != NULL) {
+                icon = g_file_icon_new (file);
+                g_object_unref (file);
+        } else {
+                icon = g_themed_icon_new (path);
+        }
+
+        return icon;
+}
+
+static void
+update_icon (NdNotification *notification,
+             const gchar    *app_icon,
+             GVariant       *hints)
+{
+        GIcon *icon;
+        GVariantDict dict;
+        GVariant *image_data;
+        const char *image_path;
+
+        g_variant_dict_init (&dict, hints);
+
+        if (g_variant_dict_lookup (&dict, "image-data", "@(iiibiiay)", &image_data) ||
+            g_variant_dict_lookup (&dict, "image_data", "@(iiibiiay)", &image_data)) {
+                icon = icon_from_data (image_data);
+        } else if (g_variant_dict_lookup (&dict, "image-path", "&s", &image_path) ||
+                   g_variant_dict_lookup (&dict, "image_path", "&s", &image_path)) {
+                icon = icon_from_path (image_path);
+        } else if (*app_icon != '\0') {
+                icon = icon_from_path (app_icon);
+        } else if (g_variant_dict_lookup (&dict, "icon_data", "v", &image_data)) {
+                icon = icon_from_data (image_data);
+        } else {
+                icon = NULL;
+        }
+
+        g_clear_object (&notification->icon);
+        notification->icon = icon;
+}
+
 static void
 nd_notification_class_init (NdNotificationClass *class)
 {
@@ -234,7 +348,7 @@ nd_notification_init (NdNotification *notification)
         notification->id = get_next_notification_serial ();
 
         notification->app_name = NULL;
-        notification->app_icon = NULL;
+        notification->icon = NULL;
         notification->summary = NULL;
         notification->body = NULL;
         notification->actions = NULL;
@@ -253,7 +367,7 @@ nd_notification_finalize (GObject *object)
 
         g_free (notification->sender);
         g_free (notification->app_name);
-        g_free (notification->app_icon);
+        g_clear_object (&notification->icon);
         g_free (notification->summary);
         g_free (notification->body);
         g_strfreev (notification->actions);
@@ -284,8 +398,7 @@ nd_notification_update (NdNotification     *notification,
         g_free (notification->app_name);
         notification->app_name = g_strdup (app_name);
 
-        g_free (notification->app_icon);
-        notification->app_icon = g_strdup (app_icon);
+        update_icon (notification, app_icon, hints);
 
         g_free (notification->summary);
         notification->summary = g_strdup (summary);
@@ -456,191 +569,10 @@ nd_notification_get_timeout (NdNotification *notification)
         return notification->timeout;
 }
 
-static GdkPixbuf *
-scale_pixbuf (GdkPixbuf *pixbuf,
-              int        max_width,
-              int        max_height,
-              gboolean   no_stretch_hint)
-{
-        int        pw;
-        int        ph;
-        float      scale_factor_x = 1.0;
-        float      scale_factor_y = 1.0;
-        float      scale_factor = 1.0;
-
-        pw = gdk_pixbuf_get_width (pixbuf);
-        ph = gdk_pixbuf_get_height (pixbuf);
-
-        /* Determine which dimension requires the smallest scale. */
-        scale_factor_x = (float) max_width / (float) pw;
-        scale_factor_y = (float) max_height / (float) ph;
-
-        if (scale_factor_x > scale_factor_y) {
-                scale_factor = scale_factor_y;
-        } else {
-                scale_factor = scale_factor_x;
-        }
-
-        /* always scale down, allow to disable scaling up */
-        if (scale_factor < 1.0f || !no_stretch_hint) {
-                int scale_x;
-                int scale_y;
-
-                scale_x = (int) (pw * scale_factor);
-                scale_y = (int) (ph * scale_factor);
-                return gdk_pixbuf_scale_simple (pixbuf,
-                                                scale_x,
-                                                scale_y,
-                                                GDK_INTERP_BILINEAR);
-        } else {
-                return g_object_ref (pixbuf);
-        }
-}
-
-static void
-free_pixels (guchar   *pixels,
-             gpointer  user_data)
-{
-  g_free (pixels);
-}
-
-static GdkPixbuf *
-_notify_daemon_pixbuf_from_data_hint (GVariant *icon_data,
-                                      int       size)
-{
-        gboolean        has_alpha;
-        int             bits_per_sample;
-        int             width;
-        int             height;
-        int             rowstride;
-        int             n_channels;
-        GVariant       *data_variant;
-        gsize           expected_len;
-        guchar         *data;
-        GdkPixbuf      *pixbuf;
-
-        g_variant_get (icon_data,
-                       "(iiibii@ay)",
-                       &width,
-                       &height,
-                       &rowstride,
-                       &has_alpha,
-                       &bits_per_sample,
-                       &n_channels,
-                       &data_variant);
-
-        expected_len = (height - 1) * rowstride + width
-                * ((n_channels * bits_per_sample + 7) / 8);
-
-        if (expected_len != g_variant_get_size (data_variant)) {
-                g_warning ("Expected image data to be of length %" G_GSIZE_FORMAT
-                           " but got a " "length of %" G_GSIZE_FORMAT,
-                           expected_len,
-                           g_variant_get_size (data_variant));
-                return NULL;
-        }
-
-        data = (guchar *) g_memdup (g_variant_get_data (data_variant),
-                                    g_variant_get_size (data_variant));
-
-        pixbuf = gdk_pixbuf_new_from_data (data,
-                                           GDK_COLORSPACE_RGB,
-                                           has_alpha,
-                                           bits_per_sample,
-                                           width,
-                                           height,
-                                           rowstride,
-                                           free_pixels,
-                                           NULL);
-        if (pixbuf != NULL && size > 0) {
-                GdkPixbuf *scaled;
-                scaled = scale_pixbuf (pixbuf, size, size, TRUE);
-                g_object_unref (pixbuf);
-                pixbuf = scaled;
-        }
-
-        return pixbuf;
-}
-
-static GdkPixbuf *
-_notify_daemon_pixbuf_from_path (const char *path,
-                                 int         size)
+GIcon *
+nd_notification_get_icon (NdNotification *notification)
 {
-        GFile *file;
-        GdkPixbuf *pixbuf = NULL;
-
-        file = g_file_new_for_commandline_arg (path);
-        if (g_file_is_native (file)) {
-                char *realpath;
-
-                realpath = g_file_get_path (file);
-                pixbuf = gdk_pixbuf_new_from_file_at_size (realpath, size, size, NULL);
-                g_free (realpath);
-        }
-        g_object_unref (file);
-
-        if (pixbuf == NULL) {
-                /* Load icon theme icon */
-                GtkIconTheme *theme;
-                GtkIconInfo  *icon_info;
-
-                theme = gtk_icon_theme_get_default ();
-                icon_info = gtk_icon_theme_lookup_icon (theme,
-                                                        path,
-                                                        size,
-                                                        GTK_ICON_LOOKUP_USE_BUILTIN);
-
-                if (icon_info != NULL) {
-                        gint icon_size;
-
-                        icon_size = MIN (size,
-                                         gtk_icon_info_get_base_size (icon_info));
-
-                        if (icon_size == 0)
-                                icon_size = size;
-
-                        pixbuf = gtk_icon_theme_load_icon (theme,
-                                                           path,
-                                                           icon_size,
-                                                           GTK_ICON_LOOKUP_USE_BUILTIN,
-                                                           NULL);
-
-                        g_object_unref (icon_info);
-                }
-        }
-
-        return pixbuf;
-}
-
-GdkPixbuf *
-nd_notification_load_image (NdNotification *notification,
-                            int             size)
-{
-        GVariant  *data;
-        GdkPixbuf *pixbuf;
-
-        pixbuf = NULL;
-
-        if ((data = (GVariant *) g_hash_table_lookup (notification->hints, "image-data"))
-            || (data = (GVariant *) g_hash_table_lookup (notification->hints, "image_data"))) {
-                pixbuf = _notify_daemon_pixbuf_from_data_hint (data, size);
-        } else if ((data = (GVariant *) g_hash_table_lookup (notification->hints, "image-path"))
-                   || (data = (GVariant *) g_hash_table_lookup (notification->hints, "image_path"))) {
-                if (g_variant_is_of_type (data, G_VARIANT_TYPE_STRING)) {
-                        const char *path;
-                        path = g_variant_get_string (data, NULL);
-                        pixbuf = _notify_daemon_pixbuf_from_path (path, size);
-                } else {
-                        g_warning ("Expected image_path hint to be of type string");
-                }
-        } else if (*notification->app_icon != '\0') {
-                pixbuf = _notify_daemon_pixbuf_from_path (notification->app_icon, size);
-        } else if ((data = (GVariant *) g_hash_table_lookup (notification->hints, "icon_data"))) {
-                g_warning("\"icon_data\" hint is deprecated, please use \"image_data\" instead");
-                pixbuf = _notify_daemon_pixbuf_from_data_hint (data, size);
-        }
-
-        return pixbuf;
+        return notification->icon;
 }
 
 void
diff --git a/gnome-flashback/libnotifications/nd-notification.h 
b/gnome-flashback/libnotifications/nd-notification.h
index 3cf5249..47e9bb0 100644
--- a/gnome-flashback/libnotifications/nd-notification.h
+++ b/gnome-flashback/libnotifications/nd-notification.h
@@ -70,8 +70,8 @@ const char *          nd_notification_get_body            (NdNotification *notif
 char **               nd_notification_get_actions         (NdNotification *notification);
 GHashTable *          nd_notification_get_hints           (NdNotification *notification);
 
-GdkPixbuf *           nd_notification_load_image          (NdNotification *notification,
-                                                           int             size);
+GIcon *               nd_notification_get_icon            (NdNotification *notification);
+
 gboolean              nd_notification_get_is_resident     (NdNotification *notification);
 gboolean              nd_notification_get_is_transient    (NdNotification *notification);
 gboolean              nd_notification_get_action_icons    (NdNotification *notification);


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