Merge lp:~muktupavels/libappindicator/no-host into lp:libappindicator

Proposed by Alberts Muktupāvels
Status: Merged
Approved by: Dmitry Shachnev
Approved revision: 298
Merged at revision: 297
Proposed branch: lp:~muktupavels/libappindicator/no-host
Merge into: lp:libappindicator
Diff against target: 354 lines (+226/-88)
2 files modified
src/app-indicator.c (+38/-2)
tests/test-libappindicator-fallback-watcher.c (+188/-86)
To merge this branch: bzr merge lp:~muktupavels/libappindicator/no-host
Reviewer Review Type Date Requested Status
Khurshid Alam (community) Approve
Dmitry Shachnev Pending
Review via email: mp+386817@code.launchpad.net

Commit message

Fall back to tray icon when StatusNotifierHost is not available.

Description of the change

Fall back to tray icon when StatusNotifierHost is not available.

https://gitlab.gnome.org/GNOME/gnome-flashback/-/issues/64

To post a comment you must log in.
Revision history for this message
Alberts Muktupāvels (muktupavels) wrote :

indicator-application-service does not support RegisterStatusNotifierHost method, but it does return TRUE for IsStatusNotifierHostRegistered.

Revision history for this message
Khurshid Alam (khurshid-alam) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/app-indicator.c'
2--- src/app-indicator.c 2020-04-08 18:39:30 +0000
3+++ src/app-indicator.c 2020-07-06 13:03:40 +0000
4@@ -213,6 +213,38 @@
5 G_DEFINE_TYPE (AppIndicator, app_indicator, G_TYPE_OBJECT);
6
7 static void
8+check_is_host_registered (AppIndicator *self)
9+{
10+ GVariant *variant;
11+ gboolean is_host_registered;
12+
13+ variant = g_dbus_proxy_get_cached_property (self->priv->watcher_proxy,
14+ "IsStatusNotifierHostRegistered");
15+
16+ is_host_registered = FALSE;
17+ if (variant != NULL) {
18+ is_host_registered = g_variant_get_boolean (variant);
19+ g_variant_unref (variant);
20+ }
21+
22+ if (!is_host_registered) {
23+ start_fallback_timer (self, FALSE);
24+ return;
25+ }
26+
27+ check_connect (self);
28+}
29+
30+static void
31+watcher_properties_changed_cb (GDBusProxy *proxy,
32+ GVariant *changed_properties,
33+ GStrv invalidated_properties,
34+ AppIndicator *self)
35+{
36+ check_is_host_registered (self);
37+}
38+
39+static void
40 watcher_ready_cb (GObject *source_object,
41 GAsyncResult *res,
42 gpointer user_data)
43@@ -230,7 +262,12 @@
44 return;
45 }
46
47- check_connect (self);
48+ g_signal_connect (self->priv->watcher_proxy,
49+ "g-properties-changed",
50+ G_CALLBACK (watcher_properties_changed_cb),
51+ self);
52+
53+ check_is_host_registered (self);
54 g_object_unref (self);
55 }
56
57@@ -243,7 +280,6 @@
58 AppIndicator *self = (AppIndicator *) user_data;
59
60 g_dbus_proxy_new (self->priv->connection,
61- G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES |
62 G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
63 watcher_interface_info,
64 NOTIFICATION_WATCHER_DBUS_ADDR,
65
66=== modified file 'tests/test-libappindicator-fallback-watcher.c'
67--- tests/test-libappindicator-fallback-watcher.c 2013-01-16 19:53:52 +0000
68+++ tests/test-libappindicator-fallback-watcher.c 2020-07-06 13:03:40 +0000
69@@ -20,97 +20,199 @@
70 with this program. If not, see <http://www.gnu.org/licenses/>.
71 */
72
73-#include <glib.h>
74-#include <dbus/dbus-glib.h>
75-#include <dbus/dbus-glib-bindings.h>
76-#include <dbus/dbus-glib-lowlevel.h>
77+#include <gio/gio.h>
78
79 #include "../src/dbus-shared.h"
80
81-gboolean kill_func (gpointer userdata);
82-
83-static GMainLoop * mainloop = NULL;
84-
85-static DBusHandlerResult
86-dbus_filter (DBusConnection * connection, DBusMessage * message, void * user_data)
87-{
88- if (dbus_message_is_method_call(message, NOTIFICATION_WATCHER_DBUS_ADDR, "RegisterStatusNotifierItem")) {
89- DBusMessage * reply = dbus_message_new_method_return(message);
90- dbus_connection_send(connection, reply, NULL);
91- dbus_message_unref(reply);
92-
93- /* Let the messages get out, but we're done at this point */
94- g_timeout_add(50, kill_func, NULL);
95-
96- return DBUS_HANDLER_RESULT_HANDLED;
97- }
98-
99- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
100-}
101-
102-gboolean
103-kill_func (gpointer userdata)
104-{
105- g_main_loop_quit(mainloop);
106- return FALSE;
107+typedef struct
108+{
109+ int status;
110+
111+ GMainLoop *loop;
112+} TestData;
113+
114+static const gchar introspection_xml[] =
115+ "<node>"
116+ " <interface name='" NOTIFICATION_WATCHER_DBUS_IFACE "'>"
117+ " <method name='RegisterStatusNotifierItem'>"
118+ " <arg type='s' name='service' direction='in'/>"
119+ " </method>"
120+ " <property type='b' name='IsStatusNotifierHostRegistered' access='read'/>"
121+ " </interface>"
122+ "</node>";
123+
124+static gboolean
125+kill_func (gpointer user_data)
126+{
127+ TestData *data;
128+
129+ data = user_data;
130+ data->status = EXIT_FAILURE;
131+
132+ g_main_loop_quit (data->loop);
133+
134+ return G_SOURCE_REMOVE;
135+}
136+
137+static void
138+handle_method_call (GDBusConnection *connection,
139+ const gchar *sender,
140+ const gchar *object_path,
141+ const gchar *interface_name,
142+ const gchar *method_name,
143+ GVariant *parameters,
144+ GDBusMethodInvocation *invocation,
145+ gpointer user_data)
146+{
147+ TestData *data;
148+
149+ data = user_data;
150+
151+ if (g_strcmp0 (method_name, "RegisterStatusNotifierItem") == 0)
152+ {
153+ g_dbus_method_invocation_return_value (invocation, NULL);
154+ g_main_loop_quit (data->loop);
155+ }
156+}
157+
158+static GVariant *
159+handle_get_property (GDBusConnection *connection,
160+ const gchar *sender,
161+ const gchar *object_path,
162+ const gchar *interface_name,
163+ const gchar *property_name,
164+ GError **error,
165+ gpointer user_data)
166+{
167+ if (g_strcmp0 (property_name, "IsStatusNotifierHostRegistered") == 0)
168+ return g_variant_new_boolean (TRUE);
169+
170+ return NULL;
171+}
172+
173+static const GDBusInterfaceVTable interface_vtable =
174+{
175+ handle_method_call,
176+ handle_get_property,
177+ NULL
178+};
179+
180+static void
181+bus_acquired_cb (GDBusConnection *connection,
182+ const gchar *name,
183+ gpointer user_data)
184+{
185+
186+ GDBusNodeInfo *introspection_info;
187+
188+ introspection_info = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
189+
190+ g_dbus_connection_register_object (connection,
191+ NOTIFICATION_WATCHER_DBUS_OBJ,
192+ introspection_info->interfaces[0],
193+ &interface_vtable,
194+ user_data,
195+ NULL,
196+ NULL);
197+
198+ g_dbus_node_info_unref (introspection_info);
199+}
200+
201+static void
202+name_lost_cb (GDBusConnection *connection,
203+ const gchar *name,
204+ gpointer user_data)
205+{
206+ TestData *data;
207+
208+ data = user_data;
209+ data->status = EXIT_FAILURE;
210+
211+ g_main_loop_quit (data->loop);
212 }
213
214 int
215-main (int argv, char ** argc)
216+main (int argc,
217+ char *argv[])
218 {
219- g_debug("Waiting to init.");
220-
221-
222- GError * error = NULL;
223- DBusGConnection * session_bus = dbus_g_bus_get(DBUS_BUS_SESSION, &error);
224- if (error != NULL) {
225- g_error("Unable to get session bus: %s", error->message);
226- return 1;
227- }
228-
229- DBusGProxy * bus_proxy = dbus_g_proxy_new_for_name(session_bus, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS);
230-
231- gboolean has_owner = FALSE;
232- gint owner_count = 0;
233- while (!has_owner && owner_count < 10000) {
234- org_freedesktop_DBus_name_has_owner(bus_proxy, "org.test", &has_owner, NULL);
235- owner_count++;
236- g_usleep(500000);
237- }
238-
239- if (owner_count == 10000) {
240- g_error("Unable to get name owner after 10000 tries");
241- return 1;
242- }
243-
244- g_usleep(500000);
245-
246- g_debug("Initing");
247-
248- guint nameret = 0;
249-
250- if (!org_freedesktop_DBus_request_name(bus_proxy, NOTIFICATION_WATCHER_DBUS_ADDR, 0, &nameret, &error)) {
251- g_error("Unable to call to request name");
252- return 1;
253- }
254-
255- if (nameret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
256- g_error("Unable to get name");
257- return 1;
258- }
259-
260- dbus_connection_add_filter(dbus_g_connection_get_connection(session_bus), dbus_filter, NULL, NULL);
261-
262- /* This is the final kill function. It really shouldn't happen
263- unless we get an error. */
264- g_timeout_add_seconds(20, kill_func, NULL);
265-
266- g_debug("Entering Mainloop");
267-
268- mainloop = g_main_loop_new(NULL, FALSE);
269- g_main_loop_run(mainloop);
270-
271- g_debug("Exiting");
272-
273- return 0;
274+ GDBusProxy *proxy;
275+ gboolean has_owner;
276+ gint owner_count;
277+ TestData data;
278+ guint owner_id;
279+
280+ g_debug ("Waiting to init.");
281+
282+ proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
283+ G_DBUS_PROXY_FLAGS_NONE,
284+ NULL,
285+ "org.freedesktop.DBus",
286+ "/org/freedesktop/DBus",
287+ "org.freedesktop.DBus",
288+ NULL,
289+ NULL);
290+
291+ has_owner = FALSE;
292+ owner_count = 0;
293+
294+ while (!has_owner && owner_count < 10000)
295+ {
296+ GVariant *variant;
297+
298+ variant = g_dbus_proxy_call_sync (proxy,
299+ "NameHasOwner",
300+ g_variant_new ("(s)", "org.test"),
301+ G_DBUS_CALL_FLAGS_NONE,
302+ -1,
303+ NULL,
304+ NULL);
305+
306+ if (variant != NULL)
307+ {
308+ g_variant_get (variant, "(b)", &has_owner);
309+ g_variant_unref (variant);
310+ }
311+
312+ g_usleep (500000);
313+ owner_count++;
314+ }
315+
316+ g_object_unref (proxy);
317+
318+ if (owner_count == 10000)
319+ {
320+ g_error ("Unable to get name owner after 10000 tries");
321+ return EXIT_FAILURE;
322+ }
323+
324+ g_usleep (500000);
325+ g_debug ("Initing");
326+
327+ data.status = EXIT_SUCCESS;
328+ data.loop = g_main_loop_new (NULL, FALSE);
329+
330+ owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
331+ NOTIFICATION_WATCHER_DBUS_ADDR,
332+ G_BUS_NAME_OWNER_FLAGS_NONE,
333+ bus_acquired_cb,
334+ NULL,
335+ name_lost_cb,
336+ &data,
337+ NULL);
338+
339+ /* This is the final kill function. It really shouldn't happen
340+ * unless we get an error.
341+ */
342+ g_timeout_add_seconds (20, kill_func, &data);
343+
344+ g_debug ("Entering Mainloop");
345+
346+ g_main_loop_run (data.loop);
347+
348+ g_main_loop_unref (data.loop);
349+ g_bus_unown_name (owner_id);
350+
351+ g_debug ("Exiting");
352+
353+ return data.status;
354 }

Subscribers

People subscribed via source and target branches