2
DBus facing code for the HUD
4
Copyright 2011 Canonical Ltd.
7
Ted Gould <ted@canonical.com>
9
This program is free software: you can redistribute it and/or modify it
10
under the terms of the GNU General Public License version 3, as published
11
by the Free Software Foundation.
13
This program is distributed in the hope that it will be useful, but
14
WITHOUT ANY WARRANTY; without even the implied warranties of
15
MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
16
PURPOSE. See the GNU General Public License for more details.
18
You should have received a copy of the GNU General Public License along
19
with this program. If not, see <http://www.gnu.org/licenses/>.
27
#include <gio/gdesktopappinfo.h>
29
#include "shared-values.h"
30
#include "hud.interface.h"
32
#include "hud-search.h"
34
struct _HudDbusPrivate {
35
GDBusConnection * bus;
36
GCancellable * bus_lookup;
37
guint bus_registration;
41
#define HUD_DBUS_GET_PRIVATE(o) \
42
(G_TYPE_INSTANCE_GET_PRIVATE ((o), HUD_DBUS_TYPE, HudDbusPrivate))
44
static void hud_dbus_class_init (HudDbusClass *klass);
45
static void hud_dbus_init (HudDbus *self);
46
static void hud_dbus_dispose (GObject *object);
47
static void hud_dbus_finalize (GObject *object);
49
static void bus_got_cb (GObject *object, GAsyncResult * res, gpointer user_data);
50
static void bus_method (GDBusConnection *connection,
52
const gchar *object_path,
53
const gchar *interface_name,
54
const gchar *method_name,
56
GDBusMethodInvocation *invocation,
58
static GVariant * get_suggestions (HudDbus * self, const gchar * query);
59
static void execute_query (HudDbus * self, GVariant * key, guint timestamp);
62
G_DEFINE_TYPE (HudDbus, hud_dbus, G_TYPE_OBJECT);
63
static GDBusNodeInfo * node_info = NULL;
64
static GDBusInterfaceInfo * iface_info = NULL;
65
static GDBusInterfaceVTable bus_vtable = {
66
method_call: bus_method,
72
hud_dbus_class_init (HudDbusClass *klass)
74
GObjectClass *object_class = G_OBJECT_CLASS (klass);
76
g_type_class_add_private (klass, sizeof (HudDbusPrivate));
78
object_class->dispose = hud_dbus_dispose;
79
object_class->finalize = hud_dbus_finalize;
81
if (node_info == NULL) {
82
GError * error = NULL;
84
node_info = g_dbus_node_info_new_for_xml(hud_interface, &error);
86
g_error("Unable to parse HUD interface: %s", error->message);
91
if (node_info != NULL && iface_info == NULL) {
92
iface_info = g_dbus_node_info_lookup_interface(node_info, DBUS_IFACE);
93
if (iface_info == NULL) {
94
g_error("Unable to find interface '" DBUS_IFACE "'");
102
hud_dbus_init (HudDbus *self)
104
self->priv = HUD_DBUS_GET_PRIVATE(self);
106
self->priv->bus = NULL;
107
self->priv->bus_lookup = NULL;
108
self->priv->bus_registration = 0;
109
self->priv->search = NULL;
111
self->priv->bus_lookup = g_cancellable_new();
112
g_bus_get(G_BUS_TYPE_SESSION, self->priv->bus_lookup, bus_got_cb, self);
114
self->priv->search = hud_search_new();
120
hud_dbus_dispose (GObject *object)
122
HudDbus * self = HUD_DBUS(object);
123
g_return_if_fail(self != NULL);
125
if (self->priv->bus_lookup != NULL) {
126
g_cancellable_cancel(self->priv->bus_lookup);
127
g_object_unref(self->priv->bus_lookup);
128
self->priv->bus_lookup = NULL;
131
if (self->priv->bus_registration != 0) {
132
g_dbus_connection_unregister_object(self->priv->bus, self->priv->bus_registration);
133
self->priv->bus_registration = 0;
136
if (self->priv->bus != NULL) {
137
g_object_unref(self->priv->bus);
138
self->priv->bus = NULL;
141
if (self->priv->search != NULL) {
142
g_object_unref(self->priv->search);
143
self->priv->search = NULL;
146
G_OBJECT_CLASS (hud_dbus_parent_class)->dispose (object);
151
hud_dbus_finalize (GObject *object)
154
G_OBJECT_CLASS (hud_dbus_parent_class)->finalize (object);
161
return g_object_new(HUD_DBUS_TYPE, NULL);
165
bus_got_cb (GObject *object, GAsyncResult * res, gpointer user_data)
167
GError * error = NULL;
168
HudDbus * self = HUD_DBUS(user_data);
169
GDBusConnection * bus;
171
bus = g_bus_get_finish(res, &error);
173
g_critical("Unable to get bus: %s", error->message);
178
self->priv->bus = bus;
180
/* Register object */
181
self->priv->bus_registration = g_dbus_connection_register_object(bus,
182
/* path */ DBUS_PATH,
183
/* interface */ iface_info,
184
/* vtable */ &bus_vtable,
193
bus_method (GDBusConnection *connection, const gchar *sender, const gchar *object_path, const gchar *interface_name, const gchar *method_name, GVariant *parameters, GDBusMethodInvocation *invocation, gpointer user_data)
195
HudDbus * self = HUD_DBUS(user_data);
197
if (g_strcmp0(method_name, "GetSuggestions") == 0) {
198
GVariant * ret = NULL;
199
gchar * query = NULL;
201
g_variant_get(parameters, "(s)", &query);
203
ret = get_suggestions(self, query);
205
g_dbus_method_invocation_return_value(invocation, ret);
207
} else if (g_strcmp0(method_name, "ExecuteQuery") == 0) {
208
GVariant * key = NULL;
211
key = g_variant_get_child_value(parameters, 0);
212
g_variant_get_child(parameters, 1, "u", ×tamp);
214
execute_query(self, key, timestamp);
216
g_dbus_method_invocation_return_value(invocation, NULL);
217
g_variant_unref(key);
223
/* Take a path to a desktop file and find its icon */
225
desktop2icon (gchar * desktop)
227
g_return_val_if_fail(desktop != NULL, g_strdup(""));
229
if (!g_file_test(desktop, G_FILE_TEST_EXISTS)) {
233
/* Try to build an app info from the desktop file
235
GDesktopAppInfo * appinfo = g_desktop_app_info_new_from_filename(desktop);
237
if (!G_IS_DESKTOP_APP_INFO(appinfo)) {
241
/* Get the name out of the icon, note the icon is not
242
ref'd so it doesn't need to be free'd */
243
gchar * retval = NULL;
244
GIcon * icon = g_app_info_get_icon(G_APP_INFO(appinfo));
246
retval = g_icon_to_string(icon);
248
retval = g_strdup("");
251
/* Drop the app info */
252
g_object_unref(appinfo);
258
/* Respond to the GetSuggestions command from DBus by looking
259
in our HUD search object for suggestions from that query */
261
get_suggestions (HudDbus * self, const gchar * query)
264
gchar * desktop = NULL;
265
gchar * target = NULL;
266
GList * suggestions = hud_search_suggestions(self->priv->search, query, &desktop, &target);
269
icon = desktop2icon(desktop);
271
/* Build into into a variant */
273
g_variant_builder_init(&ret, G_VARIANT_TYPE_TUPLE);
274
g_variant_builder_add_value(&ret, g_variant_new_string(icon));
275
g_variant_builder_add_value(&ret, g_variant_new_string(target));
277
/* Free the strings */
282
if (suggestions != NULL) {
283
GList * suggestion = suggestions;
284
GVariantBuilder builder;
285
g_variant_builder_init(&builder, G_VARIANT_TYPE_ARRAY);
287
while (suggestion != NULL) {
288
HudSearchSuggest * suggest = (HudSearchSuggest *)suggestion->data;
290
GVariantBuilder tuple;
291
g_variant_builder_init(&tuple, G_VARIANT_TYPE_TUPLE);
292
g_variant_builder_add_value(&tuple, g_variant_new_string(hud_search_suggest_get_display(suggest)));
293
g_variant_builder_add_value(&tuple, g_variant_new_string(hud_search_suggest_get_icon(suggest)));
294
g_variant_builder_add_value(&tuple, hud_search_suggest_get_key(suggest));
296
g_variant_builder_add_value(&builder, g_variant_builder_end(&tuple));
298
suggestion = g_list_next(suggestion);
301
g_variant_builder_add_value(&ret, g_variant_builder_end(&builder));
303
/* If we didn't get any suggestions we need to build
304
a null array to make the DBus interface happy */
305
g_variant_builder_add_value(&ret, g_variant_new_array(G_VARIANT_TYPE("(ssv)"), NULL, 0));
308
/* Clean up the list */
309
g_list_free_full(suggestions, (GDestroyNotify)hud_search_suggest_free);
311
return g_variant_builder_end(&ret);
315
execute_query (HudDbus * self, GVariant * key, guint timestamp)
317
hud_search_execute(self->priv->search, key, timestamp);