[gnome-flashback/wip/segeiger/statusicon: 3/3] input-sources: implement status icon with pango and cairo



commit 9f97238a061fcbde3fbbbae2334f099e5cbb612b
Author: Sebastian Geiger <sbastig gmx net>
Date:   Wed Sep 30 14:54:55 2015 +0200

    input-sources: implement status icon with pango and cairo

 data/schemas/org.gnome.gnome-flashback.gschema.xml |    4 +-
 .../libinput-sources/gf-input-sources.c            |  268 ++++++++++++++++++++
 2 files changed, 270 insertions(+), 2 deletions(-)
---
diff --git a/data/schemas/org.gnome.gnome-flashback.gschema.xml 
b/data/schemas/org.gnome.gnome-flashback.gschema.xml
index 12c6e94..cdcbf4f 100644
--- a/data/schemas/org.gnome.gnome-flashback.gschema.xml
+++ b/data/schemas/org.gnome.gnome-flashback.gschema.xml
@@ -103,13 +103,13 @@
   <schema id="org.gnome.gnome-flashback.input-sources" path="/org/gnome/gnome-flashback/input-sources/">
 
       <key name="status-icon-bg-color" type="s">
-          <default>'#000000'</default>
+          <default>'rgba(255, 255, 255, 1.0)'</default>
           <summary>The background color for the status icon.</summary>
           <description>This contains the background color for the status icon that is shown in the system 
tray.</description>
       </key>
 
       <key name="status-icon-fg-color" type="s">
-          <default>'#FFFFFF'</default>
+          <default>'rgba(0, 0, 0, 1.0)'</default>
           <summary>The foreground color for the status icon.</summary>
           <description>This contains the foreground color for the status icon that is shown in the system 
tray.</description>
       </key>
diff --git a/gnome-flashback/libinput-sources/gf-input-sources.c 
b/gnome-flashback/libinput-sources/gf-input-sources.c
index ce708ad..6645df8 100644
--- a/gnome-flashback/libinput-sources/gf-input-sources.c
+++ b/gnome-flashback/libinput-sources/gf-input-sources.c
@@ -17,9 +17,34 @@
 
 #include "config.h"
 
+#define _XOPEN_SOURCE
+
+#include <gtk/gtk.h>
+
 #include "gf-ibus-manager.h"
 #include "gf-input-sources.h"
 #include "gf-input-source-manager.h"
+#include "gf-input-source.h"
+
+#include <pango/pangocairo.h>
+#include <math.h>
+
+#define INPUT_SOURCES_SCHEMA "org.gnome.gnome-flashback.input-sources"
+#define GNOME_DESKTOP_SCHEMA "org.gnome.desktop.interface"
+#define SIZE 256
+
+struct IconInfo_
+{
+  gchar   *font_name,
+          *short_name;
+
+  gdouble  font_size;
+
+  GdkRGBA  bg_color,
+           fg_color;
+};
+
+typedef struct IconInfo_ IconInfo;
 
 struct _GfInputSources
 {
@@ -27,10 +52,101 @@ struct _GfInputSources
 
   GfIBusManager        *ibus_manager;
   GfInputSourceManager *input_source_manager;
+
+  GtkStatusIcon        *status_icon;
+
+  IconInfo             *icon_info;
 };
 
 G_DEFINE_TYPE (GfInputSources, gf_input_sources, G_TYPE_OBJECT)
 
+static void draw_short_name (cairo_t *cr, IconInfo *info)
+{
+  gdouble text_width, text_y;
+  gdouble pango_font_size;
+  gdouble baseline;
+  gdouble x, y;
+
+  gint center;
+
+  gchar *short_name, *font_name;
+
+  PangoLayout *layout;
+  PangoFontDescription *font_description;
+  PangoRectangle ink_rect, logical_rect;
+
+  short_name = info->short_name;
+  font_name = info->font_name;
+
+  font_description = pango_font_description_from_string (font_name);
+  pango_font_description_set_weight (font_description, PANGO_WEIGHT_BOLD);
+  pango_font_size = SIZE * info->font_size * PANGO_SCALE;
+  pango_font_description_set_absolute_size (font_description,
+                                            pango_font_size);
+
+  layout = pango_cairo_create_layout (cr);
+  pango_layout_set_font_description (layout, font_description);
+  pango_layout_set_text (layout, short_name, -1);
+
+  pango_layout_get_extents (layout, &ink_rect, &logical_rect);
+
+  text_width = ink_rect.width / (gdouble) PANGO_SCALE;
+  text_y = ink_rect.y / (gdouble) PANGO_SCALE;
+
+  baseline = pango_layout_get_baseline (layout) / PANGO_SCALE;
+
+  center = SIZE / 2;
+  y = center + baseline / 2.0 - text_y / 2.0;
+  x = (SIZE - text_width) / 2.0 - (ink_rect.x / PANGO_SCALE);
+
+  gdk_cairo_set_source_rgba (cr, &info->fg_color);
+  cairo_move_to (cr, x, y);
+  pango_cairo_show_layout_line (cr, pango_layout_get_line (layout, 0));
+
+  g_object_unref (layout);
+  pango_font_description_free (font_description);
+}
+
+static void draw_rounded_rectangle (cairo_t *cr, IconInfo *info)
+{
+  double
+    x             = 10,
+    y             = 10,
+    width         = SIZE - 2*x,
+    height        = SIZE - 2*y,
+    aspect        = 1.0,             /* aspect ratio */
+    corner_radius = height / 10.0;   /* and corner curvature radius */
+
+  double radius = corner_radius / aspect;
+  double degrees = M_PI / 180.0;
+
+  cairo_new_sub_path (cr);
+  cairo_arc (cr, x + width - radius, y + radius, radius, -90 * degrees, 0 * degrees);
+  cairo_arc (cr, x + width - radius, y + height - radius, radius, 0 * degrees, 90 * degrees);
+  cairo_arc (cr, x + radius, y + height - radius, radius, 90 * degrees, 180 * degrees);
+  cairo_arc (cr, x + radius, y + radius, radius, 180 * degrees, 270 * degrees);
+  cairo_close_path (cr);
+
+  gdk_cairo_set_source_rgba (cr, &info->bg_color);
+  cairo_fill_preserve (cr);
+}
+
+static GdkPixbuf *get_pixbuf_for_icon_info(IconInfo *info)
+{
+  cairo_surface_t *surface;
+  cairo_t * cr;
+
+  surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, SIZE, SIZE);
+  cr = cairo_create (surface);
+
+  draw_rounded_rectangle (cr, info);
+  draw_short_name (cr, info);
+
+  return gdk_pixbuf_get_from_surface (surface, 0, 0, SIZE, SIZE);
+
+}
+
+
 static void
 sources_changed_cb (GfInputSourceManager *manager,
                     gpointer              user_data)
@@ -38,6 +154,95 @@ sources_changed_cb (GfInputSourceManager *manager,
 }
 
 static void
+update_status_icon_pixbuf (GfInputSources *sources)
+{
+  GdkPixbuf *pixbuf;
+
+  pixbuf = get_pixbuf_for_icon_info (sources->icon_info);
+
+  gtk_status_icon_set_from_pixbuf (sources->status_icon, pixbuf);
+}
+
+static void
+current_source_changed_cb (GfInputSourceManager *manager,
+                           GfInputSource        *old_source,
+                           GfInputSources       *sources)
+{
+  GfInputSource *current_source;
+  gchar *display_name, *short_name;
+
+  current_source = gf_input_source_manager_get_current_source (manager);
+  display_name = g_strdup (gf_input_source_get_display_name (current_source));
+  short_name = g_strdup (gf_input_source_get_short_name (current_source));
+
+  if (sources->status_icon == NULL)
+    {
+      sources->status_icon = gtk_status_icon_new ();
+    }
+
+  gtk_status_icon_set_tooltip_text (sources->status_icon, display_name);
+
+  sources->icon_info->short_name = short_name;
+
+  update_status_icon_pixbuf (sources);
+}
+
+static void
+status_icon_bg_color_changed_cb (GSettings *settings,
+                                 gchar     *key,
+                                 gpointer   user_data)
+{
+  GfInputSources *sources;
+  const gchar* bg_color;
+  GVariant *variant;
+
+  sources = GF_INPUT_SOURCES (user_data);
+  variant = g_settings_get_value (settings, key);
+  bg_color = g_variant_get_string (variant, NULL);
+
+  gdk_rgba_parse (&sources->icon_info->bg_color, bg_color);
+
+  update_status_icon_pixbuf (sources);
+}
+
+static void
+status_icon_fg_color_changed_cb (GSettings *settings,
+                                 gchar     *key,
+                                 gpointer   user_data)
+{
+  GfInputSources *sources;
+  const gchar* fg_color;
+  GVariant *variant;
+
+  sources = GF_INPUT_SOURCES (user_data);
+  variant = g_settings_get_value (settings, key);
+  fg_color = g_variant_get_string (variant, NULL);
+
+  gdk_rgba_parse (&sources->icon_info->fg_color, fg_color);
+
+  update_status_icon_pixbuf (sources);
+}
+
+static void
+font_name_changed_cb (GSettings *settings,
+                      gchar     *key,
+                      gpointer   user_data)
+{
+  GfInputSources *sources;
+  const gchar* font_name;
+  GVariant *variant;
+
+  sources = GF_INPUT_SOURCES (user_data);
+  variant = g_settings_get_value (settings, key);
+  font_name = g_variant_get_string (variant, NULL);
+
+  g_free (sources->icon_info->font_name);
+  sources->icon_info->font_name = g_strdup (font_name);
+
+  update_status_icon_pixbuf (sources);
+}
+
+static void
 gf_input_sources_dispose (GObject *object)
 {
   GfInputSources *sources;
@@ -51,6 +256,18 @@ gf_input_sources_dispose (GObject *object)
 }
 
 static void
+gf_input_sources_finalize (GObject *object)
+{
+  GfInputSources *sources;
+
+  sources = GF_INPUT_SOURCES (object);
+
+  g_free (sources->icon_info->font_name);
+  g_free (sources->icon_info->short_name);
+  g_free (sources->icon_info);
+}
+
+static void
 gf_input_sources_class_init (GfInputSourcesClass *sources_class)
 {
   GObjectClass *object_class;
@@ -58,17 +275,68 @@ gf_input_sources_class_init (GfInputSourcesClass *sources_class)
   object_class = G_OBJECT_CLASS (sources_class);
 
   object_class->dispose = gf_input_sources_dispose;
+  object_class->finalize= gf_input_sources_finalize;
 }
 
 static void
 gf_input_sources_init (GfInputSources *sources)
 {
+  GdkRGBA bg, fg;
+
+  const gchar* bg_color;
+  const gchar* fg_color;
+  const gchar* font_name;
+
+  GSettings *input_sources_settings;
+  GSettings *gnome_desktop_settings;
+
+  GVariant *variant;
+
   sources->ibus_manager = gf_ibus_manager_new ();
   sources->input_source_manager = gf_input_source_manager_new (sources->ibus_manager);
+  sources->icon_info = g_new0 (IconInfo, 1);
+
+  input_sources_settings = g_settings_new (INPUT_SOURCES_SCHEMA);
+  gnome_desktop_settings = g_settings_new (GNOME_DESKTOP_SCHEMA);
+
+  variant = g_settings_get_value (gnome_desktop_settings,
+                                  "font-name");
+
+  font_name = g_variant_get_string (variant, NULL);
+
+  variant = g_settings_get_value (input_sources_settings,
+                                  "status-icon-bg-color");
+
+  bg_color = g_variant_get_string (variant, NULL);
+
+  variant = g_settings_get_value (input_sources_settings,
+                                  "status-icon-fg-color");
+
+  fg_color = g_variant_get_string (variant, NULL);
+
+  gdk_rgba_parse (&bg, bg_color);
+  gdk_rgba_parse (&fg, fg_color);
+
+  sources->icon_info->font_name = g_strdup (font_name);
+  sources->icon_info->bg_color = bg;
+  sources->icon_info->fg_color = fg;
+  sources->icon_info->font_size = 0.6;
 
   g_signal_connect (sources->input_source_manager, "sources-changed",
                     G_CALLBACK (sources_changed_cb), sources);
 
+  g_signal_connect (sources->input_source_manager, "current-source-changed",
+                    G_CALLBACK (current_source_changed_cb), sources);
+
+  g_signal_connect (input_sources_settings, "changed::status-icon-bg-color",
+                    G_CALLBACK (status_icon_bg_color_changed_cb), sources);
+
+  g_signal_connect (input_sources_settings, "changed::status-icon-fg-color",
+                    G_CALLBACK (status_icon_fg_color_changed_cb), sources);
+
+  g_signal_connect (gnome_desktop_settings, "changed::font-name",
+                    G_CALLBACK (font_name_changed_cb), sources);
+
   gf_input_source_manager_reload (sources->input_source_manager);
 }
 


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