[gnome-panel] status-notifier: load icon and show dbus menu
- From: Alberts Muktupāvels <muktupavels src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-panel] status-notifier: load icon and show dbus menu
- Date: Fri, 4 Nov 2016 20:13:21 +0000 (UTC)
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]