67
76
GDBusConnection *session;
68
77
gchar *unique_bus_name;
70
/* If this is an application, is_application will be set and
71
* 'application' and 'window' will contain the two action groups for
72
* the window that we are collecting.
74
* If this is an indicator, is_application will be false and the
75
* (singular) action group for the indicator will be in 'application'.
77
GDBusActionGroup *application;
78
GDBusActionGroup *window;
79
gboolean is_application;
81
/* The GMenuModel for the app menu.
83
* If this is an indicator, the indicator menu is stored here.
85
* app_menu_is_hud_aware is TRUE if we should send HudActiveChanged
86
* calls to app_menu_object_path when our use_count goes above 0.
88
GDBusMenuModel *app_menu;
89
gchar *app_menu_object_path;
90
gboolean app_menu_is_hud_aware;
92
/* Ditto for the menubar.
94
* If this is an indicator then these will all be unset.
96
GDBusMenuModel *menubar;
97
gchar *menubar_object_path;
98
gboolean menubar_is_hud_aware;
79
/* GActionGroup's indexed by their prefix */
100
82
/* Boring details about the app/indicator we are showing. */
87
/* Class to map labels to keywords */
88
HudKeywordMapping* keyword_mapping;
106
90
/* Each time we see a new menumodel added we add it to 'models', start
107
91
* watching it for changes and add its contents to 'items', possibly
108
92
* finding more menumodels to do the same to.
121
105
* apps and indicators.
109
/* This is the export path that we've been given */
110
gchar * base_export_path;
113
HudSourceItemType type;
116
/* Structure for when we're tracking a model, all the info
117
that we need to keep on it. */
118
typedef struct _model_data_t model_data_t;
119
struct _model_data_t {
120
GDBusConnection *session;
123
gboolean is_hud_aware;
124
GCancellable * cancellable;
130
/* Structure to pass two values in a single pointer, amazing! */
131
typedef struct _exported_menu_id_t exported_menu_id_t;
132
struct _exported_menu_id_t {
134
GDBusConnection * bus;
137
struct _HudModelItem {
128
138
HudItem parent_instance;
130
140
GRemoteActionGroup *group;
131
141
gchar *action_name;
142
gchar *action_name_full;
132
144
GVariant *target;
145
HudClientQueryToolbarItems toolbar_item;
147
GMenuModel * submodel;
135
150
typedef HudItemClass HudModelItemClass;
153
static void model_data_free (gpointer data);
154
static void hud_menu_model_collector_hud_awareness_cb (GObject *source,
155
GAsyncResult *result,
157
static GList * hud_menu_model_collector_get_items (HudSource * source);
158
static void hud_menu_model_collector_activate_toolbar (HudSource * source,
159
HudClientQueryToolbarItems titem,
160
GVariant * platform_data);
161
static const gchar * hud_menu_model_collector_get_app_icon (HudSource * collector);
162
static const gchar * hud_menu_model_collector_get_app_id (HudSource * collector);
138
hud_menu_model_context_get_action_name (HudMenuModelContext *context,
139
const gchar *action_name)
166
hud_menu_model_context_get_prefix (HudMenuModelContext *context,
167
const gchar *action_name)
141
169
if (context && context->action_namespace)
142
170
/* Note: this will (intentionally) work if action_name is NULL */
143
return g_strjoin (".", context->action_namespace, action_name, NULL);
145
return g_strdup (action_name);
171
return g_strdup (context->action_namespace);
173
gchar * retval = g_strdup (action_name);
174
gchar * dot = g_strstr_len(retval, -1, ".");
148
184
static HudStringList *
237
316
class->activate = hud_model_item_activate;
319
/* Breaks apart the string and adds it to the list */
320
static HudStringList *
321
append_keywords_string (HudStringList * list, const gchar * string)
323
if (string == NULL) {
327
/* Limiting to 64 keywords. A bit arbitrary, but we need to ensure
328
that bad apps can't hurt us. */
329
gchar ** split = g_strsplit(string, ";", 64);
336
for (i = 0; split[i] != NULL; i++) {
337
if (split[i][0] != '\0')
338
list = hud_string_list_cons(split[i], list);
241
346
hud_model_item_new (HudMenuModelCollector *collector,
242
347
HudMenuModelContext *context,
243
348
const gchar *label,
244
349
const gchar *action_name,
351
const gchar *description,
352
const gchar *keywords_string,
354
const gchar *toolbar)
247
356
HudModelItem *item;
248
357
const gchar *stripped_action_name;
249
gchar *full_action_name;
250
GDBusActionGroup *group = NULL;
251
HudStringList *full_label;
253
full_action_name = hud_menu_model_context_get_action_name (context, action_name);
255
if (collector->is_application)
257
/* For applications we support "app." and "win." actions and
258
* deliver them to the application or the window, with the prefix
261
if (g_str_has_prefix (full_action_name, "app."))
262
group = collector->application;
263
else if (g_str_has_prefix (full_action_name, "win."))
264
group = collector->window;
266
stripped_action_name = full_action_name + 4;
270
/* For indicators, we deliver directly to the (one) action group
271
* that we were given the object path for at construction.
273
stripped_action_name = full_action_name;
274
group = collector->application;
359
GActionGroup *group = NULL;
360
HudStringList *full_label, *keywords;
362
prefix = hud_menu_model_context_get_prefix (context, action_name);
364
if (prefix[0] == '\0')
365
g_clear_pointer(&prefix, g_free);
367
group = g_action_muxer_get(collector->muxer, prefix);
279
g_free (full_action_name);
375
/* Kinda silly, think we can do better here */
376
if (prefix != NULL && g_str_has_prefix(action_name, prefix)) {
377
stripped_action_name = action_name + strlen(prefix) + 1;
379
stripped_action_name = action_name;
283
382
full_label = hud_menu_model_context_get_label (context, label);
383
keywords = hud_menu_model_context_get_tokens(label, collector->keyword_mapping);
384
keywords = append_keywords_string(keywords, keywords_string);
285
item = hud_item_construct (hud_model_item_get_type (), full_label, collector->desktop_file, collector->icon, TRUE);
386
item = hud_item_construct (hud_model_item_get_type (), full_label, keywords, accel, collector->app_id, collector->icon, description, TRUE);
286
387
item->group = g_object_ref (group);
287
388
item->action_name = g_strdup (stripped_action_name);
389
item->action_name_full = g_strdup (action_name);
288
390
item->target = target ? g_variant_ref_sink (target) : NULL;
394
item->toolbar_item = hud_client_query_toolbar_items_get_value_from_nick(toolbar);
290
397
hud_string_list_unref (full_label);
291
g_free (full_action_name);
398
hud_string_list_unref (keywords);
293
401
return HUD_ITEM (item);
404
/* Set the submenu property for the item */
406
hud_model_item_set_submenu (HudModelItem * item, GMenuModel * submenu, const gchar * action_path)
408
g_return_if_fail(G_IS_MENU_MODEL(submenu));
409
g_return_if_fail(g_object_get_data(G_OBJECT(submenu), EXPORT_PATH) != NULL);
411
item->submodel = g_object_ref(submenu);
412
item->action_path = g_strdup(action_path);
418
* hud_model_item_is_toolbar:
419
* @item: A #HudModelItem to check
421
* Check to see if an item has a toolbar representation
423
* Return value: Whether this is in the toolbar
426
hud_model_item_is_toolbar (HudModelItem * item)
428
g_return_val_if_fail(HUD_IS_MODEL_ITEM(item), FALSE);
430
return item->toolbar_item != -1;
434
* hud_model_item_is_parameterized:
435
* @item: A #HudModelItem to check
437
* Check to see if an item represents a parameterized set of
440
* Return value: Whether this has parameterized actions or not
443
hud_model_item_is_parameterized (HudModelItem * item)
445
g_return_val_if_fail(HUD_IS_MODEL_ITEM(item), FALSE);
447
return item->submodel != NULL;
451
* hud_model_item_activate_parameterized:
452
* @item: A #HudModelItem to check
453
* @timestamp: The time of the user event from the dispaly server
454
* @base_action: Action to activate the base events on
455
* @action_path: Path that the actions can be found on
456
* @model_path: Path to the models
457
* @section: Model section to use
459
* Uses the item to find all the information about creating a parameterized
460
* view of the item in the HUD.
463
hud_model_item_activate_parameterized (HudModelItem * item, guint32 timestamp, const gchar ** base_action, const gchar ** action_path, const gchar ** model_path, gint * section)
465
g_return_if_fail(HUD_IS_MODEL_ITEM(item));
467
/* Make sure we have a place to put things, we require it */
468
g_return_if_fail(base_action != NULL);
469
g_return_if_fail(action_path != NULL);
470
g_return_if_fail(model_path != NULL);
471
g_return_if_fail(section != NULL);
472
g_return_if_fail(hud_model_item_is_parameterized(item));
474
*base_action = item->action_name_full;
475
*model_path = (const gchar *)g_object_get_data(G_OBJECT(item->submodel), EXPORT_PATH);
476
*action_path = item->action_path;
479
hud_item_mark_usage(HUD_ITEM(item));
296
484
typedef GObjectClass HudMenuModelCollectorClass;
298
486
static void hud_menu_model_collector_iface_init (HudSourceInterface *iface);
348
548
return context_quark;
551
/* Function to convert from the GMenu format for the accel to something
554
format_accel_for_users (gchar * accel)
560
GString * output = g_string_new("");
561
gchar * head = accel;
563
/* YEAH! String parsing, always my favorite. */
564
while (head[0] != '\0') {
565
if (head[0] == '<') {
566
/* We're in modifier land */
567
if (strncmp(head, "<Alt>", strlen("<Alt>")) == 0) {
568
g_string_append(output, "Alt + ");
569
head += strlen("<Alt>");
570
} else if (strncmp(head, "<Primary>", strlen("<Primary>")) == 0) {
571
g_string_append(output, "Ctrl + ");
572
head += strlen("<Primary>");
573
} else if (strncmp(head, "<Control>", strlen("<Control>")) == 0) {
574
g_string_append(output, "Ctrl + ");
575
head += strlen("<Control>");
576
} else if (strncmp(head, "<Shift>", strlen("<Shift>")) == 0) {
577
g_string_append(output, "Shift + ");
578
head += strlen("<Shift>");
579
} else if (strncmp(head, "<Super>", strlen("<Super>")) == 0) {
580
g_string_append(output, "Super + ");
581
head += strlen("<Super>");
583
/* Go to the close of the modifier */
584
head = g_strstr_len(head, -1, ">") + 1;
589
g_string_append(output, head);
595
return g_string_free(output, FALSE);
352
599
hud_menu_model_collector_model_changed (GMenuModel *model,
418
678
if ((link = g_menu_model_get_item_link (model, i, G_MENU_LINK_SECTION)))
420
hud_menu_model_collector_add_model (collector, link, context, action_namespace, label);
680
hud_menu_model_collector_add_model_internal (collector, link, NULL, context, action_namespace, label, recurse, collector->type);
421
681
g_object_unref (link);
424
684
if ((link = g_menu_model_get_item_link (model, i, G_MENU_LINK_SUBMENU)))
426
hud_menu_model_collector_add_model (collector, link, context, action_namespace, label);
686
hud_menu_model_collector_add_model_internal (collector, link, NULL, context, action_namespace, label, recurse - 1, collector->type);
687
if (item != NULL && recurse <= 1)
689
hud_model_item_set_submenu((HudModelItem *)item, link, collector->base_export_path);
427
691
g_object_unref (link);
430
694
g_free (action_namespace);
699
g_free (description);
436
704
hud_source_changed (HUD_SOURCE (collector));
440
hud_menu_model_collector_add_model (HudMenuModelCollector *collector,
442
HudMenuModelContext *parent_context,
443
const gchar *action_namespace,
707
/* Unexport a menu and unref the bus we kept */
709
unexport_menu (gpointer user_data)
711
exported_menu_id_t * idt = (exported_menu_id_t *)user_data;
713
g_dbus_connection_unexport_menu_model(idt->bus, idt->id);
714
g_object_unref(idt->bus);
721
hud_menu_model_collector_add_model_internal (HudMenuModelCollector *collector,
724
HudMenuModelContext *parent_context,
725
const gchar *action_namespace,
728
HudSourceItemType type)
730
g_return_if_fail(G_IS_MENU_MODEL(model));
732
collector->type = type;
734
/* We don't want to parse this one, just export it so that
735
the UI could use it if needed */
736
if (recurse == 0 && collector->base_export_path != NULL) {
737
/* Create the exported model */
738
GMenu * export = g_menu_new();
739
GMenuItem * item = g_menu_item_new_submenu("Root Export", model);
740
g_menu_append_item(export, item);
741
g_object_unref(item);
743
/* Build a struct for all the info we need */
744
exported_menu_id_t * idt = g_new0(exported_menu_id_t, 1);
745
idt->bus = g_object_ref(collector->session);
748
gchar * menu_path = g_strdup_printf("%s/menu%X", collector->base_export_path, GPOINTER_TO_UINT(model));
749
g_debug("Exporting menu model: %s", menu_path);
750
idt->id = g_dbus_connection_export_menu_model(collector->session, menu_path, G_MENU_MODEL(export), NULL);
752
/* Make sure we're ready to clean up */
753
g_object_set_data_full(G_OBJECT(model), EXPORT_PATH, menu_path, g_free);
754
g_object_set_data_full(G_OBJECT(model), EXPORT_MENU, export, g_object_unref);
756
/* All the callers of this function assume that we take the responsibility
757
* to manage the lifecycle of the model. Or in other words, HudMenuModelCollector
758
* takes the responsibility.
760
* g_dbus_connection_export_menu_model() increases the reference count of the given
761
* model and the model is not disposed before it's unexported.
763
* By using g_object_set_data_full() we guarantee that the model gets unexported
764
* and cleaned up when the collector disposes it self.
766
* menu_path is simply used as a unique key to store the idt in collector GObject.
767
* There is no need to retrieve the idt using g_object_get_data().
769
* The reason that it can't be on the model is because the model is referenced
770
* by the exported item. So the model will never be free'd until the export is
773
g_object_set_data_full(G_OBJECT(collector), menu_path, idt, unexport_menu);
780
g_object_set_data (G_OBJECT(model), RECURSE_DATA, GINT_TO_POINTER(recurse));
448
781
g_signal_connect (model, "items-changed", G_CALLBACK (hud_menu_model_collector_model_changed), collector);
449
collector->models = g_slist_prepend (collector->models, g_object_ref (model));
783
/* Setup the base structure */
784
model_data_t * model_data = g_new0(model_data_t, 1);
785
model_data->session = collector->session;
786
model_data->model = g_object_ref(model);
787
model_data->is_hud_aware = FALSE;
788
model_data->cancellable = g_cancellable_new();
789
model_data->path = g_strdup(path);
790
model_data->label = g_strdup(label);
791
model_data->recurse = recurse;
793
/* Add to our list of models */
794
collector->models = g_slist_prepend (collector->models, model_data);
797
g_dbus_connection_call (collector->session, collector->unique_bus_name, path,
798
"com.canonical.hud.Awareness", "CheckAwareness",
799
NULL, G_VARIANT_TYPE_UNIT, G_DBUS_CALL_FLAGS_NONE, -1, model_data->cancellable,
800
hud_menu_model_collector_hud_awareness_cb, &model_data->is_hud_aware);
451
803
/* The tokens in 'context' are the list of strings that got us up to
452
804
* where we are now, like "View > Toolbars".
473
825
g_signal_handlers_disconnect_by_func (data, hud_menu_model_collector_model_changed, user_data);
828
/* Sends an awareness to a model that needs it */
830
set_awareness (HudMenuModelCollector * collector, model_data_t * model_data, gboolean active)
832
if (!model_data->is_hud_aware) {
836
g_dbus_connection_call (collector->session, collector->unique_bus_name, model_data->path,
837
"com.canonical.hud.Awareness", "HudActiveChanged", g_variant_new ("(b)", active),
838
NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
843
/* We're avoiding having to allocate a struct by using the function
844
pointer here. Kinda sneaky, but it works */
846
make_aware (gpointer data, gpointer user_data)
848
return set_awareness(HUD_MENU_MODEL_COLLECTOR(user_data), (model_data_t *)data, TRUE);
852
make_unaware (gpointer data, gpointer user_data)
854
return set_awareness(HUD_MENU_MODEL_COLLECTOR(user_data), (model_data_t *)data, FALSE);
857
/* Handles the activeness of this collector */
477
859
hud_menu_model_collector_active_changed (HudMenuModelCollector *collector,
480
if (collector->app_menu_is_hud_aware)
481
g_dbus_connection_call (collector->session, collector->unique_bus_name, collector->app_menu_object_path,
482
"com.canonical.hud.Awareness", "HudActiveChanged", g_variant_new ("(b)", active),
483
NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
863
g_slist_foreach(collector->models, make_aware, collector);
865
g_slist_foreach(collector->models, make_unaware, collector);
485
if (collector->menubar_is_hud_aware)
486
g_dbus_connection_call (collector->session, collector->unique_bus_name, collector->menubar_object_path,
487
"com.canonical.hud.Awareness", "HudActiveChanged", g_variant_new ("(b)", active),
488
NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
529
910
item = g_ptr_array_index (items, i);
912
if (search_string == NULL && hud_model_item_is_toolbar(HUD_MODEL_ITEM(item))) {
530
916
result = hud_result_get_if_matched (item, search_string, collector->penalty);
532
g_ptr_array_add (results_array, result);
918
append_func(result, user_data);
923
hud_menu_model_collector_list_applications (HudSource *source,
924
HudTokenList *search_string,
925
void (*append_func) (const gchar *application_id, const gchar *application_icon, HudSourceItemType type, gpointer user_data),
928
HudMenuModelCollector *collector = HUD_MENU_MODEL_COLLECTOR (source);
932
items = collector->items;
934
for (i = 0; i < items->len; i++)
939
item = g_ptr_array_index (items, i);
940
result = hud_result_get_if_matched (item, search_string, collector->penalty);
942
append_func(collector->app_id, collector->icon, collector->type, user_data);
943
g_object_unref(result);
950
hud_menu_model_collector_get (HudSource *source,
951
const gchar *application_id)
953
HudMenuModelCollector *collector = HUD_MENU_MODEL_COLLECTOR (source);
955
if (g_strcmp0(collector->app_id, application_id) == 0)
962
hud_menu_model_collector_activate_toolbar (HudSource * source,
963
HudClientQueryToolbarItems titem,
964
GVariant *platform_data)
966
HudMenuModelCollector *collector = HUD_MENU_MODEL_COLLECTOR (source);
969
for (i = 0; i < collector->items->len; i++) {
970
HudModelItem * item = g_ptr_array_index(collector->items, i);
971
hud_model_item_activate_toolbar(item, titem, platform_data);
977
/* Free's the model data structure */
979
model_data_free (gpointer data)
981
model_data_t * model_data = (model_data_t *)data;
983
/* Make sure we don't have an operation outstanding */
984
g_cancellable_cancel (model_data->cancellable);
985
g_clear_object(&model_data->cancellable);
987
g_clear_pointer(&model_data->path, g_free);
988
g_clear_pointer(&model_data->label, g_free);
990
g_clear_object(&model_data->model);
536
997
hud_menu_model_collector_finalize (GObject *object)
543
1004
if (collector->refresh_id)
544
1005
g_source_remove (collector->refresh_id);
546
g_slist_free_full (collector->models, g_object_unref);
547
g_clear_object (&collector->app_menu);
548
g_clear_object (&collector->menubar);
549
g_clear_object (&collector->application);
550
g_clear_object (&collector->window);
1007
if (collector->muxer_export) {
1008
g_dbus_connection_unexport_action_group(collector->session, collector->muxer_export);
1009
collector->muxer_export = 0;
1012
g_slist_free_full (collector->models, model_data_free);
1013
g_clear_object (&collector->muxer);
552
1015
g_object_unref (collector->session);
553
1016
g_free (collector->unique_bus_name);
554
g_free (collector->app_menu_object_path);
555
g_free (collector->menubar_object_path);
556
g_free (collector->prefix);
557
g_free (collector->desktop_file);
1017
g_free (collector->app_id);
558
1018
g_free (collector->icon);
1019
g_object_unref (collector->keyword_mapping);
560
1021
g_ptr_array_unref (collector->items);
1023
g_clear_pointer(&collector->base_export_path, g_free);
562
1025
G_OBJECT_CLASS (hud_menu_model_collector_parent_class)
563
1026
->finalize (object);
622
* hud_menu_model_collector_get:
1101
* hud_menu_model_collector_new:
1102
* @application_id: a unique identifier for the application
1103
* @icon: the icon for the appliction
1104
* @penalty: the penalty to apply to all results
1105
* @export_path: the path to export items on dbus
1106
* @type: the type of items in this collector
1108
* Create a new #HudMenuModelCollector object
1110
* Return value: New #HudMenuModelCollector
1112
HudMenuModelCollector *
1113
hud_menu_model_collector_new (const gchar *application_id,
1116
const gchar *export_path,
1117
HudSourceItemType type)
1119
g_return_val_if_fail(application_id != NULL, NULL);
1120
g_return_val_if_fail(export_path != NULL, NULL);
1122
HudMenuModelCollector * collector = g_object_new(HUD_TYPE_MENU_MODEL_COLLECTOR, NULL);
1124
collector->app_id = g_strdup (application_id);
1125
collector->icon = g_strdup (icon);
1126
collector->penalty = penalty;
1127
collector->base_export_path = g_strdup(export_path);
1128
collector->type = type;
1130
collector->keyword_mapping = hud_keyword_mapping_new();
1131
hud_keyword_mapping_load(collector->keyword_mapping, collector->app_id, DATADIR, GNOMELOCALEDIR);
1133
GError * error = NULL;
1134
collector->muxer_export = g_dbus_connection_export_action_group(collector->session,
1135
collector->base_export_path,
1136
G_ACTION_GROUP(collector->muxer),
1139
if (error != NULL) {
1140
g_warning("Unable to export action group: %s", error->message);
1141
g_error_free(error);
1149
* hud_menu_model_collector_add_window:
623
1150
* @window: a #BamfWindow
624
* @desktop_file: the desktop file of the application of @window
625
* @icon: the application icon's name
627
1152
* If the given @window has #GMenuModel-style menus then returns a
628
1153
* collector for them, otherwise returns %NULL.
630
* @desktop_file is used for usage tracking.
632
1155
* Returns: a #HudMenuModelCollector, or %NULL
634
HudMenuModelCollector *
635
hud_menu_model_collector_get (BamfWindow *window,
636
const gchar *desktop_file,
1158
hud_menu_model_collector_add_window (HudMenuModelCollector * collector,
639
HudMenuModelCollector *collector;
1161
g_return_if_fail(HUD_IS_MENU_MODEL_COLLECTOR(collector));
640
1163
gchar *unique_bus_name;
641
1164
gchar *application_object_path;
642
1165
gchar *window_object_path;
643
GDBusConnection *session;
1166
gchar *app_menu_object_path;
1167
gchar *menubar_object_path;
1169
GDBusMenuModel * app_menu;
1170
GDBusMenuModel * menubar;
645
1172
unique_bus_name = bamf_window_get_utf8_prop (window, "_GTK_UNIQUE_BUS_NAME");
647
if (!unique_bus_name) {
651
session = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
656
collector = g_object_new (HUD_TYPE_MENU_MODEL_COLLECTOR, NULL);
657
collector->session = session;
658
collector->unique_bus_name = unique_bus_name;
660
collector->app_menu_object_path = bamf_window_get_utf8_prop (window, "_GTK_APP_MENU_OBJECT_PATH");
661
collector->menubar_object_path = bamf_window_get_utf8_prop (window, "_GTK_MENUBAR_OBJECT_PATH");
1174
if (!unique_bus_name)
1175
/* If this isn't set, we won't get very far... */
1178
if (!g_dbus_is_name(unique_bus_name)) {
1179
g_warning("Invalid BUS name '%s'", unique_bus_name);
1183
if (collector->unique_bus_name == NULL) {
1184
collector->unique_bus_name = g_strdup(unique_bus_name);
1187
if (g_strcmp0(unique_bus_name, collector->unique_bus_name) != 0) {
1188
g_warning("Bus name '%s' does not match '%s'", unique_bus_name, collector->unique_bus_name);
1189
g_free(unique_bus_name);
1192
g_clear_pointer(&unique_bus_name, g_free);
1194
app_menu_object_path = bamf_window_get_utf8_prop (window, "_GTK_APP_MENU_OBJECT_PATH");
1195
menubar_object_path = bamf_window_get_utf8_prop (window, "_GTK_MENUBAR_OBJECT_PATH");
662
1196
application_object_path = bamf_window_get_utf8_prop (window, "_GTK_APPLICATION_OBJECT_PATH");
663
1197
window_object_path = bamf_window_get_utf8_prop (window, "_GTK_WINDOW_OBJECT_PATH");
665
if (collector->app_menu_object_path)
1199
if (app_menu_object_path)
667
collector->app_menu = g_dbus_menu_model_get (session, unique_bus_name, collector->app_menu_object_path);
668
hud_menu_model_collector_add_model (collector, G_MENU_MODEL (collector->app_menu), NULL, NULL, NULL);
669
g_dbus_connection_call (session, unique_bus_name, collector->app_menu_object_path,
670
"com.canonical.hud.Awareness", "CheckAwareness",
671
NULL, G_VARIANT_TYPE_UNIT, G_DBUS_CALL_FLAGS_NONE, -1, collector->cancellable,
672
hud_menu_model_collector_hud_awareness_cb, &collector->app_menu_is_hud_aware);
1201
app_menu = g_dbus_menu_model_get (collector->session, collector->unique_bus_name, app_menu_object_path);
1202
hud_menu_model_collector_add_model_internal (collector, G_MENU_MODEL (app_menu), app_menu_object_path, NULL, NULL, NULL, DEFAULT_MENU_DEPTH, collector->type);
1203
g_object_unref(app_menu);
675
if (collector->menubar_object_path)
1206
if (menubar_object_path)
677
collector->menubar = g_dbus_menu_model_get (session, unique_bus_name, collector->menubar_object_path);
678
hud_menu_model_collector_add_model (collector, G_MENU_MODEL (collector->menubar), NULL, NULL, NULL);
679
g_dbus_connection_call (session, unique_bus_name, collector->menubar_object_path,
680
"com.canonical.hud.Awareness", "CheckAwareness",
681
NULL, G_VARIANT_TYPE_UNIT, G_DBUS_CALL_FLAGS_NONE, -1, collector->cancellable,
682
hud_menu_model_collector_hud_awareness_cb, &collector->menubar_is_hud_aware);
1208
menubar = g_dbus_menu_model_get (collector->session, collector->unique_bus_name, menubar_object_path);
1209
hud_menu_model_collector_add_model_internal (collector, G_MENU_MODEL (menubar), menubar_object_path, NULL, NULL, NULL, DEFAULT_MENU_DEPTH, collector->type);
1210
g_object_unref(menubar);
685
1213
if (application_object_path)
686
collector->application = g_dbus_action_group_get (session, unique_bus_name, application_object_path);
1214
hud_menu_model_collector_add_actions(collector, G_ACTION_GROUP(g_dbus_action_group_get (collector->session, collector->unique_bus_name, application_object_path)), "app");
688
1216
if (window_object_path)
689
collector->window = g_dbus_action_group_get (session, unique_bus_name, window_object_path);
691
collector->is_application = TRUE;
692
collector->desktop_file = g_strdup (desktop_file);
693
collector->icon = g_strdup (icon);
1217
hud_menu_model_collector_add_actions(collector, G_ACTION_GROUP(g_dbus_action_group_get (collector->session, collector->unique_bus_name, window_object_path)), "win");
695
1219
/* when the action groups change, we could end up having items
696
1220
* enabled/disabled. how to deal with that?
726
1249
* Returns: a new #HudMenuModelCollector
728
HudMenuModelCollector *
729
hud_menu_model_collector_new_for_endpoint (const gchar *application_id,
733
const gchar *bus_name,
734
const gchar *object_path)
736
HudMenuModelCollector *collector;
738
collector = g_object_new (HUD_TYPE_MENU_MODEL_COLLECTOR, NULL);
740
collector->session = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
742
collector->app_menu = g_dbus_menu_model_get (collector->session, bus_name, object_path);
743
collector->application = g_dbus_action_group_get (collector->session, bus_name, object_path);
745
collector->is_application = FALSE;
746
collector->prefix = g_strdup (prefix);
747
collector->desktop_file = g_strdup (application_id);
748
collector->icon = g_strdup (icon);
749
collector->penalty = penalty;
751
hud_menu_model_collector_add_model (collector, G_MENU_MODEL (collector->app_menu), NULL, NULL, prefix);
1252
hud_menu_model_collector_add_endpoint (HudMenuModelCollector * collector,
1253
const gchar *prefix,
1254
const gchar *bus_name,
1255
const gchar *menu_path,
1256
const gchar *action_path)
1258
g_return_if_fail(HUD_IS_MENU_MODEL_COLLECTOR(collector));
1260
GActionGroup * group = G_ACTION_GROUP(g_dbus_action_group_get (collector->session, bus_name, action_path));
1261
hud_menu_model_collector_add_actions(collector, group, NULL);
1262
g_object_unref(group);
1264
GDBusMenuModel * app_menu = g_dbus_menu_model_get (collector->session, bus_name, menu_path);
1265
hud_menu_model_collector_add_model(collector, G_MENU_MODEL (app_menu), prefix, DEFAULT_MENU_DEPTH);
1266
g_object_unref(app_menu);
1272
* hud_menu_model_collector_add_model:
1273
* @collector: A #HudMenuModelCollector object
1274
* @model: Model to add
1275
* @prefix: (allow none): Text prefix to add to all entries if needed
1276
* @recurse: Amount of levels to go down the model.
1278
* Adds a Menu Model to the collector.
1281
hud_menu_model_collector_add_model (HudMenuModelCollector * collector, GMenuModel * model, const gchar * prefix, guint recurse)
1283
g_return_if_fail(HUD_IS_MENU_MODEL_COLLECTOR(collector));
1284
g_return_if_fail(G_IS_MENU_MODEL(model));
1286
return hud_menu_model_collector_add_model_internal(collector, model, NULL, NULL, NULL, prefix, recurse, collector->type);
1290
* hud_menu_model_collector_add_actions:
1291
* @collector: A #HudMenuModelCollector object
1292
* @group: Action Group to add
1293
* @prefix: (allow none): Text prefix to add to all entries if needed
1295
* Add a set of actios to the collector
1298
hud_menu_model_collector_add_actions (HudMenuModelCollector * collector, GActionGroup * group, const gchar * prefix)
1300
g_return_if_fail(HUD_IS_MENU_MODEL_COLLECTOR(collector));
1301
g_return_if_fail(G_IS_ACTION_GROUP(group));
1303
g_action_muxer_insert(collector->muxer, prefix, group);
1309
* hud_menu_model_collector_get_items:
1310
* @collector: A #HudMenuModelCollector
1312
* Get the list of items that are currently being watched
1314
* Return value: (transfer full) (element-type HudItem): Items to look at
1317
hud_menu_model_collector_get_items (HudSource * source)
1319
g_return_val_if_fail(HUD_IS_MENU_MODEL_COLLECTOR(source), NULL);
1320
HudMenuModelCollector * mcollector = HUD_MENU_MODEL_COLLECTOR(source);
1322
GList * retval = NULL;
1324
for (i = 0; i < mcollector->items->len; i++) {
1325
retval = g_list_prepend(retval, g_object_ref(g_ptr_array_index(mcollector->items, i)));
1332
* hud_menu_model_collector_get_app_id:
1333
* @collector: A #HudMenuModelCollector
1335
* The ID of the application here
1337
* Return value: Application ID
1339
static const gchar *
1340
hud_menu_model_collector_get_app_id (HudSource * collector)
1342
g_return_val_if_fail(HUD_IS_MENU_MODEL_COLLECTOR(collector), NULL);
1343
return HUD_MENU_MODEL_COLLECTOR(collector)->app_id;
1347
* hud_menu_model_collector_get_app_icon:
1348
* @collector: A #HudMenuModelCollector
1350
* The icon of the application here
1352
* Return value: Application icon
1354
static const gchar *
1355
hud_menu_model_collector_get_app_icon (HudSource * collector)
1357
g_return_val_if_fail(HUD_IS_MENU_MODEL_COLLECTOR(collector), NULL);
1358
return HUD_MENU_MODEL_COLLECTOR(collector)->icon;