~ubuntu-branches/ubuntu/trusty/hud/trusty-updates

« back to all changes in this revision

Viewing changes to src/application-list.c

  • Committer: Package Import Robot
  • Author(s): Ubuntu daily release
  • Date: 2014-01-20 19:43:59 UTC
  • mfrom: (1.1.26)
  • Revision ID: package-import@ubuntu.com-20140120194359-jxxxqtd4ql9elvpf
Tags: 13.10.1+14.04.20140120-0ubuntu1
* New rebuild forced
* Automatic snapshot from revision 362

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © 2012 Canonical Ltd.
3
 
 *
4
 
 * This program is free software: you can redistribute it and/or modify it
5
 
 * under the terms of the GNU General Public License version 3, as
6
 
 * published by the Free Software Foundation.
7
 
 *
8
 
 * This program is distributed in the hope that it will be useful, but
9
 
 * WITHOUT ANY WARRANTY; without even the implied warranties of
10
 
 * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
11
 
 * PURPOSE.  See the GNU General Public License for more details.
12
 
 *
13
 
 * You should have received a copy of the GNU General Public License along
14
 
 * with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 
 *
16
 
 * Author: Ted Gould <ted@canonical.com>
17
 
 */
18
 
 
19
 
#define G_LOG_DOMAIN "hudapplicationlist"
20
 
 
21
 
#ifdef HAVE_CONFIG_H
22
 
#include "config.h"
23
 
#endif
24
 
 
25
 
#include "window-info.h"
26
 
 
27
 
#include "application-list.h"
28
 
#include "application-source.h"
29
 
#include "source.h"
30
 
#include "window-stack-iface.h"
31
 
 
32
 
typedef struct _HudApplicationListPrivate HudApplicationListPrivate;
33
 
 
34
 
struct _HudApplicationListPrivate {
35
 
        HudApplicationSource * last_focused_main_stage_source;
36
 
 
37
 
        DBusWindowStack * window_stack;
38
 
        guint bus_watch_id;
39
 
        gulong matcher_app_sig;
40
 
        gulong matcher_view_open_sig;
41
 
        gulong matcher_view_close_sig;
42
 
        GHashTable * applications;
43
 
        HudSource * used_source;
44
 
};
45
 
 
46
 
#define HUD_APPLICATION_LIST_GET_PRIVATE(o) \
47
 
        (G_TYPE_INSTANCE_GET_PRIVATE ((o), HUD_TYPE_APPLICATION_LIST, HudApplicationListPrivate))
48
 
 
49
 
static void hud_application_list_class_init (HudApplicationListClass * klass);
50
 
static void hud_application_list_init       (HudApplicationList *      self);
51
 
static void hud_application_list_constructed (GObject * object);
52
 
static void matching_setup             (HudApplicationList *      self);
53
 
static void hud_application_list_dispose    (GObject *                 object);
54
 
static void hud_application_list_finalize   (GObject *                 object);
55
 
static void source_iface_init               (HudSourceInterface *      iface);
56
 
static void window_changed                  (DBusWindowStack *         matcher,
57
 
                                             guint                     window_id,
58
 
                                             const gchar *             app_id,
59
 
                                             guint                     stage,
60
 
                                             gpointer                  user_data);
61
 
static void view_opened                     (DBusWindowStack *         matcher,
62
 
                                             guint                     window_id,
63
 
                                             const gchar *             app_id,
64
 
                                             gpointer                  user_data);
65
 
static void view_closed                     (DBusWindowStack *         matcher,
66
 
                                             guint                     window_id,
67
 
                                             const gchar *             app_id,
68
 
                                             gpointer                  user_data);
69
 
static void source_use                      (HudSource *               hud_source);
70
 
static void source_unuse                    (HudSource *               hud_source);
71
 
static void source_search                   (HudSource *               hud_source,
72
 
                                             HudTokenList *            search_string,
73
 
                                             void                    (*append_func) (HudResult * result, gpointer user_data),
74
 
                                             gpointer                  user_data);
75
 
static void source_list_applications        (HudSource *               hud_source,
76
 
                                             HudTokenList *            search_string,
77
 
                                             void                    (*append_func) (const gchar *application_id, const gchar *application_icon, HudSourceItemType type, gpointer user_data),
78
 
                                             gpointer                  user_data);
79
 
static HudSource * source_get               (HudSource *               hud_source,
80
 
                                             const gchar *             application_id);
81
 
static GList * source_get_items             (HudSource *               list);
82
 
static void application_source_changed      (HudSource *               source,
83
 
                                             gpointer                  user_data);
84
 
static gboolean hud_application_list_name_in_ignore_list (HudWindowInfo *window);
85
 
 
86
 
G_DEFINE_TYPE_WITH_CODE (HudApplicationList, hud_application_list, G_TYPE_OBJECT,
87
 
                         G_IMPLEMENT_INTERFACE (HUD_TYPE_SOURCE, source_iface_init))
88
 
 
89
 
/* Class Init */
90
 
static void
91
 
hud_application_list_class_init (HudApplicationListClass *klass)
92
 
{
93
 
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
94
 
 
95
 
        g_type_class_add_private (klass, sizeof (HudApplicationListPrivate));
96
 
 
97
 
        object_class->constructed = hud_application_list_constructed;
98
 
        object_class->dispose = hud_application_list_dispose;
99
 
        object_class->finalize = hud_application_list_finalize;
100
 
 
101
 
        klass->matching_setup = matching_setup;
102
 
 
103
 
        return;
104
 
}
105
 
 
106
 
/* Intialized the source interface */
107
 
static void
108
 
source_iface_init (HudSourceInterface *iface)
109
 
{
110
 
        iface->use = source_use;
111
 
        iface->unuse = source_unuse;
112
 
        iface->search = source_search;
113
 
        iface->list_applications = source_list_applications;
114
 
        iface->get = source_get;
115
 
        iface->get_items = source_get_items;
116
 
 
117
 
        return;
118
 
}
119
 
 
120
 
/* Instance Init */
121
 
static void
122
 
hud_application_list_init (HudApplicationList *self)
123
 
{
124
 
        self->priv = HUD_APPLICATION_LIST_GET_PRIVATE(self);
125
 
        self->priv->applications = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_object_unref);
126
 
 
127
 
        return;
128
 
}
129
 
 
130
 
/* Final build steps */
131
 
static void
132
 
hud_application_list_constructed (GObject * object)
133
 
{
134
 
        HudApplicationList * self = HUD_APPLICATION_LIST(object);
135
 
 
136
 
        HudApplicationListClass * aclass = HUD_APPLICATION_LIST_GET_CLASS(self);
137
 
        if (aclass->matching_setup != NULL) {
138
 
                aclass->matching_setup(self);
139
 
        }
140
 
 
141
 
        return;
142
 
}
143
 
 
144
 
static void
145
 
window_stack_vanished(G_GNUC_UNUSED GDBusConnection *connection,
146
 
                const gchar *name, gpointer user_data) {
147
 
        HudApplicationList *self = HUD_APPLICATION_LIST(user_data);
148
 
 
149
 
        g_debug("window stack vanished %s", name);
150
 
 
151
 
        g_hash_table_remove_all(self->priv->applications);
152
 
 
153
 
        self->priv->used_source = NULL;
154
 
        self->priv->last_focused_main_stage_source = NULL;
155
 
 
156
 
        hud_source_changed(HUD_SOURCE(self));
157
 
}
158
 
 
159
 
static void
160
 
matching_setup (HudApplicationList * self)
161
 
{
162
 
        self->priv->bus_watch_id = g_bus_watch_name(G_BUS_TYPE_SESSION,
163
 
                        "com.canonical.Unity.WindowStack", G_BUS_NAME_WATCHER_FLAGS_NONE,
164
 
                        NULL, window_stack_vanished, self, NULL);
165
 
 
166
 
        GError *error = NULL;
167
 
        self->priv->window_stack = dbus_window_stack_proxy_new_for_bus_sync(
168
 
                        G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_NONE,
169
 
                        "com.canonical.Unity.WindowStack",
170
 
                        "/com/canonical/Unity/WindowStack",
171
 
                        NULL, &error);
172
 
        if(self->priv->window_stack == NULL) {
173
 
                g_warning("Could not construct window stack proxy: %s", error->message);
174
 
                g_error_free(error);
175
 
                return;
176
 
        }
177
 
 
178
 
        g_debug("connecting to window stack signals");
179
 
        self->priv->matcher_app_sig = g_signal_connect(self->priv->window_stack,
180
 
                "focused-window-changed",
181
 
                G_CALLBACK(window_changed), self);
182
 
        self->priv->matcher_view_open_sig = g_signal_connect(self->priv->window_stack,
183
 
                "window-created",
184
 
                G_CALLBACK(view_opened), self);
185
 
        self->priv->matcher_view_close_sig = g_signal_connect(self->priv->window_stack,
186
 
                "window-destroyed",
187
 
                G_CALLBACK(view_closed), self);
188
 
        g_debug("connected to window stack signals");
189
 
 
190
 
        GVariant *stack_variant = NULL;
191
 
        error = NULL;
192
 
        if (!dbus_window_stack_call_get_window_stack_sync(self->priv->window_stack,
193
 
                        &stack_variant, NULL, &error)) {
194
 
                g_warning("Could not get window stack: %s", error->message);
195
 
                g_error_free(error);
196
 
                return;
197
 
        }
198
 
 
199
 
        GVariantIter iter;
200
 
        g_variant_iter_init(&iter, stack_variant);
201
 
 
202
 
        GVariant *window_info = NULL;
203
 
        while ((window_info = g_variant_iter_next_value(&iter))) {
204
 
                GVariantIter window_info_iter;
205
 
                g_variant_iter_init(&window_info_iter, window_info);
206
 
 
207
 
                GVariant *window_id_variant = g_variant_iter_next_value(&window_info_iter);
208
 
                GVariant *app_id_variant = g_variant_iter_next_value(&window_info_iter);
209
 
                GVariant *focused_variant = g_variant_iter_next_value(&window_info_iter);
210
 
                GVariant *stage_variant = g_variant_iter_next_value(&window_info_iter);
211
 
 
212
 
                view_opened(self->priv->window_stack,
213
 
                                g_variant_get_uint32(window_id_variant),
214
 
                                g_variant_get_string(app_id_variant, NULL),
215
 
                                /*g_variant_get_uint32(stage_variant),*/self);
216
 
 
217
 
                if (g_variant_get_boolean(focused_variant)) {
218
 
                        HudApplicationSource *source = g_hash_table_lookup(
219
 
                                        self->priv->applications,
220
 
                                        g_variant_get_string(app_id_variant, NULL));
221
 
 
222
 
                        if (source
223
 
                                        && !hud_application_list_name_in_ignore_list(
224
 
                                                        hud_application_source_get_application_info(
225
 
                                                                        source))) {
226
 
                                window_changed(self->priv->window_stack,
227
 
                                                g_variant_get_uint32(window_id_variant),
228
 
                                                g_variant_get_string(app_id_variant, NULL),
229
 
                                                g_variant_get_uint32(stage_variant), self);
230
 
                        }
231
 
                }
232
 
 
233
 
                g_variant_unref (window_id_variant);
234
 
                g_variant_unref (app_id_variant);
235
 
                g_variant_unref (focused_variant);
236
 
                g_variant_unref (stage_variant);
237
 
                g_variant_unref (window_info);
238
 
        }
239
 
 
240
 
        g_variant_unref(stack_variant);
241
 
}
242
 
 
243
 
/* Clean up references */
244
 
static void
245
 
hud_application_list_dispose (GObject *object)
246
 
{
247
 
        HudApplicationList * self = HUD_APPLICATION_LIST(object);
248
 
        g_debug("Application List Dispose Start");
249
 
 
250
 
        if(self->priv->bus_watch_id > 0) {
251
 
                g_bus_unwatch_name(self->priv->bus_watch_id);
252
 
        }
253
 
 
254
 
        if (self->priv->used_source != NULL) {
255
 
                hud_source_unuse(self->priv->used_source);
256
 
                self->priv->used_source = NULL;
257
 
        }
258
 
 
259
 
        if (self->priv->matcher_app_sig != 0 && self->priv->window_stack != NULL) {
260
 
                g_signal_handler_disconnect(self->priv->window_stack, self->priv->matcher_app_sig);
261
 
        }
262
 
        self->priv->matcher_app_sig = 0;
263
 
 
264
 
        if (self->priv->matcher_view_open_sig != 0 && self->priv->window_stack != NULL) {
265
 
                g_signal_handler_disconnect(self->priv->window_stack, self->priv->matcher_view_open_sig);
266
 
        }
267
 
        self->priv->matcher_view_open_sig = 0;
268
 
 
269
 
        if (self->priv->matcher_view_close_sig != 0 && self->priv->window_stack != NULL) {
270
 
                g_signal_handler_disconnect(self->priv->window_stack, self->priv->matcher_view_close_sig);
271
 
        }
272
 
        self->priv->matcher_view_close_sig = 0;
273
 
 
274
 
        g_debug("Unrefing window stack");
275
 
        g_clear_object(&self->priv->window_stack);
276
 
        g_debug("Unref'd window stack");
277
 
 
278
 
        g_hash_table_remove_all(self->priv->applications);
279
 
 
280
 
        g_debug("Application List Dispose Recurse");
281
 
        G_OBJECT_CLASS (hud_application_list_parent_class)->dispose (object);
282
 
        g_debug("Application List Dispose Stop");
283
 
        return;
284
 
}
285
 
 
286
 
/* Free memory */
287
 
static void
288
 
hud_application_list_finalize (GObject *object)
289
 
{
290
 
        HudApplicationList * self = HUD_APPLICATION_LIST(object);
291
 
        g_debug("Application List Finalize Start");
292
 
 
293
 
        g_clear_pointer(&self->priv->applications, g_hash_table_unref);
294
 
 
295
 
        g_debug("Application List Finalize Recurse");
296
 
        G_OBJECT_CLASS (hud_application_list_parent_class)->finalize (object);
297
 
        g_debug("Application List Finalize Stop");
298
 
        return;
299
 
}
300
 
 
301
 
static HudApplicationSource *
302
 
application_info_to_source (HudApplicationList * list, HudApplicationInfo * bapp)
303
 
{
304
 
        const gchar * id = hud_window_info_get_app_id(bapp);
305
 
 
306
 
        HudApplicationSource * source = g_hash_table_lookup(list->priv->applications, id);
307
 
        if (source == NULL) {
308
 
                source = hud_application_source_new_for_app(bapp);
309
 
                g_signal_connect(source, "changed", G_CALLBACK(application_source_changed), list);
310
 
 
311
 
                g_hash_table_insert(list->priv->applications, g_strdup(id), source);
312
 
                id = NULL; /* We used the malloc in the table */
313
 
 
314
 
                hud_source_changed(HUD_SOURCE(list));
315
 
        }
316
 
 
317
 
        return source;
318
 
}
319
 
 
320
 
static gboolean
321
 
hud_application_list_name_in_ignore_list (HudWindowInfo *window)
322
 
{
323
 
  static const gchar * const ignored_names[] = {
324
 
    "Hud Prototype Test",
325
 
    "Hud",
326
 
    "DNDCollectionWindow",
327
 
    "launcher",
328
 
    "dash",
329
 
    "Dash",
330
 
    "panel",
331
 
    "hud",
332
 
    "unity-2d-shell",
333
 
    "unity-dash",
334
 
    "unity-panel",
335
 
    "unity-launcher",
336
 
    "XdndCollectionWindowImp",
337
 
  };
338
 
  gboolean ignored = FALSE;
339
 
  gint i;
340
 
 
341
 
  gchar *window_name = hud_window_info_get_utf8_prop(window, "WM_NAME");
342
 
  g_debug ("checking window name '%s'", window_name);
343
 
 
344
 
  /* it's possible to get NULL here */
345
 
  if (window_name == NULL)
346
 
    return FALSE;
347
 
 
348
 
 
349
 
  for (i = 0; i < G_N_ELEMENTS (ignored_names); i++)
350
 
    if (g_str_equal (ignored_names[i], window_name))
351
 
      {
352
 
        g_debug ("window name '%s' blocked", window_name);
353
 
        ignored = TRUE;
354
 
        break;
355
 
      }
356
 
 
357
 
  g_free(window_name);
358
 
 
359
 
  return ignored;
360
 
}
361
 
 
362
 
/* Called each time the focused application changes */
363
 
static void
364
 
window_changed (DBusWindowStack *window_stack, guint window_id, const gchar *app_id, guint stack, gpointer user_data)
365
 
{
366
 
        g_debug("window_changed(%d, %s, %d)", window_id, app_id, stack);
367
 
 
368
 
        HudApplicationList * list = HUD_APPLICATION_LIST(user_data);
369
 
 
370
 
        HudWindowInfo *window = hud_window_info_new(list->priv->window_stack, window_id, app_id, stack);
371
 
 
372
 
        if (hud_application_list_name_in_ignore_list (window)) {
373
 
                g_object_unref(window);
374
 
            return;
375
 
        }
376
 
 
377
 
        /* Clear the last source, as we've obviously changed */
378
 
        list->priv->last_focused_main_stage_source = NULL;
379
 
 
380
 
        HudApplicationSource *source = application_info_to_source(list, window);
381
 
 
382
 
        g_debug("looking up application source for: %s", app_id);
383
 
 
384
 
        /* If we weren't able to lookup the app, let's try to find a source
385
 
           for the window. */
386
 
        if (source == NULL) {
387
 
                g_debug("no applicationn source was found");
388
 
                guint xid = hud_window_info_get_window_id(window);
389
 
                GList * sources = g_hash_table_get_values(list->priv->applications);
390
 
                GList * lsource = NULL;
391
 
 
392
 
                for (lsource = sources; lsource != NULL; lsource = g_list_next(lsource)) {
393
 
                        HudApplicationSource * appsource = HUD_APPLICATION_SOURCE(lsource->data);
394
 
                        if (appsource == NULL) continue;
395
 
 
396
 
                        if (hud_application_source_has_xid(appsource, xid)) {
397
 
                                source = appsource;
398
 
                                break;
399
 
                        }
400
 
                }
401
 
        }
402
 
 
403
 
        if (source == NULL) {
404
 
                g_warning("Unable to find source for window");
405
 
                return;
406
 
        }
407
 
 
408
 
        list->priv->last_focused_main_stage_source = source;
409
 
 
410
 
        hud_application_source_focus(source, window, window);
411
 
 
412
 
        hud_source_changed(HUD_SOURCE(list));
413
 
 
414
 
        g_object_unref(window);
415
 
 
416
 
        return;
417
 
}
418
 
 
419
 
 
420
 
/* A new view has been opened */
421
 
static void
422
 
view_opened (DBusWindowStack * window_stack, guint window_id, const gchar *app_id, gpointer user_data)
423
 
{
424
 
        g_debug("view_opened(%d, %s)", window_id, app_id);
425
 
        HudApplicationList * list = HUD_APPLICATION_LIST(user_data);
426
 
 
427
 
        HudWindowInfo *window = hud_window_info_new(list->priv->window_stack,
428
 
                        window_id, app_id, HUD_WINDOW_INFO_STAGE_MAIN);
429
 
 
430
 
        HudApplicationSource * source = application_info_to_source(list, window);
431
 
        if (source == NULL) {
432
 
                g_object_unref(window);
433
 
                return;
434
 
        }
435
 
 
436
 
        hud_application_source_add_window(source, window);
437
 
 
438
 
        g_object_unref(window);
439
 
 
440
 
        return;
441
 
}
442
 
 
443
 
/* A view has been closed */
444
 
static void
445
 
view_closed (DBusWindowStack * window_stack, guint window_id, const gchar *app_id, gpointer user_data)
446
 
{
447
 
        g_debug("view_closed(%d, %s)", window_id, app_id);
448
 
 
449
 
        HudApplicationList * list = HUD_APPLICATION_LIST(user_data);
450
 
        HudSource *source = source_get(HUD_SOURCE(user_data), app_id);
451
 
 
452
 
        if (source == NULL) {
453
 
                g_warning("Window closed for unknown app: %s", app_id);
454
 
                return;
455
 
        }
456
 
 
457
 
        HudApplicationSource *appsource = HUD_APPLICATION_SOURCE(source);
458
 
 
459
 
        if (hud_application_source_has_xid(appsource, window_id)) {
460
 
                hud_application_source_window_closed(appsource, window_id);
461
 
        }
462
 
 
463
 
        /* If the application source has become empty it means that
464
 
         * the corresponding app has terminated and it's time to do the
465
 
         * cleanup.
466
 
         */
467
 
        if (hud_application_source_is_empty (appsource)) {
468
 
                if ((gpointer)appsource == (gpointer)list->priv->used_source) {
469
 
                        hud_source_unuse(HUD_SOURCE(appsource));
470
 
                        list->priv->used_source = NULL;
471
 
                }
472
 
 
473
 
                if (appsource == list->priv->last_focused_main_stage_source) {
474
 
                        list->priv->last_focused_main_stage_source = NULL;
475
 
                }
476
 
 
477
 
                g_debug("Removing application %s", app_id);
478
 
                g_hash_table_remove(list->priv->applications, app_id);
479
 
        }
480
 
 
481
 
        hud_source_changed(HUD_SOURCE(list));
482
 
}
483
 
 
484
 
/* Source interface using this source */
485
 
static void
486
 
source_use (HudSource *hud_source)
487
 
{
488
 
        g_return_if_fail(HUD_IS_APPLICATION_LIST(hud_source));
489
 
        HudApplicationList * list = HUD_APPLICATION_LIST(hud_source);
490
 
 
491
 
        HudApplicationSource * source = NULL;
492
 
 
493
 
        /* First see if we've already got it */
494
 
        source = list->priv->last_focused_main_stage_source;
495
 
 
496
 
        if (source == NULL) {
497
 
                g_warning("Unable to find source for window");
498
 
                return;
499
 
        }
500
 
 
501
 
        if (list->priv->used_source != NULL) {
502
 
                hud_source_unuse(list->priv->used_source);
503
 
        }
504
 
 
505
 
        list->priv->used_source = HUD_SOURCE(source);
506
 
 
507
 
        hud_source_use(HUD_SOURCE(source));
508
 
 
509
 
        return;
510
 
}
511
 
 
512
 
/* Source interface unusing this source */
513
 
static void
514
 
source_unuse (HudSource *hud_source)
515
 
{
516
 
        g_return_if_fail(HUD_IS_APPLICATION_LIST(hud_source));
517
 
        HudApplicationList * list = HUD_APPLICATION_LIST(hud_source);
518
 
 
519
 
        g_return_if_fail(list->priv->used_source != NULL);
520
 
 
521
 
        hud_source_unuse(list->priv->used_source);
522
 
        list->priv->used_source = NULL;
523
 
 
524
 
        return;
525
 
}
526
 
 
527
 
/* Search this source */
528
 
static void
529
 
source_search (HudSource *     hud_source,
530
 
               HudTokenList *  search_string,
531
 
               void          (*append_func) (HudResult * result, gpointer user_data),
532
 
               gpointer        user_data)
533
 
{
534
 
        g_return_if_fail(HUD_IS_APPLICATION_LIST(hud_source));
535
 
        HudApplicationList * list = HUD_APPLICATION_LIST(hud_source);
536
 
 
537
 
        g_return_if_fail(list->priv->used_source != NULL);
538
 
 
539
 
        hud_source_search(list->priv->used_source, search_string, append_func, user_data);
540
 
 
541
 
        return;
542
 
}
543
 
 
544
 
static void
545
 
source_list_applications (HudSource *               hud_source,
546
 
                          HudTokenList *            search_string,
547
 
                          void                    (*append_func) (const gchar *application_id, const gchar *application_icon, HudSourceItemType type, gpointer user_data),
548
 
                          gpointer                  user_data)
549
 
{
550
 
        g_return_if_fail(HUD_IS_APPLICATION_LIST(hud_source));
551
 
        HudApplicationList * list = HUD_APPLICATION_LIST(hud_source);
552
 
        GList * sources = g_hash_table_get_values(list->priv->applications);
553
 
        GList * lsource = NULL;
554
 
 
555
 
        for (lsource = sources; lsource != NULL; lsource = g_list_next(lsource)) {
556
 
                HudApplicationSource * appsource = HUD_APPLICATION_SOURCE(lsource->data);
557
 
                if (appsource == NULL || HUD_SOURCE(appsource) == list->priv->used_source) continue;
558
 
 
559
 
                hud_source_list_applications(HUD_SOURCE(appsource), search_string, append_func, user_data);
560
 
        }
561
 
        
562
 
        if (list->priv->used_source != NULL) {
563
 
                hud_source_list_applications(list->priv->used_source, search_string, append_func, user_data);
564
 
        }
565
 
}
566
 
 
567
 
static HudSource *
568
 
source_get (HudSource *     hud_source,
569
 
            const gchar *   application_id)
570
 
{
571
 
        g_return_val_if_fail(HUD_IS_APPLICATION_LIST(hud_source), NULL);
572
 
        g_return_val_if_fail(application_id != NULL, NULL);
573
 
        HudApplicationList * list = HUD_APPLICATION_LIST(hud_source);
574
 
 
575
 
        return g_hash_table_lookup(list->priv->applications, application_id);
576
 
}
577
 
 
578
 
/* An application has signaled that it's items have changed */
579
 
static void
580
 
application_source_changed (HudSource * source, gpointer user_data)
581
 
{
582
 
        HudApplicationList * list = HUD_APPLICATION_LIST(user_data);
583
 
 
584
 
        hud_source_changed(HUD_SOURCE(list));
585
 
 
586
 
        return;
587
 
}
588
 
 
589
 
/**
590
 
 * hud_application_list_new:
591
 
 *
592
 
 * Create a new application list.
593
 
 *
594
 
 * Return Value: (transfer full): New #HudApplicationList
595
 
 */
596
 
HudApplicationList *
597
 
hud_application_list_new (void)
598
 
{
599
 
        return g_object_new(HUD_TYPE_APPLICATION_LIST,
600
 
                            NULL);
601
 
}
602
 
 
603
 
/**
604
 
 * hud_application_list_get_source:
605
 
 * @list: A #HudApplicationList object
606
 
 * @id: Application ID to find
607
 
 *
608
 
 * Looks for a source in the application list database or if it
609
 
 * doesn't exist, it creates it.
610
 
 *
611
 
 * Return value: (transfer none): An #HudApplicationSource matching @id
612
 
 */
613
 
HudApplicationSource *
614
 
hud_application_list_get_source (HudApplicationList * list, const gchar * id)
615
 
{
616
 
        g_return_val_if_fail(HUD_IS_APPLICATION_LIST(list), NULL);
617
 
        g_return_val_if_fail(id != NULL, NULL);
618
 
 
619
 
 
620
 
        HudApplicationSource * source = HUD_APPLICATION_SOURCE(source_get(HUD_SOURCE(list), id));
621
 
        if (source == NULL) {
622
 
                source = hud_application_source_new_for_id(id);
623
 
                g_signal_connect(source, "changed", G_CALLBACK(application_source_changed), list);
624
 
                g_hash_table_insert(list->priv->applications, g_strdup(id), source);
625
 
        }
626
 
 
627
 
        return source;
628
 
}
629
 
 
630
 
/**
631
 
 * hud_application_list_get_focused_app:
632
 
 * @list: A #HudApplicationList object
633
 
 * 
634
 
 * Gets the focused app source
635
 
 *
636
 
 * Return value: (transfer none): The current #HudApplicationSource
637
 
 */
638
 
HudSource *
639
 
hud_application_list_get_focused_app (HudApplicationList * list)
640
 
{
641
 
        g_return_val_if_fail(HUD_IS_APPLICATION_LIST(list), NULL);
642
 
 
643
 
        HudApplicationListClass * aclass = HUD_APPLICATION_LIST_GET_CLASS(list);
644
 
        if (G_UNLIKELY(aclass->get_focused_app != NULL)) {
645
 
                return aclass->get_focused_app(list);
646
 
        }
647
 
 
648
 
        return HUD_SOURCE(list->priv->last_focused_main_stage_source);
649
 
}
650
 
 
651
 
/**
652
 
 * hud_application_list_get_side_stage_focused_app:
653
 
 * @list: A #HudApplicationList object
654
 
 * 
655
 
 * Gets the side stage focused app source
656
 
 *
657
 
 * Return value: (transfer none): The current #HudApplicationSource
658
 
 */
659
 
HudSource *
660
 
hud_application_list_get_side_stage_focused_app (HudApplicationList * list)
661
 
{
662
 
    g_return_val_if_fail(HUD_IS_APPLICATION_LIST(list), NULL);
663
 
 
664
 
    return NULL;
665
 
}
666
 
 
667
 
/**
668
 
 * hud_application_list_get_apps:
669
 
 * @list: A #HudApplicationList object
670
 
 * 
671
 
 * Gets a list of applications
672
 
 *
673
 
 * Return value: A list of #HudApplicationSource objects
674
 
 */
675
 
GList *
676
 
hud_application_list_get_apps (HudApplicationList * list)
677
 
{
678
 
  g_return_val_if_fail(HUD_IS_APPLICATION_LIST(list), NULL);
679
 
 
680
 
  return g_hash_table_get_values(list->priv->applications);
681
 
}
682
 
 
683
 
/**
684
 
 * hud_application_list_get_active_collector:
685
 
 *
686
 
 * Returns the active collector if there is one
687
 
 *
688
 
 * Returns: (transfer none): A #HudCollector or NULL if none
689
 
 */
690
 
GList *
691
 
source_get_items (HudSource * source)
692
 
{
693
 
  g_return_val_if_fail(HUD_IS_APPLICATION_LIST(source), NULL);
694
 
  HudApplicationList *list = HUD_APPLICATION_LIST(source);
695
 
  g_return_val_if_fail(list->priv->used_source != NULL, NULL);
696
 
  return hud_source_get_items(list->priv->used_source);
697
 
}