1 /* GIO - GLib Input, Output and Streaming Library
3 * Copyright © 2010 Red Hat, Inc
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General
16 * Public License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18 * Boston, MA 02111-1307, USA.
20 * Authors: Colin Walters <walters@verbum.org>
23 #define G_APPLICATION_IFACE "org.gtk.Application"
26 application_dbus_method_call (GDBusConnection *connection,
28 const gchar *object_path,
29 const gchar *interface_name,
30 const gchar *method_name,
32 GDBusMethodInvocation *invocation,
35 GApplication *app = G_APPLICATION (user_data);
37 if (method_name == NULL && *method_name == '\0')
40 if (strcmp (method_name, "Quit") == 0)
43 g_variant_get (parameters, "(u)", ×tamp);
45 g_dbus_method_invocation_return_value (invocation, NULL);
47 g_application_quit (app, timestamp);
49 else if (strcmp (method_name, "ListActions") == 0)
52 GApplicationAction *value;
53 GVariantBuilder builder;
54 GVariant *return_args;
57 g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
58 g_hash_table_iter_init (&iter, app->priv->actions);
59 while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&value))
60 g_variant_builder_add (&builder, "{s(sb)}",
62 value->description ? value->description : "",
65 result = g_variant_builder_end (&builder);
66 return_args = g_variant_new_tuple (&result, 1);
67 g_dbus_method_invocation_return_value (invocation, return_args);
68 g_variant_unref (return_args);
69 g_variant_unref (result);
71 else if (strcmp (method_name, "InvokeAction") == 0)
73 const char *action_name;
75 GApplicationAction *action;
77 g_variant_get (parameters, "(&su)", &action_name, ×tamp);
79 action = g_hash_table_lookup (app->priv->actions, action_name);
83 char *errmsg = g_strdup_printf ("Invalid action: %s", action_name);
84 g_dbus_method_invocation_return_dbus_error (invocation, G_APPLICATION_IFACE ".InvalidAction", errmsg);
89 g_signal_emit (app, application_signals[ACTION], g_quark_from_string (action_name), action_name, (guint)timestamp);
91 g_dbus_method_invocation_return_value (invocation, NULL);
93 else if (strcmp (method_name, "Activate") == 0)
96 GVariant *platform_data;
98 g_variant_get (parameters, "(@aay@a{sv})", &args, &platform_data);
100 g_signal_emit (app, application_signals[PREPARE_ACTIVATION], 0, args, platform_data);
102 g_variant_unref (args);
103 g_variant_unref (platform_data);
105 g_dbus_method_invocation_return_value (invocation, NULL);
109 static const GDBusArgInfo application_quit_in_args[] =
119 static const GDBusArgInfo * const application_quit_in_args_p[] = {
120 &application_quit_in_args[0],
124 static const GDBusArgInfo application_list_actions_out_args[] =
134 static const GDBusArgInfo * const application_list_actions_out_args_p[] = {
135 &application_list_actions_out_args[0],
139 static const GDBusArgInfo application_invoke_action_in_args[] =
155 static const GDBusArgInfo * const application_invoke_action_in_args_p[] = {
156 &application_invoke_action_in_args[0],
157 &application_invoke_action_in_args[1],
161 static const GDBusMethodInfo application_quit_method_info =
165 (GDBusArgInfo **) &application_quit_in_args_p,
170 static const GDBusMethodInfo application_list_actions_method_info =
175 (GDBusArgInfo **) &application_list_actions_out_args_p,
179 static const GDBusMethodInfo application_invoke_action_method_info =
183 (GDBusArgInfo **) &application_invoke_action_in_args_p,
188 static const GDBusArgInfo application_activate_in_args[] =
204 static const GDBusArgInfo * const application_activate_in_args_p[] = {
205 &application_activate_in_args[0],
206 &application_activate_in_args[1],
210 static const GDBusMethodInfo application_activate_method_info =
214 (GDBusArgInfo **) &application_activate_in_args_p,
219 static const GDBusMethodInfo * const application_dbus_method_info_p[] =
221 &application_quit_method_info,
222 &application_list_actions_method_info,
223 &application_invoke_action_method_info,
224 &application_activate_method_info,
228 static const GDBusSignalInfo application_dbus_signal_info[] =
238 static const GDBusSignalInfo * const application_dbus_signal_info_p[] = {
239 &application_dbus_signal_info[0],
243 static const GDBusInterfaceInfo application_dbus_interface_info =
247 (GDBusMethodInfo **) application_dbus_method_info_p,
248 (GDBusSignalInfo **) application_dbus_signal_info_p,
252 static GDBusInterfaceVTable application_dbus_vtable =
254 application_dbus_method_call,
260 application_path_from_appid (const gchar *appid)
262 gchar *appid_path, *iter;
265 appid_path = g_strconcat ("/", appid, NULL);
266 for (iter = appid_path; *iter; iter++)
276 ensure_bus (GApplication *app)
278 GError *error = NULL;
280 if (app->priv->session_bus == NULL)
281 app->priv->session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
282 if (app->priv->session_bus == NULL)
284 g_error ("%s", error->message);
285 g_error_free (error);
288 if (app->priv->dbus_path == NULL)
289 app->priv->dbus_path = application_path_from_appid (app->priv->appid);
293 _g_application_platform_init (GApplication *app)
295 GError *error = NULL;
296 guint registration_id;
300 registration_id = g_dbus_connection_register_object (app->priv->session_bus,
301 app->priv->dbus_path,
302 &application_dbus_interface_info,
303 &application_dbus_vtable,
306 if (registration_id == 0)
308 g_error ("%s", error->message);
309 g_error_free (error);
314 _g_application_platform_acquire_single_instance (GApplication *app,
317 GVariant *request_result;
318 guint32 request_status;
321 if (app->priv->session_bus == NULL)
324 request_result = g_dbus_connection_call_sync (app->priv->session_bus,
325 "org.freedesktop.DBus",
326 "/org/freedesktop/DBus",
327 "org.freedesktop.DBus",
329 g_variant_new ("(su)", app->priv->appid, 0x4),
330 NULL, 0, -1, NULL, error);
332 if (request_result == NULL)
335 if (g_variant_is_of_type (request_result, G_VARIANT_TYPE ("(u)")))
336 g_variant_get (request_result, "(u)", &request_status);
340 g_variant_unref (request_result);
342 if (request_status != 1 && request_status != 4)
344 if (request_status == 3)
345 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Another process has name \"%s\"", app->priv->appid);
347 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unknown error");
356 _g_application_platform_on_actions_changed (GApplication *app)
358 g_dbus_connection_emit_signal (app->priv->session_bus, NULL,
359 app->priv->dbus_path,
361 "ActionsChanged", NULL, NULL);
365 _g_application_platform_remote_invoke_action (GApplication *app,
373 result = g_dbus_connection_call_sync (app->priv->session_bus,
375 app->priv->dbus_path,
378 g_variant_new ("(su)",
381 NULL, 0, -1, NULL, NULL);
383 g_variant_unref (result);
387 _g_application_platform_remote_quit (GApplication *app,
394 result = g_dbus_connection_call_sync (app->priv->session_bus,
396 app->priv->dbus_path,
399 g_variant_new ("(u)",
401 NULL, 0, -1, NULL, NULL);
403 g_variant_unref (result);
407 _g_application_platform_activate (GApplication *app,
414 result = g_dbus_connection_call_sync (app->priv->session_bus,
416 app->priv->dbus_path,
420 NULL, 0, -1, NULL, NULL);
423 g_variant_unref (result);