Skip to content

Commit

Permalink
xapp-status-icon: Track and notify changes in types of support for th…
Browse files Browse the repository at this point in the history
…e icon -

notify when a status icon is picked up by a native applet, a traditional system
tray, or is not being picked up by anything.

FIXME: Cinnamon currently doesn't notify when the tray applet is removed because
the underlying plug/socket are still retained in cinnamon's tray subsystem.  We
should maybe eventually propagate the applet no longer displaying icons down to
cinnamon-tray-manager and na-tray-manager to remove the icon entirely (this is
done correctly in mate-panel and xfce4).
  • Loading branch information
mtwebster committed Nov 20, 2019
1 parent 4c20196 commit b875ca3
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 1 deletion.
1 change: 1 addition & 0 deletions libxapp/xapp-enums.c.template
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
#include "config.h"
#include "xapp-enums.h"
#include "xapp-icon-chooser-dialog.h"
#include "xapp-status-icon.h"

#define C_ENUM(v) ((gint) v)
#define C_FLAGS(v) ((guint) v)
Expand Down
81 changes: 80 additions & 1 deletion libxapp/xapp-status-icon.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

#include "xapp-status-icon.h"
#include "xapp-statusicon-interface.h"
#include "xapp-enums.h"

#define FDO_DBUS_NAME "org.freedesktop.DBus"
#define FDO_DBUS_PATH "/org/freedesktop/DBus"
Expand All @@ -33,6 +34,7 @@ enum
BUTTON_PRESS,
BUTTON_RELEASE,
ACTIVATE,
STATE_CHANGED,
LAST_SIGNAL
};

Expand Down Expand Up @@ -69,6 +71,8 @@ typedef struct
GtkWidget *primary_menu;
GtkWidget *secondary_menu;

XAppStatusIconState state;

gchar *name;
gchar *icon_name;
gchar *tooltip_text;
Expand All @@ -94,6 +98,8 @@ static void refresh_icon (XAppStatusIcon *self);
static void use_gtk_status_icon (XAppStatusIcon *self);
static void tear_down_dbus (XAppStatusIcon *self);

#define GET_STATE_STR(i) (g_enum_to_string(XAPP_TYPE_STATUS_ICON_STATE, i->priv->state))

static void
cancellable_reset (XAppStatusIcon *self)
{
Expand Down Expand Up @@ -634,9 +640,12 @@ on_name_acquired (GDBusConnection *connection,
{
XAppStatusIcon *self = XAPP_STATUS_ICON (user_data);

g_debug ("XAppStatusIcon: name acquired on dbus, syncing icon properties");
self->priv->state = XAPP_STATUS_ICON_STATE_NATIVE;

sync_skeleton (self);

g_debug ("XAppStatusIcon: name acquired on dbus, syncing icon properties. State is now: %s", GET_STATE_STR (self));
g_signal_emit (self, signals[STATE_CHANGED], 0, self->priv->state);
}

typedef struct
Expand Down Expand Up @@ -729,6 +738,29 @@ update_fallback_icon (XAppStatusIcon *self,
}
}

static void
on_gtk_status_icon_embedded_changed (GtkStatusIcon *icon,
GParamSpec *pspec,
gpointer user_data)
{
g_return_if_fail (GTK_IS_STATUS_ICON (icon));

XAppStatusIcon *self = XAPP_STATUS_ICON (user_data);
XAppStatusIconPrivate *priv = self->priv;

if (gtk_status_icon_is_embedded (icon))
{
priv->state = XAPP_STATUS_ICON_STATE_FALLBACK;
}
else
{
priv->state = XAPP_STATUS_ICON_STATE_NO_SUPPORT;
}

g_debug ("XAppStatusIcon fallback icon embedded_changed. State is now %s", GET_STATE_STR (self));
g_signal_emit (self, signals[STATE_CHANGED], 0, priv->state);
}

static void
use_gtk_status_icon (XAppStatusIcon *self)
{
Expand All @@ -751,6 +783,10 @@ use_gtk_status_icon (XAppStatusIcon *self)
"button-release-event",
G_CALLBACK (on_gtk_status_icon_button_release),
self);
g_signal_connect (priv->gtk_status_icon,
"notify::embedded",
G_CALLBACK (on_gtk_status_icon_embedded_changed),
self);

update_fallback_icon (self, priv->icon_name ? priv->icon_name : "");
gtk_status_icon_set_tooltip_text (self->priv->gtk_status_icon, priv->tooltip_text);
Expand Down Expand Up @@ -979,6 +1015,7 @@ xapp_status_icon_init (XAppStatusIcon *self)
self->priv = xapp_status_icon_get_instance_private (self);

self->priv->name = g_strdup_printf("%s", g_get_application_name());
self->priv->state = XAPP_STATUS_ICON_STATE_NO_SUPPORT;

g_debug ("XAppStatusIcon: init: application name: '%s'", self->priv->name);

Expand Down Expand Up @@ -1176,6 +1213,24 @@ xapp_status_icon_class_init (XAppStatusIconClass *klass)
0,
NULL, NULL, NULL,
G_TYPE_NONE, 2, G_TYPE_UINT, G_TYPE_UINT);

/**
* XAppStatusIcon::state-changed:
* @icon: The #XAppStatusIcon
* @new_state: The new #XAppStatusIconState of the icon
*
* Gets emitted when the state of the icon changes. If you wish
* to react to changes in how the status icon is being handled
* (perhaps to alter the menu or other click behavior), you should
* connect to this - see #XAppStatusIconState for more details.
*/
signals [STATE_CHANGED] =
g_signal_new ("state-changed",
XAPP_TYPE_STATUS_ICON,
G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION,
0,
NULL, NULL, NULL,
G_TYPE_NONE, 1, XAPP_TYPE_STATUS_ICON_STATE);
}

/**
Expand Down Expand Up @@ -1424,6 +1479,30 @@ xapp_status_icon_new (void)
return g_object_new (XAPP_TYPE_STATUS_ICON, NULL);
}

/**
* xapp_status_icon_get_state:
* @icon: an #XAppStatusIcon
*
* Gets the current #XAppStatusIconState of icon. The state is determined by whether
* the icon is being displayed by an #XAppStatusMonitor client, a fallback tray icon,
* or not being displayed at all.
*
* See #XAppStatusIconState for more details.
*
* Returns: the icon's state.
*
* Since: 1.6
*/
XAppStatusIconState
xapp_status_icon_get_state (XAppStatusIcon *icon)
{
g_return_val_if_fail (XAPP_IS_STATUS_ICON (icon), XAPP_STATUS_ICON_STATE_NO_SUPPORT);

g_debug ("XAppStatusIcon get_state: %s", GET_STATE_STR (icon));

return icon->priv->state;
}

/**
* xapp_status_icon_any_monitors:
*
Expand Down
17 changes: 17 additions & 0 deletions libxapp/xapp-status-icon.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,22 @@ G_BEGIN_DECLS

G_DECLARE_FINAL_TYPE (XAppStatusIcon, xapp_status_icon, XAPP, STATUS_ICON, GObject)

/**
* XAppStatusIconState:
* @XAPP_STATUS_ICON_STATE_NATIVE: The #XAppStatusIcon is currently being handled
* by an #XAppStatusIconMonitor (usually in an applet).
* @XAPP_STATUS_ICON_STATE_FALLBACK: The #XAppStatusIcon is currently being handled
* by a legacy system tray implementation (using GtkStatusIcon).
* @XAPP_STATUS_ICON_STATE_NO_SUPPORT: The #XAppStatusIcon is not currently being handled by any
* kind of status icon implementation.
*/
typedef enum
{
XAPP_STATUS_ICON_STATE_NATIVE,
XAPP_STATUS_ICON_STATE_FALLBACK,
XAPP_STATUS_ICON_STATE_NO_SUPPORT
} XAppStatusIconState;

XAppStatusIcon *xapp_status_icon_new (void);
void xapp_status_icon_set_name (XAppStatusIcon *icon, const gchar *name);
void xapp_status_icon_set_icon_name (XAppStatusIcon *icon, const gchar *icon_name);
Expand All @@ -22,6 +38,7 @@ void xapp_status_icon_set_primary_menu (XAppStatusIcon *icon, GtkMe
GtkWidget *xapp_status_icon_get_primary_menu (XAppStatusIcon *icon);
void xapp_status_icon_set_secondary_menu (XAppStatusIcon *icon, GtkMenu *menu);
GtkWidget *xapp_status_icon_get_secondary_menu (XAppStatusIcon *icon);
XAppStatusIconState xapp_status_icon_get_state (XAppStatusIcon *icon);

/* static */
gboolean xapp_status_icon_any_monitors (void);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class App(GObject.Object):
def __init__(self):
super(App, self).__init__()
self.status_icon = XApp.StatusIcon()
self.status_icon.connect("state-changed", self.on_icon_state_changed)

self.status_icon.set_icon_name("folder-symbolic")
self.status_icon.set_tooltip_text("Testing primary activate and secondary menu")
Expand All @@ -35,6 +36,9 @@ class App(GObject.Object):

GLib.timeout_add_seconds(2, self.on_timeout_cb)

def on_icon_state_changed(self, icon, new_state):
print("Icon state changed - the state is now: %s" % new_state)

def on_timeout_cb(self):
self.counter += 1
self.status_icon.set_label("label %d" % self.counter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class App(GObject.Object):
def __init__(self):
super(App, self).__init__()
self.status_icon = XApp.StatusIcon()
self.status_icon.connect("state-changed", self.on_icon_state_changed)

self.status_icon.set_icon_name("folder-symbolic")
self.status_icon.set_tooltip_text("Testing primary and secondary menus")
Expand All @@ -42,6 +43,9 @@ class App(GObject.Object):

GLib.timeout_add_seconds(2, self.on_timeout_cb)

def on_icon_state_changed(self, icon, new_state):
print("Icon state changed - the state is now: %s" % new_state)

def on_timeout_cb(self):
self.counter += 1
self.status_icon.set_label("label %d" % self.counter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class App(GObject.Object):
def __init__(self):
super(App, self).__init__()
self.status_icon = XApp.StatusIcon()
self.status_icon.connect("state-changed", self.on_icon_state_changed)

self.status_icon.set_icon_name("folder-symbolic")
self.status_icon.set_tooltip_text("Testing primary activate and secondary menu")
Expand All @@ -28,6 +29,9 @@ class App(GObject.Object):

GLib.timeout_add_seconds(2, self.on_timeout_cb)

def on_icon_state_changed(self, icon, new_state):
print("Icon state changed - the state is now: %s" % new_state)

def on_timeout_cb(self):
self.counter += 1
self.status_icon.set_label("label %d" % self.counter)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ class App(GObject.Object):
def __init__(self):
super(App, self).__init__()
self.status_icon = XApp.StatusIcon()
self.status_icon.connect("state-changed", self.on_icon_state_changed)

self.status_icon.set_icon_name("folder-symbolic")
self.status_icon.set_tooltip_text("Testing raw button press and release events")
Expand All @@ -35,6 +36,9 @@ class App(GObject.Object):

GLib.timeout_add_seconds(2, self.on_timeout_cb)

def on_icon_state_changed(self, icon, new_state):
print("Icon state changed - the state is now: %s" % new_state)

def on_timeout_cb(self):
self.counter += 1
self.status_icon.set_label("label %d" % self.counter)
Expand Down

0 comments on commit b875ca3

Please sign in to comment.