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;
55 g_variant_builder_init (&builder, G_VARIANT_TYPE ("(a{s(sb)})"));
56 g_variant_builder_open (&builder, G_VARIANT_TYPE ("a{s(sb)}"));
57 g_hash_table_iter_init (&iter, app->priv->actions);
58 while (g_hash_table_iter_next (&iter, NULL, (gpointer *)&value))
59 g_variant_builder_add (&builder, "{s(sb)}",
61 value->description ? value->description : "",
63 g_variant_builder_close (&builder);
65 g_dbus_method_invocation_return_value (invocation,
66 g_variant_builder_end (&builder));
68 else if (strcmp (method_name, "InvokeAction") == 0)
70 const char *action_name;
72 GApplicationAction *action;
74 g_variant_get (parameters, "(&su)", &action_name, ×tamp);
76 action = g_hash_table_lookup (app->priv->actions, action_name);
80 char *errmsg = g_strdup_printf ("Invalid action: %s", action_name);
81 g_dbus_method_invocation_return_dbus_error (invocation, G_APPLICATION_IFACE ".InvalidAction", errmsg);
86 g_signal_emit (app, application_signals[ACTION], g_quark_from_string (action_name), action_name, (guint)timestamp);
88 g_dbus_method_invocation_return_value (invocation, NULL);
90 else if (strcmp (method_name, "Activate") == 0)
93 GVariant *platform_data;
95 g_variant_get (parameters, "(@aay@a{sv})", &args, &platform_data);
97 g_signal_emit (app, application_signals[PREPARE_ACTIVATION], 0, args, platform_data);
99 g_variant_unref (args);
100 g_variant_unref (platform_data);
102 g_dbus_method_invocation_return_value (invocation, NULL);
106 static const GDBusArgInfo application_quit_in_args[] =
116 static const GDBusArgInfo * const application_quit_in_args_p[] = {
117 &application_quit_in_args[0],
121 static const GDBusArgInfo application_list_actions_out_args[] =
131 static const GDBusArgInfo * const application_list_actions_out_args_p[] = {
132 &application_list_actions_out_args[0],
136 static const GDBusArgInfo application_invoke_action_in_args[] =
152 static const GDBusArgInfo * const application_invoke_action_in_args_p[] = {
153 &application_invoke_action_in_args[0],
154 &application_invoke_action_in_args[1],
158 static const GDBusMethodInfo application_quit_method_info =
162 (GDBusArgInfo **) &application_quit_in_args_p,
167 static const GDBusMethodInfo application_list_actions_method_info =
172 (GDBusArgInfo **) &application_list_actions_out_args_p,
176 static const GDBusMethodInfo application_invoke_action_method_info =
180 (GDBusArgInfo **) &application_invoke_action_in_args_p,
185 static const GDBusArgInfo application_activate_in_args[] =
201 static const GDBusArgInfo * const application_activate_in_args_p[] = {
202 &application_activate_in_args[0],
203 &application_activate_in_args[1],
207 static const GDBusMethodInfo application_activate_method_info =
211 (GDBusArgInfo **) &application_activate_in_args_p,
216 static const GDBusMethodInfo * const application_dbus_method_info_p[] =
218 &application_quit_method_info,
219 &application_list_actions_method_info,
220 &application_invoke_action_method_info,
221 &application_activate_method_info,
225 static const GDBusSignalInfo application_dbus_signal_info[] =
235 static const GDBusSignalInfo * const application_dbus_signal_info_p[] = {
236 &application_dbus_signal_info[0],
240 static const GDBusInterfaceInfo application_dbus_interface_info =
244 (GDBusMethodInfo **) application_dbus_method_info_p,
245 (GDBusSignalInfo **) application_dbus_signal_info_p,
249 static GDBusInterfaceVTable application_dbus_vtable =
251 application_dbus_method_call,
257 application_path_from_appid (const gchar *appid)
259 gchar *appid_path, *iter;
262 appid_path = g_strconcat ("/", appid, NULL);
263 for (iter = appid_path; *iter; iter++)
273 ensure_bus (GApplication *app)
275 GError *error = NULL;
277 if (app->priv->session_bus == NULL)
278 app->priv->session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
279 if (app->priv->session_bus == NULL)
281 g_error ("%s", error->message);
282 g_error_free (error);
285 if (app->priv->dbus_path == NULL)
286 app->priv->dbus_path = application_path_from_appid (app->priv->appid);
290 _g_application_platform_init (GApplication *app)
292 GError *error = NULL;
293 guint registration_id;
297 registration_id = g_dbus_connection_register_object (app->priv->session_bus,
298 app->priv->dbus_path,
299 &application_dbus_interface_info,
300 &application_dbus_vtable,
303 if (registration_id == 0)
305 g_error ("%s", error->message);
306 g_error_free (error);
311 _g_application_platform_acquire_single_instance (GApplication *app,
314 GVariant *request_result;
315 guint32 request_status;
318 if (app->priv->session_bus == NULL)
321 request_result = g_dbus_connection_call_sync (app->priv->session_bus,
322 "org.freedesktop.DBus",
323 "/org/freedesktop/DBus",
324 "org.freedesktop.DBus",
326 g_variant_new ("(su)", app->priv->appid, 0x4),
327 NULL, 0, -1, NULL, error);
329 if (request_result == NULL)
332 if (g_variant_is_of_type (request_result, G_VARIANT_TYPE ("(u)")))
333 g_variant_get (request_result, "(u)", &request_status);
337 g_variant_unref (request_result);
339 if (request_status != 1 && request_status != 4)
341 if (request_status == 3)
342 g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Another process has name \"%s\"", app->priv->appid);
344 g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Unknown error");
353 _g_application_platform_on_actions_changed (GApplication *app)
355 g_dbus_connection_emit_signal (app->priv->session_bus, NULL,
356 app->priv->dbus_path,
358 "ActionsChanged", NULL, NULL);
362 _g_application_platform_remote_invoke_action (GApplication *app,
370 result = g_dbus_connection_call_sync (app->priv->session_bus,
372 app->priv->dbus_path,
375 g_variant_new ("(su)",
378 NULL, 0, -1, NULL, NULL);
380 g_variant_unref (result);
384 _g_application_platform_remote_quit (GApplication *app,
391 result = g_dbus_connection_call_sync (app->priv->session_bus,
393 app->priv->dbus_path,
396 g_variant_new ("(u)",
398 NULL, 0, -1, NULL, NULL);
400 g_variant_unref (result);
404 _g_application_platform_activate (GApplication *app,
411 result = g_dbus_connection_call_sync (app->priv->session_bus,
413 app->priv->dbus_path,
417 NULL, 0, -1, NULL, NULL);
420 g_variant_unref (result);