@@ -0,0 +1,241 @@
1+#include <gio/gio.h>
2+#include <stdio.h>
3+#include <stdlib.h>
4+
5+G_DEFINE_QUARK (SLIDER_VALUE, slider_value)
6+
7+typedef struct
8+{
9+ GSimpleActionGroup *actions;
10+ GMenu *menu;
11+
12+ guint actions_export_id;
13+ guint menu_export_id;
14+ int action_delay;
15+} IndicatorTestService;
16+
17+static void
18+bus_acquired (GDBusConnection *connection,
19+ const gchar *name,
20+ gpointer user_data)
21+{
22+ (void) name;
23+ IndicatorTestService *indicator = user_data;
24+ GError *error = NULL;
25+
26+ indicator->actions_export_id = g_dbus_connection_export_action_group (connection,
27+ "/com/canonical/indicator/test",
28+ G_ACTION_GROUP (indicator->actions),
29+ &error);
30+ if (indicator->actions_export_id == 0)
31+ {
32+ g_warning ("cannot export action group: %s", error->message);
33+ g_error_free (error);
34+ return;
35+ }
36+
37+ indicator->menu_export_id = g_dbus_connection_export_menu_model (connection,
38+ "/com/canonical/indicator/test/desktop",
39+ G_MENU_MODEL (indicator->menu),
40+ &error);
41+ if (indicator->menu_export_id == 0)
42+ {
43+ g_warning ("cannot export menu: %s", error->message);
44+ g_error_free (error);
45+ return;
46+ }
47+}
48+
49+static void
50+name_lost (GDBusConnection *connection,
51+ const gchar *name,
52+ gpointer user_data)
53+{
54+ (void) name;
55+ IndicatorTestService *indicator = user_data;
56+
57+ if (indicator->actions_export_id)
58+ g_dbus_connection_unexport_action_group (connection, indicator->actions_export_id);
59+
60+ if (indicator->menu_export_id)
61+ g_dbus_connection_unexport_menu_model (connection, indicator->menu_export_id);
62+}
63+
64+static void
65+activate_show (GSimpleAction *action,
66+ GVariant *parameter,
67+ gpointer user_data)
68+{
69+ (void) action;
70+ (void) parameter;
71+ (void) user_data;
72+ g_message ("showing");
73+}
74+
75+static gboolean
76+actual_switch (gpointer user_data)
77+{
78+ GSimpleAction *action = user_data;
79+
80+ GVariant* v = g_action_get_state(G_ACTION(action));
81+ gboolean state = g_variant_get_boolean (v);
82+ GVariant *new_state = g_variant_new_boolean (state == TRUE ? FALSE : TRUE);
83+
84+ g_simple_action_set_state(G_SIMPLE_ACTION(action), new_state);
85+
86+ g_variant_unref (v);
87+ g_message ("switching");
88+ return FALSE;
89+}
90+
91+static void
92+activate_switch (GSimpleAction *action,
93+ GVariant *parameter,
94+ gpointer user_data)
95+{
96+ (void) action;
97+ (void) parameter;
98+
99+ IndicatorTestService *indicator = user_data;
100+
101+ g_timeout_add(indicator->action_delay, actual_switch, action);
102+ g_message ("switch delay");
103+}
104+
105+static gboolean
106+actual_slide (gpointer user_data)
107+{
108+ GSimpleAction *action = user_data;
109+
110+ GVariant* new_state = g_object_get_qdata (G_OBJECT (action), slider_value_quark ());
111+
112+ g_simple_action_set_state(G_SIMPLE_ACTION(action), new_state);
113+
114+ g_message ("switching");
115+ return FALSE;
116+}
117+
118+void change_slider (GSimpleAction *action,
119+ GVariant *value,
120+ gpointer user_data)
121+{
122+ IndicatorTestService *indicator = user_data;
123+
124+ g_object_set_qdata (G_OBJECT (action), slider_value_quark (), g_variant_ref(value));
125+
126+ g_timeout_add(indicator->action_delay, actual_slide, action);
127+ g_message ("slide delay %.03f", g_variant_get_double(value));
128+}
129+
130+int
131+main (int argc, char **argv)
132+{
133+ IndicatorTestService indicator = { 0 };
134+ indicator.action_delay = -1;
135+ GMenuItem *item;
136+ GMenu *submenu;
137+ GActionEntry entries[] = {
138+ { "_header", NULL, NULL, "{'title': <'Test'>,"
139+ " 'label': <'Test'>,"
140+ " 'visible': <true>,"
141+ " 'accessible-desc': <'Test indicator'> }", NULL },
142+ { "action.show", activate_show, NULL, NULL, NULL },
143+ { "action.switch", activate_switch, NULL, "true", NULL },
144+ { "action.accessPoint", activate_switch, NULL, "false", NULL },
145+ { "action.slider", NULL, NULL, "0.5", change_slider }
146+ };
147+ GMainLoop *loop;
148+
149+ int help = 0;
150+ if (argc > 1)
151+ {
152+ int i;
153+ for (i = 1; i < argc; i++) {
154+ const char *arg = argv[i];
155+
156+ if (arg[0] == '-') {
157+ switch (arg[1])
158+ {
159+ case 't':
160+ {
161+ arg += 2;
162+ if (!arg[0] && i < argc-1) {
163+ i++;
164+ int delay = -1;
165+
166+ if (sscanf(argv[i], "%d", &delay) == 1) {
167+ indicator.action_delay = delay;
168+ } else {
169+ printf("Invalid action delay value: %s\n", argv[i]);
170+ help = 1;
171+ }
172+ } else {
173+ printf("Invalid action delay value: %s\n", argv[i]);
174+ help = 1;
175+ }
176+ break;
177+ }
178+ case 'h':
179+ help = 1;
180+ break;
181+ }
182+ }
183+ }
184+ }
185+
186+ if (help) {
187+ printf("Usage: %s [<options>]\n"
188+ " -t DELAY Action activation delay\n"
189+ " -h Show this help text\n"
190+ , argv[0]);
191+ return 0;
192+ }
193+
194+ indicator.actions = g_simple_action_group_new ();
195+ g_action_map_add_action_entries (G_ACTION_MAP (indicator.actions), entries, G_N_ELEMENTS (entries), &indicator);
196+
197+ submenu = g_menu_new ();
198+ g_menu_append (submenu, "Show", "indicator.action.show");
199+
200+ // Switch
201+ item = g_menu_item_new("Switch", "indicator.action.switch");
202+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.switch");
203+ g_menu_append_item(submenu, item);
204+
205+ // Access Point
206+ item = g_menu_item_new("Slider", "indicator.action.slider");
207+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.slider");
208+ g_menu_append_item(submenu, item);
209+
210+ // Access Point
211+ item = g_menu_item_new("Access Point", "indicator.action.accessPoint");
212+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "unity.widgets.systemsettings.tablet.accesspoint");
213+ g_menu_append_item(submenu, item);
214+
215+
216+ item = g_menu_item_new (NULL, "indicator._header");
217+ g_menu_item_set_attribute (item, "x-canonical-type", "s", "com.canonical.indicator.root");
218+ g_menu_item_set_submenu (item, G_MENU_MODEL (submenu));
219+ indicator.menu = g_menu_new ();
220+ g_menu_append_item (indicator.menu, item);
221+
222+ g_bus_own_name (G_BUS_TYPE_SESSION,
223+ "com.canonical.indicator.test",
224+ G_BUS_NAME_OWNER_FLAGS_NONE,
225+ bus_acquired,
226+ NULL,
227+ name_lost,
228+ &indicator,
229+ NULL);
230+
231+ loop = g_main_loop_new (NULL, FALSE);
232+ g_main_loop_run (loop);
233+
234+ g_object_unref (submenu);
235+ g_object_unref (item);
236+ g_object_unref (indicator.actions);
237+ g_object_unref (indicator.menu);
238+ g_object_unref (loop);
239+
240+ return 1;
241+}