indicators
About Indicators
Application indicators provide a simple and effective API to provide an application icon in the notification area in the top-right part of the screen, and provide simple, accessible, and complete access to key parts of your application. With bindings for C, Python, and Mono, you can integrate your app into the Unity desktop quickly and easily.
Features
- Application indicators are more consistent – no more left and right-click inconsistency. Always left click to see the items.
- Scrubbing – you can click once on an app indicator and scrub left and right through other indicators with your mouse.
- More accessible – importantly, scrubbing also applies to the keyboard: this means you could bind a key to the indicator applet, hit that key and then use the arrow keys to navigate through all the indicators.
- Themable panel icons – you can set a specific icon to be a panel icon for an indicator: this should make it easier for creating single colour panel icons for light and dark themes.
- KDE/GNOME compatability – KDE applications running in GNOME will have their application notification menus rendered with GTK widgets and vice-versa.
Porting Guide for Applications
The application indicators API is similar to the GtkStatusIcon API in some ways, but simpler and more opinionated in its design.
Indicators are grouped together by category, so it's important for the application to accurately specify its category. Possible categories for indicators include:
- APP_INDICATOR_CATEGORY_APPLICATION_STATUS: used to tell the user the current state of the application and allow users to act on that.
- APP_INDICATOR_CATEGORY_COMMUNICATIONS: might be used by applications such as IM clients to let the user know they have received new messages.
- APP_INDICATOR_CATEGORY_SYSTEM_SERVICES: inform the user about system-related events. Maybe there are updates available?
- APP_INDICATOR_CATEGORY_HARDWARE: used for hardware-related tasks, for example Bluetooth.
- APP_INDICATOR_CATEGORY_OTHER: if the app doesn't belong in one of the other categories but needs an indicator, it should use other.
The category is set when the indicator is created and isn't changed.
Application indicators fall into one of three states:
- APP_INDICATOR_STATUS_PASSIVE: the indicator should be hidden from the user
- APP_INDICATOR_STATUS_ACTIVE: the indicator should be shown normally
- APP_INDICATOR_STATUS_ATTENTION: the application wants the user's attention
The indicator status can be set using app_indicator_set_status().
The icons need to use icon names from themes, direct paths to icon files are not supported. For example, icon names used with gtk_status_icon_new_from_file() won't work.
Typical usage (C version)
Indicators should typically be created using the helper function app_indicator_new(). This returns a pointer to a newly created AppIndicator object, which is may be unref'd normally when it is no longer needed. This function expects three parameters:
AppIndicator* app_indicator_new (const gchar *id, const gchar *icon_name, AppIndicatorCategory category);
The id parameter should be unique to your application. Because app indicators are cross-desktop, the icon_name parameter expects an icon name according to the usual icon naming spec. The category parameter is the indicator category as described above.
Once an indicator object is created, the application may decide to set an attention icon using app_indicator_set_attention_icon().
Lastly, the indicator should be given a GtkMenu object. This can be either created manually or using some other method such as GtkUIManager. Below is an example using GtkUIManager.
1 #include <gtk/gtk.h>
2 #include <libappindicator/app-indicator.h>
3
4 static void activate_action (GtkAction *action);
5
6 static GtkActionEntry entries[] = {
7 { "FileMenu", NULL, "_File" },
8 { "New", "document-new", "_New", "<control>N",
9 "Create a new file", G_CALLBACK (activate_action) },
10 { "Open", "document-open", "_Open", "<control>O",
11 "Open a file", G_CALLBACK (activate_action) },
12 { "Save", "document-save", "_Save", "<control>S",
13 "Save file", G_CALLBACK (activate_action) },
14 { "Quit", "application-exit", "_Quit", "<control>Q",
15 "Exit the application", G_CALLBACK (gtk_main_quit) },
16 };
17 static guint n_entries = G_N_ELEMENTS (entries);
18
19 static const gchar *ui_info =
20 "<ui>"
21 " <menubar name='MenuBar'>"
22 " <menu action='FileMenu'>"
23 " <menuitem action='New'/>"
24 " <menuitem action='Open'/>"
25 " <menuitem action='Save'/>"
26 " <separator/>"
27 " <menuitem action='Quit'/>"
28 " </menu>"
29 " </menubar>"
30 " <popup name='IndicatorPopup'>"
31 " <menuitem action='New' />"
32 " <menuitem action='Open' />"
33 " <menuitem action='Save' />"
34 " <menuitem action='Quit' />"
35 " </popup>"
36 "</ui>";
37
38 static void
39 activate_action (GtkAction *action)
40 {
41 const gchar *name = gtk_action_get_name (action);
42 GtkWidget *dialog;
43
44 dialog = gtk_message_dialog_new (NULL,
45 GTK_DIALOG_DESTROY_WITH_PARENT,
46 GTK_MESSAGE_INFO,
47 GTK_BUTTONS_CLOSE,
48 "You activated action: \"%s\"",
49 name);
50
51 g_signal_connect (dialog, "response",
52 G_CALLBACK (gtk_widget_destroy), NULL);
53
54 gtk_widget_show (dialog);
55 }
56
57 int main (int argc, char **argv)
58 {
59 GtkWidget *window;
60 GtkWidget *menubar;
61 GtkWidget *table;
62 GtkWidget *sw;
63 GtkWidget *contents;
64 GtkWidget *statusbar;
65 GtkWidget *indicator_menu;
66 GtkActionGroup *action_group;
67 GtkUIManager *uim;
68 AppIndicator *indicator;
69 GError *error = NULL;
70
71 gtk_init (&argc, &argv);
72
73 /* main window */
74 window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
75 gtk_window_set_title (GTK_WINDOW (window), "Indicator Demo");
76 gtk_window_set_icon_name (GTK_WINDOW (window), "indicator-messages-new");
77 g_signal_connect (G_OBJECT (window),
78 "destroy",
79 G_CALLBACK (gtk_main_quit),
80 NULL);
81
82 table = gtk_table_new (1, 5, FALSE);
83 gtk_container_add (GTK_CONTAINER (window), table);
84
85 /* Menus */
86 action_group = gtk_action_group_new ("AppActions");
87 gtk_action_group_add_actions (action_group,
88 entries, n_entries,
89 window);
90
91 uim = gtk_ui_manager_new ();
92 g_object_set_data_full (G_OBJECT (window),
93 "ui-manager", uim,
94 g_object_unref);
95 gtk_ui_manager_insert_action_group (uim, action_group, 0);
96 gtk_window_add_accel_group (GTK_WINDOW (window),
97 gtk_ui_manager_get_accel_group (uim));
98
99 if (!gtk_ui_manager_add_ui_from_string (uim, ui_info, -1, &error))
100 {
101 g_message ("Failed to build menus: %s\n", error->message);
102 g_error_free (error);
103 error = NULL;
104 }
105
106 menubar = gtk_ui_manager_get_widget (uim, "/ui/MenuBar");
107 gtk_widget_show (menubar);
108 gtk_table_attach (GTK_TABLE (table),
109 menubar,
110 0, 1, 0, 1,
111 GTK_EXPAND | GTK_FILL, 0,
112 0, 0);
113
114 /* Document */
115 sw = gtk_scrolled_window_new (NULL, NULL);
116
117 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (sw),
118 GTK_POLICY_AUTOMATIC,
119 GTK_POLICY_AUTOMATIC);
120
121 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (sw),
122 GTK_SHADOW_IN);
123
124 gtk_table_attach (GTK_TABLE (table),
125 sw,
126 /* X direction */ /* Y direction */
127 0, 1, 3, 4,
128 GTK_EXPAND | GTK_FILL, GTK_EXPAND | GTK_FILL,
129 0, 0);
130
131 gtk_window_set_default_size (GTK_WINDOW (window),
132 200, 200);
133
134 contents = gtk_text_view_new ();
135 gtk_widget_grab_focus (contents);
136
137 gtk_container_add (GTK_CONTAINER (sw),
138 contents);
139
140
141 /* Create statusbar */
142 statusbar = gtk_statusbar_new ();
143 gtk_table_attach (GTK_TABLE (table),
144 statusbar,
145 /* X direction */ /* Y direction */
146 0, 1, 4, 5,
147 GTK_EXPAND | GTK_FILL, 0,
148 0, 0);
149
150 /* Show the window */
151 gtk_widget_show_all (window);
152
153 /* Indicator */
154 indicator = app_indicator_new ("example-simple-client",
155 "indicator-messages",
156 APP_INDICATOR_CATEGORY_APPLICATION_STATUS);
157
158 indicator_menu = gtk_ui_manager_get_widget (uim, "/ui/IndicatorPopup");
159
160 app_indicator_set_status (indicator, APP_INDICATOR_STATUS_ACTIVE);
161 app_indicator_set_attention_icon (indicator, "indicator-messages-new");
162
163 app_indicator_set_menu (indicator, GTK_MENU (indicator_menu));
164
165 gtk_main ();
166
167 return 0;
168 }
Python version
PyGI
1 #!/usr/bin/env python
2 #
3 # Copyright 2009-2012 Canonical Ltd.
4 #
5 # Authors: Neil Jagdish Patel <neil.patel@canonical.com>
6 # Jono Bacon <jono@ubuntu.com>
7 # David Planella <david.planella@ubuntu.com>
8 #
9 # This program is free software: you can redistribute it and/or modify it
10 # under the terms of either or both of the following licenses:
11 #
12 # 1) the GNU Lesser General Public License version 3, as published by the
13 # Free Software Foundation; and/or
14 # 2) the GNU Lesser General Public License version 2.1, as published by
15 # the Free Software Foundation.
16 #
17 # This program is distributed in the hope that it will be useful, but
18 # WITHOUT ANY WARRANTY; without even the implied warranties of
19 # MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
20 # PURPOSE. See the applicable version of the GNU Lesser General Public
21 # License for more details.
22 #
23 # You should have received a copy of both the GNU Lesser General Public
24 # License version 3 and version 2.1 along with this program. If not, see
25 # <http://www.gnu.org/licenses/>
26 #
27
28 from gi.repository import Gtk
29 from gi.repository import AppIndicator3 as appindicator
30
31
32 def menuitem_response(w, buf):
33 print buf
34
35 if __name__ == "__main__":
36 ind = appindicator.Indicator.new (
37 "example-simple-client",
38 "indicator-messages",
39 appindicator.IndicatorCategory.APPLICATION_STATUS)
40 ind.set_status (appindicator.IndicatorStatus.ACTIVE)
41 ind.set_attention_icon ("indicator-messages-new")
42
43 # create a menu
44 menu = Gtk.Menu()
45
46 # create some
47 for i in range(3):
48 buf = "Test-undermenu - %d" % i
49
50 menu_items = Gtk.MenuItem(buf)
51
52 menu.append(menu_items)
53
54 # this is where you would connect your menu item up with a function:
55
56 # menu_items.connect("activate", menuitem_response, buf)
57
58 # show the items
59 menu_items.show()
60
61 ind.set_menu(menu)
62
63 Gtk.main()
PyGTK
1 #!/usr/bin/env python
2 #
3 # Copyright 2009 Canonical Ltd.
4 #
5 # Authors: Neil Jagdish Patel <neil.patel@canonical.com>
6 # Jono Bacon <jono@ubuntu.com>
7 #
8 # This program is free software: you can redistribute it and/or modify it
9 # under the terms of either or both of the following licenses:
10 #
11 # 1) the GNU Lesser General Public License version 3, as published by the
12 # Free Software Foundation; and/or
13 # 2) the GNU Lesser General Public License version 2.1, as published by
14 # the Free Software Foundation.
15 #
16 # This program is distributed in the hope that it will be useful, but
17 # WITHOUT ANY WARRANTY; without even the implied warranties of
18 # MERCHANTABILITY, SATISFACTORY QUALITY or FITNESS FOR A PARTICULAR
19 # PURPOSE. See the applicable version of the GNU Lesser General Public
20 # License for more details.
21 #
22 # You should have received a copy of both the GNU Lesser General Public
23 # License version 3 and version 2.1 along with this program. If not, see
24 # <http://www.gnu.org/licenses/>
25 #
26
27 import gobject
28 import gtk
29 import appindicator
30
31
32 def menuitem_response(w, buf):
33 print buf
34
35 if __name__ == "__main__":
36 ind = appindicator.Indicator ("example-simple-client",
37 "indicator-messages",
38 appindicator.CATEGORY_APPLICATION_STATUS)
39 ind.set_status (appindicator.STATUS_ACTIVE)
40 ind.set_attention_icon ("indicator-messages-new")
41
42 # create a menu
43 menu = gtk.Menu()
44
45 # create some
46 for i in range(3):
47 buf = "Test-undermenu - %d" % i
48
49 menu_items = gtk.MenuItem(buf)
50
51 menu.append(menu_items)
52
53 # this is where you would connect your menu item up with a function:
54
55 # menu_items.connect("activate", menuitem_response, buf)
56
57 # show the items
58 menu_items.show()
59
60 ind.set_menu(menu)
61
62 gtk.main()
C# Example
1 using Gtk;
2 using AppIndicator;
3
4 public class IndicatorExample
5 {
6 public static void Main ()
7 {
8 Application.Init ();
9
10 Window win = new Window ("Test");
11 win.Resize (200, 200);
12
13 Label label = new Label ();
14 label.Text = "Hello, world!";
15
16 win.Add (label);
17
18 ApplicationIndicator indicator = new ApplicationIndicator ("my-id",
19 "my-name",
20 Category.ApplicationStatus);
21
22 indicator.Status = Status.Attention;
23
24 /*
25 Menu menu = new Menu ();
26 menu.Append (new MenuItem ("Foo"));
27 menu.Append (new MenuItem ("Bar"));
28
29 indicator.Menu = menu;
30 */
31
32 win.ShowAll ();
33
34 Application.Run ();
35 }
36 }
Vala Example
1 /*
2 * Copyright 2011 Canonical Ltd.
3 *
4 * This program is free software: you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License version 3, as published
6 * by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranties of
10 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11 * PURPOSE. See the GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License along
14 * with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * Authors:
17 * Marco Trevisan (Treviño) <mail@3v1n0.net>
18 */
19
20 using Gtk;
21 using AppIndicator;
22
23 public class IndicatorExample {
24 public static int main(string[] args) {
25 Gtk.init(ref args);
26
27 var win = new Window();
28 win.title = "Indicator Test";
29 win.resize(200, 200);
30 win.destroy.connect(Gtk.main_quit);
31
32 var label = new Label("Hello, world!");
33 win.add(label);
34
35 var indicator = new Indicator(win.title, "indicator-messages",
36 IndicatorCategory.APPLICATION_STATUS);
37
38 indicator.set_status(IndicatorStatus.ACTIVE);
39 indicator.set_attention_icon("indicator-messages-new");
40
41 var menu = new Menu();
42
43 var item = new MenuItem.with_label("Foo");
44 item.activate.connect(() => {
45 indicator.set_status(IndicatorStatus.ATTENTION);
46 });
47 item.show();
48 menu.append(item);
49
50 item = new MenuItem.with_label("Bar");
51 item.show();
52 item.activate.connect(() => {
53 indicator.set_status(IndicatorStatus.ATTENTION);
54 });
55 menu.append(item);
56
57 indicator.set_menu(menu);
58
59 win.show_all();
60
61 Gtk.main();
62 return 0;
63 }
64 }
Haskell example
1 -- Either install the Haskell bindings through cabal (cabal install happindicator) or clone the git repository
2 -- at https://github.com/A1kmm/happindicator and install from there.
3
4 import Graphics.UI.AppIndicator
5 import Graphics.UI.Gtk
6 import Control.Monad
7
8 main = do
9 initGUI
10 appInd <- appIndicatorNew "appIndicatorDemo" "appointment-soon" AppIndicatorCategoryApplicationStatus
11 appIndicatorSetStatus appInd AppIndicatorStatusActive
12 set appInd [ appIndicatorAttentionIconName := Just "folder",
13 appIndicatorIconDesc := Just "Demo - non-attention",
14 appIndicatorAttentionIconDesc := Just "Demo - attention",
15 appIndicatorLabel := Just "1" ]
16 indMenu <- menuNew
17 forM_ ["Hello", "World", "I'm a MenuItem"] $ \itemName -> do
18 item <- menuItemNewWithLabel itemName
19 menuShellAppend indMenu item
20 item `on` menuItemActivate $ do
21 appIndicatorSetStatus appInd AppIndicatorStatusAttention
22 widgetShow item
23 widgetShow indMenu
24 appIndicatorSetMenu appInd indMenu
25 mainGUI
mhall119/devportal/indicators (last edited 2012-03-08 22:14:00 by mhall119)