diff options
-rw-r--r-- | bindings/mono/libappindicator-api.metadata | 2 | ||||
-rw-r--r-- | bindings/vala/Makefile.am | 18 | ||||
-rw-r--r-- | bindings/vala/examples/indicator-example.vala | 2 | ||||
-rw-r--r-- | configure.ac | 1 | ||||
-rw-r--r-- | example/Makefile.am | 29 | ||||
-rw-r--r-- | example/simple-client-vala.vala | 170 | ||||
-rw-r--r-- | example/simple-client.c | 9 | ||||
-rw-r--r-- | src/AppIndicator-0.1.metadata.in (renamed from src/AppIndicator-0.1.metadata) | 0 | ||||
-rw-r--r-- | src/AppIndicator3-0.1.metadata.in | 3 | ||||
-rw-r--r-- | src/Makefile.am | 8 | ||||
-rw-r--r-- | src/app-indicator.c | 84 | ||||
-rw-r--r-- | src/app-indicator.h | 15 | ||||
-rw-r--r-- | src/application-service-marshal.list | 1 | ||||
-rw-r--r-- | src/notification-item.xml | 6 |
14 files changed, 332 insertions, 16 deletions
diff --git a/bindings/mono/libappindicator-api.metadata b/bindings/mono/libappindicator-api.metadata index ccf58f1..e241ecf 100644 --- a/bindings/mono/libappindicator-api.metadata +++ b/bindings/mono/libappindicator-api.metadata @@ -9,6 +9,8 @@ <attr path="/api/namespace/object[@cname='AppIndicator']/signal[@field_name='new_label']" name="cname">new-label</attr> <attr path="/api/namespace/object[@cname='AppIndicator']/signal[@field_name='connection_changed']" name="name">ConnectionChanged</attr> <attr path="/api/namespace/object[@cname='AppIndicator']/signal[@field_name='connection_changed']" name="cname">connection-changed</attr> + <attr path="/api/namespace/object[@cname='AppIndicator']/signal[@field_name='scroll_event']" name="name">ScrollEvent</attr> + <attr path="/api/namespace/object[@cname='AppIndicator']/signal[@field_name='scroll_event']" name="cname">scroll-event</attr> <attr path="/api/namespace/object[@cname='AppIndicator']/signal[@field_name='new_icon']" name="name">NewIcon</attr> <attr path="/api/namespace/object[@cname='AppIndicator']/signal[@field_name='new_icon']" name="cname">new-icon</attr> <attr path="/api/namespace/object[@cname='AppIndicator']/signal[@field_name='new_icon_theme_path']" name="name">NewIconThemePath</attr> diff --git a/bindings/vala/Makefile.am b/bindings/vala/Makefile.am index c4627f5..f80b48c 100644 --- a/bindings/vala/Makefile.am +++ b/bindings/vala/Makefile.am @@ -1,16 +1,18 @@ -SUBDIRS = . examples +if HAVE_INTROSPECTION +if HAVE_VAPIGEN +SUBDIRS = . examples ######################### # VAPI Files ######################### -if HAVE_INTROSPECTION - if USE_GTK3 GTKVAPI = gtk+-3.0 +VER=3 else GTKVAPI = gtk+-2.0 +VER= endif vapidir = $(datadir)/vala/vapi @@ -21,12 +23,14 @@ DEPS = $(GTKVAPI) $(vapiprefix).deps: echo $(DEPS) > $@ -$(vapiprefix).vapi: $(top_builddir)/src/AppIndicator$(VER)-0.1.gir $(vapiprefix).deps - $(VALA_API_GEN) --library=$(vapiprefix) \ - --pkg $(GTKVAPI) \ - $< +$(vapiprefix).vapi: $(top_builddir)/src/AppIndicator$(VER)-0.1.gir \ + $(top_builddir)/src/AppIndicator$(VER)-0.1.metadata \ + $(vapiprefix).deps + $(VALA_API_GEN) --library=$(vapiprefix) --girdir=$(srcdir)/src \ + $< CLEANFILES = $(vapi_DATA) endif +endif diff --git a/bindings/vala/examples/indicator-example.vala b/bindings/vala/examples/indicator-example.vala index c91dfae..621c962 100644 --- a/bindings/vala/examples/indicator-example.vala +++ b/bindings/vala/examples/indicator-example.vala @@ -23,7 +23,7 @@ using AppIndicator; public class IndicatorExample { public static int main(string[] args) { Gtk.init(ref args); - + var win = new Window(); win.title = "Indicator Test"; win.resize(200, 200); diff --git a/configure.ac b/configure.ac index f689003..758914b 100644 --- a/configure.ac +++ b/configure.ac @@ -94,6 +94,7 @@ AM_CONDITIONAL(INTROSPECTION_TEN, [test "x$introspection_ten" = "xyes"]) ########################### AC_PATH_PROG([VALA_API_GEN], [vapigen]) +AM_CONDITIONAL(HAVE_VAPIGEN, [test "x$VALA_API_GEN" != "x"]) ########################### # Vala Compiler support diff --git a/example/Makefile.am b/example/Makefile.am index 0900baf..606317c 100644 --- a/example/Makefile.am +++ b/example/Makefile.am @@ -4,9 +4,11 @@ else VER= endif +CLEANFILES = check_PROGRAMS = \ - simple-client + simple-client \ + simple-client-vala ######################################### ## simple-client @@ -27,3 +29,28 @@ simple_client_LDADD = \ EXTRA_DIST = \ simple-client-test-icon.png + +######################################### +## simple-client-vala +######################################### +if HAVE_VALAC + +VALAFLAGS = \ + --pkg appindicator$(VER)-0.1 \ + --vapidir=$(top_builddir)/bindings/vala + +BUILT_SOURCES = simple-client-vala.c +simple-client-vala.c: $(srcdir)/simple-client-vala.vala + $(VALAC) $(VALAFLAGS) -C $< -o $@ + $(SED) -i "s|#include\s*<\s*libappindicator/app-indicator.h\s*>||g" $@ + +simple_client_vala_SOURCES = simple-client-vala.c +simple_client_vala_CFLAGS = \ + $(simple_client_CFLAGS) \ + -include $(top_srcdir)/src/app-indicator.h + +simple_client_vala_LDADD = $(simple_client_LDADD) + +CLEANFILES += *.stamp *-vala.c + +endif diff --git a/example/simple-client-vala.vala b/example/simple-client-vala.vala new file mode 100644 index 0000000..61e0c2f --- /dev/null +++ b/example/simple-client-vala.vala @@ -0,0 +1,170 @@ +/* +A small piece of sample code demonstrating a very simple application +with an indicator. + +Copyright 2011 Canonical Ltd. + +Authors: + Marco Trevisan <mail@3v1n0.net> + +This program is free software: you can redistribute it and/or modify it +under the terms of the GNU General Public License version 3, 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 GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along +with this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +using Gtk; +using AppIndicator; + +static int main(string[] args) { + var sc = new SimpleClient(args); + sc.run(); + return 0; +} + +class SimpleClient { + Menu menu; + Indicator ci; + int percentage; + bool active; + bool can_haz_label; + + public SimpleClient(string[] args) { + Gtk.init(ref args); + + ci = new Indicator("example-simple-client", + "indicator-messages", + IndicatorCategory.APPLICATION_STATUS); + + ci.set_status(IndicatorStatus.ACTIVE); + ci.set_attention_icon("indicator-messages-new"); + ci.set_label("1%", "100%"); + + active = true; + can_haz_label = true; + } + + private void toggle_sensitivity(Widget widget) { + widget.set_sensitive(!widget.is_sensitive()); + } + + private void append_submenu(MenuItem item) { + var menu = new Menu(); + MenuItem mi; + + mi = new MenuItem.with_label("Sub 1"); + menu.append(mi); + mi.activate.connect(() => { print("Sub1\n"); }); + + MenuItem prev_mi = mi; + mi = new MenuItem.with_label("Sub 2"); + menu.append(mi); + mi.activate.connect(() => { toggle_sensitivity(prev_mi); }); + + mi = new MenuItem.with_label("Sub 3"); + menu.append(mi); + mi.activate.connect(() => { print("Sub3\n"); }); + + menu.show_all(); + item.set_submenu(menu); + } + + private void label_toggle(MenuItem item) { + can_haz_label = !can_haz_label; + + if (can_haz_label) { + item.set_label("Hide label"); + } else { + item.set_label("Show label"); + } + } + + public void run() { + + ci.scroll_event.connect((delta, direction) => { + print(@"Got scroll event! delta: $delta, direction: $direction\n"); + }); + + Timeout.add_seconds(1, () => { + percentage = (percentage + 1) % 100; + if (can_haz_label) { + ci.set_label(@"$(percentage+1)%", ""); + } else { + ci.set_label("", ""); + } + return true; + }); + + menu = new Menu(); + var chk = new CheckMenuItem.with_label("1"); + chk.activate.connect(() => { print("1\n"); }); + menu.append(chk); + chk.show(); + + var radio = new RadioMenuItem.with_label(new SList<RadioMenuItem>(), "2"); + radio.activate.connect(() => { print("2\n"); }); + menu.append(radio); + radio.show(); + + var submenu = new MenuItem.with_label("3"); + menu.append(submenu); + append_submenu(submenu); + submenu.show(); + + var toggle_item = new MenuItem.with_label("Toggle 3"); + toggle_item.activate.connect(() => { toggle_sensitivity(submenu); }); + menu.append(toggle_item); + toggle_item.show(); + + var imgitem = new ImageMenuItem.from_stock(Stock.NEW, null); + imgitem.activate.connect(() => { + Image img = (Image) imgitem.get_image(); + img.set_from_stock(Stock.OPEN, IconSize.MENU); + }); + menu.append(imgitem); + imgitem.show(); + + var att = new MenuItem.with_label("Get Attention"); + att.activate.connect(() => { + if (active) { + ci.set_status(IndicatorStatus.ATTENTION); + att.set_label("I'm okay now"); + active = false; + } else { + ci.set_status(IndicatorStatus.ACTIVE); + att.set_label("Get Attention"); + active = false; + } + }); + menu.append(att); + att.show(); + + var show = new MenuItem.with_label("Show Label"); + label_toggle(show); + show.activate.connect(() => { label_toggle(show); }); + menu.append(show); + show.show(); + + var icon = new CheckMenuItem.with_label("Set Local Icon"); + icon.activate.connect(() => { + if (icon.get_active()) { + ci.set_icon("simple-client-test-icon.png"); + } else { + ci.set_icon("indicator-messages"); + } + }); + menu.append(icon); + icon.show(); + + ci.set_menu(menu); + + Gtk.main(); + } +} diff --git a/example/simple-client.c b/example/simple-client.c index ac8360f..1cf06dc 100644 --- a/example/simple-client.c +++ b/example/simple-client.c @@ -98,6 +98,12 @@ image_clicked_cb (GtkWidget *widget, gpointer data) } static void +scroll_event_cb (AppIndicator * ci, gint delta, guint direction) +{ + g_print("Got scroll event! delta: %d, direction: %d\n", delta, direction); +} + +static void append_submenu (GtkWidget *item) { GtkWidget *menu; @@ -162,6 +168,9 @@ main (int argc, char ** argv) app_indicator_set_attention_icon(ci, "indicator-messages-new"); app_indicator_set_label (ci, "1%", "100%"); + g_signal_connect (ci, "scroll-event", + G_CALLBACK (scroll_event_cb), NULL); + g_timeout_add_seconds(1, percent_change, ci); menu = gtk_menu_new (); diff --git a/src/AppIndicator-0.1.metadata b/src/AppIndicator-0.1.metadata.in index 5790ddb..5790ddb 100644 --- a/src/AppIndicator-0.1.metadata +++ b/src/AppIndicator-0.1.metadata.in diff --git a/src/AppIndicator3-0.1.metadata.in b/src/AppIndicator3-0.1.metadata.in new file mode 100644 index 0000000..5790ddb --- /dev/null +++ b/src/AppIndicator3-0.1.metadata.in @@ -0,0 +1,3 @@ +AppIndicator name="AppIndicator" +Indicator.priv hidden="1" +IndicatorPrivate hidden="1" diff --git a/src/Makefile.am b/src/Makefile.am index b9696c5..f83a6c4 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -14,7 +14,7 @@ BUILT_SOURCES = EXTRA_DIST = \ appindicator-0.1.pc.in \ appindicator3-0.1.pc.in \ - AppIndicator-0.1.metadata + AppIndicator$(VER)-0.1.metadata.in include $(top_srcdir)/Makefile.am.enum include $(top_srcdir)/Makefile.am.marshal @@ -164,6 +164,12 @@ AppIndicator3_0_1_gir_FILES = $(AppIndicator_0_1_gir_FILES) INTROSPECTION_GIRS += AppIndicator$(VER)-0.1.gir +AppIndicator$(VER)-0.1.metadata: AppIndicator$(VER)-0.1.gir + cp -f $(srcdir)/$@.in $@ + +BUILT_SOURCES += AppIndicator$(VER)-0.1.metadata +CLEANFILES += AppIndicator$(VER)-0.1.metadata + girdir = $(datadir)/gir-1.0 gir_DATA = $(INTROSPECTION_GIRS) diff --git a/src/app-indicator.c b/src/app-indicator.c index 039b980..7bee341 100644 --- a/src/app-indicator.c +++ b/src/app-indicator.c @@ -103,6 +103,7 @@ enum { NEW_LABEL, CONNECTION_CHANGED, NEW_ICON_THEME_PATH, + SCROLL_EVENT, LAST_SIGNAL }; @@ -170,19 +171,22 @@ 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 gboolean scroll_event_wrapper(GtkWidget *status_icon, GdkEventScroll *event, gpointer user_data); static void status_icon_changes (AppIndicator * self, gpointer data); static void status_icon_activate (GtkStatusIcon * icon, gpointer data); +static void status_icon_menu_activate (GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data); static void unfallback (AppIndicator * self, GtkStatusIcon * status_icon); static gchar * append_panel_icon_suffix (const gchar * icon_name); static void watcher_owner_changed (GObject * obj, GParamSpec * pspec, gpointer user_data); static void client_menu_changed (GtkWidget *widget, GtkWidget *child, AppIndicator *indicator); static void theme_changed_cb (GtkIconTheme * theme, gpointer user_data); static GVariant * bus_get_prop (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * property, GError ** error, gpointer user_data); +static void bus_method_call (GDBusConnection * connection, const gchar * sender, const gchar * path, const gchar * interface, const gchar * method, GVariant * params, GDBusMethodInvocation * invocation, gpointer user_data); static void bus_creation (GObject * obj, GAsyncResult * res, gpointer user_data); static void bus_watcher_ready (GObject * obj, GAsyncResult * res, gpointer user_data); static const GDBusInterfaceVTable item_interface_table = { - method_call: NULL, /* No methods on this object */ + method_call: bus_method_call, get_property: bus_get_prop, set_property: NULL /* No properties that can be set */ }; @@ -469,6 +473,21 @@ app_indicator_class_init (AppIndicatorClass *klass) g_cclosure_marshal_VOID__STRING, G_TYPE_NONE, 1, G_TYPE_STRING); + /** + AppIndicator::scroll-event: + @arg0: The #AppIndicator object + + Signaled when there is a new icon set for the + object. + */ + signals[SCROLL_EVENT] = g_signal_new (APP_INDICATOR_SIGNAL_SCROLL_EVENT, + G_TYPE_FROM_CLASS(klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (AppIndicatorClass, scroll_event), + NULL, NULL, + _application_service_marshal_VOID__INT_UINT, + G_TYPE_NONE, 2, G_TYPE_INT, G_TYPE_UINT); + /* DBus interfaces */ if (item_node_info == NULL) { GError * error = NULL; @@ -899,6 +918,43 @@ bus_creation (GObject * obj, GAsyncResult * res, gpointer user_data) return; } +static void +bus_method_call (GDBusConnection * connection, const gchar * sender, + const gchar * path, const gchar * interface, + const gchar * method, GVariant * params, + GDBusMethodInvocation * invocation, gpointer user_data) +{ + g_return_if_fail(IS_APP_INDICATOR(user_data)); + + AppIndicator * app = APP_INDICATOR(user_data); + GVariant * retval = NULL; + + if (g_strcmp0(method, "Scroll") == 0) { + guint direction; + gint delta; + const gchar *orientation; + + g_variant_get(params, "(i&s)", &delta, &orientation); + + if (g_strcmp0(orientation, "horizontal") == 0) { + direction = (delta >= 0) ? GDK_SCROLL_RIGHT : GDK_SCROLL_LEFT; + } else if (g_strcmp0(orientation, "vertical") == 0) { + direction = (delta >= 0) ? GDK_SCROLL_DOWN : GDK_SCROLL_UP; + } else { + g_dbus_method_invocation_return_value(invocation, retval); + return; + } + + delta = ABS(delta); + g_signal_emit(app, signals[SCROLL_EVENT], 0, delta, direction); + + } else { + g_warning("Calling method '%s' on the app-indicator and it's unknown", method); + } + + g_dbus_method_invocation_return_value(invocation, retval); +} + /* DBus is asking for a property so we should figure out what it wants and try and deliver. */ static GVariant * @@ -1053,7 +1109,8 @@ check_connect (AppIndicator *self) if (priv->watcher_proxy == NULL) { /* Build Watcher Proxy */ g_dbus_proxy_new(priv->connection, - G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, /* We don't use these, don't bother with them */ + G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES| + G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, /* We don't use these, don't bother with them */ watcher_interface_info, NOTIFICATION_WATCHER_DBUS_ADDR, NOTIFICATION_WATCHER_DBUS_OBJ, @@ -1315,6 +1372,8 @@ fallback (AppIndicator * self) status_icon_changes(self, icon); g_signal_connect(G_OBJECT(icon), "activate", G_CALLBACK(status_icon_activate), self); + g_signal_connect(G_OBJECT(icon), "popup-menu", G_CALLBACK(status_icon_menu_activate), self); + g_signal_connect(G_OBJECT(icon), "scroll-event", G_CALLBACK(scroll_event_wrapper), self); return icon; } @@ -1327,6 +1386,18 @@ status_icon_status_wrapper (AppIndicator * self, const gchar * status, gpointer return status_icon_changes(self, data); } +/* A wrapper for redirecting the scroll events to the app-indicator from status + icon widget. */ +static gboolean +scroll_event_wrapper(GtkWidget *status_icon, GdkEventScroll *event, gpointer data) +{ + g_return_val_if_fail(IS_APP_INDICATOR(data), FALSE); + AppIndicator * app = APP_INDICATOR(data); + g_signal_emit(app, signals[SCROLL_EVENT], 0, 1, event->direction); + + return FALSE; +} + /* This tracks changes to either the status or the icons that are associated with the app indicator */ static void @@ -1388,6 +1459,14 @@ status_icon_activate (GtkStatusIcon * icon, gpointer data) return; } +/* Handles the right-click action by the status icon by showing + the menu in a popup. */ +static void +status_icon_menu_activate (GtkStatusIcon *status_icon, guint button, guint activate_time, gpointer user_data) +{ + status_icon_activate(status_icon, user_data); +} + /* Removes the status icon as the application indicator area is now up and running again. */ static void @@ -1395,6 +1474,7 @@ 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); + g_signal_handlers_disconnect_by_func(G_OBJECT(self), scroll_event_wrapper, status_icon); gtk_status_icon_set_visible(status_icon, FALSE); g_object_unref(G_OBJECT(status_icon)); return; diff --git a/src/app-indicator.h b/src/app-indicator.h index 3e159db..abd6699 100644 --- a/src/app-indicator.h +++ b/src/app-indicator.h @@ -107,12 +107,18 @@ G_BEGIN_DECLS String identifier for the #AppIndicator::new-icon-theme-path signal. */ +/** + APP_INDICATOR_SIGNAL_SCROLL_EVENT: + + String identifier for the #AppIndicator::scroll-event 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_NEW_LABEL "new-label" #define APP_INDICATOR_SIGNAL_CONNECTION_CHANGED "connection-changed" #define APP_INDICATOR_SIGNAL_NEW_ICON_THEME_PATH "new-icon-theme-path" +#define APP_INDICATOR_SIGNAL_SCROLL_EVENT "scroll-event" /** AppIndicatorCategory: @@ -163,7 +169,7 @@ typedef struct _AppIndicatorPrivate AppIndicatorPrivate; @new_icon_theme_path: Slot for #AppIndicator::new-icon-theme-path @new_label: Slot for #AppIndicator::new-label. @connection_changed: Slot for #AppIndicator::connection-changed. - @app_indicator_reserved_sw: Reserved for future use. + @scroll-event: Slot for #AppIndicator::scroll-event @app_indicator_reserved_ats: Reserved for future use. @fallback: Function that gets called to make a #GtkStatusIcon when there is no Application Indicator area available. @@ -203,7 +209,12 @@ struct _AppIndicatorClass { void (* connection_changed) (AppIndicator * indicator, gboolean connected, gpointer user_data); - void (*app_indicator_reserved_sw)(void); + + void (* scroll_event) (AppIndicator * indicator, + gint delta, + guint direction, + gpointer user_data); + void (*app_indicator_reserved_ats)(void); /* Overridable Functions */ diff --git a/src/application-service-marshal.list b/src/application-service-marshal.list index 2b2efa5..39a55fe 100644 --- a/src/application-service-marshal.list +++ b/src/application-service-marshal.list @@ -21,3 +21,4 @@ VOID: INT, STRING, STRING VOID: INT, STRING VOID: STRING, STRING VOID: BOOL, STRING, OBJECT +VOID: INT, UINT diff --git a/src/notification-item.xml b/src/notification-item.xml index 05afd83..127eb3a 100644 --- a/src/notification-item.xml +++ b/src/notification-item.xml @@ -17,7 +17,10 @@ <property name="XAyatanaOrderingIndex" type="u" access="read" /> <!-- Methods --> - <!-- None currently --> + <method name="Scroll"> + <arg type="i" name="delta" direction="in" /> + <arg type="s" name="orientation" direction="in" /> + </method> <!-- Signals --> <signal name="NewIcon"> @@ -34,6 +37,5 @@ <arg type="s" name="label" direction="out" /> <arg type="s" name="guide" direction="out" /> </signal> - </interface> </node> |