[gnome-panel] status-notifier: load icon and show dbus menu



commit 97da5606b088c3c660afc730275c5032cc81be16
Author: Alberts Muktupāvels <alberts muktupavels gmail com>
Date:   Fri Nov 4 16:38:42 2016 +0200

    status-notifier: load icon and show dbus menu

 applets/status-notifier/sn-applet.c  |    4 +
 applets/status-notifier/sn-item-v0.c |  174 ++++++++++++++++++++++++++++++-
 applets/status-notifier/sn-item.c    |  193 +++++++++++++++++++++++++++++++++-
 applets/status-notifier/sn-item.h    |   31 +++++-
 4 files changed, 395 insertions(+), 7 deletions(-)
---
diff --git a/applets/status-notifier/sn-applet.c b/applets/status-notifier/sn-applet.c
index 427ee2e..d09debc 100644
--- a/applets/status-notifier/sn-applet.c
+++ b/applets/status-notifier/sn-applet.c
@@ -84,6 +84,10 @@ item_added_cb (SnHost   *host,
 
   sn->items = g_slist_sort (sn->items, compare_items);
   gtk_container_foreach (GTK_CONTAINER (sn->box), reorder_items, sn);
+
+  g_object_bind_property (sn->box, "orientation",
+                          item, "orientation",
+                          G_BINDING_DEFAULT);
 }
 
 static void
diff --git a/applets/status-notifier/sn-item-v0.c b/applets/status-notifier/sn-item-v0.c
index 83955df..a727600 100644
--- a/applets/status-notifier/sn-item-v0.c
+++ b/applets/status-notifier/sn-item-v0.c
@@ -34,6 +34,8 @@ struct _SnItemV0
 {
   SnItem         parent;
 
+  GtkWidget     *image;
+
   GCancellable  *cancellable;
   SnItemV0Gen   *proxy;
 
@@ -65,6 +67,23 @@ update (SnItemV0 *v0)
 {
   gboolean visible;
 
+  if (v0->icon_name != NULL)
+    {
+      GtkIconTheme *icon_theme;
+      GtkImage *image;
+
+      icon_theme = gtk_icon_theme_get_default ();
+      image = GTK_IMAGE (v0->image);
+
+      gtk_icon_theme_rescan_if_needed (icon_theme);
+      gtk_image_set_from_icon_name (image, v0->icon_name, GTK_ICON_SIZE_MENU);
+      gtk_image_set_pixel_size (image, 16);
+    }
+  else if (v0->icon_pixmap != NULL)
+    {
+      g_debug ("status notifier item does not have icon name");
+    }
+
   visible = g_strcmp0 (v0->status, "Passive") != 0;
   gtk_widget_set_visible (GTK_WIDGET (v0), visible);
 }
@@ -481,6 +500,15 @@ new_icon_theme_path_cb (SnItemV0 *v0,
   v0->icon_theme_path = g_variant_dup_string (variant, NULL);
   g_variant_unref (variant);
 
+  if (v0->icon_theme_path != NULL)
+    {
+      GtkIconTheme *icon_theme;
+
+      icon_theme = gtk_icon_theme_get_default ();
+
+      gtk_icon_theme_append_search_path (icon_theme, v0->icon_theme_path);
+    }
+
   queue_update (v0);
 }
 
@@ -589,7 +617,7 @@ get_all_cb (GObject      *source_object,
       else if (g_strcmp0 (key, "ItemIsMenu") == 0)
         v0->item_is_menu = g_variant_get_boolean (value);
       else
-        g_assert_not_reached ();
+        g_debug ("property '%s' not handled!", key);
     }
 
   g_variant_iter_free (iter);
@@ -611,6 +639,15 @@ get_all_cb (GObject      *source_object,
       return;
     }
 
+  if (v0->icon_theme_path != NULL)
+    {
+      GtkIconTheme *icon_theme;
+
+      icon_theme = gtk_icon_theme_get_default ();
+
+      gtk_icon_theme_append_search_path (icon_theme, v0->icon_theme_path);
+    }
+
   g_signal_connect (v0->proxy, "g-properties-changed",
                     G_CALLBACK (g_properties_changed_cb), v0);
 
@@ -745,13 +782,137 @@ sn_item_v0_get_category (SnItem *item)
   return v0->category;
 }
 
+static const gchar *
+sn_item_v0_get_menu (SnItem *item)
+{
+  SnItemV0 *v0;
+
+  v0 = SN_ITEM_V0 (item);
+
+  return v0->menu;
+}
+
+static void
+context_menu_cb (GObject      *source_object,
+                 GAsyncResult *res,
+                 gpointer      user_data)
+{
+  SnItemV0 *v0;
+
+  v0 = SN_ITEM_V0 (user_data);
+
+  sn_item_v0_gen_call_context_menu_finish (v0->proxy, res, NULL);
+}
+
+static void
+sn_item_v0_context_menu (SnItem *item,
+                         gint    x,
+                         gint    y)
+{
+  SnItemV0 *v0;
+
+  v0 = SN_ITEM_V0 (item);
+
+  sn_item_v0_gen_call_context_menu (v0->proxy, x, y, NULL,
+                                    context_menu_cb, v0);
+}
+
+static void
+activate_cb (GObject      *source_object,
+             GAsyncResult *res,
+             gpointer      user_data)
+{
+  SnItemV0 *v0;
+
+  v0 = SN_ITEM_V0 (user_data);
+
+  sn_item_v0_gen_call_activate_finish (v0->proxy, res, NULL);
+}
+
+static void
+sn_item_v0_activate (SnItem *item,
+                     gint    x,
+                     gint    y)
+{
+  SnItemV0 *v0;
+
+  v0 = SN_ITEM_V0 (item);
+
+  sn_item_v0_gen_call_activate (v0->proxy, x, y, NULL,
+                                activate_cb, v0);
+}
+
+static void
+secondary_activate_cb (GObject      *source_object,
+                       GAsyncResult *res,
+                       gpointer      user_data)
+{
+  SnItemV0 *v0;
+
+  v0 = SN_ITEM_V0 (user_data);
+
+  sn_item_v0_gen_call_secondary_activate_finish (v0->proxy, res, NULL);
+}
+
+static void
+sn_item_v0_secondary_activate (SnItem *item,
+                               gint    x,
+                               gint    y)
+{
+  SnItemV0 *v0;
+
+  v0 = SN_ITEM_V0 (item);
+
+  sn_item_v0_gen_call_secondary_activate (v0->proxy, x, y, NULL,
+                                          secondary_activate_cb, v0);
+}
+
+static void
+scroll_cb (GObject      *source_object,
+           GAsyncResult *res,
+           gpointer      user_data)
+{
+  SnItemV0 *v0;
+
+  v0 = SN_ITEM_V0 (user_data);
+
+  sn_item_v0_gen_call_scroll_finish (v0->proxy, res, NULL);
+}
+
+static void
+sn_item_v0_scroll (SnItem            *item,
+                   gint               delta,
+                   SnItemOrientation  orientation)
+{
+  SnItemV0 *v0;
+  const gchar *tmp;
+
+  v0 = SN_ITEM_V0 (item);
+
+  switch (orientation)
+    {
+      case SN_ITEM_ORIENTATION_VERTICAL:
+        tmp = "Vertical";
+        break;
+
+      case SN_ITEM_ORIENTATION_HORIZONTAL:
+      default:
+        tmp = "Horizontal";
+        break;
+    }
+
+  sn_item_v0_gen_call_scroll (v0->proxy, delta, tmp, NULL, scroll_cb, v0);
+}
+
 static void
 sn_item_v0_class_init (SnItemV0Class *v0_class)
 {
   GObjectClass *object_class;
+  GtkWidgetClass *widget_class;
   SnItemClass *item_class;
 
   object_class = G_OBJECT_CLASS (v0_class);
+  widget_class = GTK_WIDGET_CLASS (v0_class);
   item_class = SN_ITEM_CLASS (v0_class);
 
   object_class->constructed = sn_item_v0_constructed;
@@ -760,11 +921,22 @@ sn_item_v0_class_init (SnItemV0Class *v0_class)
 
   item_class->get_id = sn_item_v0_get_id;
   item_class->get_category = sn_item_v0_get_category;
+  item_class->get_menu = sn_item_v0_get_menu;
+
+  item_class->context_menu = sn_item_v0_context_menu;
+  item_class->activate = sn_item_v0_activate;
+  item_class->secondary_activate = sn_item_v0_secondary_activate;
+  item_class->scroll = sn_item_v0_scroll;
+
+  gtk_widget_class_set_css_name (widget_class, "sn-item");
 }
 
 static void
 sn_item_v0_init (SnItemV0 *v0)
 {
+  v0->image = gtk_image_new ();
+  gtk_container_add (GTK_CONTAINER (v0), v0->image);
+  gtk_widget_show (v0->image);
 }
 
 SnItem *
diff --git a/applets/status-notifier/sn-item.c b/applets/status-notifier/sn-item.c
index 41b0a84..9c059d4 100644
--- a/applets/status-notifier/sn-item.c
+++ b/applets/status-notifier/sn-item.c
@@ -17,12 +17,17 @@
 
 #include "config.h"
 
+#include "sn-dbus-menu.h"
 #include "sn-item.h"
 
 typedef struct
 {
-  gchar *bus_name;
-  gchar *object_path;
+  gchar          *bus_name;
+  gchar          *object_path;
+
+  GtkOrientation  orientation;
+
+  GtkMenu        *menu;
 } SnItemPrivate;
 
 enum
@@ -32,6 +37,8 @@ enum
   PROP_BUS_NAME,
   PROP_OBJECT_PATH,
 
+  PROP_ORIENTATION,
+
   LAST_PROP
 };
 
@@ -49,6 +56,20 @@ static guint signals[LAST_SIGNAL] = { 0 };
 G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (SnItem, sn_item, GTK_TYPE_BUTTON)
 
 static void
+sn_item_dispose (GObject *object)
+{
+  SnItem *item;
+  SnItemPrivate *priv;
+
+  item = SN_ITEM (object);
+  priv = sn_item_get_instance_private (item);
+
+  g_clear_object (&priv->menu);
+
+  G_OBJECT_CLASS (sn_item_parent_class)->dispose (object);
+}
+
+static void
 sn_item_finalize (GObject *object)
 {
   SnItem *item;
@@ -85,6 +106,10 @@ sn_item_get_property (GObject    *object,
         g_value_set_string (value, priv->object_path);
         break;
 
+      case PROP_ORIENTATION:
+        g_value_set_enum (value, priv->orientation);
+        break;
+
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
         break;
@@ -113,12 +138,158 @@ sn_item_set_property (GObject      *object,
         priv->object_path = g_value_dup_string (value);
         break;
 
+      case PROP_ORIENTATION:
+        priv->orientation = g_value_get_enum (value);
+        break;
+
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
         break;
     }
 }
 
+static gboolean
+sn_item_button_press_event (GtkWidget      *widget,
+                            GdkEventButton *event)
+{
+  SnItem *item;
+  SnItemPrivate *priv;
+
+  if (event->button < 1 || event->button > 3)
+    return GTK_WIDGET_CLASS (sn_item_parent_class)->button_press_event (widget, event);
+
+  item = SN_ITEM (widget);
+  priv = sn_item_get_instance_private (item);
+
+  if (priv->menu != NULL && event->button == 1)
+    {
+      gtk_menu_popup_at_widget (priv->menu, widget,
+                                GDK_GRAVITY_SOUTH_WEST,
+                                GDK_GRAVITY_NORTH_WEST,
+                                (GdkEvent *) event);
+    }
+  else
+    {
+      GdkWindow *window;
+      GtkWidget *toplevel;
+      gint x;
+      gint y;
+      gint width;
+      gint height;
+
+      window = gtk_widget_get_window (widget);
+      toplevel = gtk_widget_get_toplevel (widget);
+
+      gdk_window_get_geometry (window, &x, &y, &width, &height);
+      gtk_widget_translate_coordinates (widget, toplevel, x, y, &x, &y);
+
+      if (priv->orientation == GTK_ORIENTATION_HORIZONTAL)
+        y += height;
+      else
+        x += width;
+
+      if (event->button == 1)
+        SN_ITEM_GET_CLASS (item)->activate (item, x, y);
+      else if (event->button == 2)
+        SN_ITEM_GET_CLASS (item)->secondary_activate (item, x, y);
+      else if (event->button == 3)
+        SN_ITEM_GET_CLASS (item)->context_menu (item, x, y);
+      else
+        g_assert_not_reached ();
+    }
+
+  return GTK_WIDGET_CLASS (sn_item_parent_class)->button_press_event (widget, event);
+}
+
+static gboolean
+sn_item_scroll_event (GtkWidget      *widget,
+                      GdkEventScroll *event)
+{
+  SnItem *item;
+  GdkScrollDirection direction;
+  SnItemOrientation orientation;
+  gdouble dx;
+  gdouble dy;
+  gint delta;
+
+  item = SN_ITEM (widget);
+
+  if (!gdk_event_get_scroll_direction ((GdkEvent *) event, &direction))
+    {
+      g_assert_not_reached ();
+    }
+  else
+    {
+      switch (direction)
+        {
+          case GDK_SCROLL_UP:
+          case GDK_SCROLL_DOWN:
+            orientation = SN_ITEM_ORIENTATION_VERTICAL;
+            break;
+
+          case GDK_SCROLL_LEFT:
+          case GDK_SCROLL_RIGHT:
+            orientation = SN_ITEM_ORIENTATION_HORIZONTAL;
+            break;
+
+          case GDK_SCROLL_SMOOTH:
+          default:
+            g_assert_not_reached ();
+            break;
+        }
+    }
+
+  if (!gdk_event_get_scroll_deltas ((GdkEvent *) event, &dx, &dy))
+    {
+      switch (direction)
+        {
+          case GDK_SCROLL_UP:
+          case GDK_SCROLL_LEFT:
+            delta = 1;
+            break;
+
+          case GDK_SCROLL_DOWN:
+          case GDK_SCROLL_RIGHT:
+            delta = -1;
+            break;
+
+          case GDK_SCROLL_SMOOTH:
+          default:
+            g_assert_not_reached ();
+            break;
+        }
+    }
+  else
+    {
+      if (dy != 0)
+        delta = (gint) dy;
+      else
+        delta = (gint) dx;
+    }
+
+  SN_ITEM_GET_CLASS (item)->scroll (item, delta, orientation);
+
+  return GDK_EVENT_STOP;
+}
+
+static void
+sn_item_ready (SnItem *item)
+{
+  const gchar *menu;
+  SnItemPrivate *priv;
+
+  menu = SN_ITEM_GET_CLASS (item)->get_menu (item);
+  if (menu == NULL)
+    return;
+
+  if (menu == NULL || *menu == '\0' || g_strcmp0 (menu, "/") == 0)
+    return;
+
+  priv = sn_item_get_instance_private (item);
+  priv->menu = sn_dbus_menu_new (priv->bus_name, menu);
+  g_object_ref_sink (priv->menu);
+}
+
 static void
 install_properties (GObjectClass *object_class)
 {
@@ -132,6 +303,11 @@ install_properties (GObjectClass *object_class)
                          G_PARAM_CONSTRUCT_ONLY | G_PARAM_READWRITE |
                          G_PARAM_STATIC_STRINGS);
 
+  properties[PROP_ORIENTATION] =
+    g_param_spec_enum ("orientation", "orientation", "orientation",
+                       GTK_TYPE_ORIENTATION, GTK_ORIENTATION_HORIZONTAL,
+                       G_PARAM_WRITABLE | G_PARAM_STATIC_STRINGS);
+
   g_object_class_install_properties (object_class, LAST_PROP, properties);
 }
 
@@ -139,8 +315,8 @@ static void
 install_signals (SnItemClass *item_class)
 {
   signals[SIGNAL_READY] =
-    g_signal_new ("ready", G_TYPE_FROM_CLASS (item_class),
-                  G_SIGNAL_RUN_LAST, 0, NULL, NULL, NULL,
+    g_signal_new ("ready", G_TYPE_FROM_CLASS (item_class), G_SIGNAL_RUN_LAST,
+                  G_STRUCT_OFFSET (SnItemClass, ready), NULL, NULL, NULL,
                   G_TYPE_NONE, 0);
 }
 
@@ -148,13 +324,21 @@ static void
 sn_item_class_init (SnItemClass *item_class)
 {
   GObjectClass *object_class;
+  GtkWidgetClass *widget_class;
 
   object_class = G_OBJECT_CLASS (item_class);
+  widget_class = GTK_WIDGET_CLASS (item_class);
 
+  object_class->dispose = sn_item_dispose;
   object_class->finalize = sn_item_finalize;
   object_class->get_property = sn_item_get_property;
   object_class->set_property = sn_item_set_property;
 
+  widget_class->button_press_event = sn_item_button_press_event;
+  widget_class->scroll_event = sn_item_scroll_event;
+
+  item_class->ready = sn_item_ready;
+
   install_properties (object_class);
   install_signals (item_class);
 }
@@ -162,6 +346,7 @@ sn_item_class_init (SnItemClass *item_class)
 static void
 sn_item_init (SnItem *item)
 {
+  gtk_widget_add_events (GTK_WIDGET (item), GDK_SCROLL_MASK);
 }
 
 const gchar *
diff --git a/applets/status-notifier/sn-item.h b/applets/status-notifier/sn-item.h
index b40f8e1..86e4c58 100644
--- a/applets/status-notifier/sn-item.h
+++ b/applets/status-notifier/sn-item.h
@@ -33,12 +33,39 @@ typedef enum
   SN_ITEM_CATEGORY_HARDWARE
 } SnItemCategory;
 
+typedef enum
+{
+  SN_ITEM_ORIENTATION_HORIZONTAL,
+  SN_ITEM_ORIENTATION_VERTICAL
+} SnItemOrientation;
+
 struct _SnItemClass
 {
   GtkButtonClass parent_class;
 
-  const gchar * (* get_id)       (SnItem *item);
-  const gchar * (* get_category) (SnItem *item);
+  void          (* ready)              (SnItem            *item);
+
+  const gchar * (* get_id)             (SnItem            *item);
+
+  const gchar * (* get_category)       (SnItem            *item);
+
+  const gchar * (* get_menu)           (SnItem            *item);
+
+  void          (* context_menu)       (SnItem            *item,
+                                        gint               x,
+                                        gint               y);
+
+  void          (* activate)           (SnItem            *item,
+                                        gint               x,
+                                        gint               y);
+
+  void          (* secondary_activate) (SnItem            *item,
+                                        gint               x,
+                                        gint               y);
+
+  void          (* scroll)             (SnItem            *item,
+                                        gint               delta,
+                                        SnItemOrientation  orientation);
 };
 
 const gchar    *sn_item_get_id          (SnItem *item);


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