1 /*
2  * Copyright (C) 2013 Nick Schermer <nick@xfce.org>
3  *
4  * This program is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation; either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License along
15  * with this program; if not, write to the Free Software Foundation, Inc.,
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17  */
18 
19 #ifdef HAVE_CONFIG_H
20 #include <config.h>
21 #endif
22 
23 #include <libxfce4ui/libxfce4ui.h>
24 
25 #include <src/appfinder-gdbus.h>
26 #include <src/appfinder-private.h>
27 
28 
29 
30 #define APPFINDER_DBUS_SERVICE     "org.xfce.Appfinder"
31 #define APPFINDER_DBUS_INTERFACE   APPFINDER_DBUS_SERVICE
32 #define APPFINDER_DBUS_PATH        "/org/xfce/Appfinder"
33 #define APPFINDER_DBUS_METHOD_OPEN "OpenWindow"
34 #define APPFINDER_DBUS_METHOD_QUIT "Quit"
35 
36 
37 
38 static const gchar appfinder_gdbus_introspection_xml[] =
39   "<node>"
40     "<interface name='" APPFINDER_DBUS_INTERFACE "'>"
41       "<method name='" APPFINDER_DBUS_METHOD_OPEN "'>"
42         "<arg type='b' name='expanded' direction='in'/>"
43         "<arg type='s' name='startup-id' direction='in'/>"
44       "</method>"
45       "<method name='" APPFINDER_DBUS_METHOD_QUIT "'/>"
46     "</interface>"
47   "</node>";
48 
49 
50 
51 static void
appfinder_gdbus_method_call(GDBusConnection * connection,const gchar * sender,const gchar * object_path,const gchar * interface_name,const gchar * method_name,GVariant * parameters,GDBusMethodInvocation * invocation,gpointer user_data)52 appfinder_gdbus_method_call (GDBusConnection       *connection,
53                              const gchar           *sender,
54                              const gchar           *object_path,
55                              const gchar           *interface_name,
56                              const gchar           *method_name,
57                              GVariant              *parameters,
58                              GDBusMethodInvocation *invocation,
59                              gpointer               user_data)
60 {
61   gboolean  expanded;
62   gchar    *startup_id = NULL;
63 
64   g_return_if_fail (!g_strcmp0 (object_path, APPFINDER_DBUS_PATH));
65   g_return_if_fail (!g_strcmp0 (interface_name, APPFINDER_DBUS_INTERFACE));
66 
67   APPFINDER_DEBUG ("received dbus method %s", method_name);
68 
69   if (g_strcmp0 (method_name, APPFINDER_DBUS_METHOD_OPEN) == 0)
70     {
71       /* get paramenters */
72       g_variant_get (parameters, "(bs)", &expanded, &startup_id);
73 
74       appfinder_window_new (startup_id, expanded);
75 
76       /* everything went fine */
77       g_dbus_method_invocation_return_value (invocation, NULL);
78 
79       g_free (startup_id);
80     }
81   else if (g_strcmp0 (method_name, APPFINDER_DBUS_METHOD_QUIT) == 0)
82     {
83       /* close all windows and quit */
84       g_printerr ("%s: %s.\n", PACKAGE_NAME, _("Forced to quit"));
85 
86       gtk_main_quit ();
87     }
88   else
89     {
90       g_dbus_method_invocation_return_error (invocation,
91           G_DBUS_ERROR, G_DBUS_ERROR_UNKNOWN_METHOD,
92           "Unknown method for DBus service " APPFINDER_DBUS_SERVICE);
93     }
94 }
95 
96 
97 
98 static const GDBusInterfaceVTable appfinder_gdbus_vtable =
99 {
100   appfinder_gdbus_method_call,
101   NULL, /* get property */
102   NULL  /* set property */
103 };
104 
105 
106 
107 static void
appfinder_gdbus_bus_acquired(GDBusConnection * connection,const gchar * name,gpointer user_data)108 appfinder_gdbus_bus_acquired (GDBusConnection *connection,
109                               const gchar     *name,
110                               gpointer         user_data)
111 {
112   guint          register_id;
113   GDBusNodeInfo *info;
114   GError        *error = NULL;
115 
116   info = g_dbus_node_info_new_for_xml (appfinder_gdbus_introspection_xml, NULL);
117   g_assert (info != NULL);
118   g_assert (*info->interfaces != NULL);
119 
120   register_id = g_dbus_connection_register_object (connection,
121                                                    APPFINDER_DBUS_PATH,
122                                                    *info->interfaces, /* first iface */
123                                                    &appfinder_gdbus_vtable,
124                                                    user_data,
125                                                    NULL,
126                                                    &error);
127 
128   APPFINDER_DEBUG ("registered interface with id %d", register_id);
129 
130   if (register_id == 0)
131     {
132       g_message ("Failed to register object: %s", error->message);
133       g_error_free (error);
134     }
135 
136   g_dbus_node_info_unref (info);
137 }
138 
139 
140 
141 gboolean
appfinder_gdbus_service(GError ** error)142 appfinder_gdbus_service (GError **error)
143 {
144   guint owner_id;
145 
146   owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
147                              APPFINDER_DBUS_SERVICE,
148                              G_BUS_NAME_OWNER_FLAGS_NONE,
149                              appfinder_gdbus_bus_acquired,
150                              NULL,
151                              NULL,
152                              NULL,
153                              NULL);
154 
155   return (owner_id != 0);
156 }
157 
158 
159 
160 gboolean
appfinder_gdbus_quit(GError ** error)161 appfinder_gdbus_quit (GError **error)
162 {
163   GVariant        *reply;
164   GDBusConnection *connection;
165   GError          *err = NULL;
166   gboolean         result;
167 
168   connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
169   if (G_UNLIKELY (connection == NULL))
170     return FALSE;
171 
172   reply = g_dbus_connection_call_sync (connection,
173                                        APPFINDER_DBUS_SERVICE,
174                                        APPFINDER_DBUS_PATH,
175                                        APPFINDER_DBUS_INTERFACE,
176                                        APPFINDER_DBUS_METHOD_QUIT,
177                                        NULL,
178                                        NULL,
179                                        G_DBUS_CALL_FLAGS_NO_AUTO_START,
180                                        2000,
181                                        NULL,
182                                        &err);
183 
184   g_object_unref (connection);
185 
186   result = (reply != NULL);
187   if (G_LIKELY (result))
188     g_variant_unref (reply);
189   else
190     g_propagate_error (error, err);
191 
192   return result;
193 }
194 
195 
196 
197 gboolean
appfinder_gdbus_open_window(gboolean expanded,const gchar * startup_id,GError ** error)198 appfinder_gdbus_open_window (gboolean      expanded,
199                              const gchar  *startup_id,
200                              GError      **error)
201 {
202   GVariant        *reply;
203   GDBusConnection *connection;
204   GError          *err = NULL;
205   gboolean         result;
206 
207   connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, error);
208   if (G_UNLIKELY (connection == NULL))
209     return FALSE;
210 
211   if (startup_id == NULL)
212     startup_id = "";
213 
214   reply = g_dbus_connection_call_sync (connection,
215                                        APPFINDER_DBUS_SERVICE,
216                                        APPFINDER_DBUS_PATH,
217                                        APPFINDER_DBUS_INTERFACE,
218                                        APPFINDER_DBUS_METHOD_OPEN,
219                                        g_variant_new ("(bs)",
220                                                       expanded,
221                                                       startup_id),
222                                        NULL,
223                                        G_DBUS_CALL_FLAGS_NO_AUTO_START,
224                                        2000,
225                                        NULL,
226                                        &err);
227 
228   g_object_unref (connection);
229 
230   result = (reply != NULL);
231   if (G_LIKELY (result))
232     g_variant_unref (reply);
233   else
234     g_propagate_error (error, err);
235 
236   return result;
237 }
238