From 3dc48c02f8b5ea06a3a267d420db8bd304936799 Mon Sep 17 00:00:00 2001
From: Ted Gould
Date: Wed, 28 Apr 2010 15:08:11 -0500
Subject: Adding introspection and VAPI checks
---
configure.ac | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/configure.ac b/configure.ac
index c34bed2..dfffa00 100644
--- a/configure.ac
+++ b/configure.ac
@@ -52,6 +52,18 @@ PKG_CHECK_MODULES(INDICATOR, gtk+-2.0 >= $GTK_REQUIRED_VERSION
AC_SUBST(INDICATOR_CFLAGS)
AC_SUBST(INDICATOR_LIBS)
+###########################
+# GObject Introspection
+###########################
+
+GOBJECT_INTROSPECTION_CHECK([0.6.7])
+
+###########################
+# Vala API Generation
+###########################
+
+AC_PATH_PROG([VALA_API_GEN], [vapigen])
+
###########################
# Check for Mono support
###########################
--
cgit v1.2.3
From 27490e36d0134d22c32c0385ab0fcf8359d23b58 Mon Sep 17 00:00:00 2001
From: Ted Gould
Date: Wed, 28 Apr 2010 15:11:30 -0500
Subject: Adding the introspection.m4 for our new rules
---
.bzrignore | 1 +
m4/introspection.m4 | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 95 insertions(+)
create mode 100644 m4/introspection.m4
diff --git a/.bzrignore b/.bzrignore
index 0f2b3d0..07f160a 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -100,3 +100,4 @@ indicator-application-[0-9].[0-9].[0-9].tar.gz
indicator-application-[0-9].[0-9].[0-9].tar.gz.asc
indicator-application-[0-9].[0-9].[0-9][0-9].tar.gz
indicator-application-[0-9].[0-9].[0-9][0-9].tar.gz.asc
+m4/gtk-doc.m4
diff --git a/m4/introspection.m4 b/m4/introspection.m4
new file mode 100644
index 0000000..589721c
--- /dev/null
+++ b/m4/introspection.m4
@@ -0,0 +1,94 @@
+dnl -*- mode: autoconf -*-
+dnl Copyright 2009 Johan Dahlin
+dnl
+dnl This file is free software; the author(s) gives unlimited
+dnl permission to copy and/or distribute it, with or without
+dnl modifications, as long as this notice is preserved.
+dnl
+
+# serial 1
+
+m4_define([_GOBJECT_INTROSPECTION_CHECK_INTERNAL],
+[
+ AC_BEFORE([AC_PROG_LIBTOOL],[$0])dnl setup libtool first
+ AC_BEFORE([AM_PROG_LIBTOOL],[$0])dnl setup libtool first
+ AC_BEFORE([LT_INIT],[$0])dnl setup libtool first
+
+ dnl enable/disable introspection
+ m4_if([$2], [require],
+ [dnl
+ enable_introspection=yes
+ ],[dnl
+ AC_ARG_ENABLE(introspection,
+ AS_HELP_STRING([--enable-introspection[=@<:@no/auto/yes@:>@]],
+ [Enable introspection for this build]),,
+ [enable_introspection=auto])
+ ])dnl
+
+ AC_MSG_CHECKING([for gobject-introspection])
+
+ dnl presence/version checking
+ AS_CASE([$enable_introspection],
+ [no], [dnl
+ found_introspection="no (disabled, use --enable-introspection to enable)"
+ ],dnl
+ [yes],[dnl
+ PKG_CHECK_EXISTS([gobject-introspection-1.0],,
+ AC_MSG_ERROR([gobject-introspection-1.0 is not installed]))
+ PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1],
+ found_introspection=yes,
+ AC_MSG_ERROR([You need to have gobject-introspection >= $1 installed to build AC_PACKAGE_NAME]))
+ ],dnl
+ [auto],[dnl
+ PKG_CHECK_EXISTS([gobject-introspection-1.0 >= $1], found_introspection=yes, found_introspection=no)
+ ],dnl
+ [dnl
+ AC_MSG_ERROR([invalid argument passed to --enable-introspection, should be one of @<:@no/auto/yes@:>@])
+ ])dnl
+
+ AC_MSG_RESULT([$found_introspection])
+
+ INTROSPECTION_SCANNER=
+ INTROSPECTION_COMPILER=
+ INTROSPECTION_GENERATE=
+ INTROSPECTION_GIRDIR=
+ INTROSPECTION_TYPELIBDIR=
+ if test "x$found_introspection" = "xyes"; then
+ INTROSPECTION_SCANNER=`$PKG_CONFIG --variable=g_ir_scanner gobject-introspection-1.0`
+ INTROSPECTION_COMPILER=`$PKG_CONFIG --variable=g_ir_compiler gobject-introspection-1.0`
+ INTROSPECTION_GENERATE=`$PKG_CONFIG --variable=g_ir_generate gobject-introspection-1.0`
+ INTROSPECTION_GIRDIR=`$PKG_CONFIG --variable=girdir gobject-introspection-1.0`
+ INTROSPECTION_TYPELIBDIR="$($PKG_CONFIG --variable=typelibdir gobject-introspection-1.0)"
+ INTROSPECTION_CFLAGS=`$PKG_CONFIG --cflags gobject-introspection-1.0`
+ INTROSPECTION_LIBS=`$PKG_CONFIG --libs gobject-introspection-1.0`
+ INTROSPECTION_MAKEFILE=`$PKG_CONFIG --variable=datadir gobject-introspection-1.0`/gobject-introspection-1.0/Makefile.introspection
+ fi
+ AC_SUBST(INTROSPECTION_SCANNER)
+ AC_SUBST(INTROSPECTION_COMPILER)
+ AC_SUBST(INTROSPECTION_GENERATE)
+ AC_SUBST(INTROSPECTION_GIRDIR)
+ AC_SUBST(INTROSPECTION_TYPELIBDIR)
+ AC_SUBST(INTROSPECTION_CFLAGS)
+ AC_SUBST(INTROSPECTION_LIBS)
+ AC_SUBST(INTROSPECTION_MAKEFILE)
+
+ AM_CONDITIONAL(HAVE_INTROSPECTION, test "x$found_introspection" = "xyes")
+])
+
+
+dnl Usage:
+dnl GOBJECT_INTROSPECTION_CHECK([minimum-g-i-version])
+
+AC_DEFUN([GOBJECT_INTROSPECTION_CHECK],
+[
+ _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1])
+])
+
+dnl Usage:
+dnl GOBJECT_INTROSPECTION_REQUIRE([minimum-g-i-version])
+
+
+AC_DEFUN([GOBJECT_INTROSPECTION_REQUIRE],
+[
+ _GOBJECT_INTROSPECTION_CHECK_INTERNAL([$1], [require])
+])
--
cgit v1.2.3
From 0bd103ade67391a34eac443acfd46ca126ea33db Mon Sep 17 00:00:00 2001
From: Ted Gould
Date: Thu, 29 Apr 2010 10:49:09 -0500
Subject: Add introspection stuff here
---
Makefile.am | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/Makefile.am b/Makefile.am
index 4d38ef8..ba772b0 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -6,6 +6,7 @@ SUBDIRS = data \
docs
EXTRA_DIST = \
+ m4/introspection.m4 \
gtk-doc.make \
omf.make \
xmldocs.make \
@@ -14,7 +15,7 @@ EXTRA_DIST = \
COPYING.LGPL.3 \
ChangeLog
-DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-localinstall
+DISTCHECK_CONFIGURE_FLAGS = --enable-gtk-doc --enable-localinstall --enable-introspection
dist-hook:
@if test -d "$(top_srcdir)/.bzr"; \
--
cgit v1.2.3
From ba1fd3904b920d017b532a0e1ff2ba4941cdb47d Mon Sep 17 00:00:00 2001
From: Ted Gould
Date: Thu, 29 Apr 2010 11:31:36 -0500
Subject: Removing the libappindicator directory to make things simpler
---
bindings/python/appindicator.override | 4 +-
configure.ac | 2 +-
docs/reference/Makefile.am | 8 +-
example/simple-client.c | 2 +-
src/Makefile.am | 18 +-
src/app-indicator-enum-types.gen.c.in | 61 +
src/app-indicator-enum-types.h.in | 61 +
src/app-indicator.c | 1610 ++++++++++++++++++++
src/app-indicator.h | 257 ++++
src/appindicator-0.1.pc.in | 14 +
.../app-indicator-enum-types.gen.c.in | 61 -
src/libappindicator/app-indicator-enum-types.h.in | 61 -
src/libappindicator/app-indicator.c | 1610 --------------------
src/libappindicator/app-indicator.h | 257 ----
src/libappindicator/appindicator-0.1.pc.in | 14 -
tests/test-libappindicator-dbus-client.c | 2 +-
tests/test-libappindicator-dbus-server.c | 2 +-
tests/test-libappindicator-fallback-item.c | 2 +-
tests/test-libappindicator-status-server.c | 2 +-
tests/test-libappindicator.c | 2 +-
tests/test-simple-app.c | 2 +-
21 files changed, 2026 insertions(+), 2026 deletions(-)
create mode 100644 src/app-indicator-enum-types.gen.c.in
create mode 100644 src/app-indicator-enum-types.h.in
create mode 100644 src/app-indicator.c
create mode 100644 src/app-indicator.h
create mode 100644 src/appindicator-0.1.pc.in
delete mode 100644 src/libappindicator/app-indicator-enum-types.gen.c.in
delete mode 100644 src/libappindicator/app-indicator-enum-types.h.in
delete mode 100644 src/libappindicator/app-indicator.c
delete mode 100644 src/libappindicator/app-indicator.h
delete mode 100644 src/libappindicator/appindicator-0.1.pc.in
diff --git a/bindings/python/appindicator.override b/bindings/python/appindicator.override
index a01a9a6..b252994 100644
--- a/bindings/python/appindicator.override
+++ b/bindings/python/appindicator.override
@@ -28,8 +28,8 @@ License version 3 and version 2.1 along with this program. If not, see
%%
headers
#include
-#include "../src/libappindicator/app-indicator.h"
-#include "../src/libappindicator/app-indicator-enum-types.h"
+#include "../src/app-indicator.h"
+#include "../src/app-indicator-enum-types.h"
#include
#include "pygobject.h"
#include "pyglib.h"
diff --git a/configure.ac b/configure.ac
index dfffa00..eab3411 100644
--- a/configure.ac
+++ b/configure.ac
@@ -190,7 +190,7 @@ AC_MSG_RESULT($PYGTK_CODEGEN)
AC_OUTPUT([
Makefile
src/Makefile
-src/libappindicator/appindicator-0.1.pc
+src/appindicator-0.1.pc
bindings/Makefile
bindings/mono/Makefile
bindings/mono/appindicator-sharp.dll.config
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index 1292f4d..3aedd60 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -22,7 +22,7 @@ DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
# gtk-doc will search all .c & .h files beneath here for inline comments
# documenting the functions and macros.
# e.g. DOC_SOURCE_DIR=../../../gtk
-DOC_SOURCE_DIR=../../src/libappindicator
+DOC_SOURCE_DIR=../../src
# Extra options to pass to gtkdoc-scangobj. Not normally needed.
SCANGOBJ_OPTIONS=--nogtkinit --type-init-func="g_type_init()"
@@ -50,8 +50,8 @@ FIXXREF_OPTIONS=
# Used for dependencies. The docs will be rebuilt if any of these change.
# e.g. HFILE_GLOB=$(top_srcdir)/gtk/*.h
# e.g. CFILE_GLOB=$(top_srcdir)/gtk/*.c
-HFILE_GLOB=$(top_srcdir)/src/libappindicator/*.h
-CFILE_GLOB=$(top_srcdir)/src/libappindicator/*.c
+HFILE_GLOB=$(top_srcdir)/src/*.h
+CFILE_GLOB=$(top_srcdir)/src/*.c
# Header files to ignore when scanning.
# e.g. IGNORE_HFILES=gtkdebug.h gtkintl.h
@@ -75,7 +75,7 @@ expand_content_files=
# signals and properties.
# e.g. GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_builddir) $(GTK_DEBUG_FLAGS)
# e.g. GTKDOC_LIBS=$(top_builddir)/gtk/$(gtktargetlib)
-GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_srcdir)/src -I$(top_srcdir)/src/libappindicator $(INDICATOR_CFLAGS)
+GTKDOC_CFLAGS=-I$(top_srcdir) -I$(top_srcdir)/src -I$(top_srcdir)/src $(INDICATOR_CFLAGS)
GTKDOC_LIBS=$(top_builddir)/src/libappindicator.la $(top_builddir)/src/libapplication.la
# This includes the standard gtk-doc make rules, copied by gtkdocize.
diff --git a/example/simple-client.c b/example/simple-client.c
index a698b48..fbcaaaa 100644
--- a/example/simple-client.c
+++ b/example/simple-client.c
@@ -20,7 +20,7 @@ You should have received a copy of the GNU General Public License along
with this program. If not, see .
*/
-#include "libappindicator/app-indicator.h"
+#include "app-indicator.h"
#include "libdbusmenu-glib/server.h"
#include "libdbusmenu-glib/menuitem.h"
diff --git a/src/Makefile.am b/src/Makefile.am
index 9f2771e..d8599d8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,7 +1,7 @@
CLEANFILES =
DISTCLEANFILES =
BUILT_SOURCES =
-EXTRA_DIST = libappindicator/appindicator-0.1.pc.in
+EXTRA_DIST = appindicator-0.1.pc.in
include $(top_srcdir)/Makefile.am.enum
include $(top_srcdir)/Makefile.am.marshal
@@ -61,14 +61,14 @@ glib_marshal_prefix = _application_service_marshal
# Library
##################################
-pkgconfig_DATA = libappindicator/appindicator-0.1.pc
+pkgconfig_DATA = appindicator-0.1.pc
pkgconfigdir = $(libdir)/pkgconfig
-glib_enum_h = libappindicator/app-indicator-enum-types.h
-glib_enum_c = libappindicator/app-indicator-enum-types.gen.c
+glib_enum_h = app-indicator-enum-types.h
+glib_enum_c = app-indicator-enum-types.gen.c
glib_enum_headers = $(libappindicator_headers)
-libappindicator/app-indicator-enum-types.c: libappindicator/app-indicator-enum-types.gen.c
+app-indicator-enum-types.c: app-indicator-enum-types.gen.c
sed -e "s|\"passive\"|\"Passive\"|" \
-e "s|\"active\"|\"Active\"|" \
-e "s|\"attention\"|\"NeedsAttention\"|" \
@@ -78,7 +78,7 @@ libappindicator/app-indicator-enum-types.c: libappindicator/app-indicator-enum-t
-e "s|\"hardware\"|\"Hardware\"|" \
-e "s|\"other\"|\"Other\"|" \
$< > $@
-DISTCLEANFILES += libappindicator/app-indicator-enum-types.c
+DISTCLEANFILES += app-indicator-enum-types.c
lib_LTLIBRARIES = \
libappindicator.la
@@ -86,7 +86,7 @@ lib_LTLIBRARIES = \
libappindicatorincludedir=$(includedir)/libappindicator-0.1/libappindicator
libappindicator_headers = \
- $(srcdir)/libappindicator/app-indicator.h
+ $(srcdir)/app-indicator.h
libappindicatorinclude_HEADERS = \
$(libappindicator_headers) \
@@ -94,10 +94,10 @@ libappindicatorinclude_HEADERS = \
libappindicator_la_SOURCES = \
$(libappindicator_headers) \
- libappindicator/app-indicator-enum-types.c \
+ app-indicator-enum-types.c \
notification-watcher-client.h \
notification-item-server.h \
- libappindicator/app-indicator.c
+ app-indicator.c
libappindicator_la_LDFLAGS = \
-version-info 0:0:0 \
diff --git a/src/app-indicator-enum-types.gen.c.in b/src/app-indicator-enum-types.gen.c.in
new file mode 100644
index 0000000..6a647b8
--- /dev/null
+++ b/src/app-indicator-enum-types.gen.c.in
@@ -0,0 +1,61 @@
+/*** BEGIN file-header ***/
+/*
+An object to represent the application as an application indicator
+in the system panel.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+ Ted Gould
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+ Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, as published by
+ the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+
+*/
+
+#include "app-indicator-enum-types.h"
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+#include "@filename@"
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType
+@enum_name@_get_type (void)
+{
+ static GType etype = 0;
+ if (G_UNLIKELY(etype == 0)) {
+ static const G@Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+ { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+ { 0, NULL, NULL}
+ };
+
+ etype = g_@type@_register_static (g_intern_static_string("@EnumName@"), values);
+ }
+
+ return etype;
+}
+
+/*** END value-tail ***/
diff --git a/src/app-indicator-enum-types.h.in b/src/app-indicator-enum-types.h.in
new file mode 100644
index 0000000..da3bf98
--- /dev/null
+++ b/src/app-indicator-enum-types.h.in
@@ -0,0 +1,61 @@
+/*** BEGIN file-header ***/
+/*
+An object to represent the application as an application indicator
+in the system panel.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+ Ted Gould
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+ Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, as published by
+ the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+
+*/
+
+#ifndef __APP_INDICATOR_ENUM_TYPES_H__
+#define __APP_INDICATOR_ENUM_TYPES_H__
+
+#include
+
+G_BEGIN_DECLS
+
+/*** END file-header ***/
+
+/*** BEGIN file-tail ***/
+
+G_END_DECLS
+
+#endif /* __APP_INDICATOR_ENUM_TYPES_H__ */
+/*** END file-tail ***/
+
+/*** BEGIN file-production ***/
+/* Enumerations from file: "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+/**
+ @enum_name@_get_type:
+
+ Builds a glib type for the @EnumName@ enumeration.
+
+ Return value: A registered type for the enum
+*/
+GType @enum_name@_get_type (void) G_GNUC_CONST;
+#define APP_INDICATOR_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
+
+/*** END value-header ***/
diff --git a/src/app-indicator.c b/src/app-indicator.c
new file mode 100644
index 0000000..6ac48c7
--- /dev/null
+++ b/src/app-indicator.c
@@ -0,0 +1,1610 @@
+/*
+An object to represent the application as an application indicator
+in the system panel.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+ Ted Gould
+ Cody Russell
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+ Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, as published by
+ the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+
+*/
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include
+#include
+#include
+
+#include "app-indicator.h"
+#include "app-indicator-enum-types.h"
+
+#include "notification-item-server.h"
+#include "notification-watcher-client.h"
+
+#include "dbus-shared.h"
+
+#define PANEL_ICON_SUFFIX "panel"
+
+/**
+ AppIndicatorPrivate:
+
+ All of the private data in an instance of a
+ application indicator.
+*/
+/* Private Fields
+ @id: The ID of the indicator. Maps to AppIndicator::id.
+ @category: Which category the indicator is. Maps to AppIndicator::category.
+ @status: The status of the indicator. Maps to AppIndicator::status.
+ @icon_name: The name of the icon to use. Maps to AppIndicator::icon-name.
+ @attention_icon_name: The name of the attention icon to use. Maps to AppIndicator::attention-icon-name.
+ @menu: The menu for this indicator. Maps to AppIndicator::menu
+ @watcher_proxy: The proxy connection to the watcher we're connected to. If we're not connected to one this will be #NULL.
+*/
+struct _AppIndicatorPrivate {
+ /*< Private >*/
+ /* Properties */
+ gchar *id;
+ gchar *clean_id;
+ AppIndicatorCategory category;
+ AppIndicatorStatus status;
+ gchar *icon_name;
+ gchar *attention_icon_name;
+ gchar * icon_path;
+ DbusmenuServer *menuservice;
+ GtkWidget *menu;
+
+ GtkStatusIcon * status_icon;
+ gint fallback_timer;
+
+ /* Fun stuff */
+ DBusGProxy *watcher_proxy;
+ DBusGConnection *connection;
+ DBusGProxy * dbus_proxy;
+};
+
+/* Signals Stuff */
+enum {
+ NEW_ICON,
+ NEW_ATTENTION_ICON,
+ NEW_STATUS,
+ CONNECTION_CHANGED,
+ LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+/* Enum for the properties so that they can be quickly
+ found and looked up. */
+enum {
+ PROP_0,
+ PROP_ID,
+ PROP_CATEGORY,
+ PROP_STATUS,
+ PROP_ICON_NAME,
+ PROP_ATTENTION_ICON_NAME,
+ PROP_ICON_THEME_PATH,
+ PROP_MENU,
+ PROP_CONNECTED
+};
+
+/* The strings so that they can be slowly looked up. */
+#define PROP_ID_S "id"
+#define PROP_CATEGORY_S "category"
+#define PROP_STATUS_S "status"
+#define PROP_ICON_NAME_S "icon-name"
+#define PROP_ATTENTION_ICON_NAME_S "attention-icon-name"
+#define PROP_ICON_THEME_PATH_S "icon-theme-path"
+#define PROP_MENU_S "menu"
+#define PROP_CONNECTED_S "connected"
+
+/* Private macro, shhhh! */
+#define APP_INDICATOR_GET_PRIVATE(o) \
+ (G_TYPE_INSTANCE_GET_PRIVATE ((o), APP_INDICATOR_TYPE, AppIndicatorPrivate))
+
+/* Default Path */
+#define DEFAULT_ITEM_PATH "/org/ayatana/NotificationItem"
+
+/* More constants */
+#define DEFAULT_FALLBACK_TIMER 100 /* in milliseconds */
+
+/* Boiler plate */
+static void app_indicator_class_init (AppIndicatorClass *klass);
+static void app_indicator_init (AppIndicator *self);
+static void app_indicator_dispose (GObject *object);
+static void app_indicator_finalize (GObject *object);
+/* Property functions */
+static void app_indicator_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
+static void app_indicator_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
+/* Other stuff */
+static void check_connect (AppIndicator * self);
+static void register_service_cb (DBusGProxy * proxy, GError * error, gpointer data);
+static void start_fallback_timer (AppIndicator * self, gboolean disable_timeout);
+static gboolean fallback_timer_expire (gpointer data);
+static GtkStatusIcon * fallback (AppIndicator * self);
+static void status_icon_status_wrapper (AppIndicator * self, const gchar * status, gpointer data);
+static void status_icon_changes (AppIndicator * self, gpointer data);
+static void status_icon_activate (GtkStatusIcon * icon, gpointer data);
+static void unfallback (AppIndicator * self, GtkStatusIcon * status_icon);
+static gchar * append_panel_icon_suffix (const gchar * icon_name);
+static void watcher_proxy_destroyed (GObject * object, gpointer data);
+static void client_menu_changed (GtkWidget *widget, GtkWidget *child, AppIndicator *indicator);
+static void submenu_changed (GtkWidget *widget, GtkWidget *child, gpointer data);
+
+static void theme_changed_cb (GtkIconTheme * theme, gpointer user_data);
+
+/* GObject type */
+G_DEFINE_TYPE (AppIndicator, app_indicator, G_TYPE_OBJECT);
+
+static void
+app_indicator_class_init (AppIndicatorClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ g_type_class_add_private (klass, sizeof (AppIndicatorPrivate));
+
+ /* Clean up */
+ object_class->dispose = app_indicator_dispose;
+ object_class->finalize = app_indicator_finalize;
+
+ /* Property funcs */
+ object_class->set_property = app_indicator_set_property;
+ object_class->get_property = app_indicator_get_property;
+
+ /* Our own funcs */
+ klass->fallback = fallback;
+ klass->unfallback = unfallback;
+
+ /* Properties */
+ g_object_class_install_property (object_class,
+ PROP_ID,
+ g_param_spec_string(PROP_ID_S,
+ "The ID for this indicator",
+ "An ID that should be unique, but used consistently by this program and it's indicator.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_CATEGORY,
+ g_param_spec_string (PROP_CATEGORY_S,
+ "Indicator Category",
+ "The type of indicator that this represents. Please don't use 'other'. Defaults to 'Application Status'.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_STATUS,
+ g_param_spec_string (PROP_STATUS_S,
+ "Indicator Status",
+ "Whether the indicator is shown or requests attention. Defaults to 'off'.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property(object_class,
+ PROP_ICON_NAME,
+ g_param_spec_string (PROP_ICON_NAME_S,
+ "An icon for the indicator",
+ "The default icon that is shown for the indicator.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class,
+ PROP_ATTENTION_ICON_NAME,
+ g_param_spec_string (PROP_ATTENTION_ICON_NAME_S,
+ "An icon to show when the indicator request attention.",
+ "If the indicator sets it's status to 'attention' then this icon is shown.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property(object_class,
+ PROP_ICON_THEME_PATH,
+ g_param_spec_string (PROP_ICON_THEME_PATH_S,
+ "An additional path for custom icons.",
+ "An additional place to look for icon names that may be installed by the application.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property(object_class,
+ PROP_MENU,
+ g_param_spec_boxed (PROP_MENU_S,
+ "The object path of the menu on DBus.",
+ "A method for getting the menu path as a string for DBus.",
+ DBUS_TYPE_G_OBJECT_PATH,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+ g_object_class_install_property (object_class,
+ PROP_CONNECTED,
+ g_param_spec_boolean (PROP_CONNECTED_S,
+ "Whether we're conneced to a watcher",
+ "Pretty simple, true if we have a reasonable expectation of being displayed through this object. You should hide your TrayIcon if so.",
+ FALSE,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+
+ /* Signals */
+
+ /**
+ AppIndicator::new-icon:
+ @arg0: The #AppIndicator object
+
+ Signaled when there is a new icon set for the
+ object.
+ */
+ signals[NEW_ICON] = g_signal_new (APP_INDICATOR_SIGNAL_NEW_ICON,
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (AppIndicatorClass, new_icon),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0, G_TYPE_NONE);
+
+ /**
+ AppIndicator::new-attention-icon:
+ @arg0: The #AppIndicator object
+
+ Signaled when there is a new attention icon set for the
+ object.
+ */
+ signals[NEW_ATTENTION_ICON] = g_signal_new (APP_INDICATOR_SIGNAL_NEW_ATTENTION_ICON,
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (AppIndicatorClass, new_attention_icon),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0, G_TYPE_NONE);
+
+ /**
+ AppIndicator::new-status:
+ @arg0: The #AppIndicator object
+ @arg1: The string value of the #AppIndicatorStatus enum.
+
+ Signaled when the status of the indicator changes.
+ */
+ signals[NEW_STATUS] = g_signal_new (APP_INDICATOR_SIGNAL_NEW_STATUS,
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (AppIndicatorClass, new_status),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE, 1,
+ G_TYPE_STRING);
+
+ /**
+ AppIndicator::connection-changed:
+ @arg0: The #AppIndicator object
+ @arg1: Whether we're connected or not
+
+ Signaled when we connect to a watcher, or when it drops
+ away.
+ */
+ signals[CONNECTION_CHANGED] = g_signal_new (APP_INDICATOR_SIGNAL_CONNECTION_CHANGED,
+ G_TYPE_FROM_CLASS(klass),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (AppIndicatorClass, connection_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE, 1, G_TYPE_BOOLEAN, G_TYPE_NONE);
+
+ /* Initialize the object as a DBus type */
+ dbus_g_object_type_install_info(APP_INDICATOR_TYPE,
+ &dbus_glib__notification_item_server_object_info);
+
+ return;
+}
+
+static void
+app_indicator_init (AppIndicator *self)
+{
+ AppIndicatorPrivate * priv = APP_INDICATOR_GET_PRIVATE(self);
+
+ priv->id = NULL;
+ priv->clean_id = NULL;
+ priv->category = APP_INDICATOR_CATEGORY_OTHER;
+ priv->status = APP_INDICATOR_STATUS_PASSIVE;
+ priv->icon_name = NULL;
+ priv->attention_icon_name = NULL;
+ priv->icon_path = NULL;
+ priv->menu = NULL;
+ priv->menuservice = NULL;
+
+ priv->watcher_proxy = NULL;
+ priv->connection = NULL;
+ priv->dbus_proxy = NULL;
+
+ priv->status_icon = NULL;
+ priv->fallback_timer = 0;
+
+ /* Put the object on DBus */
+ GError * error = NULL;
+ priv->connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
+ if (error != NULL) {
+ g_error("Unable to connect to the session bus when creating application indicator: %s", error->message);
+ g_error_free(error);
+ return;
+ }
+ dbus_g_connection_ref(priv->connection);
+
+ g_signal_connect(G_OBJECT(gtk_icon_theme_get_default()),
+ "changed", G_CALLBACK(theme_changed_cb), self);
+
+ self->priv = priv;
+
+ return;
+}
+
+/* Free all objects, make sure that all the dbus
+ signals are sent out before we shut this down. */
+static void
+app_indicator_dispose (GObject *object)
+{
+ AppIndicator *self = APP_INDICATOR (object);
+ AppIndicatorPrivate *priv = self->priv;
+
+ if (priv->status != APP_INDICATOR_STATUS_PASSIVE) {
+ app_indicator_set_status(self, APP_INDICATOR_STATUS_PASSIVE);
+ }
+
+ if (priv->status_icon != NULL) {
+ AppIndicatorClass * class = APP_INDICATOR_GET_CLASS(object);
+ if (class->unfallback != NULL) {
+ class->unfallback(self, priv->status_icon);
+ }
+ priv->status_icon = NULL;
+ }
+
+ if (priv->fallback_timer != 0) {
+ g_source_remove(priv->fallback_timer);
+ priv->fallback_timer = 0;
+ }
+
+ if (priv->menu != NULL) {
+ g_signal_handlers_disconnect_by_func (G_OBJECT (priv->menu),
+ client_menu_changed,
+ self);
+ g_object_unref(G_OBJECT(priv->menu));
+ priv->menu = NULL;
+ }
+
+ if (priv->menuservice != NULL) {
+ g_object_unref (priv->menuservice);
+ }
+
+ if (priv->dbus_proxy != NULL) {
+ g_object_unref(G_OBJECT(priv->dbus_proxy));
+ priv->dbus_proxy = NULL;
+ }
+
+ if (priv->watcher_proxy != NULL) {
+ dbus_g_connection_flush(priv->connection);
+ g_signal_handlers_disconnect_by_func(G_OBJECT(priv->watcher_proxy), watcher_proxy_destroyed, self);
+ g_object_unref(G_OBJECT(priv->watcher_proxy));
+ priv->watcher_proxy = NULL;
+
+ /* Emit the AppIndicator::connection-changed signal*/
+ g_signal_emit (self, signals[CONNECTION_CHANGED], 0, FALSE);
+ }
+
+ if (priv->connection != NULL) {
+ dbus_g_connection_unref(priv->connection);
+ priv->connection = NULL;
+ }
+
+ G_OBJECT_CLASS (app_indicator_parent_class)->dispose (object);
+ return;
+}
+
+/* Free all of the memory that we could be using in
+ the object. */
+static void
+app_indicator_finalize (GObject *object)
+{
+ AppIndicator * self = APP_INDICATOR(object);
+ AppIndicatorPrivate *priv = self->priv;
+
+ if (priv->status != APP_INDICATOR_STATUS_PASSIVE) {
+ g_warning("Finalizing Application Status with the status set to: %d", priv->status);
+ }
+
+ if (priv->id != NULL) {
+ g_free(priv->id);
+ priv->id = NULL;
+ }
+
+ if (priv->clean_id != NULL) {
+ g_free(priv->clean_id);
+ priv->clean_id = NULL;
+ }
+
+ if (priv->icon_name != NULL) {
+ g_free(priv->icon_name);
+ priv->icon_name = NULL;
+ }
+
+ if (priv->attention_icon_name != NULL) {
+ g_free(priv->attention_icon_name);
+ priv->attention_icon_name = NULL;
+ }
+
+ if (priv->icon_path != NULL) {
+ g_free(priv->icon_path);
+ priv->icon_path = NULL;
+ }
+
+ G_OBJECT_CLASS (app_indicator_parent_class)->finalize (object);
+ return;
+}
+
+#define WARN_BAD_TYPE(prop, value) g_warning("Can not work with property '%s' with value of type '%s'.", prop, G_VALUE_TYPE_NAME(value))
+
+/* Set some properties */
+static void
+app_indicator_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ AppIndicator *self = APP_INDICATOR (object);
+ AppIndicatorPrivate *priv = self->priv;
+ GEnumValue *enum_val;
+
+ switch (prop_id) {
+ case PROP_ID:
+ if (priv->id != NULL) {
+ g_warning ("Resetting ID value when I already had a value of: %s", priv->id);
+ break;
+ }
+
+ priv->id = g_strdup (g_value_get_string (value));
+
+ priv->clean_id = g_strdup(priv->id);
+ gchar * cleaner;
+ for (cleaner = priv->clean_id; *cleaner != '\0'; cleaner++) {
+ if (!g_ascii_isalnum(*cleaner)) {
+ *cleaner = '_';
+ }
+ }
+
+ check_connect (self);
+ break;
+
+ case PROP_CATEGORY:
+ enum_val = g_enum_get_value_by_nick ((GEnumClass *) g_type_class_ref (APP_INDICATOR_TYPE_INDICATOR_CATEGORY),
+ g_value_get_string (value));
+
+ if (priv->category != enum_val->value)
+ {
+ priv->category = enum_val->value;
+ }
+
+ break;
+
+ case PROP_STATUS:
+ enum_val = g_enum_get_value_by_nick ((GEnumClass *) g_type_class_ref (APP_INDICATOR_TYPE_INDICATOR_STATUS),
+ g_value_get_string (value));
+
+ app_indicator_set_status (APP_INDICATOR (object),
+ enum_val->value);
+ break;
+
+ case PROP_ICON_NAME:
+ app_indicator_set_icon (APP_INDICATOR (object),
+ g_value_get_string (value));
+ check_connect (self);
+ break;
+
+ case PROP_ATTENTION_ICON_NAME:
+ app_indicator_set_attention_icon (APP_INDICATOR (object),
+ g_value_get_string (value));
+ break;
+
+ case PROP_ICON_THEME_PATH:
+ if (priv->icon_path != NULL) {
+ g_free(priv->icon_path);
+ }
+ priv->icon_path = g_value_dup_string(value);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+
+ return;
+}
+
+/* Function to fill our value with the property it's requesting. */
+static void
+app_indicator_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ AppIndicator *self = APP_INDICATOR (object);
+ AppIndicatorPrivate *priv = self->priv;
+ GEnumValue *enum_value;
+
+ switch (prop_id) {
+ case PROP_ID:
+ g_value_set_string (value, priv->id);
+ break;
+
+ case PROP_CATEGORY:
+ enum_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (APP_INDICATOR_TYPE_INDICATOR_CATEGORY), priv->category);
+ g_value_set_string (value, enum_value->value_nick);
+ break;
+
+ case PROP_STATUS:
+ enum_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (APP_INDICATOR_TYPE_INDICATOR_STATUS), priv->status);
+ g_value_set_string (value, enum_value->value_nick);
+ break;
+
+ case PROP_ICON_NAME:
+ g_value_set_string (value, priv->icon_name);
+ break;
+
+ case PROP_ATTENTION_ICON_NAME:
+ g_value_set_string (value, priv->attention_icon_name);
+ break;
+
+ case PROP_ICON_THEME_PATH:
+ g_value_set_string (value, priv->icon_path);
+ break;
+
+ case PROP_MENU:
+ if (priv->menuservice != NULL) {
+ GValue strval = { 0 };
+ g_value_init(&strval, G_TYPE_STRING);
+ g_object_get_property (G_OBJECT (priv->menuservice), DBUSMENU_SERVER_PROP_DBUS_OBJECT, &strval);
+ g_value_set_boxed(value, g_value_get_string(&strval));
+ g_value_unset(&strval);
+ }
+ break;
+
+ case PROP_CONNECTED:
+ g_value_set_boolean (value, priv->watcher_proxy != NULL ? TRUE : FALSE);
+ break;
+
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+
+ return;
+}
+
+/* This function is used to see if we have enough information to
+ connect to things. If we do, and we're not connected, it
+ connects for us. */
+static void
+check_connect (AppIndicator *self)
+{
+ AppIndicatorPrivate *priv = self->priv;
+
+ /* We're alreadying connecting or trying to connect. */
+ if (priv->watcher_proxy != NULL) return;
+
+ /* Do we have enough information? */
+ if (priv->menu == NULL) return;
+ if (priv->icon_name == NULL) return;
+ if (priv->id == NULL) return;
+
+ gchar * path = g_strdup_printf(DEFAULT_ITEM_PATH "/%s", priv->clean_id);
+
+ dbus_g_connection_register_g_object(priv->connection,
+ path,
+ G_OBJECT(self));
+
+ GError * error = NULL;
+ priv->watcher_proxy = dbus_g_proxy_new_for_name_owner(priv->connection,
+ NOTIFICATION_WATCHER_DBUS_ADDR,
+ NOTIFICATION_WATCHER_DBUS_OBJ,
+ NOTIFICATION_WATCHER_DBUS_IFACE,
+ &error);
+ if (error != NULL) {
+ /* Unable to get proxy, but we're handling that now so
+ it's not a warning anymore. */
+ g_error_free(error);
+ dbus_g_connection_unregister_g_object(priv->connection,
+ G_OBJECT(self));
+ start_fallback_timer(self, FALSE);
+ g_free(path);
+ return;
+ }
+
+ g_signal_connect(G_OBJECT(priv->watcher_proxy), "destroy", G_CALLBACK(watcher_proxy_destroyed), self);
+ org_kde_StatusNotifierWatcher_register_status_notifier_item_async(priv->watcher_proxy, path, register_service_cb, self);
+ g_free(path);
+
+ /* Emit the AppIndicator::connection-changed signal*/
+ g_signal_emit (self, signals[CONNECTION_CHANGED], 0, TRUE);
+
+ return;
+}
+
+/* A function that gets called when the watcher dies. Like
+ dies dies. Not our friend anymore. */
+static void
+watcher_proxy_destroyed (GObject * object, gpointer data)
+{
+ AppIndicator * self = APP_INDICATOR(data);
+ g_return_if_fail(self != NULL);
+
+ dbus_g_connection_unregister_g_object(self->priv->connection,
+ G_OBJECT(self));
+ self->priv->watcher_proxy = NULL;
+
+ /* Emit the AppIndicator::connection-changed signal*/
+ g_signal_emit (self, signals[CONNECTION_CHANGED], 0, FALSE);
+
+ start_fallback_timer(self, FALSE);
+ return;
+}
+
+/* Responce from the DBus command to register a service
+ with a NotificationWatcher. */
+static void
+register_service_cb (DBusGProxy * proxy, GError * error, gpointer data)
+{
+ g_return_if_fail(IS_APP_INDICATOR(data));
+ AppIndicatorPrivate * priv = APP_INDICATOR(data)->priv;
+
+ if (error != NULL) {
+ /* They didn't respond, ewww. Not sure what they could
+ be doing */
+ g_warning("Unable to connect to the Notification Watcher: %s", error->message);
+ dbus_g_connection_unregister_g_object(priv->connection,
+ G_OBJECT(data));
+ g_object_unref(G_OBJECT(priv->watcher_proxy));
+ priv->watcher_proxy = NULL;
+ start_fallback_timer(APP_INDICATOR(data), TRUE);
+ }
+
+ if (priv->status_icon) {
+ AppIndicatorClass * class = APP_INDICATOR_GET_CLASS(data);
+ if (class->unfallback != NULL) {
+ class->unfallback(APP_INDICATOR(data), priv->status_icon);
+ priv->status_icon = NULL;
+ }
+ }
+
+ return;
+}
+
+/* A helper function to get the nick out of a given
+ category enum value. */
+static const gchar *
+category_from_enum (AppIndicatorCategory category)
+{
+ GEnumValue *value;
+
+ value = g_enum_get_value ((GEnumClass *)g_type_class_ref (APP_INDICATOR_TYPE_INDICATOR_CATEGORY), category);
+ return value->value_nick;
+}
+
+/* Watching the dbus owner change events to see if someone
+ we care about pops up! */
+static void
+dbus_owner_change (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, gpointer data)
+{
+ if (new == NULL || new[0] == '\0') {
+ /* We only care about folks coming on the bus. Exit quickly otherwise. */
+ return;
+ }
+
+ if (g_strcmp0(name, NOTIFICATION_WATCHER_DBUS_ADDR)) {
+ /* We only care about this address, reject all others. */
+ return;
+ }
+
+ /* Woot, there's a new notification watcher in town. */
+
+ AppIndicatorPrivate * priv = APP_INDICATOR_GET_PRIVATE(data);
+
+ if (priv->fallback_timer != 0) {
+ /* Stop a timer */
+ g_source_remove(priv->fallback_timer);
+
+ /* Stop listening to bus events */
+ g_object_unref(G_OBJECT(priv->dbus_proxy));
+ priv->dbus_proxy = NULL;
+ }
+
+ /* Let's start from the very beginning */
+ check_connect(APP_INDICATOR(data));
+
+ return;
+}
+
+/* This is an idle function to create the proxy. This is mostly
+ because start_fallback_timer can get called in the distruction
+ of a proxy and thus the proxy manager gets confused when creating
+ a new proxy as part of destroying an old one. This function being
+ on idle means that we'll just do it outside of the same stack where
+ the previous proxy is being destroyed. */
+static gboolean
+setup_name_owner_proxy (gpointer data)
+{
+ g_return_val_if_fail(IS_APP_INDICATOR(data), FALSE);
+ AppIndicatorPrivate * priv = APP_INDICATOR(data)->priv;
+
+ if (priv->dbus_proxy == NULL) {
+ priv->dbus_proxy = dbus_g_proxy_new_for_name(priv->connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+ dbus_g_proxy_add_signal(priv->dbus_proxy, "NameOwnerChanged",
+ G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
+ G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal(priv->dbus_proxy, "NameOwnerChanged",
+ G_CALLBACK(dbus_owner_change), data, NULL);
+ }
+
+ return FALSE;
+}
+
+/* A function that will start the fallback timer if it's not
+ already started. It sets up the DBus watcher to see if
+ there is a change. Also, provides an override mode for cases
+ where it's unlikely that a timer will help anything. */
+static void
+start_fallback_timer (AppIndicator * self, gboolean disable_timeout)
+{
+ g_return_if_fail(IS_APP_INDICATOR(self));
+ AppIndicatorPrivate * priv = APP_INDICATOR(self)->priv;
+
+ if (priv->fallback_timer != 0) {
+ /* The timer is set, let's just be happy with the one
+ we've already got running */
+ return;
+ }
+
+ if (priv->status_icon != NULL) {
+ /* We're already fallen back. Let's not do it again. */
+ return;
+ }
+
+ if (priv->dbus_proxy == NULL) {
+ /* NOTE: Read the comment on setup_name_owner_proxy */
+ g_idle_add(setup_name_owner_proxy, self);
+ }
+
+ if (disable_timeout) {
+ fallback_timer_expire(self);
+ } else {
+ priv->fallback_timer = g_timeout_add(DEFAULT_FALLBACK_TIMER, fallback_timer_expire, self);
+ }
+
+ return;
+}
+
+/* A function that gets executed when we want to change the
+ state of the fallback. */
+static gboolean
+fallback_timer_expire (gpointer data)
+{
+ g_return_val_if_fail(IS_APP_INDICATOR(data), FALSE);
+
+ AppIndicatorPrivate * priv = APP_INDICATOR(data)->priv;
+ AppIndicatorClass * class = APP_INDICATOR_GET_CLASS(data);
+
+ if (priv->status_icon == NULL) {
+ if (class->fallback != NULL) {
+ priv->status_icon = class->fallback(APP_INDICATOR(data));
+ }
+ } else {
+ if (class->unfallback != NULL) {
+ class->unfallback(APP_INDICATOR(data), priv->status_icon);
+ priv->status_icon = NULL;
+ } else {
+ g_warning("No 'unfallback' function but the 'fallback' function returned a non-NULL result.");
+ }
+ }
+
+ priv->fallback_timer = 0;
+ return FALSE;
+}
+
+/* emit a NEW_ICON signal in response for the theme change */
+static void
+theme_changed_cb (GtkIconTheme * theme, gpointer user_data)
+{
+ g_signal_emit (user_data, signals[NEW_ICON], 0, TRUE);
+}
+
+/* Creates a StatusIcon that can be used when the application
+ indicator area isn't available. */
+static GtkStatusIcon *
+fallback (AppIndicator * self)
+{
+ GtkStatusIcon * icon = gtk_status_icon_new();
+
+ gtk_status_icon_set_title(icon, app_indicator_get_id(self));
+
+ g_signal_connect(G_OBJECT(self), APP_INDICATOR_SIGNAL_NEW_STATUS,
+ G_CALLBACK(status_icon_status_wrapper), icon);
+ g_signal_connect(G_OBJECT(self), APP_INDICATOR_SIGNAL_NEW_ICON,
+ G_CALLBACK(status_icon_changes), icon);
+ g_signal_connect(G_OBJECT(self), APP_INDICATOR_SIGNAL_NEW_ATTENTION_ICON,
+ G_CALLBACK(status_icon_changes), icon);
+
+ status_icon_changes(self, icon);
+
+ g_signal_connect(G_OBJECT(icon), "activate", G_CALLBACK(status_icon_activate), self);
+
+ return icon;
+}
+
+/* A wrapper as the status update prototype is a little
+ bit different, but we want to handle it the same. */
+static void
+status_icon_status_wrapper (AppIndicator * self, const gchar * status, gpointer data)
+{
+ return status_icon_changes(self, data);
+}
+
+/* This tracks changes to either the status or the icons
+ that are associated with the app indicator */
+static void
+status_icon_changes (AppIndicator * self, gpointer data)
+{
+ GtkStatusIcon * icon = GTK_STATUS_ICON(data);
+ GIcon *themed_icon = NULL;
+ gchar *longname = NULL;
+
+ switch (app_indicator_get_status(self)) {
+ case APP_INDICATOR_STATUS_PASSIVE:
+ longname = append_panel_icon_suffix(app_indicator_get_icon(self));
+ themed_icon = g_themed_icon_new_with_default_fallbacks (longname);
+ gtk_status_icon_set_visible(icon, FALSE);
+ gtk_status_icon_set_from_gicon(icon, themed_icon);
+ break;
+ case APP_INDICATOR_STATUS_ACTIVE:
+ longname = append_panel_icon_suffix(app_indicator_get_icon(self));
+ themed_icon = g_themed_icon_new_with_default_fallbacks (longname);
+ gtk_status_icon_set_from_gicon(icon, themed_icon);
+ gtk_status_icon_set_visible(icon, TRUE);
+ break;
+ case APP_INDICATOR_STATUS_ATTENTION:
+ longname = append_panel_icon_suffix(app_indicator_get_attention_icon(self));
+ themed_icon = g_themed_icon_new_with_default_fallbacks (longname);
+ gtk_status_icon_set_from_gicon(icon, themed_icon);
+ gtk_status_icon_set_visible(icon, TRUE);
+ break;
+ };
+
+ if (themed_icon) {
+ g_object_unref (themed_icon);
+ }
+
+ if (longname) {
+ g_free(longname);
+ }
+
+ return;
+}
+
+/* Handles the activate action by the status icon by showing
+ the menu in a popup. */
+static void
+status_icon_activate (GtkStatusIcon * icon, gpointer data)
+{
+ GtkMenu * menu = app_indicator_get_menu(APP_INDICATOR(data));
+ if (menu == NULL)
+ return;
+
+ gtk_menu_popup(menu,
+ NULL, /* Parent Menu */
+ NULL, /* Parent item */
+ gtk_status_icon_position_menu,
+ icon,
+ 1, /* Button */
+ gtk_get_current_event_time());
+
+ return;
+}
+
+/* Removes the status icon as the application indicator area
+ is now up and running again. */
+static void
+unfallback (AppIndicator * self, GtkStatusIcon * status_icon)
+{
+ g_signal_handlers_disconnect_by_func(G_OBJECT(self), status_icon_status_wrapper, status_icon);
+ g_signal_handlers_disconnect_by_func(G_OBJECT(self), status_icon_changes, status_icon);
+ gtk_status_icon_set_visible(status_icon, FALSE);
+ g_object_unref(G_OBJECT(status_icon));
+ return;
+}
+
+/* A helper function that appends PANEL_ICON_SUFFIX to the given icon name
+ if it's missing. */
+static gchar *
+append_panel_icon_suffix (const gchar *icon_name)
+{
+ gchar * long_name = NULL;
+
+ if (!g_str_has_suffix (icon_name, PANEL_ICON_SUFFIX)) {
+ long_name =
+ g_strdup_printf("%s-%s", icon_name, PANEL_ICON_SUFFIX);
+ } else {
+ long_name = g_strdup (icon_name);
+ }
+
+ return long_name;
+}
+
+
+/* ************************* */
+/* Public Functions */
+/* ************************* */
+
+/**
+ app_indicator_new:
+ @id: The unique id of the indicator to create.
+ @icon_name: The icon name for this indicator
+ @category: The category of indicator.
+
+ Creates a new #AppIndicator setting the properties:
+ #AppIndicator::id with @id, #AppIndicator::category
+ with @category and #AppIndicator::icon-name with
+ @icon_name.
+
+ Return value: A pointer to a new #AppIndicator object.
+ */
+AppIndicator *
+app_indicator_new (const gchar *id,
+ const gchar *icon_name,
+ AppIndicatorCategory category)
+{
+ AppIndicator *indicator = g_object_new (APP_INDICATOR_TYPE,
+ PROP_ID_S, id,
+ PROP_CATEGORY_S, category_from_enum (category),
+ PROP_ICON_NAME_S, icon_name,
+ NULL);
+
+ return indicator;
+}
+
+/**
+ app_indicator_new_with_path:
+ @id: The unique id of the indicator to create.
+ @icon_name: The icon name for this indicator
+ @category: The category of indicator.
+ @icon_path: A custom path for finding icons.
+
+ Creates a new #AppIndicator setting the properties:
+ #AppIndicator::id with @id, #AppIndicator::category
+ with @category, #AppIndicator::icon-name with
+ @icon_name and #AppIndicator::icon-theme-path with @icon_path.
+
+ Return value: A pointer to a new #AppIndicator object.
+ */
+AppIndicator *
+app_indicator_new_with_path (const gchar *id,
+ const gchar *icon_name,
+ AppIndicatorCategory category,
+ const gchar *icon_path)
+{
+ AppIndicator *indicator = g_object_new (APP_INDICATOR_TYPE,
+ PROP_ID_S, id,
+ PROP_CATEGORY_S, category_from_enum (category),
+ PROP_ICON_NAME_S, icon_name,
+ PROP_ICON_THEME_PATH_S, icon_path,
+ NULL);
+
+ return indicator;
+}
+
+/**
+ app_indicator_get_type:
+
+ Generates or returns the unique #GType for #AppIndicator.
+
+ Return value: A unique #GType for #AppIndicator objects.
+*/
+
+/**
+ app_indicator_set_status:
+ @self: The #AppIndicator object to use
+ @status: The status to set for this indicator
+
+ Wrapper function for property #AppIndicator::status.
+*/
+void
+app_indicator_set_status (AppIndicator *self, AppIndicatorStatus status)
+{
+ g_return_if_fail (IS_APP_INDICATOR (self));
+
+ if (self->priv->status != status)
+ {
+ GEnumValue *value = g_enum_get_value ((GEnumClass *) g_type_class_ref (APP_INDICATOR_TYPE_INDICATOR_STATUS), status);
+
+ self->priv->status = status;
+ g_signal_emit (self, signals[NEW_STATUS], 0, value->value_nick);
+ }
+}
+
+/**
+ app_indicator_set_attention_icon:
+ @self: The #AppIndicator object to use
+ @icon_name: The name of the attention icon to set for this indicator
+
+ Wrapper function for property #AppIndicator::attention-icon.
+*/
+void
+app_indicator_set_attention_icon (AppIndicator *self, const gchar *icon_name)
+{
+ g_return_if_fail (IS_APP_INDICATOR (self));
+ g_return_if_fail (icon_name != NULL);
+
+ if (g_strcmp0 (self->priv->attention_icon_name, icon_name) != 0)
+ {
+ if (self->priv->attention_icon_name)
+ g_free (self->priv->attention_icon_name);
+
+ self->priv->attention_icon_name = g_strdup(icon_name);
+
+ g_signal_emit (self, signals[NEW_ATTENTION_ICON], 0, TRUE);
+ }
+
+ return;
+}
+
+/**
+ app_indicator_set_icon:
+ @self: The #AppIndicator object to use
+ @icon_name: The icon name to set.
+
+ Sets the default icon to use when the status is active but
+ not set to attention. In most cases, this should be the
+ application icon for the program.
+**/
+void
+app_indicator_set_icon (AppIndicator *self, const gchar *icon_name)
+{
+ g_return_if_fail (IS_APP_INDICATOR (self));
+ g_return_if_fail (icon_name != NULL);
+
+ if (g_strcmp0 (self->priv->icon_name, icon_name) != 0)
+ {
+ if (self->priv->icon_name)
+ g_free (self->priv->icon_name);
+
+ self->priv->icon_name = g_strdup(icon_name);
+
+ g_signal_emit (self, signals[NEW_ICON], 0, TRUE);
+ }
+
+ return;
+}
+
+static void
+activate_menuitem (DbusmenuMenuitem *mi, guint timestamp, gpointer user_data)
+{
+ GtkWidget *widget = (GtkWidget *)user_data;
+
+ gtk_menu_item_activate (GTK_MENU_ITEM (widget));
+}
+
+static void
+widget_toggled (GtkWidget *widget, DbusmenuMenuitem *mi)
+{
+ dbusmenu_menuitem_property_set_int (mi,
+ DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
+ gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
+}
+
+static void
+menuitem_iterate (GtkWidget *widget,
+ gpointer data)
+{
+ if (GTK_IS_LABEL (widget))
+ {
+ DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
+
+ dbusmenu_menuitem_property_set (child,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ gtk_label_get_text (GTK_LABEL (widget)));
+ }
+}
+
+static gboolean
+should_show_image (GtkImage *image)
+{
+ GtkWidget *item;
+
+ item = gtk_widget_get_ancestor (GTK_WIDGET (image),
+ GTK_TYPE_IMAGE_MENU_ITEM);
+
+ if (item)
+ {
+ GtkSettings *settings;
+ gboolean gtk_menu_images;
+
+ settings = gtk_widget_get_settings (item);
+
+ g_object_get (settings, "gtk-menu-images", >k_menu_images, NULL);
+
+ if (gtk_menu_images)
+ return TRUE;
+
+ return gtk_image_menu_item_get_always_show_image (GTK_IMAGE_MENU_ITEM (item));
+ }
+
+ return FALSE;
+}
+
+static void
+update_icon_name (DbusmenuMenuitem *menuitem,
+ GtkImage *image)
+{
+ if (gtk_image_get_storage_type (image) != GTK_IMAGE_ICON_NAME)
+ return;
+
+ if (should_show_image (image))
+ dbusmenu_menuitem_property_set (menuitem,
+ DBUSMENU_MENUITEM_PROP_ICON_NAME,
+ image->data.name.icon_name);
+ else
+ dbusmenu_menuitem_property_remove (menuitem,
+ DBUSMENU_MENUITEM_PROP_ICON_NAME);
+}
+
+/* return value specifies whether the label is set or not */
+static gboolean
+update_stock_item (DbusmenuMenuitem *menuitem,
+ GtkImage *image)
+{
+ GtkStockItem stock;
+
+ if (gtk_image_get_storage_type (image) != GTK_IMAGE_STOCK)
+ return FALSE;
+
+ gtk_stock_lookup (image->data.stock.stock_id, &stock);
+
+ if (should_show_image (image))
+ dbusmenu_menuitem_property_set (menuitem,
+ DBUSMENU_MENUITEM_PROP_ICON_NAME,
+ image->data.stock.stock_id);
+ else
+ dbusmenu_menuitem_property_remove (menuitem,
+ DBUSMENU_MENUITEM_PROP_ICON_NAME);
+
+ const gchar * label = dbusmenu_menuitem_property_get (menuitem,
+ DBUSMENU_MENUITEM_PROP_LABEL);
+
+ if (stock.label != NULL && label != NULL)
+ {
+ dbusmenu_menuitem_property_set (menuitem,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ stock.label);
+
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+image_notify_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ gpointer data)
+{
+ DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
+ GtkImage *image = GTK_IMAGE (widget);
+
+ if (pspec->name == g_intern_static_string ("stock"))
+ {
+ update_stock_item (child, image);
+ }
+ else if (pspec->name == g_intern_static_string ("icon-name"))
+ {
+ update_icon_name (child, image);
+ }
+}
+
+static void
+widget_notify_cb (GtkWidget *widget,
+ GParamSpec *pspec,
+ gpointer data)
+{
+ DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
+
+ if (pspec->name == g_intern_static_string ("sensitive"))
+ {
+ dbusmenu_menuitem_property_set_bool (child,
+ DBUSMENU_MENUITEM_PROP_ENABLED,
+ GTK_WIDGET_IS_SENSITIVE (widget));
+ }
+ else if (pspec->name == g_intern_static_string ("label"))
+ {
+ dbusmenu_menuitem_property_set (child,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ gtk_menu_item_get_label (GTK_MENU_ITEM (widget)));
+ }
+ else if (pspec->name == g_intern_static_string ("visible"))
+ {
+ dbusmenu_menuitem_property_set_bool (child,
+ DBUSMENU_MENUITEM_PROP_VISIBLE,
+ gtk_widget_get_visible (widget));
+ }
+}
+
+static void
+action_notify_cb (GtkAction *action,
+ GParamSpec *pspec,
+ gpointer data)
+{
+ DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
+
+ if (pspec->name == g_intern_static_string ("active"))
+ {
+ dbusmenu_menuitem_property_set_bool (child,
+ DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
+ gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
+ }
+
+ if (pspec->name == g_intern_static_string ("label"))
+ {
+ dbusmenu_menuitem_property_set (child,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ gtk_action_get_label (action));
+ }
+}
+
+static void
+container_iterate (GtkWidget *widget,
+ gpointer data)
+{
+ DbusmenuMenuitem *root = (DbusmenuMenuitem *)data;
+ DbusmenuMenuitem *child;
+ GtkWidget *submenu = NULL;
+ const gchar *label = NULL;
+ gboolean label_set = FALSE;
+
+ if (GTK_IS_TEAROFF_MENU_ITEM(widget)) {
+ return;
+ }
+
+ child = dbusmenu_menuitem_new ();
+
+ if (GTK_IS_SEPARATOR_MENU_ITEM (widget))
+ {
+ dbusmenu_menuitem_property_set (child,
+ "type",
+ DBUSMENU_CLIENT_TYPES_SEPARATOR);
+ }
+ else
+ {
+ if (GTK_IS_CHECK_MENU_ITEM (widget))
+ {
+ GtkCheckMenuItem *check;
+
+ check = GTK_CHECK_MENU_ITEM (widget);
+ label = gtk_menu_item_get_label (GTK_MENU_ITEM (widget));
+
+ dbusmenu_menuitem_property_set (child,
+ DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE,
+ GTK_IS_RADIO_MENU_ITEM (widget) ? DBUSMENU_MENUITEM_TOGGLE_RADIO : DBUSMENU_MENUITEM_TOGGLE_CHECK);
+
+ dbusmenu_menuitem_property_set (child,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ label);
+
+ label_set = TRUE;
+
+ dbusmenu_menuitem_property_set_int (child,
+ DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
+ gtk_check_menu_item_get_active (check) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
+
+ g_signal_connect (widget,
+ "toggled",
+ G_CALLBACK (widget_toggled),
+ child);
+ }
+ else if (GTK_IS_IMAGE_MENU_ITEM (widget))
+ {
+ GtkWidget *image;
+ GtkImageType image_type;
+
+ image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (widget));
+ image_type = gtk_image_get_storage_type (GTK_IMAGE (image));
+
+ g_signal_connect (image,
+ "notify",
+ G_CALLBACK (image_notify_cb),
+ child);
+
+ if (image_type == GTK_IMAGE_STOCK)
+ {
+ label_set = update_stock_item (child, GTK_IMAGE (image));
+ }
+ else if (image_type == GTK_IMAGE_ICON_NAME)
+ {
+ update_icon_name (child, GTK_IMAGE (image));
+ }
+ }
+ }
+
+ if (!label_set)
+ {
+ if (label != NULL)
+ {
+ dbusmenu_menuitem_property_set (child,
+ DBUSMENU_MENUITEM_PROP_LABEL,
+ label);
+ }
+ else
+ {
+ /* find label child widget */
+ gtk_container_forall (GTK_CONTAINER (widget),
+ menuitem_iterate,
+ child);
+ }
+ }
+
+ if (GTK_IS_MENU_ITEM (widget))
+ {
+ submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
+ if (submenu != NULL)
+ {
+ gtk_container_foreach (GTK_CONTAINER (submenu),
+ container_iterate,
+ child);
+ g_signal_connect_object (submenu,
+ "add",
+ G_CALLBACK (submenu_changed),
+ child,
+ 0);
+ g_signal_connect_object (submenu,
+ "remove",
+ G_CALLBACK (submenu_changed),
+ child,
+ 0);
+ }
+ }
+
+ dbusmenu_menuitem_property_set_bool (child,
+ DBUSMENU_MENUITEM_PROP_ENABLED,
+ GTK_WIDGET_IS_SENSITIVE (widget));
+ dbusmenu_menuitem_property_set_bool (child,
+ DBUSMENU_MENUITEM_PROP_VISIBLE,
+ gtk_widget_get_visible (widget));
+
+ g_signal_connect (widget, "notify",
+ G_CALLBACK (widget_notify_cb), child);
+
+ if (GTK_IS_ACTIVATABLE (widget))
+ {
+ GtkActivatable *activatable = GTK_ACTIVATABLE (widget);
+
+ if (gtk_activatable_get_use_action_appearance (activatable))
+ {
+ GtkAction *action = gtk_activatable_get_related_action (activatable);
+
+ if (action)
+ {
+ g_signal_connect_object (action, "notify",
+ G_CALLBACK (action_notify_cb),
+ child,
+ G_CONNECT_AFTER);
+ }
+ }
+ }
+
+ g_signal_connect (G_OBJECT (child),
+ DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
+ G_CALLBACK (activate_menuitem), widget);
+ dbusmenu_menuitem_child_append (root, child);
+}
+
+static void
+submenu_changed (GtkWidget *widget,
+ GtkWidget *child,
+ gpointer data)
+{
+ DbusmenuMenuitem *root = (DbusmenuMenuitem *)data;
+ GList *children, *l;
+ children = dbusmenu_menuitem_get_children (root);
+
+ for (l = children; l;)
+ {
+ DbusmenuMenuitem *c = (DbusmenuMenuitem *)l->data;
+ l = l->next;
+ dbusmenu_menuitem_child_delete (root, c);
+ }
+
+ gtk_container_foreach (GTK_CONTAINER (widget),
+ container_iterate,
+ root);
+}
+
+static void
+setup_dbusmenu (AppIndicator *self)
+{
+ AppIndicatorPrivate *priv;
+ DbusmenuMenuitem *root;
+
+ priv = self->priv;
+ root = dbusmenu_menuitem_new ();
+
+ if (priv->menu)
+ {
+ gtk_container_foreach (GTK_CONTAINER (priv->menu),
+ container_iterate,
+ root);
+ }
+
+ if (priv->menuservice == NULL)
+ {
+ gchar * path = g_strdup_printf(DEFAULT_ITEM_PATH "/%s/Menu", priv->clean_id);
+ priv->menuservice = dbusmenu_server_new (path);
+ g_free(path);
+ }
+
+ dbusmenu_server_set_root (priv->menuservice, root);
+
+ return;
+}
+
+static void
+client_menu_changed (GtkWidget *widget,
+ GtkWidget *child,
+ AppIndicator *indicator)
+{
+ setup_dbusmenu (indicator);
+}
+
+/**
+ app_indicator_set_menu:
+ @self: The #AppIndicator
+ @menu: A #GtkMenu to set
+
+ Sets the menu that should be shown when the Application Indicator
+ is clicked on in the panel. An application indicator will not
+ be rendered unless it has a menu.
+**/
+void
+app_indicator_set_menu (AppIndicator *self, GtkMenu *menu)
+{
+ AppIndicatorPrivate *priv;
+
+ g_return_if_fail (IS_APP_INDICATOR (self));
+ g_return_if_fail (GTK_IS_MENU (menu));
+ g_return_if_fail (self->priv->clean_id != NULL);
+
+ priv = self->priv;
+
+ if (priv->menu != NULL)
+ {
+ g_object_unref (priv->menu);
+ }
+
+ priv->menu = GTK_WIDGET (menu);
+ g_object_ref (priv->menu);
+
+ setup_dbusmenu (self);
+
+ check_connect (self);
+
+ g_signal_connect (menu,
+ "add",
+ G_CALLBACK (client_menu_changed),
+ self);
+ g_signal_connect (menu,
+ "remove",
+ G_CALLBACK (client_menu_changed),
+ self);
+}
+
+/**
+ app_indicator_get_id:
+ @self: The #AppIndicator object to use
+
+ Wrapper function for property #AppIndicator::id.
+
+ Return value: The current ID
+*/
+const gchar *
+app_indicator_get_id (AppIndicator *self)
+{
+ g_return_val_if_fail (IS_APP_INDICATOR (self), NULL);
+
+ return self->priv->id;
+}
+
+/**
+ app_indicator_get_category:
+ @self: The #AppIndicator object to use
+
+ Wrapper function for property #AppIndicator::category.
+
+ Return value: The current category.
+*/
+AppIndicatorCategory
+app_indicator_get_category (AppIndicator *self)
+{
+ g_return_val_if_fail (IS_APP_INDICATOR (self), APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
+
+ return self->priv->category;
+}
+
+/**
+ app_indicator_get_status:
+ @self: The #AppIndicator object to use
+
+ Wrapper function for property #AppIndicator::status.
+
+ Return value: The current status.
+*/
+AppIndicatorStatus
+app_indicator_get_status (AppIndicator *self)
+{
+ g_return_val_if_fail (IS_APP_INDICATOR (self), APP_INDICATOR_STATUS_PASSIVE);
+
+ return self->priv->status;
+}
+
+/**
+ app_indicator_get_icon:
+ @self: The #AppIndicator object to use
+
+ Wrapper function for property #AppIndicator::icon-name.
+
+ Return value: The current icon name.
+*/
+const gchar *
+app_indicator_get_icon (AppIndicator *self)
+{
+ g_return_val_if_fail (IS_APP_INDICATOR (self), NULL);
+
+ return self->priv->icon_name;
+}
+
+/**
+ app_indicator_get_attention_icon:
+ @self: The #AppIndicator object to use
+
+ Wrapper function for property #AppIndicator::attention-icon-name.
+
+ Return value: The current attention icon name.
+*/
+const gchar *
+app_indicator_get_attention_icon (AppIndicator *self)
+{
+ g_return_val_if_fail (IS_APP_INDICATOR (self), NULL);
+
+ return self->priv->attention_icon_name;
+}
+
+/**
+ app_indicator_get_menu:
+ @self: The #AppIndicator object to use
+
+ Gets the menu being used for this application indicator.
+
+ Return value: A menu object or #NULL if one hasn't been set.
+*/
+GtkMenu *
+app_indicator_get_menu (AppIndicator *self)
+{
+ AppIndicatorPrivate *priv;
+
+ g_return_val_if_fail (IS_APP_INDICATOR (self), NULL);
+
+ priv = self->priv;
+
+ return GTK_MENU(priv->menu);
+}
diff --git a/src/app-indicator.h b/src/app-indicator.h
new file mode 100644
index 0000000..549ab35
--- /dev/null
+++ b/src/app-indicator.h
@@ -0,0 +1,257 @@
+/*
+An object to represent the application as an application indicator
+in the system panel.
+
+Copyright 2009 Canonical Ltd.
+
+Authors:
+ Ted Gould
+ Cody Russell
+
+This program is free software: you can redistribute it and/or modify it
+under the terms of either or both of the following licenses:
+
+1) the GNU Lesser General Public License version 3, as published by the
+ Free Software Foundation; and/or
+2) the GNU Lesser General Public License version 2.1, as published by
+ the Free Software Foundation.
+
+This program is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranties of
+MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
+PURPOSE. See the applicable version of the GNU Lesser General Public
+License for more details.
+
+You should have received a copy of both the GNU Lesser General Public
+License version 3 and version 2.1 along with this program. If not, see
+
+*/
+
+#ifndef __APP_INDICATOR_H__
+#define __APP_INDICATOR_H__
+
+#include
+
+G_BEGIN_DECLS
+
+/**
+ APP_INDICATOR_TYPE:
+
+ Get the #GType for a #AppIndicator.
+*/
+/**
+ APP_INDICATOR:
+ @obj: The object to convert
+
+ Safely convert a #GObject into an #AppIndicator.
+*/
+/**
+ APP_INDICATOR_CLASS:
+ @klass: #GObjectClass based class to convert.
+
+ Safely convert a #GObjectClass into a #AppIndicatorClass.
+*/
+/**
+ IS_APP_INDICATOR:
+ @obj: An #GObject to check
+
+ Checks to see if @obj is in the object hierarchy of #AppIndicator.
+*/
+/**
+ IS_APP_INDICATOR_CLASS:
+ @klass: An #GObjectClass to check
+
+ Checks to see if @klass is in the object class hierarchy of #AppIndicatorClass.
+*/
+/**
+ APP_INDICATOR_GET_CLASS:
+ @obj: A #GObject in the class hierarchy of #AppIndicator.
+
+ Gets a pointer to the #AppIndicatorClass for the object @obj.
+*/
+#define APP_INDICATOR_TYPE (app_indicator_get_type ())
+#define APP_INDICATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), APP_INDICATOR_TYPE, AppIndicator))
+#define APP_INDICATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), APP_INDICATOR_TYPE, AppIndicatorClass))
+#define IS_APP_INDICATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), APP_INDICATOR_TYPE))
+#define IS_APP_INDICATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), APP_INDICATOR_TYPE))
+#define APP_INDICATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), APP_INDICATOR_TYPE, AppIndicatorClass))
+
+/**
+ APP_INDICATOR_SIGNAL_NEW_ICON:
+
+ String identifier for the #AppIndicator::new-icon signal.
+*/
+/**
+ APP_INDICATOR_SIGNAL_NEW_ATTENTION_ICON:
+
+ String identifier for the #AppIndicator::new-attention-icon signal.
+*/
+/**
+ APP_INDICATOR_SIGNAL_NEW_STATUS:
+
+ String identifier for the #AppIndicator::new-status signal.
+*/
+/**
+ APP_INDICATOR_SIGNAL_CONNECTION_CHANGED:
+
+ String identifier for the #AppIndicator::connection-changed signal.
+*/
+#define APP_INDICATOR_SIGNAL_NEW_ICON "new-icon"
+#define APP_INDICATOR_SIGNAL_NEW_ATTENTION_ICON "new-attention-icon"
+#define APP_INDICATOR_SIGNAL_NEW_STATUS "new-status"
+#define APP_INDICATOR_SIGNAL_CONNECTION_CHANGED "connection-changed"
+
+/**
+ AppIndicatorCategory:
+ @APP_INDICATOR_CATEGORY_APPLICATION_STATUS: The indicator is used to display the status of the application.
+ @APP_INDICATOR_CATEGORY_COMMUNICATIONS: The application is used for communication with other people.
+ @APP_INDICATOR_CATEGORY_SYSTEM_SERVICES: A system indicator relating to something in the user's system.
+ @APP_INDICATOR_CATEGORY_HARDWARE: An indicator relating to the user's hardware.
+ @APP_INDICATOR_CATEGORY_OTHER: Something not defined in this enum, please don't use unless you really need it.
+
+ The category provides grouping for the indicators so that
+ users can find indicators that are similar together.
+*/
+typedef enum { /*< prefix=APP_INDICATOR_CATEGORY >*/
+ APP_INDICATOR_CATEGORY_APPLICATION_STATUS,
+ APP_INDICATOR_CATEGORY_COMMUNICATIONS,
+ APP_INDICATOR_CATEGORY_SYSTEM_SERVICES,
+ APP_INDICATOR_CATEGORY_HARDWARE,
+ APP_INDICATOR_CATEGORY_OTHER
+} AppIndicatorCategory;
+
+/**
+ AppIndicatorStatus:
+ @APP_INDICATOR_STATUS_PASSIVE: The indicator should not be shown to the user.
+ @APP_INDICATOR_STATUS_ACTIVE: The indicator should be shown in it's default state.
+ @APP_INDICATOR_STATUS_ATTENTION: The indicator should show it's attention icon.
+
+ These are the states that the indicator can be on in
+ the user's panel. The indicator by default starts
+ in the state @APP_INDICATOR_STATUS_PASSIVE and can be
+ shown by setting it to @APP_INDICATOR_STATUS_ACTIVE.
+*/
+typedef enum { /*< prefix=APP_INDICATOR_STATUS >*/
+ APP_INDICATOR_STATUS_PASSIVE,
+ APP_INDICATOR_STATUS_ACTIVE,
+ APP_INDICATOR_STATUS_ATTENTION
+} AppIndicatorStatus;
+
+typedef struct _AppIndicator AppIndicator;
+typedef struct _AppIndicatorClass AppIndicatorClass;
+typedef struct _AppIndicatorPrivate AppIndicatorPrivate;
+
+/**
+ AppIndicatorClass:
+ @parent_class: Mia familia
+ @new_icon: Slot for #AppIndicator::new-icon.
+ @new_attention_icon: Slot for #AppIndicator::new-attention-icon.
+ @new_status: Slot for #AppIndicator::new-status.
+ @connection_changed: Slot for #AppIndicator::connection-changed.
+ @fallback: Function that gets called to make a #GtkStatusIcon when
+ there is no Application Indicator area available.
+ @unfallback: The function that gets called if an Application
+ Indicator area appears after the fallback has been created.
+ @app_indicator_reserved_1: Reserved for future use.
+ @app_indicator_reserved_2: Reserved for future use.
+
+ The signals and external functions that make up the #AppIndicator
+ class object.
+*/
+struct _AppIndicatorClass {
+ /* Parent */
+ GObjectClass parent_class;
+
+ /* DBus Signals */
+ void (* new_icon) (AppIndicator *indicator,
+ gpointer user_data);
+ void (* new_attention_icon) (AppIndicator *indicator,
+ gpointer user_data);
+ void (* new_status) (AppIndicator *indicator,
+ const gchar *status,
+ gpointer user_data);
+
+ /* Local Signals */
+ void (* connection_changed) (AppIndicator * indicator,
+ gboolean connected,
+ gpointer user_data);
+
+ /* Overridable Functions */
+ GtkStatusIcon * (*fallback) (AppIndicator * indicator);
+ void (*unfallback) (AppIndicator * indicator,
+ GtkStatusIcon * status_icon);
+
+ /* Reserved */
+ void (*app_indicator_reserved_1)(void);
+ void (*app_indicator_reserved_2)(void);
+};
+
+/**
+ AppIndicator:
+
+ A application indicator represents the values that are needed to show a
+ unique status in the panel for an application. In general, applications
+ should try to fit in the other indicators that are available on the
+ panel before using this. But, sometimes it is necissary.
+*/
+/* Private fields
+ @parent: Parent object.
+ @priv: Internal data.
+*/
+struct _AppIndicator {
+ /*< Private >*/
+ GObject parent;
+
+ /*< Private >*/
+ AppIndicatorPrivate *priv;
+};
+
+/* GObject Stuff */
+GType app_indicator_get_type (void) G_GNUC_CONST;
+
+AppIndicator *app_indicator_new (const gchar *id,
+ const gchar *icon_name,
+ AppIndicatorCategory category);
+AppIndicator *app_indicator_new_with_path (const gchar *id,
+ const gchar *icon_name,
+ AppIndicatorCategory category,
+ const gchar *icon_path);
+
+/* Set properties */
+void app_indicator_set_status (AppIndicator *self,
+ AppIndicatorStatus status);
+void app_indicator_set_attention_icon (AppIndicator *self,
+ const gchar *icon_name);
+void app_indicator_set_menu (AppIndicator *self,
+ GtkMenu *menu);
+void app_indicator_set_icon (AppIndicator *self,
+ const gchar *icon_name);
+
+/* Get properties */
+const gchar * app_indicator_get_id (AppIndicator *self);
+AppIndicatorCategory app_indicator_get_category (AppIndicator *self);
+AppIndicatorStatus app_indicator_get_status (AppIndicator *self);
+const gchar * app_indicator_get_icon (AppIndicator *self);
+const gchar * app_indicator_get_attention_icon (AppIndicator *self);
+GtkMenu * app_indicator_get_menu (AppIndicator *self);
+
+G_END_DECLS
+
+/**
+ SECTION:app-indicator
+ @short_description: An object to put application information
+ into the panel.
+ @stability: Unstable
+ @include: libappindicator/app-indicator.h
+
+ An application indicator is a way for an application to put
+ a menu into the panel on the user's screen. This allows the
+ user to interact with the application even though it might
+ not be visible to the user at the time. In most cases this
+ is not a good solution as there are other ways to inform the
+ user. It should only be use if persistence is a desired
+ feature for the user (not for your marketing purpose of
+ having your logo in the panel).
+*/
+
+#endif
diff --git a/src/appindicator-0.1.pc.in b/src/appindicator-0.1.pc.in
new file mode 100644
index 0000000..b80fded
--- /dev/null
+++ b/src/appindicator-0.1.pc.in
@@ -0,0 +1,14 @@
+prefix=@prefix@
+exec_prefix=@exec_prefix@
+libdir=@libdir@
+bindir=@bindir@
+includedir=@includedir@
+
+Cflags: -I${includedir}/libappindicator-0.1
+Requires: dbusmenu-glib gtk+-2.0
+Libs: -L${libdir} -lappindicator
+
+Name: appindicator-0.1
+Description: Application indicators
+Version: @VERSION@
+
diff --git a/src/libappindicator/app-indicator-enum-types.gen.c.in b/src/libappindicator/app-indicator-enum-types.gen.c.in
deleted file mode 100644
index 449f3fc..0000000
--- a/src/libappindicator/app-indicator-enum-types.gen.c.in
+++ /dev/null
@@ -1,61 +0,0 @@
-/*** BEGIN file-header ***/
-/*
-An object to represent the application as an application indicator
-in the system panel.
-
-Copyright 2009 Canonical Ltd.
-
-Authors:
- Ted Gould
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of either or both of the following licenses:
-
-1) the GNU Lesser General Public License version 3, as published by the
- Free Software Foundation; and/or
-2) the GNU Lesser General Public License version 2.1, as published by
- the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
-PURPOSE. See the applicable version of the GNU Lesser General Public
-License for more details.
-
-You should have received a copy of both the GNU Lesser General Public
-License version 3 and version 2.1 along with this program. If not, see
-
-*/
-
-#include "libappindicator/app-indicator-enum-types.h"
-
-/*** END file-header ***/
-
-/*** BEGIN file-production ***/
-#include "@filename@"
-/*** END file-production ***/
-
-/*** BEGIN value-header ***/
-GType
-@enum_name@_get_type (void)
-{
- static GType etype = 0;
- if (G_UNLIKELY(etype == 0)) {
- static const G@Type@Value values[] = {
-/*** END value-header ***/
-
-/*** BEGIN value-production ***/
- { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
-/*** END value-production ***/
-
-/*** BEGIN value-tail ***/
- { 0, NULL, NULL}
- };
-
- etype = g_@type@_register_static (g_intern_static_string("@EnumName@"), values);
- }
-
- return etype;
-}
-
-/*** END value-tail ***/
diff --git a/src/libappindicator/app-indicator-enum-types.h.in b/src/libappindicator/app-indicator-enum-types.h.in
deleted file mode 100644
index da3bf98..0000000
--- a/src/libappindicator/app-indicator-enum-types.h.in
+++ /dev/null
@@ -1,61 +0,0 @@
-/*** BEGIN file-header ***/
-/*
-An object to represent the application as an application indicator
-in the system panel.
-
-Copyright 2009 Canonical Ltd.
-
-Authors:
- Ted Gould
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of either or both of the following licenses:
-
-1) the GNU Lesser General Public License version 3, as published by the
- Free Software Foundation; and/or
-2) the GNU Lesser General Public License version 2.1, as published by
- the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
-PURPOSE. See the applicable version of the GNU Lesser General Public
-License for more details.
-
-You should have received a copy of both the GNU Lesser General Public
-License version 3 and version 2.1 along with this program. If not, see
-
-*/
-
-#ifndef __APP_INDICATOR_ENUM_TYPES_H__
-#define __APP_INDICATOR_ENUM_TYPES_H__
-
-#include
-
-G_BEGIN_DECLS
-
-/*** END file-header ***/
-
-/*** BEGIN file-tail ***/
-
-G_END_DECLS
-
-#endif /* __APP_INDICATOR_ENUM_TYPES_H__ */
-/*** END file-tail ***/
-
-/*** BEGIN file-production ***/
-/* Enumerations from file: "@filename@" */
-/*** END file-production ***/
-
-/*** BEGIN value-header ***/
-/**
- @enum_name@_get_type:
-
- Builds a glib type for the @EnumName@ enumeration.
-
- Return value: A registered type for the enum
-*/
-GType @enum_name@_get_type (void) G_GNUC_CONST;
-#define APP_INDICATOR_TYPE_@ENUMSHORT@ (@enum_name@_get_type())
-
-/*** END value-header ***/
diff --git a/src/libappindicator/app-indicator.c b/src/libappindicator/app-indicator.c
deleted file mode 100644
index 132e279..0000000
--- a/src/libappindicator/app-indicator.c
+++ /dev/null
@@ -1,1610 +0,0 @@
-/*
-An object to represent the application as an application indicator
-in the system panel.
-
-Copyright 2009 Canonical Ltd.
-
-Authors:
- Ted Gould
- Cody Russell
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of either or both of the following licenses:
-
-1) the GNU Lesser General Public License version 3, as published by the
- Free Software Foundation; and/or
-2) the GNU Lesser General Public License version 2.1, as published by
- the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
-PURPOSE. See the applicable version of the GNU Lesser General Public
-License for more details.
-
-You should have received a copy of both the GNU Lesser General Public
-License version 3 and version 2.1 along with this program. If not, see
-
-*/
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include
-#include
-#include
-
-#include "libappindicator/app-indicator.h"
-#include "libappindicator/app-indicator-enum-types.h"
-
-#include "notification-item-server.h"
-#include "notification-watcher-client.h"
-
-#include "dbus-shared.h"
-
-#define PANEL_ICON_SUFFIX "panel"
-
-/**
- AppIndicatorPrivate:
-
- All of the private data in an instance of a
- application indicator.
-*/
-/* Private Fields
- @id: The ID of the indicator. Maps to AppIndicator::id.
- @category: Which category the indicator is. Maps to AppIndicator::category.
- @status: The status of the indicator. Maps to AppIndicator::status.
- @icon_name: The name of the icon to use. Maps to AppIndicator::icon-name.
- @attention_icon_name: The name of the attention icon to use. Maps to AppIndicator::attention-icon-name.
- @menu: The menu for this indicator. Maps to AppIndicator::menu
- @watcher_proxy: The proxy connection to the watcher we're connected to. If we're not connected to one this will be #NULL.
-*/
-struct _AppIndicatorPrivate {
- /*< Private >*/
- /* Properties */
- gchar *id;
- gchar *clean_id;
- AppIndicatorCategory category;
- AppIndicatorStatus status;
- gchar *icon_name;
- gchar *attention_icon_name;
- gchar * icon_path;
- DbusmenuServer *menuservice;
- GtkWidget *menu;
-
- GtkStatusIcon * status_icon;
- gint fallback_timer;
-
- /* Fun stuff */
- DBusGProxy *watcher_proxy;
- DBusGConnection *connection;
- DBusGProxy * dbus_proxy;
-};
-
-/* Signals Stuff */
-enum {
- NEW_ICON,
- NEW_ATTENTION_ICON,
- NEW_STATUS,
- CONNECTION_CHANGED,
- LAST_SIGNAL
-};
-
-static guint signals[LAST_SIGNAL] = { 0 };
-
-/* Enum for the properties so that they can be quickly
- found and looked up. */
-enum {
- PROP_0,
- PROP_ID,
- PROP_CATEGORY,
- PROP_STATUS,
- PROP_ICON_NAME,
- PROP_ATTENTION_ICON_NAME,
- PROP_ICON_THEME_PATH,
- PROP_MENU,
- PROP_CONNECTED
-};
-
-/* The strings so that they can be slowly looked up. */
-#define PROP_ID_S "id"
-#define PROP_CATEGORY_S "category"
-#define PROP_STATUS_S "status"
-#define PROP_ICON_NAME_S "icon-name"
-#define PROP_ATTENTION_ICON_NAME_S "attention-icon-name"
-#define PROP_ICON_THEME_PATH_S "icon-theme-path"
-#define PROP_MENU_S "menu"
-#define PROP_CONNECTED_S "connected"
-
-/* Private macro, shhhh! */
-#define APP_INDICATOR_GET_PRIVATE(o) \
- (G_TYPE_INSTANCE_GET_PRIVATE ((o), APP_INDICATOR_TYPE, AppIndicatorPrivate))
-
-/* Default Path */
-#define DEFAULT_ITEM_PATH "/org/ayatana/NotificationItem"
-
-/* More constants */
-#define DEFAULT_FALLBACK_TIMER 100 /* in milliseconds */
-
-/* Boiler plate */
-static void app_indicator_class_init (AppIndicatorClass *klass);
-static void app_indicator_init (AppIndicator *self);
-static void app_indicator_dispose (GObject *object);
-static void app_indicator_finalize (GObject *object);
-/* Property functions */
-static void app_indicator_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec);
-static void app_indicator_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec);
-/* Other stuff */
-static void check_connect (AppIndicator * self);
-static void register_service_cb (DBusGProxy * proxy, GError * error, gpointer data);
-static void start_fallback_timer (AppIndicator * self, gboolean disable_timeout);
-static gboolean fallback_timer_expire (gpointer data);
-static GtkStatusIcon * fallback (AppIndicator * self);
-static void status_icon_status_wrapper (AppIndicator * self, const gchar * status, gpointer data);
-static void status_icon_changes (AppIndicator * self, gpointer data);
-static void status_icon_activate (GtkStatusIcon * icon, gpointer data);
-static void unfallback (AppIndicator * self, GtkStatusIcon * status_icon);
-static gchar * append_panel_icon_suffix (const gchar * icon_name);
-static void watcher_proxy_destroyed (GObject * object, gpointer data);
-static void client_menu_changed (GtkWidget *widget, GtkWidget *child, AppIndicator *indicator);
-static void submenu_changed (GtkWidget *widget, GtkWidget *child, gpointer data);
-
-static void theme_changed_cb (GtkIconTheme * theme, gpointer user_data);
-
-/* GObject type */
-G_DEFINE_TYPE (AppIndicator, app_indicator, G_TYPE_OBJECT);
-
-static void
-app_indicator_class_init (AppIndicatorClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- g_type_class_add_private (klass, sizeof (AppIndicatorPrivate));
-
- /* Clean up */
- object_class->dispose = app_indicator_dispose;
- object_class->finalize = app_indicator_finalize;
-
- /* Property funcs */
- object_class->set_property = app_indicator_set_property;
- object_class->get_property = app_indicator_get_property;
-
- /* Our own funcs */
- klass->fallback = fallback;
- klass->unfallback = unfallback;
-
- /* Properties */
- g_object_class_install_property (object_class,
- PROP_ID,
- g_param_spec_string(PROP_ID_S,
- "The ID for this indicator",
- "An ID that should be unique, but used consistently by this program and it's indicator.",
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property (object_class,
- PROP_CATEGORY,
- g_param_spec_string (PROP_CATEGORY_S,
- "Indicator Category",
- "The type of indicator that this represents. Please don't use 'other'. Defaults to 'Application Status'.",
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property (object_class,
- PROP_STATUS,
- g_param_spec_string (PROP_STATUS_S,
- "Indicator Status",
- "Whether the indicator is shown or requests attention. Defaults to 'off'.",
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property(object_class,
- PROP_ICON_NAME,
- g_param_spec_string (PROP_ICON_NAME_S,
- "An icon for the indicator",
- "The default icon that is shown for the indicator.",
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (object_class,
- PROP_ATTENTION_ICON_NAME,
- g_param_spec_string (PROP_ATTENTION_ICON_NAME_S,
- "An icon to show when the indicator request attention.",
- "If the indicator sets it's status to 'attention' then this icon is shown.",
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property(object_class,
- PROP_ICON_THEME_PATH,
- g_param_spec_string (PROP_ICON_THEME_PATH_S,
- "An additional path for custom icons.",
- "An additional place to look for icon names that may be installed by the application.",
- NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
-
- g_object_class_install_property(object_class,
- PROP_MENU,
- g_param_spec_boxed (PROP_MENU_S,
- "The object path of the menu on DBus.",
- "A method for getting the menu path as a string for DBus.",
- DBUS_TYPE_G_OBJECT_PATH,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property (object_class,
- PROP_CONNECTED,
- g_param_spec_boolean (PROP_CONNECTED_S,
- "Whether we're conneced to a watcher",
- "Pretty simple, true if we have a reasonable expectation of being displayed through this object. You should hide your TrayIcon if so.",
- FALSE,
- G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
-
-
- /* Signals */
-
- /**
- AppIndicator::new-icon:
- @arg0: The #AppIndicator object
-
- Signaled when there is a new icon set for the
- object.
- */
- signals[NEW_ICON] = g_signal_new (APP_INDICATOR_SIGNAL_NEW_ICON,
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (AppIndicatorClass, new_icon),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0, G_TYPE_NONE);
-
- /**
- AppIndicator::new-attention-icon:
- @arg0: The #AppIndicator object
-
- Signaled when there is a new attention icon set for the
- object.
- */
- signals[NEW_ATTENTION_ICON] = g_signal_new (APP_INDICATOR_SIGNAL_NEW_ATTENTION_ICON,
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (AppIndicatorClass, new_attention_icon),
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0, G_TYPE_NONE);
-
- /**
- AppIndicator::new-status:
- @arg0: The #AppIndicator object
- @arg1: The string value of the #AppIndicatorStatus enum.
-
- Signaled when the status of the indicator changes.
- */
- signals[NEW_STATUS] = g_signal_new (APP_INDICATOR_SIGNAL_NEW_STATUS,
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (AppIndicatorClass, new_status),
- NULL, NULL,
- g_cclosure_marshal_VOID__STRING,
- G_TYPE_NONE, 1,
- G_TYPE_STRING);
-
- /**
- AppIndicator::connection-changed:
- @arg0: The #AppIndicator object
- @arg1: Whether we're connected or not
-
- Signaled when we connect to a watcher, or when it drops
- away.
- */
- signals[CONNECTION_CHANGED] = g_signal_new (APP_INDICATOR_SIGNAL_CONNECTION_CHANGED,
- G_TYPE_FROM_CLASS(klass),
- G_SIGNAL_RUN_LAST,
- G_STRUCT_OFFSET (AppIndicatorClass, connection_changed),
- NULL, NULL,
- g_cclosure_marshal_VOID__BOOLEAN,
- G_TYPE_NONE, 1, G_TYPE_BOOLEAN, G_TYPE_NONE);
-
- /* Initialize the object as a DBus type */
- dbus_g_object_type_install_info(APP_INDICATOR_TYPE,
- &dbus_glib__notification_item_server_object_info);
-
- return;
-}
-
-static void
-app_indicator_init (AppIndicator *self)
-{
- AppIndicatorPrivate * priv = APP_INDICATOR_GET_PRIVATE(self);
-
- priv->id = NULL;
- priv->clean_id = NULL;
- priv->category = APP_INDICATOR_CATEGORY_OTHER;
- priv->status = APP_INDICATOR_STATUS_PASSIVE;
- priv->icon_name = NULL;
- priv->attention_icon_name = NULL;
- priv->icon_path = NULL;
- priv->menu = NULL;
- priv->menuservice = NULL;
-
- priv->watcher_proxy = NULL;
- priv->connection = NULL;
- priv->dbus_proxy = NULL;
-
- priv->status_icon = NULL;
- priv->fallback_timer = 0;
-
- /* Put the object on DBus */
- GError * error = NULL;
- priv->connection = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
- if (error != NULL) {
- g_error("Unable to connect to the session bus when creating application indicator: %s", error->message);
- g_error_free(error);
- return;
- }
- dbus_g_connection_ref(priv->connection);
-
- g_signal_connect(G_OBJECT(gtk_icon_theme_get_default()),
- "changed", G_CALLBACK(theme_changed_cb), self);
-
- self->priv = priv;
-
- return;
-}
-
-/* Free all objects, make sure that all the dbus
- signals are sent out before we shut this down. */
-static void
-app_indicator_dispose (GObject *object)
-{
- AppIndicator *self = APP_INDICATOR (object);
- AppIndicatorPrivate *priv = self->priv;
-
- if (priv->status != APP_INDICATOR_STATUS_PASSIVE) {
- app_indicator_set_status(self, APP_INDICATOR_STATUS_PASSIVE);
- }
-
- if (priv->status_icon != NULL) {
- AppIndicatorClass * class = APP_INDICATOR_GET_CLASS(object);
- if (class->unfallback != NULL) {
- class->unfallback(self, priv->status_icon);
- }
- priv->status_icon = NULL;
- }
-
- if (priv->fallback_timer != 0) {
- g_source_remove(priv->fallback_timer);
- priv->fallback_timer = 0;
- }
-
- if (priv->menu != NULL) {
- g_signal_handlers_disconnect_by_func (G_OBJECT (priv->menu),
- client_menu_changed,
- self);
- g_object_unref(G_OBJECT(priv->menu));
- priv->menu = NULL;
- }
-
- if (priv->menuservice != NULL) {
- g_object_unref (priv->menuservice);
- }
-
- if (priv->dbus_proxy != NULL) {
- g_object_unref(G_OBJECT(priv->dbus_proxy));
- priv->dbus_proxy = NULL;
- }
-
- if (priv->watcher_proxy != NULL) {
- dbus_g_connection_flush(priv->connection);
- g_signal_handlers_disconnect_by_func(G_OBJECT(priv->watcher_proxy), watcher_proxy_destroyed, self);
- g_object_unref(G_OBJECT(priv->watcher_proxy));
- priv->watcher_proxy = NULL;
-
- /* Emit the AppIndicator::connection-changed signal*/
- g_signal_emit (self, signals[CONNECTION_CHANGED], 0, FALSE);
- }
-
- if (priv->connection != NULL) {
- dbus_g_connection_unref(priv->connection);
- priv->connection = NULL;
- }
-
- G_OBJECT_CLASS (app_indicator_parent_class)->dispose (object);
- return;
-}
-
-/* Free all of the memory that we could be using in
- the object. */
-static void
-app_indicator_finalize (GObject *object)
-{
- AppIndicator * self = APP_INDICATOR(object);
- AppIndicatorPrivate *priv = self->priv;
-
- if (priv->status != APP_INDICATOR_STATUS_PASSIVE) {
- g_warning("Finalizing Application Status with the status set to: %d", priv->status);
- }
-
- if (priv->id != NULL) {
- g_free(priv->id);
- priv->id = NULL;
- }
-
- if (priv->clean_id != NULL) {
- g_free(priv->clean_id);
- priv->clean_id = NULL;
- }
-
- if (priv->icon_name != NULL) {
- g_free(priv->icon_name);
- priv->icon_name = NULL;
- }
-
- if (priv->attention_icon_name != NULL) {
- g_free(priv->attention_icon_name);
- priv->attention_icon_name = NULL;
- }
-
- if (priv->icon_path != NULL) {
- g_free(priv->icon_path);
- priv->icon_path = NULL;
- }
-
- G_OBJECT_CLASS (app_indicator_parent_class)->finalize (object);
- return;
-}
-
-#define WARN_BAD_TYPE(prop, value) g_warning("Can not work with property '%s' with value of type '%s'.", prop, G_VALUE_TYPE_NAME(value))
-
-/* Set some properties */
-static void
-app_indicator_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec)
-{
- AppIndicator *self = APP_INDICATOR (object);
- AppIndicatorPrivate *priv = self->priv;
- GEnumValue *enum_val;
-
- switch (prop_id) {
- case PROP_ID:
- if (priv->id != NULL) {
- g_warning ("Resetting ID value when I already had a value of: %s", priv->id);
- break;
- }
-
- priv->id = g_strdup (g_value_get_string (value));
-
- priv->clean_id = g_strdup(priv->id);
- gchar * cleaner;
- for (cleaner = priv->clean_id; *cleaner != '\0'; cleaner++) {
- if (!g_ascii_isalnum(*cleaner)) {
- *cleaner = '_';
- }
- }
-
- check_connect (self);
- break;
-
- case PROP_CATEGORY:
- enum_val = g_enum_get_value_by_nick ((GEnumClass *) g_type_class_ref (APP_INDICATOR_TYPE_INDICATOR_CATEGORY),
- g_value_get_string (value));
-
- if (priv->category != enum_val->value)
- {
- priv->category = enum_val->value;
- }
-
- break;
-
- case PROP_STATUS:
- enum_val = g_enum_get_value_by_nick ((GEnumClass *) g_type_class_ref (APP_INDICATOR_TYPE_INDICATOR_STATUS),
- g_value_get_string (value));
-
- app_indicator_set_status (APP_INDICATOR (object),
- enum_val->value);
- break;
-
- case PROP_ICON_NAME:
- app_indicator_set_icon (APP_INDICATOR (object),
- g_value_get_string (value));
- check_connect (self);
- break;
-
- case PROP_ATTENTION_ICON_NAME:
- app_indicator_set_attention_icon (APP_INDICATOR (object),
- g_value_get_string (value));
- break;
-
- case PROP_ICON_THEME_PATH:
- if (priv->icon_path != NULL) {
- g_free(priv->icon_path);
- }
- priv->icon_path = g_value_dup_string(value);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-
- return;
-}
-
-/* Function to fill our value with the property it's requesting. */
-static void
-app_indicator_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec)
-{
- AppIndicator *self = APP_INDICATOR (object);
- AppIndicatorPrivate *priv = self->priv;
- GEnumValue *enum_value;
-
- switch (prop_id) {
- case PROP_ID:
- g_value_set_string (value, priv->id);
- break;
-
- case PROP_CATEGORY:
- enum_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (APP_INDICATOR_TYPE_INDICATOR_CATEGORY), priv->category);
- g_value_set_string (value, enum_value->value_nick);
- break;
-
- case PROP_STATUS:
- enum_value = g_enum_get_value ((GEnumClass *) g_type_class_ref (APP_INDICATOR_TYPE_INDICATOR_STATUS), priv->status);
- g_value_set_string (value, enum_value->value_nick);
- break;
-
- case PROP_ICON_NAME:
- g_value_set_string (value, priv->icon_name);
- break;
-
- case PROP_ATTENTION_ICON_NAME:
- g_value_set_string (value, priv->attention_icon_name);
- break;
-
- case PROP_ICON_THEME_PATH:
- g_value_set_string (value, priv->icon_path);
- break;
-
- case PROP_MENU:
- if (priv->menuservice != NULL) {
- GValue strval = { 0 };
- g_value_init(&strval, G_TYPE_STRING);
- g_object_get_property (G_OBJECT (priv->menuservice), DBUSMENU_SERVER_PROP_DBUS_OBJECT, &strval);
- g_value_set_boxed(value, g_value_get_string(&strval));
- g_value_unset(&strval);
- }
- break;
-
- case PROP_CONNECTED:
- g_value_set_boolean (value, priv->watcher_proxy != NULL ? TRUE : FALSE);
- break;
-
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
-
- return;
-}
-
-/* This function is used to see if we have enough information to
- connect to things. If we do, and we're not connected, it
- connects for us. */
-static void
-check_connect (AppIndicator *self)
-{
- AppIndicatorPrivate *priv = self->priv;
-
- /* We're alreadying connecting or trying to connect. */
- if (priv->watcher_proxy != NULL) return;
-
- /* Do we have enough information? */
- if (priv->menu == NULL) return;
- if (priv->icon_name == NULL) return;
- if (priv->id == NULL) return;
-
- gchar * path = g_strdup_printf(DEFAULT_ITEM_PATH "/%s", priv->clean_id);
-
- dbus_g_connection_register_g_object(priv->connection,
- path,
- G_OBJECT(self));
-
- GError * error = NULL;
- priv->watcher_proxy = dbus_g_proxy_new_for_name_owner(priv->connection,
- NOTIFICATION_WATCHER_DBUS_ADDR,
- NOTIFICATION_WATCHER_DBUS_OBJ,
- NOTIFICATION_WATCHER_DBUS_IFACE,
- &error);
- if (error != NULL) {
- /* Unable to get proxy, but we're handling that now so
- it's not a warning anymore. */
- g_error_free(error);
- dbus_g_connection_unregister_g_object(priv->connection,
- G_OBJECT(self));
- start_fallback_timer(self, FALSE);
- g_free(path);
- return;
- }
-
- g_signal_connect(G_OBJECT(priv->watcher_proxy), "destroy", G_CALLBACK(watcher_proxy_destroyed), self);
- org_kde_StatusNotifierWatcher_register_status_notifier_item_async(priv->watcher_proxy, path, register_service_cb, self);
- g_free(path);
-
- /* Emit the AppIndicator::connection-changed signal*/
- g_signal_emit (self, signals[CONNECTION_CHANGED], 0, TRUE);
-
- return;
-}
-
-/* A function that gets called when the watcher dies. Like
- dies dies. Not our friend anymore. */
-static void
-watcher_proxy_destroyed (GObject * object, gpointer data)
-{
- AppIndicator * self = APP_INDICATOR(data);
- g_return_if_fail(self != NULL);
-
- dbus_g_connection_unregister_g_object(self->priv->connection,
- G_OBJECT(self));
- self->priv->watcher_proxy = NULL;
-
- /* Emit the AppIndicator::connection-changed signal*/
- g_signal_emit (self, signals[CONNECTION_CHANGED], 0, FALSE);
-
- start_fallback_timer(self, FALSE);
- return;
-}
-
-/* Responce from the DBus command to register a service
- with a NotificationWatcher. */
-static void
-register_service_cb (DBusGProxy * proxy, GError * error, gpointer data)
-{
- g_return_if_fail(IS_APP_INDICATOR(data));
- AppIndicatorPrivate * priv = APP_INDICATOR(data)->priv;
-
- if (error != NULL) {
- /* They didn't respond, ewww. Not sure what they could
- be doing */
- g_warning("Unable to connect to the Notification Watcher: %s", error->message);
- dbus_g_connection_unregister_g_object(priv->connection,
- G_OBJECT(data));
- g_object_unref(G_OBJECT(priv->watcher_proxy));
- priv->watcher_proxy = NULL;
- start_fallback_timer(APP_INDICATOR(data), TRUE);
- }
-
- if (priv->status_icon) {
- AppIndicatorClass * class = APP_INDICATOR_GET_CLASS(data);
- if (class->unfallback != NULL) {
- class->unfallback(APP_INDICATOR(data), priv->status_icon);
- priv->status_icon = NULL;
- }
- }
-
- return;
-}
-
-/* A helper function to get the nick out of a given
- category enum value. */
-static const gchar *
-category_from_enum (AppIndicatorCategory category)
-{
- GEnumValue *value;
-
- value = g_enum_get_value ((GEnumClass *)g_type_class_ref (APP_INDICATOR_TYPE_INDICATOR_CATEGORY), category);
- return value->value_nick;
-}
-
-/* Watching the dbus owner change events to see if someone
- we care about pops up! */
-static void
-dbus_owner_change (DBusGProxy * proxy, const gchar * name, const gchar * prev, const gchar * new, gpointer data)
-{
- if (new == NULL || new[0] == '\0') {
- /* We only care about folks coming on the bus. Exit quickly otherwise. */
- return;
- }
-
- if (g_strcmp0(name, NOTIFICATION_WATCHER_DBUS_ADDR)) {
- /* We only care about this address, reject all others. */
- return;
- }
-
- /* Woot, there's a new notification watcher in town. */
-
- AppIndicatorPrivate * priv = APP_INDICATOR_GET_PRIVATE(data);
-
- if (priv->fallback_timer != 0) {
- /* Stop a timer */
- g_source_remove(priv->fallback_timer);
-
- /* Stop listening to bus events */
- g_object_unref(G_OBJECT(priv->dbus_proxy));
- priv->dbus_proxy = NULL;
- }
-
- /* Let's start from the very beginning */
- check_connect(APP_INDICATOR(data));
-
- return;
-}
-
-/* This is an idle function to create the proxy. This is mostly
- because start_fallback_timer can get called in the distruction
- of a proxy and thus the proxy manager gets confused when creating
- a new proxy as part of destroying an old one. This function being
- on idle means that we'll just do it outside of the same stack where
- the previous proxy is being destroyed. */
-static gboolean
-setup_name_owner_proxy (gpointer data)
-{
- g_return_val_if_fail(IS_APP_INDICATOR(data), FALSE);
- AppIndicatorPrivate * priv = APP_INDICATOR(data)->priv;
-
- if (priv->dbus_proxy == NULL) {
- priv->dbus_proxy = dbus_g_proxy_new_for_name(priv->connection,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS);
- dbus_g_proxy_add_signal(priv->dbus_proxy, "NameOwnerChanged",
- G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING,
- G_TYPE_INVALID);
- dbus_g_proxy_connect_signal(priv->dbus_proxy, "NameOwnerChanged",
- G_CALLBACK(dbus_owner_change), data, NULL);
- }
-
- return FALSE;
-}
-
-/* A function that will start the fallback timer if it's not
- already started. It sets up the DBus watcher to see if
- there is a change. Also, provides an override mode for cases
- where it's unlikely that a timer will help anything. */
-static void
-start_fallback_timer (AppIndicator * self, gboolean disable_timeout)
-{
- g_return_if_fail(IS_APP_INDICATOR(self));
- AppIndicatorPrivate * priv = APP_INDICATOR(self)->priv;
-
- if (priv->fallback_timer != 0) {
- /* The timer is set, let's just be happy with the one
- we've already got running */
- return;
- }
-
- if (priv->status_icon != NULL) {
- /* We're already fallen back. Let's not do it again. */
- return;
- }
-
- if (priv->dbus_proxy == NULL) {
- /* NOTE: Read the comment on setup_name_owner_proxy */
- g_idle_add(setup_name_owner_proxy, self);
- }
-
- if (disable_timeout) {
- fallback_timer_expire(self);
- } else {
- priv->fallback_timer = g_timeout_add(DEFAULT_FALLBACK_TIMER, fallback_timer_expire, self);
- }
-
- return;
-}
-
-/* A function that gets executed when we want to change the
- state of the fallback. */
-static gboolean
-fallback_timer_expire (gpointer data)
-{
- g_return_val_if_fail(IS_APP_INDICATOR(data), FALSE);
-
- AppIndicatorPrivate * priv = APP_INDICATOR(data)->priv;
- AppIndicatorClass * class = APP_INDICATOR_GET_CLASS(data);
-
- if (priv->status_icon == NULL) {
- if (class->fallback != NULL) {
- priv->status_icon = class->fallback(APP_INDICATOR(data));
- }
- } else {
- if (class->unfallback != NULL) {
- class->unfallback(APP_INDICATOR(data), priv->status_icon);
- priv->status_icon = NULL;
- } else {
- g_warning("No 'unfallback' function but the 'fallback' function returned a non-NULL result.");
- }
- }
-
- priv->fallback_timer = 0;
- return FALSE;
-}
-
-/* emit a NEW_ICON signal in response for the theme change */
-static void
-theme_changed_cb (GtkIconTheme * theme, gpointer user_data)
-{
- g_signal_emit (user_data, signals[NEW_ICON], 0, TRUE);
-}
-
-/* Creates a StatusIcon that can be used when the application
- indicator area isn't available. */
-static GtkStatusIcon *
-fallback (AppIndicator * self)
-{
- GtkStatusIcon * icon = gtk_status_icon_new();
-
- gtk_status_icon_set_title(icon, app_indicator_get_id(self));
-
- g_signal_connect(G_OBJECT(self), APP_INDICATOR_SIGNAL_NEW_STATUS,
- G_CALLBACK(status_icon_status_wrapper), icon);
- g_signal_connect(G_OBJECT(self), APP_INDICATOR_SIGNAL_NEW_ICON,
- G_CALLBACK(status_icon_changes), icon);
- g_signal_connect(G_OBJECT(self), APP_INDICATOR_SIGNAL_NEW_ATTENTION_ICON,
- G_CALLBACK(status_icon_changes), icon);
-
- status_icon_changes(self, icon);
-
- g_signal_connect(G_OBJECT(icon), "activate", G_CALLBACK(status_icon_activate), self);
-
- return icon;
-}
-
-/* A wrapper as the status update prototype is a little
- bit different, but we want to handle it the same. */
-static void
-status_icon_status_wrapper (AppIndicator * self, const gchar * status, gpointer data)
-{
- return status_icon_changes(self, data);
-}
-
-/* This tracks changes to either the status or the icons
- that are associated with the app indicator */
-static void
-status_icon_changes (AppIndicator * self, gpointer data)
-{
- GtkStatusIcon * icon = GTK_STATUS_ICON(data);
- GIcon *themed_icon = NULL;
- gchar *longname = NULL;
-
- switch (app_indicator_get_status(self)) {
- case APP_INDICATOR_STATUS_PASSIVE:
- longname = append_panel_icon_suffix(app_indicator_get_icon(self));
- themed_icon = g_themed_icon_new_with_default_fallbacks (longname);
- gtk_status_icon_set_visible(icon, FALSE);
- gtk_status_icon_set_from_gicon(icon, themed_icon);
- break;
- case APP_INDICATOR_STATUS_ACTIVE:
- longname = append_panel_icon_suffix(app_indicator_get_icon(self));
- themed_icon = g_themed_icon_new_with_default_fallbacks (longname);
- gtk_status_icon_set_from_gicon(icon, themed_icon);
- gtk_status_icon_set_visible(icon, TRUE);
- break;
- case APP_INDICATOR_STATUS_ATTENTION:
- longname = append_panel_icon_suffix(app_indicator_get_attention_icon(self));
- themed_icon = g_themed_icon_new_with_default_fallbacks (longname);
- gtk_status_icon_set_from_gicon(icon, themed_icon);
- gtk_status_icon_set_visible(icon, TRUE);
- break;
- };
-
- if (themed_icon) {
- g_object_unref (themed_icon);
- }
-
- if (longname) {
- g_free(longname);
- }
-
- return;
-}
-
-/* Handles the activate action by the status icon by showing
- the menu in a popup. */
-static void
-status_icon_activate (GtkStatusIcon * icon, gpointer data)
-{
- GtkMenu * menu = app_indicator_get_menu(APP_INDICATOR(data));
- if (menu == NULL)
- return;
-
- gtk_menu_popup(menu,
- NULL, /* Parent Menu */
- NULL, /* Parent item */
- gtk_status_icon_position_menu,
- icon,
- 1, /* Button */
- gtk_get_current_event_time());
-
- return;
-}
-
-/* Removes the status icon as the application indicator area
- is now up and running again. */
-static void
-unfallback (AppIndicator * self, GtkStatusIcon * status_icon)
-{
- g_signal_handlers_disconnect_by_func(G_OBJECT(self), status_icon_status_wrapper, status_icon);
- g_signal_handlers_disconnect_by_func(G_OBJECT(self), status_icon_changes, status_icon);
- gtk_status_icon_set_visible(status_icon, FALSE);
- g_object_unref(G_OBJECT(status_icon));
- return;
-}
-
-/* A helper function that appends PANEL_ICON_SUFFIX to the given icon name
- if it's missing. */
-static gchar *
-append_panel_icon_suffix (const gchar *icon_name)
-{
- gchar * long_name = NULL;
-
- if (!g_str_has_suffix (icon_name, PANEL_ICON_SUFFIX)) {
- long_name =
- g_strdup_printf("%s-%s", icon_name, PANEL_ICON_SUFFIX);
- } else {
- long_name = g_strdup (icon_name);
- }
-
- return long_name;
-}
-
-
-/* ************************* */
-/* Public Functions */
-/* ************************* */
-
-/**
- app_indicator_new:
- @id: The unique id of the indicator to create.
- @icon_name: The icon name for this indicator
- @category: The category of indicator.
-
- Creates a new #AppIndicator setting the properties:
- #AppIndicator::id with @id, #AppIndicator::category
- with @category and #AppIndicator::icon-name with
- @icon_name.
-
- Return value: A pointer to a new #AppIndicator object.
- */
-AppIndicator *
-app_indicator_new (const gchar *id,
- const gchar *icon_name,
- AppIndicatorCategory category)
-{
- AppIndicator *indicator = g_object_new (APP_INDICATOR_TYPE,
- PROP_ID_S, id,
- PROP_CATEGORY_S, category_from_enum (category),
- PROP_ICON_NAME_S, icon_name,
- NULL);
-
- return indicator;
-}
-
-/**
- app_indicator_new_with_path:
- @id: The unique id of the indicator to create.
- @icon_name: The icon name for this indicator
- @category: The category of indicator.
- @icon_path: A custom path for finding icons.
-
- Creates a new #AppIndicator setting the properties:
- #AppIndicator::id with @id, #AppIndicator::category
- with @category, #AppIndicator::icon-name with
- @icon_name and #AppIndicator::icon-theme-path with @icon_path.
-
- Return value: A pointer to a new #AppIndicator object.
- */
-AppIndicator *
-app_indicator_new_with_path (const gchar *id,
- const gchar *icon_name,
- AppIndicatorCategory category,
- const gchar *icon_path)
-{
- AppIndicator *indicator = g_object_new (APP_INDICATOR_TYPE,
- PROP_ID_S, id,
- PROP_CATEGORY_S, category_from_enum (category),
- PROP_ICON_NAME_S, icon_name,
- PROP_ICON_THEME_PATH_S, icon_path,
- NULL);
-
- return indicator;
-}
-
-/**
- app_indicator_get_type:
-
- Generates or returns the unique #GType for #AppIndicator.
-
- Return value: A unique #GType for #AppIndicator objects.
-*/
-
-/**
- app_indicator_set_status:
- @self: The #AppIndicator object to use
- @status: The status to set for this indicator
-
- Wrapper function for property #AppIndicator::status.
-*/
-void
-app_indicator_set_status (AppIndicator *self, AppIndicatorStatus status)
-{
- g_return_if_fail (IS_APP_INDICATOR (self));
-
- if (self->priv->status != status)
- {
- GEnumValue *value = g_enum_get_value ((GEnumClass *) g_type_class_ref (APP_INDICATOR_TYPE_INDICATOR_STATUS), status);
-
- self->priv->status = status;
- g_signal_emit (self, signals[NEW_STATUS], 0, value->value_nick);
- }
-}
-
-/**
- app_indicator_set_attention_icon:
- @self: The #AppIndicator object to use
- @icon_name: The name of the attention icon to set for this indicator
-
- Wrapper function for property #AppIndicator::attention-icon.
-*/
-void
-app_indicator_set_attention_icon (AppIndicator *self, const gchar *icon_name)
-{
- g_return_if_fail (IS_APP_INDICATOR (self));
- g_return_if_fail (icon_name != NULL);
-
- if (g_strcmp0 (self->priv->attention_icon_name, icon_name) != 0)
- {
- if (self->priv->attention_icon_name)
- g_free (self->priv->attention_icon_name);
-
- self->priv->attention_icon_name = g_strdup(icon_name);
-
- g_signal_emit (self, signals[NEW_ATTENTION_ICON], 0, TRUE);
- }
-
- return;
-}
-
-/**
- app_indicator_set_icon:
- @self: The #AppIndicator object to use
- @icon_name: The icon name to set.
-
- Sets the default icon to use when the status is active but
- not set to attention. In most cases, this should be the
- application icon for the program.
-**/
-void
-app_indicator_set_icon (AppIndicator *self, const gchar *icon_name)
-{
- g_return_if_fail (IS_APP_INDICATOR (self));
- g_return_if_fail (icon_name != NULL);
-
- if (g_strcmp0 (self->priv->icon_name, icon_name) != 0)
- {
- if (self->priv->icon_name)
- g_free (self->priv->icon_name);
-
- self->priv->icon_name = g_strdup(icon_name);
-
- g_signal_emit (self, signals[NEW_ICON], 0, TRUE);
- }
-
- return;
-}
-
-static void
-activate_menuitem (DbusmenuMenuitem *mi, guint timestamp, gpointer user_data)
-{
- GtkWidget *widget = (GtkWidget *)user_data;
-
- gtk_menu_item_activate (GTK_MENU_ITEM (widget));
-}
-
-static void
-widget_toggled (GtkWidget *widget, DbusmenuMenuitem *mi)
-{
- dbusmenu_menuitem_property_set_int (mi,
- DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
- gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (widget)) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
-}
-
-static void
-menuitem_iterate (GtkWidget *widget,
- gpointer data)
-{
- if (GTK_IS_LABEL (widget))
- {
- DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
-
- dbusmenu_menuitem_property_set (child,
- DBUSMENU_MENUITEM_PROP_LABEL,
- gtk_label_get_text (GTK_LABEL (widget)));
- }
-}
-
-static gboolean
-should_show_image (GtkImage *image)
-{
- GtkWidget *item;
-
- item = gtk_widget_get_ancestor (GTK_WIDGET (image),
- GTK_TYPE_IMAGE_MENU_ITEM);
-
- if (item)
- {
- GtkSettings *settings;
- gboolean gtk_menu_images;
-
- settings = gtk_widget_get_settings (item);
-
- g_object_get (settings, "gtk-menu-images", >k_menu_images, NULL);
-
- if (gtk_menu_images)
- return TRUE;
-
- return gtk_image_menu_item_get_always_show_image (GTK_IMAGE_MENU_ITEM (item));
- }
-
- return FALSE;
-}
-
-static void
-update_icon_name (DbusmenuMenuitem *menuitem,
- GtkImage *image)
-{
- if (gtk_image_get_storage_type (image) != GTK_IMAGE_ICON_NAME)
- return;
-
- if (should_show_image (image))
- dbusmenu_menuitem_property_set (menuitem,
- DBUSMENU_MENUITEM_PROP_ICON_NAME,
- image->data.name.icon_name);
- else
- dbusmenu_menuitem_property_remove (menuitem,
- DBUSMENU_MENUITEM_PROP_ICON_NAME);
-}
-
-/* return value specifies whether the label is set or not */
-static gboolean
-update_stock_item (DbusmenuMenuitem *menuitem,
- GtkImage *image)
-{
- GtkStockItem stock;
-
- if (gtk_image_get_storage_type (image) != GTK_IMAGE_STOCK)
- return FALSE;
-
- gtk_stock_lookup (image->data.stock.stock_id, &stock);
-
- if (should_show_image (image))
- dbusmenu_menuitem_property_set (menuitem,
- DBUSMENU_MENUITEM_PROP_ICON_NAME,
- image->data.stock.stock_id);
- else
- dbusmenu_menuitem_property_remove (menuitem,
- DBUSMENU_MENUITEM_PROP_ICON_NAME);
-
- const gchar * label = dbusmenu_menuitem_property_get (menuitem,
- DBUSMENU_MENUITEM_PROP_LABEL);
-
- if (stock.label != NULL && label != NULL)
- {
- dbusmenu_menuitem_property_set (menuitem,
- DBUSMENU_MENUITEM_PROP_LABEL,
- stock.label);
-
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-image_notify_cb (GtkWidget *widget,
- GParamSpec *pspec,
- gpointer data)
-{
- DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
- GtkImage *image = GTK_IMAGE (widget);
-
- if (pspec->name == g_intern_static_string ("stock"))
- {
- update_stock_item (child, image);
- }
- else if (pspec->name == g_intern_static_string ("icon-name"))
- {
- update_icon_name (child, image);
- }
-}
-
-static void
-widget_notify_cb (GtkWidget *widget,
- GParamSpec *pspec,
- gpointer data)
-{
- DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
-
- if (pspec->name == g_intern_static_string ("sensitive"))
- {
- dbusmenu_menuitem_property_set_bool (child,
- DBUSMENU_MENUITEM_PROP_ENABLED,
- GTK_WIDGET_IS_SENSITIVE (widget));
- }
- else if (pspec->name == g_intern_static_string ("label"))
- {
- dbusmenu_menuitem_property_set (child,
- DBUSMENU_MENUITEM_PROP_LABEL,
- gtk_menu_item_get_label (GTK_MENU_ITEM (widget)));
- }
- else if (pspec->name == g_intern_static_string ("visible"))
- {
- dbusmenu_menuitem_property_set_bool (child,
- DBUSMENU_MENUITEM_PROP_VISIBLE,
- gtk_widget_get_visible (widget));
- }
-}
-
-static void
-action_notify_cb (GtkAction *action,
- GParamSpec *pspec,
- gpointer data)
-{
- DbusmenuMenuitem *child = (DbusmenuMenuitem *)data;
-
- if (pspec->name == g_intern_static_string ("active"))
- {
- dbusmenu_menuitem_property_set_bool (child,
- DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
- gtk_toggle_action_get_active (GTK_TOGGLE_ACTION (action)));
- }
-
- if (pspec->name == g_intern_static_string ("label"))
- {
- dbusmenu_menuitem_property_set (child,
- DBUSMENU_MENUITEM_PROP_LABEL,
- gtk_action_get_label (action));
- }
-}
-
-static void
-container_iterate (GtkWidget *widget,
- gpointer data)
-{
- DbusmenuMenuitem *root = (DbusmenuMenuitem *)data;
- DbusmenuMenuitem *child;
- GtkWidget *submenu = NULL;
- const gchar *label = NULL;
- gboolean label_set = FALSE;
-
- if (GTK_IS_TEAROFF_MENU_ITEM(widget)) {
- return;
- }
-
- child = dbusmenu_menuitem_new ();
-
- if (GTK_IS_SEPARATOR_MENU_ITEM (widget))
- {
- dbusmenu_menuitem_property_set (child,
- "type",
- DBUSMENU_CLIENT_TYPES_SEPARATOR);
- }
- else
- {
- if (GTK_IS_CHECK_MENU_ITEM (widget))
- {
- GtkCheckMenuItem *check;
-
- check = GTK_CHECK_MENU_ITEM (widget);
- label = gtk_menu_item_get_label (GTK_MENU_ITEM (widget));
-
- dbusmenu_menuitem_property_set (child,
- DBUSMENU_MENUITEM_PROP_TOGGLE_TYPE,
- GTK_IS_RADIO_MENU_ITEM (widget) ? DBUSMENU_MENUITEM_TOGGLE_RADIO : DBUSMENU_MENUITEM_TOGGLE_CHECK);
-
- dbusmenu_menuitem_property_set (child,
- DBUSMENU_MENUITEM_PROP_LABEL,
- label);
-
- label_set = TRUE;
-
- dbusmenu_menuitem_property_set_int (child,
- DBUSMENU_MENUITEM_PROP_TOGGLE_STATE,
- gtk_check_menu_item_get_active (check) ? DBUSMENU_MENUITEM_TOGGLE_STATE_CHECKED : DBUSMENU_MENUITEM_TOGGLE_STATE_UNCHECKED);
-
- g_signal_connect (widget,
- "toggled",
- G_CALLBACK (widget_toggled),
- child);
- }
- else if (GTK_IS_IMAGE_MENU_ITEM (widget))
- {
- GtkWidget *image;
- GtkImageType image_type;
-
- image = gtk_image_menu_item_get_image (GTK_IMAGE_MENU_ITEM (widget));
- image_type = gtk_image_get_storage_type (GTK_IMAGE (image));
-
- g_signal_connect (image,
- "notify",
- G_CALLBACK (image_notify_cb),
- child);
-
- if (image_type == GTK_IMAGE_STOCK)
- {
- label_set = update_stock_item (child, GTK_IMAGE (image));
- }
- else if (image_type == GTK_IMAGE_ICON_NAME)
- {
- update_icon_name (child, GTK_IMAGE (image));
- }
- }
- }
-
- if (!label_set)
- {
- if (label != NULL)
- {
- dbusmenu_menuitem_property_set (child,
- DBUSMENU_MENUITEM_PROP_LABEL,
- label);
- }
- else
- {
- /* find label child widget */
- gtk_container_forall (GTK_CONTAINER (widget),
- menuitem_iterate,
- child);
- }
- }
-
- if (GTK_IS_MENU_ITEM (widget))
- {
- submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget));
- if (submenu != NULL)
- {
- gtk_container_foreach (GTK_CONTAINER (submenu),
- container_iterate,
- child);
- g_signal_connect_object (submenu,
- "add",
- G_CALLBACK (submenu_changed),
- child,
- 0);
- g_signal_connect_object (submenu,
- "remove",
- G_CALLBACK (submenu_changed),
- child,
- 0);
- }
- }
-
- dbusmenu_menuitem_property_set_bool (child,
- DBUSMENU_MENUITEM_PROP_ENABLED,
- GTK_WIDGET_IS_SENSITIVE (widget));
- dbusmenu_menuitem_property_set_bool (child,
- DBUSMENU_MENUITEM_PROP_VISIBLE,
- gtk_widget_get_visible (widget));
-
- g_signal_connect (widget, "notify",
- G_CALLBACK (widget_notify_cb), child);
-
- if (GTK_IS_ACTIVATABLE (widget))
- {
- GtkActivatable *activatable = GTK_ACTIVATABLE (widget);
-
- if (gtk_activatable_get_use_action_appearance (activatable))
- {
- GtkAction *action = gtk_activatable_get_related_action (activatable);
-
- if (action)
- {
- g_signal_connect_object (action, "notify",
- G_CALLBACK (action_notify_cb),
- child,
- G_CONNECT_AFTER);
- }
- }
- }
-
- g_signal_connect (G_OBJECT (child),
- DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
- G_CALLBACK (activate_menuitem), widget);
- dbusmenu_menuitem_child_append (root, child);
-}
-
-static void
-submenu_changed (GtkWidget *widget,
- GtkWidget *child,
- gpointer data)
-{
- DbusmenuMenuitem *root = (DbusmenuMenuitem *)data;
- GList *children, *l;
- children = dbusmenu_menuitem_get_children (root);
-
- for (l = children; l;)
- {
- DbusmenuMenuitem *c = (DbusmenuMenuitem *)l->data;
- l = l->next;
- dbusmenu_menuitem_child_delete (root, c);
- }
-
- gtk_container_foreach (GTK_CONTAINER (widget),
- container_iterate,
- root);
-}
-
-static void
-setup_dbusmenu (AppIndicator *self)
-{
- AppIndicatorPrivate *priv;
- DbusmenuMenuitem *root;
-
- priv = self->priv;
- root = dbusmenu_menuitem_new ();
-
- if (priv->menu)
- {
- gtk_container_foreach (GTK_CONTAINER (priv->menu),
- container_iterate,
- root);
- }
-
- if (priv->menuservice == NULL)
- {
- gchar * path = g_strdup_printf(DEFAULT_ITEM_PATH "/%s/Menu", priv->clean_id);
- priv->menuservice = dbusmenu_server_new (path);
- g_free(path);
- }
-
- dbusmenu_server_set_root (priv->menuservice, root);
-
- return;
-}
-
-static void
-client_menu_changed (GtkWidget *widget,
- GtkWidget *child,
- AppIndicator *indicator)
-{
- setup_dbusmenu (indicator);
-}
-
-/**
- app_indicator_set_menu:
- @self: The #AppIndicator
- @menu: A #GtkMenu to set
-
- Sets the menu that should be shown when the Application Indicator
- is clicked on in the panel. An application indicator will not
- be rendered unless it has a menu.
-**/
-void
-app_indicator_set_menu (AppIndicator *self, GtkMenu *menu)
-{
- AppIndicatorPrivate *priv;
-
- g_return_if_fail (IS_APP_INDICATOR (self));
- g_return_if_fail (GTK_IS_MENU (menu));
- g_return_if_fail (self->priv->clean_id != NULL);
-
- priv = self->priv;
-
- if (priv->menu != NULL)
- {
- g_object_unref (priv->menu);
- }
-
- priv->menu = GTK_WIDGET (menu);
- g_object_ref (priv->menu);
-
- setup_dbusmenu (self);
-
- check_connect (self);
-
- g_signal_connect (menu,
- "add",
- G_CALLBACK (client_menu_changed),
- self);
- g_signal_connect (menu,
- "remove",
- G_CALLBACK (client_menu_changed),
- self);
-}
-
-/**
- app_indicator_get_id:
- @self: The #AppIndicator object to use
-
- Wrapper function for property #AppIndicator::id.
-
- Return value: The current ID
-*/
-const gchar *
-app_indicator_get_id (AppIndicator *self)
-{
- g_return_val_if_fail (IS_APP_INDICATOR (self), NULL);
-
- return self->priv->id;
-}
-
-/**
- app_indicator_get_category:
- @self: The #AppIndicator object to use
-
- Wrapper function for property #AppIndicator::category.
-
- Return value: The current category.
-*/
-AppIndicatorCategory
-app_indicator_get_category (AppIndicator *self)
-{
- g_return_val_if_fail (IS_APP_INDICATOR (self), APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
-
- return self->priv->category;
-}
-
-/**
- app_indicator_get_status:
- @self: The #AppIndicator object to use
-
- Wrapper function for property #AppIndicator::status.
-
- Return value: The current status.
-*/
-AppIndicatorStatus
-app_indicator_get_status (AppIndicator *self)
-{
- g_return_val_if_fail (IS_APP_INDICATOR (self), APP_INDICATOR_STATUS_PASSIVE);
-
- return self->priv->status;
-}
-
-/**
- app_indicator_get_icon:
- @self: The #AppIndicator object to use
-
- Wrapper function for property #AppIndicator::icon-name.
-
- Return value: The current icon name.
-*/
-const gchar *
-app_indicator_get_icon (AppIndicator *self)
-{
- g_return_val_if_fail (IS_APP_INDICATOR (self), NULL);
-
- return self->priv->icon_name;
-}
-
-/**
- app_indicator_get_attention_icon:
- @self: The #AppIndicator object to use
-
- Wrapper function for property #AppIndicator::attention-icon-name.
-
- Return value: The current attention icon name.
-*/
-const gchar *
-app_indicator_get_attention_icon (AppIndicator *self)
-{
- g_return_val_if_fail (IS_APP_INDICATOR (self), NULL);
-
- return self->priv->attention_icon_name;
-}
-
-/**
- app_indicator_get_menu:
- @self: The #AppIndicator object to use
-
- Gets the menu being used for this application indicator.
-
- Return value: A menu object or #NULL if one hasn't been set.
-*/
-GtkMenu *
-app_indicator_get_menu (AppIndicator *self)
-{
- AppIndicatorPrivate *priv;
-
- g_return_val_if_fail (IS_APP_INDICATOR (self), NULL);
-
- priv = self->priv;
-
- return GTK_MENU(priv->menu);
-}
diff --git a/src/libappindicator/app-indicator.h b/src/libappindicator/app-indicator.h
deleted file mode 100644
index 549ab35..0000000
--- a/src/libappindicator/app-indicator.h
+++ /dev/null
@@ -1,257 +0,0 @@
-/*
-An object to represent the application as an application indicator
-in the system panel.
-
-Copyright 2009 Canonical Ltd.
-
-Authors:
- Ted Gould
- Cody Russell
-
-This program is free software: you can redistribute it and/or modify it
-under the terms of either or both of the following licenses:
-
-1) the GNU Lesser General Public License version 3, as published by the
- Free Software Foundation; and/or
-2) the GNU Lesser General Public License version 2.1, as published by
- the Free Software Foundation.
-
-This program is distributed in the hope that it will be useful, but
-WITHOUT ANY WARRANTY; without even the implied warranties of
-MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
-PURPOSE. See the applicable version of the GNU Lesser General Public
-License for more details.
-
-You should have received a copy of both the GNU Lesser General Public
-License version 3 and version 2.1 along with this program. If not, see
-
-*/
-
-#ifndef __APP_INDICATOR_H__
-#define __APP_INDICATOR_H__
-
-#include
-
-G_BEGIN_DECLS
-
-/**
- APP_INDICATOR_TYPE:
-
- Get the #GType for a #AppIndicator.
-*/
-/**
- APP_INDICATOR:
- @obj: The object to convert
-
- Safely convert a #GObject into an #AppIndicator.
-*/
-/**
- APP_INDICATOR_CLASS:
- @klass: #GObjectClass based class to convert.
-
- Safely convert a #GObjectClass into a #AppIndicatorClass.
-*/
-/**
- IS_APP_INDICATOR:
- @obj: An #GObject to check
-
- Checks to see if @obj is in the object hierarchy of #AppIndicator.
-*/
-/**
- IS_APP_INDICATOR_CLASS:
- @klass: An #GObjectClass to check
-
- Checks to see if @klass is in the object class hierarchy of #AppIndicatorClass.
-*/
-/**
- APP_INDICATOR_GET_CLASS:
- @obj: A #GObject in the class hierarchy of #AppIndicator.
-
- Gets a pointer to the #AppIndicatorClass for the object @obj.
-*/
-#define APP_INDICATOR_TYPE (app_indicator_get_type ())
-#define APP_INDICATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), APP_INDICATOR_TYPE, AppIndicator))
-#define APP_INDICATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), APP_INDICATOR_TYPE, AppIndicatorClass))
-#define IS_APP_INDICATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), APP_INDICATOR_TYPE))
-#define IS_APP_INDICATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), APP_INDICATOR_TYPE))
-#define APP_INDICATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), APP_INDICATOR_TYPE, AppIndicatorClass))
-
-/**
- APP_INDICATOR_SIGNAL_NEW_ICON:
-
- String identifier for the #AppIndicator::new-icon signal.
-*/
-/**
- APP_INDICATOR_SIGNAL_NEW_ATTENTION_ICON:
-
- String identifier for the #AppIndicator::new-attention-icon signal.
-*/
-/**
- APP_INDICATOR_SIGNAL_NEW_STATUS:
-
- String identifier for the #AppIndicator::new-status signal.
-*/
-/**
- APP_INDICATOR_SIGNAL_CONNECTION_CHANGED:
-
- String identifier for the #AppIndicator::connection-changed signal.
-*/
-#define APP_INDICATOR_SIGNAL_NEW_ICON "new-icon"
-#define APP_INDICATOR_SIGNAL_NEW_ATTENTION_ICON "new-attention-icon"
-#define APP_INDICATOR_SIGNAL_NEW_STATUS "new-status"
-#define APP_INDICATOR_SIGNAL_CONNECTION_CHANGED "connection-changed"
-
-/**
- AppIndicatorCategory:
- @APP_INDICATOR_CATEGORY_APPLICATION_STATUS: The indicator is used to display the status of the application.
- @APP_INDICATOR_CATEGORY_COMMUNICATIONS: The application is used for communication with other people.
- @APP_INDICATOR_CATEGORY_SYSTEM_SERVICES: A system indicator relating to something in the user's system.
- @APP_INDICATOR_CATEGORY_HARDWARE: An indicator relating to the user's hardware.
- @APP_INDICATOR_CATEGORY_OTHER: Something not defined in this enum, please don't use unless you really need it.
-
- The category provides grouping for the indicators so that
- users can find indicators that are similar together.
-*/
-typedef enum { /*< prefix=APP_INDICATOR_CATEGORY >*/
- APP_INDICATOR_CATEGORY_APPLICATION_STATUS,
- APP_INDICATOR_CATEGORY_COMMUNICATIONS,
- APP_INDICATOR_CATEGORY_SYSTEM_SERVICES,
- APP_INDICATOR_CATEGORY_HARDWARE,
- APP_INDICATOR_CATEGORY_OTHER
-} AppIndicatorCategory;
-
-/**
- AppIndicatorStatus:
- @APP_INDICATOR_STATUS_PASSIVE: The indicator should not be shown to the user.
- @APP_INDICATOR_STATUS_ACTIVE: The indicator should be shown in it's default state.
- @APP_INDICATOR_STATUS_ATTENTION: The indicator should show it's attention icon.
-
- These are the states that the indicator can be on in
- the user's panel. The indicator by default starts
- in the state @APP_INDICATOR_STATUS_PASSIVE and can be
- shown by setting it to @APP_INDICATOR_STATUS_ACTIVE.
-*/
-typedef enum { /*< prefix=APP_INDICATOR_STATUS >*/
- APP_INDICATOR_STATUS_PASSIVE,
- APP_INDICATOR_STATUS_ACTIVE,
- APP_INDICATOR_STATUS_ATTENTION
-} AppIndicatorStatus;
-
-typedef struct _AppIndicator AppIndicator;
-typedef struct _AppIndicatorClass AppIndicatorClass;
-typedef struct _AppIndicatorPrivate AppIndicatorPrivate;
-
-/**
- AppIndicatorClass:
- @parent_class: Mia familia
- @new_icon: Slot for #AppIndicator::new-icon.
- @new_attention_icon: Slot for #AppIndicator::new-attention-icon.
- @new_status: Slot for #AppIndicator::new-status.
- @connection_changed: Slot for #AppIndicator::connection-changed.
- @fallback: Function that gets called to make a #GtkStatusIcon when
- there is no Application Indicator area available.
- @unfallback: The function that gets called if an Application
- Indicator area appears after the fallback has been created.
- @app_indicator_reserved_1: Reserved for future use.
- @app_indicator_reserved_2: Reserved for future use.
-
- The signals and external functions that make up the #AppIndicator
- class object.
-*/
-struct _AppIndicatorClass {
- /* Parent */
- GObjectClass parent_class;
-
- /* DBus Signals */
- void (* new_icon) (AppIndicator *indicator,
- gpointer user_data);
- void (* new_attention_icon) (AppIndicator *indicator,
- gpointer user_data);
- void (* new_status) (AppIndicator *indicator,
- const gchar *status,
- gpointer user_data);
-
- /* Local Signals */
- void (* connection_changed) (AppIndicator * indicator,
- gboolean connected,
- gpointer user_data);
-
- /* Overridable Functions */
- GtkStatusIcon * (*fallback) (AppIndicator * indicator);
- void (*unfallback) (AppIndicator * indicator,
- GtkStatusIcon * status_icon);
-
- /* Reserved */
- void (*app_indicator_reserved_1)(void);
- void (*app_indicator_reserved_2)(void);
-};
-
-/**
- AppIndicator:
-
- A application indicator represents the values that are needed to show a
- unique status in the panel for an application. In general, applications
- should try to fit in the other indicators that are available on the
- panel before using this. But, sometimes it is necissary.
-*/
-/* Private fields
- @parent: Parent object.
- @priv: Internal data.
-*/
-struct _AppIndicator {
- /*< Private >*/
- GObject parent;
-
- /*< Private >*/
- AppIndicatorPrivate *priv;
-};
-
-/* GObject Stuff */
-GType app_indicator_get_type (void) G_GNUC_CONST;
-
-AppIndicator *app_indicator_new (const gchar *id,
- const gchar *icon_name,
- AppIndicatorCategory category);
-AppIndicator *app_indicator_new_with_path (const gchar *id,
- const gchar *icon_name,
- AppIndicatorCategory category,
- const gchar *icon_path);
-
-/* Set properties */
-void app_indicator_set_status (AppIndicator *self,
- AppIndicatorStatus status);
-void app_indicator_set_attention_icon (AppIndicator *self,
- const gchar *icon_name);
-void app_indicator_set_menu (AppIndicator *self,
- GtkMenu *menu);
-void app_indicator_set_icon (AppIndicator *self,
- const gchar *icon_name);
-
-/* Get properties */
-const gchar * app_indicator_get_id (AppIndicator *self);
-AppIndicatorCategory app_indicator_get_category (AppIndicator *self);
-AppIndicatorStatus app_indicator_get_status (AppIndicator *self);
-const gchar * app_indicator_get_icon (AppIndicator *self);
-const gchar * app_indicator_get_attention_icon (AppIndicator *self);
-GtkMenu * app_indicator_get_menu (AppIndicator *self);
-
-G_END_DECLS
-
-/**
- SECTION:app-indicator
- @short_description: An object to put application information
- into the panel.
- @stability: Unstable
- @include: libappindicator/app-indicator.h
-
- An application indicator is a way for an application to put
- a menu into the panel on the user's screen. This allows the
- user to interact with the application even though it might
- not be visible to the user at the time. In most cases this
- is not a good solution as there are other ways to inform the
- user. It should only be use if persistence is a desired
- feature for the user (not for your marketing purpose of
- having your logo in the panel).
-*/
-
-#endif
diff --git a/src/libappindicator/appindicator-0.1.pc.in b/src/libappindicator/appindicator-0.1.pc.in
deleted file mode 100644
index b80fded..0000000
--- a/src/libappindicator/appindicator-0.1.pc.in
+++ /dev/null
@@ -1,14 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-bindir=@bindir@
-includedir=@includedir@
-
-Cflags: -I${includedir}/libappindicator-0.1
-Requires: dbusmenu-glib gtk+-2.0
-Libs: -L${libdir} -lappindicator
-
-Name: appindicator-0.1
-Description: Application indicators
-Version: @VERSION@
-
diff --git a/tests/test-libappindicator-dbus-client.c b/tests/test-libappindicator-dbus-client.c
index f5482aa..1500213 100644
--- a/tests/test-libappindicator-dbus-client.c
+++ b/tests/test-libappindicator-dbus-client.c
@@ -25,7 +25,7 @@ with this program. If not, see .
#include
#include
#include
-#include
+#include
#include "test-defines.h"
#include "../src/dbus-shared.h"
diff --git a/tests/test-libappindicator-dbus-server.c b/tests/test-libappindicator-dbus-server.c
index 2d68950..995d49b 100644
--- a/tests/test-libappindicator-dbus-server.c
+++ b/tests/test-libappindicator-dbus-server.c
@@ -24,7 +24,7 @@ with this program. If not, see .
#include
#include
#include
-#include
+#include
#include "test-defines.h"
static GMainLoop * mainloop = NULL;
diff --git a/tests/test-libappindicator-fallback-item.c b/tests/test-libappindicator-fallback-item.c
index 9fd1b45..426b6a6 100644
--- a/tests/test-libappindicator-fallback-item.c
+++ b/tests/test-libappindicator-fallback-item.c
@@ -2,7 +2,7 @@
#include
#include
#include
-#include
+#include
#define TEST_LIBAPPINDICATOR_FALLBACK_ITEM_TYPE (test_libappindicator_fallback_item_get_type ())
#define TEST_LIBAPPINDICATOR_FALLBACK_ITEM(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEST_LIBAPPINDICATOR_FALLBACK_ITEM_TYPE, TestLibappindicatorFallbackItem))
diff --git a/tests/test-libappindicator-status-server.c b/tests/test-libappindicator-status-server.c
index 79b1759..8cd5571 100644
--- a/tests/test-libappindicator-status-server.c
+++ b/tests/test-libappindicator-status-server.c
@@ -25,7 +25,7 @@ with this program. If not, see .
#include
#include
#include
-#include
+#include
static GMainLoop * mainloop = NULL;
static gboolean active = FALSE;
diff --git a/tests/test-libappindicator.c b/tests/test-libappindicator.c
index c987a8f..86879b3 100644
--- a/tests/test-libappindicator.c
+++ b/tests/test-libappindicator.c
@@ -23,7 +23,7 @@ with this program. If not, see .
#include
#include
-#include
+#include
void
test_libappindicator_prop_signals_status_helper (AppIndicator * ci, gchar * status, gboolean * signalactivated)
diff --git a/tests/test-simple-app.c b/tests/test-simple-app.c
index f5957c8..d60d9b9 100644
--- a/tests/test-simple-app.c
+++ b/tests/test-simple-app.c
@@ -24,7 +24,7 @@ with this program. If not, see .
#include
#include
#include
-#include
+#include
static GMainLoop * mainloop = NULL;
--
cgit v1.2.3
From 3ef5fec331863cb0f079a109cd1eaa0410c40b09 Mon Sep 17 00:00:00 2001
From: Ted Gould
Date: Thu, 29 Apr 2010 11:54:42 -0500
Subject: Building the GIR file
---
src/Makefile.am | 34 ++++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/src/Makefile.am b/src/Makefile.am
index d8599d8..a1d018b 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -142,3 +142,37 @@ BUILT_SOURCES += \
CLEANFILES += $(BUILT_SOURCES)
EXTRA_DIST += $(DBUS_SPECS)
+
+#########################
+# GObject Introsepction
+#########################
+
+-include $(INTROSPECTION_MAKEFILE)
+INTROSPECTION_GIRS =
+INTROSPECTION_SCANNER_ARGS = --add-include-path=$(srcdir)
+INTROSPECTION_COMPILER_ARGS = --includedir=$(builddir)
+
+if HAVE_INTROSPECTION
+
+introspection_sources = $(libappindicatorinclude_HEADERS)
+
+AppIndicator-0.1.gir: libappindicator.la
+AppIndicator_0_1_gir_INCLUDES = \
+ GObject-2.0 \
+ Gtk-2.0
+AppIndicator_0_1_gir_CFLAGS = $(INDICATOR_CFLAGS)
+AppIndicator_0_1_gir_LIBS = libappindicator.la
+AppIndicator_0_1_gir_FILES = $(addprefix $(srcdir)/, $(introspection_sources))
+
+INTROSPECTION_GIRS += AppIndicator-0.1.gir
+
+girdir = $(datadir)/gir-1.0
+gir_DATA = $(INTROSPECTION_GIRS)
+
+typelibdir = $(libdir)/girepository-1.0
+typelib_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
+
+CLEANFILES += $(gir_DATA) $(typelib_DATA)
+
+endif
+
--
cgit v1.2.3
From f5c58a84fb15018f8d60347d156f4e1660921791 Mon Sep 17 00:00:00 2001
From: Ted Gould
Date: Thu, 29 Apr 2010 11:58:25 -0500
Subject: Fixing the ignore list.
---
.bzrignore | 16 ++++++++++------
1 file changed, 10 insertions(+), 6 deletions(-)
diff --git a/.bzrignore b/.bzrignore
index 07f160a..134e14f 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -10,8 +10,8 @@ src/notification-watcher-client.h
src/notification-watcher-server.h
src/libappindicator.la
src/libappindicator_la-application-indicator.lo
-src/libappindicatorindicator/application-indicator-enum-types.h
-src/libappindicatorindicator/application-indicator-enum-types.c
+src/application-indicator-enum-types.h
+src/application-indicator-enum-types.c
src/stamp-enum-types
src/libappindicator_la-application-indicator-enum-types.lo
tests/.deps
@@ -41,8 +41,8 @@ src/libappindicator_la-app-indicator.lo
src/libapplication.la
src/libapplication_la-application-service-marshal.lo
src/libapplication_la-indicator-application.lo
-src/libappindicator/app-indicator-enum-types.c
-src/libappindicator/app-indicator-enum-types.h
+src/app-indicator-enum-types.c
+src/app-indicator-enum-types.h
gtk-doc.make
py-compile
bindings/mono/appindicator-sharp-0.1.pc
@@ -85,7 +85,7 @@ docs/reference/version.xml
docs/reference/xml
docs/reference/tmpl/app-indicator.sgml
docs/reference/tmpl/app-indicator.sgml.bak
-src/libappindicator/appindicator-0.1.pc
+src/appindicator-0.1.pc
tests/test-libappindicator-fallback-item
tests/test-libappindicator-fallback-watcher
tests/test-libappindicator-fallback
@@ -95,9 +95,13 @@ tests/test-libappindicator-status-server
bindings/mono/AppIndicator.Test.dll
bindings/mono/libappindicator-api.middle
bindings/mono/examples/IndicatorExample.exe
-src/libappindicator/app-indicator-enum-types.gen.c
+src/app-indicator-enum-types.gen.c
indicator-application-[0-9].[0-9].[0-9].tar.gz
indicator-application-[0-9].[0-9].[0-9].tar.gz.asc
indicator-application-[0-9].[0-9].[0-9][0-9].tar.gz
indicator-application-[0-9].[0-9].[0-9][0-9].tar.gz.asc
m4/gtk-doc.m4
+src/AppIndicator-0.1.gir
+src/AppIndicator-0.1.typelib
+docs/reference/libappindicator-decl.txt.bak
+docs/reference/libappindicator-decl-list.txt.bak
--
cgit v1.2.3
From fae0a61f431325f1f9023026368ec27cb5b2b01a Mon Sep 17 00:00:00 2001
From: Ted Gould
Date: Thu, 29 Apr 2010 12:07:21 -0500
Subject: Now, build us a VAPI!
---
src/Makefile.am | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/src/Makefile.am b/src/Makefile.am
index a1d018b..c2bac63 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -176,3 +176,22 @@ CLEANFILES += $(gir_DATA) $(typelib_DATA)
endif
+#########################
+# VAPI Files
+#########################
+
+if HAVE_INTROSPECTION
+
+vapidir = $(datadir)/vala/vapi
+vapi_DATA = AppIndicator-0.1.vapi
+
+AppIndicator-0.1.vapi: AppIndicator-0.1.gir Makefile.am
+ $(VALA_API_GEN) --library=AppIndicator-0.1 \
+ --pkg gtk+-2.0 \
+ --vapidir=$(top_builddir)/src \
+ $<
+
+CLEANFILES += $(vapi_DATA)
+
+endif
+
--
cgit v1.2.3
From 0b091646a8ecf62c36cde27a1d0e784a55e9a0c2 Mon Sep 17 00:00:00 2001
From: Ted Gould
Date: Thu, 29 Apr 2010 12:08:21 -0500
Subject: Ignoring built VAPI file
---
.bzrignore | 1 +
1 file changed, 1 insertion(+)
diff --git a/.bzrignore b/.bzrignore
index 134e14f..df407b6 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -105,3 +105,4 @@ src/AppIndicator-0.1.gir
src/AppIndicator-0.1.typelib
docs/reference/libappindicator-decl.txt.bak
docs/reference/libappindicator-decl-list.txt.bak
+src/AppIndicator-0.1.vapi
--
cgit v1.2.3
From 8566afcd564d10cc11be09bba56e02b78df101e7 Mon Sep 17 00:00:00 2001
From: Ted Gould
Date: Wed, 19 May 2010 13:23:24 -0500
Subject: Changing it so the object gets unref'd
---
src/libappindicator/app-indicator.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/libappindicator/app-indicator.c b/src/libappindicator/app-indicator.c
index 132e279..f7e121b 100644
--- a/src/libappindicator/app-indicator.c
+++ b/src/libappindicator/app-indicator.c
@@ -1408,6 +1408,12 @@ container_iterate (GtkWidget *widget,
DBUSMENU_MENUITEM_SIGNAL_ITEM_ACTIVATED,
G_CALLBACK (activate_menuitem), widget);
dbusmenu_menuitem_child_append (root, child);
+
+ /* Get rid of initial ref now that the root is
+ holding the object */
+ g_object_unref(child);
+
+ return;
}
static void
--
cgit v1.2.3
--
cgit v1.2.3
From 629324674c65f9ddcc89ec50cac747ac7040d798 Mon Sep 17 00:00:00 2001
From: Ted Gould
Date: Wed, 19 May 2010 14:04:33 -0500
Subject: releasing version 0.2.0~dev-0ubuntu1~ppa1
---
debian/changelog | 2 +-
docs/reference/html/ch01.html | 2 +-
docs/reference/html/index.html | 2 +-
.../html/libappindicator-app-indicator.html | 128 ++++++++++-----------
docs/reference/html/object-tree.html | 2 +-
docs/reference/xml/app-indicator.xml | 6 +-
6 files changed, 66 insertions(+), 76 deletions(-)
diff --git a/debian/changelog b/debian/changelog
index 5102ed8..b6a0673 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -3,7 +3,7 @@ indicator-application (0.2.0~dev-0ubuntu1~ppa1) lucid; urgency=low
* Upstream Merge
* kicking off new branch
- -- Ted Gould Wed, 19 May 2010 14:02:06 -0500
+ -- Ted Gould Wed, 19 May 2010 14:04:29 -0500
indicator-application (0.0.19-0ubuntu4) UNRELEASED; urgency=low
diff --git a/docs/reference/html/ch01.html b/docs/reference/html/ch01.html
index 24cb9d9..e549aea 100644
--- a/docs/reference/html/ch01.html
+++ b/docs/reference/html/ch01.html
@@ -21,7 +21,7 @@
-Base Classes for Applications
+
Base Classes for Applications
-
AppIndicator — An object to put application information
into the panel.
diff --git a/docs/reference/html/index.html b/docs/reference/html/index.html
index 670eb45..de1a3d6 100644
--- a/docs/reference/html/index.html
+++ b/docs/reference/html/index.html
@@ -15,7 +15,7 @@
libappindicator Reference Manual |
---|
- for libappindicator 0.0.18
+ for libappindicator 0.0.19
diff --git a/docs/reference/html/libappindicator-app-indicator.html b/docs/reference/html/libappindicator-app-indicator.html
index e8517b7..332e705 100644
--- a/docs/reference/html/libappindicator-app-indicator.html
+++ b/docs/reference/html/libappindicator-app-indicator.html
@@ -66,48 +66,48 @@ enum AppIndicatorPrivate;
AppIndicator;
AppIndicatorClass;
-GType app_indicator_get_type (void
);
-AppIndicator * app_indicator_new (const gchar *id
,
- const gchar *icon_name
,
+GType app_indicator_get_type (void
);
+AppIndicator * app_indicator_new (const gchar *id
,
+ const gchar *icon_name
,
AppIndicatorCategory category
);
-AppIndicator * app_indicator_new_with_path (const gchar *id
,
- const gchar *icon_name
,
+AppIndicator * app_indicator_new_with_path (const gchar *id
,
+ const gchar *icon_name
,
AppIndicatorCategory category
,
- const gchar *icon_path
);
+ const gchar *icon_path
);
void app_indicator_set_status (AppIndicator *self
,
AppIndicatorStatus status
);
void app_indicator_set_attention_icon (AppIndicator *self
,
- const gchar *icon_name
);
+ const gchar *icon_name
);
void app_indicator_set_menu (AppIndicator *self
,
- GtkMenu *menu
);
+ GtkMenu *menu
);
void app_indicator_set_icon (AppIndicator *self
,
- const gchar *icon_name
);
-const gchar * app_indicator_get_id (AppIndicator *self
);
+ const gchar *icon_name
);
+const gchar * app_indicator_get_id (AppIndicator *self
);
AppIndicatorCategory app_indicator_get_category (AppIndicator *self
);
AppIndicatorStatus app_indicator_get_status (AppIndicator *self
);
-const gchar * app_indicator_get_icon (AppIndicator *self
);
-const gchar * app_indicator_get_attention_icon (AppIndicator *self
);
-GtkMenu * app_indicator_get_menu (AppIndicator *self
);
+const gchar * app_indicator_get_icon (AppIndicator *self
);
+const gchar * app_indicator_get_attention_icon (AppIndicator *self
);
+GtkMenu * app_indicator_get_menu (AppIndicator *self
);
@@ -139,7 +139,7 @@ An application indicator is a way for an application to put
#define APP_INDICATOR_TYPE (app_indicator_get_type ())
-Get the GType for a AppIndicator.
+Get the GType for a AppIndicator.
@@ -148,7 +148,7 @@ Get the #define APP_INDICATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), APP_INDICATOR_TYPE, AppIndicator))
-Safely convert a GObject into an AppIndicator.
+Safely convert a GObject into an AppIndicator.
@@ -206,7 +206,7 @@ Checks to see if klass
is in the object
klass :
|
-An GObjectClass to check
+ | An GObjectClass to check
|
@@ -223,7 +223,7 @@ Gets a pointer to the
obj :
|
-A GObject in the class hierarchy of AppIndicator.
+ | A GObject in the class hierarchy of AppIndicator.
|
@@ -354,10 +354,6 @@ These are the states that the indicator can be on in
All of the private data in an instance of a
application indicator.
-
@@ -369,10 +365,6 @@ A application indicator represents the values that are needed to show a
should try to fit in the other indicators that are available on the
panel before using this. But, sometimes it is necissary.
-