Merge lp:~3v1n0/bamf/wmclass-matching into lp:bamf/0.4

Proposed by Marco Trevisan (Treviño)
Status: Merged
Merged at revision: 387
Proposed branch: lp:~3v1n0/bamf/wmclass-matching
Merge into: lp:bamf/0.4
Diff against target: 488 lines (+198/-40)
3 files modified
src/bamf-application.c (+50/-3)
src/bamf-application.h (+6/-0)
src/bamf-matcher.c (+142/-37)
To merge this branch: bzr merge lp:~3v1n0/bamf/wmclass-matching
Reviewer Review Type Date Requested Status
Jason Smith (community) Approve
Review via email: mp+54941@code.launchpad.net

Description of the change

Now bamf uses also the window WMCLASS parameter and the .desktop file StartupWMClass to associate a window to its application.
This causes that each bamf application should now have its own class; a window is considered as part of that application only if its wmclass matches the application one.

A desktop file is now associated to an application also considering the StartupWMClass key value.

To post a comment you must log in.
Revision history for this message
Mikkel Kamstrup Erlandsen (kamstrup) wrote :

I am not sure I'm the right person to review this branch, but I got one nitpick nontheless :-)

The get_class() and set_class() methods on BamfApplication are not very binding friendly. If I called app.get_class() from Vala or PyGI it would normally give me the GObjectClass struct for the object, but this patch would override that method.

Maybe get/set_wmclass() instead?

Revision history for this message
Marco Trevisan (Treviño) (3v1n0) wrote :

Yes, you're right about that. I'll fix it.

lp:~3v1n0/bamf/wmclass-matching updated
392. By Marco Trevisan (Treviño)

application_class renamed as application_wmclass

To avoid gobjet get_class function overriding

393. By Marco Trevisan (Treviño)

Some code spaces cleanup.

Revision history for this message
Jason Smith (jassmith) wrote :

Works for me, looks good

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'src/bamf-application.c'
--- src/bamf-application.c 2011-01-14 15:53:35 +0000
+++ src/bamf-application.c 2011-03-29 11:26:03 +0000
@@ -48,6 +48,7 @@
48 GList * desktop_file_list;48 GList * desktop_file_list;
49 char * app_type;49 char * app_type;
50 char * icon;50 char * icon;
51 char * wmclass;
51 gboolean is_tab_container;52 gboolean is_tab_container;
52 gboolean show_stubs;53 gboolean show_stubs;
53};54};
@@ -83,6 +84,19 @@
83 return result;84 return result;
84}85}
8586
87char *
88bamf_application_get_wmclass (BamfApplication *application)
89{
90 BamfApplicationPrivate *priv;
91 char *result = NULL;
92
93 g_return_val_if_fail (BAMF_IS_APPLICATION (application), NULL);
94 priv = application->priv;
95
96 result = g_strdup (priv->wmclass);
97 return result;
98}
99
86static gboolean100static gboolean
87icon_name_is_valid (char *name)101icon_name_is_valid (char *name)
88{102{
@@ -212,6 +226,18 @@
212 bamf_application_setup_icon_and_name (application);226 bamf_application_setup_icon_and_name (application);
213}227}
214228
229void
230bamf_application_set_wmclass (BamfApplication *application,
231 char *wmclass)
232{
233 g_return_if_fail (BAMF_IS_APPLICATION (application));
234
235 if (wmclass && wmclass[0] != '\0')
236 application->priv->wmclass = g_strdup (wmclass);
237 else
238 application->priv->wmclass = NULL;
239}
240
215GArray *241GArray *
216bamf_application_get_xids (BamfApplication *application)242bamf_application_get_xids (BamfApplication *application)
217{243{
@@ -312,12 +338,15 @@
312 GList *children, *l;338 GList *children, *l;
313 BamfView *child;339 BamfView *child;
314340
315 g_return_val_if_fail (BAMF_IS_APPLICATION (view), NULL); 341 g_return_val_if_fail (BAMF_IS_APPLICATION (view), NULL);
316 self = BAMF_APPLICATION (view);342 self = BAMF_APPLICATION (view);
317 343
344 if (self->priv->wmclass)
345 return g_strdup_printf ("application%i", abs (g_str_hash (self->priv->wmclass)));
346
318 if (self->priv->desktop_file)347 if (self->priv->desktop_file)
319 return g_strdup_printf ("application%i", abs (g_str_hash (self->priv->desktop_file)));348 return g_strdup_printf ("application%i", abs (g_str_hash (self->priv->desktop_file)));
320 349
321 children = bamf_view_get_children (BAMF_VIEW (self));350 children = bamf_view_get_children (BAMF_VIEW (self));
322 for (l = children; l; l = l->next)351 for (l = children; l; l = l->next)
323 {352 {
@@ -562,6 +591,12 @@
562 g_free (priv->app_type);591 g_free (priv->app_type);
563 priv->app_type = NULL;592 priv->app_type = NULL;
564 }593 }
594
595 if (priv->wmclass)
596 {
597 g_free (priv->wmclass);
598 priv->wmclass = NULL;
599 }
565 600
566 g_signal_handlers_disconnect_by_func (G_OBJECT (bamf_matcher_get_default ()), matcher_favorites_changed, object);601 g_signal_handlers_disconnect_by_func (G_OBJECT (bamf_matcher_get_default ()), matcher_favorites_changed, object);
567602
@@ -577,6 +612,7 @@
577 priv->is_tab_container = FALSE;612 priv->is_tab_container = FALSE;
578 priv->app_type = g_strdup ("system");613 priv->app_type = g_strdup ("system");
579 priv->show_stubs = TRUE;614 priv->show_stubs = TRUE;
615 priv->wmclass = NULL;
580 616
581 g_signal_connect (G_OBJECT (bamf_matcher_get_default ()), "favorites-changed", 617 g_signal_connect (G_OBJECT (bamf_matcher_get_default ()), "favorites-changed",
582 (GCallback) matcher_favorites_changed, self);618 (GCallback) matcher_favorites_changed, self);
@@ -651,6 +687,17 @@
651 return application; 687 return application;
652}688}
653689
690BamfApplication *
691bamf_application_new_with_wmclass (char *wmclass)
692{
693 BamfApplication *application;
694 application = (BamfApplication *) g_object_new (BAMF_TYPE_APPLICATION, NULL);
695
696 bamf_application_set_wmclass (application, wmclass);
697
698 return application;
699}
700
654/**701/**
655 bamf_application_get_show_stubs:702 bamf_application_get_show_stubs:
656 @application: Application to check for menu stubs703 @application: Application to check for menu stubs
657704
=== modified file 'src/bamf-application.h'
--- src/bamf-application.h 2010-09-11 02:52:33 +0000
+++ src/bamf-application.h 2011-03-29 11:26:03 +0000
@@ -66,6 +66,10 @@
66gboolean bamf_application_contains_similar_to_window (BamfApplication *app, 66gboolean bamf_application_contains_similar_to_window (BamfApplication *app,
67 BamfWindow *window);67 BamfWindow *window);
6868
69char * bamf_application_get_wmclass (BamfApplication *application);
70void bamf_application_set_wmclass (BamfApplication *application,
71 char *wmclass);
72
69BamfApplication * bamf_application_new (void);73BamfApplication * bamf_application_new (void);
7074
71BamfApplication * bamf_application_new_from_desktop_file (char * desktop_file);75BamfApplication * bamf_application_new_from_desktop_file (char * desktop_file);
@@ -73,4 +77,6 @@
7377
74BamfApplication * bamf_application_new_from_desktop_files (GList * desktop_files);78BamfApplication * bamf_application_new_from_desktop_files (GList * desktop_files);
7579
80BamfApplication * bamf_application_new_with_wmclass (char *wmclass);
81
76#endif82#endif
7783
=== modified file 'src/bamf-matcher.c'
--- src/bamf-matcher.c 2011-03-15 12:09:16 +0000
+++ src/bamf-matcher.c 2011-03-29 11:26:03 +0000
@@ -61,6 +61,7 @@
61 GArray * known_pids;61 GArray * known_pids;
62 GHashTable * desktop_id_table;62 GHashTable * desktop_id_table;
63 GHashTable * desktop_file_table;63 GHashTable * desktop_file_table;
64 GHashTable * desktop_class_table;
64 GHashTable * exec_list;65 GHashTable * exec_list;
65 GHashTable * registered_pids;66 GHashTable * registered_pids;
66 GList * views;67 GList * views;
@@ -416,17 +417,43 @@
416 file_list = g_list_append (file_list, datadup);417 file_list = g_list_append (file_list, datadup);
417 id_list = g_list_append (id_list, datadup);418 id_list = g_list_append (id_list, datadup);
418 }419 }
419 420
420 g_hash_table_insert (desktop_file_table, g_strdup (exec), file_list);421 g_hash_table_insert (desktop_file_table, g_strdup (exec), file_list);
421 g_hash_table_insert (desktop_id_table, g_strdup (desktop_id), id_list);422 g_hash_table_insert (desktop_id_table, g_strdup (desktop_id), id_list);
422423}
424
425static void
426insert_desktop_file_class_into_table (BamfMatcher *self,
427 const char *desktop_file,
428 GHashTable *desktop_class_table)
429{
430 GKeyFile *desktop_keyfile;
431 char *class;
432
433 g_return_if_fail (desktop_file);
434
435 desktop_keyfile = g_key_file_new ();
436
437 if (g_key_file_load_from_file (desktop_keyfile, desktop_file, G_KEY_FILE_NONE,
438 NULL))
439 {
440 class = g_key_file_get_string (desktop_keyfile,
441 G_KEY_FILE_DESKTOP_GROUP,
442 G_KEY_FILE_DESKTOP_KEY_STARTUP_WM_CLASS,
443 NULL);
444 if (class)
445 g_hash_table_insert (desktop_class_table, g_strdup (desktop_file), class);
446
447 g_key_file_free (desktop_keyfile);
448 }
423}449}
424450
425static void451static void
426load_desktop_file_to_table (BamfMatcher * self,452load_desktop_file_to_table (BamfMatcher * self,
427 const char *file,453 const char *file,
428 GHashTable *desktop_file_table,454 GHashTable *desktop_file_table,
429 GHashTable *desktop_id_table)455 GHashTable *desktop_id_table,
456 GHashTable *desktop_class_table)
430{457{
431 GAppInfo *desktop_file;458 GAppInfo *desktop_file;
432 char *exec;459 char *exec;
@@ -467,6 +494,7 @@
467 desktop_id = g_string_truncate (desktop_id, desktop_id->len - 8); /* remove last 8 characters for .desktop */494 desktop_id = g_string_truncate (desktop_id, desktop_id->len - 8); /* remove last 8 characters for .desktop */
468 495
469 insert_data_into_tables (self, file, exec, desktop_id->str, desktop_file_table, desktop_id_table);496 insert_data_into_tables (self, file, exec, desktop_id->str, desktop_file_table, desktop_id_table);
497 insert_desktop_file_class_into_table (self, file, desktop_class_table);
470498
471 g_free (exec);499 g_free (exec);
472 g_string_free (desktop_id, TRUE);500 g_string_free (desktop_id, TRUE);
@@ -476,7 +504,8 @@
476load_directory_to_table (BamfMatcher * self,504load_directory_to_table (BamfMatcher * self,
477 const char *directory,505 const char *directory,
478 GHashTable *desktop_file_table,506 GHashTable *desktop_file_table,
479 GHashTable *desktop_id_table)507 GHashTable *desktop_id_table,
508 GHashTable *desktop_class_table)
480{509{
481 GFile *dir;510 GFile *dir;
482 GFileEnumerator *enumerator;511 GFileEnumerator *enumerator;
@@ -506,7 +535,8 @@
506 load_desktop_file_to_table (self,535 load_desktop_file_to_table (self,
507 path,536 path,
508 desktop_file_table,537 desktop_file_table,
509 desktop_id_table);538 desktop_id_table,
539 desktop_class_table);
510540
511 g_free ((gpointer) path);541 g_free ((gpointer) path);
512 g_object_unref (info);542 g_object_unref (info);
@@ -520,7 +550,8 @@
520load_index_file_to_table (BamfMatcher * self,550load_index_file_to_table (BamfMatcher * self,
521 const char *index_file,551 const char *index_file,
522 GHashTable *desktop_file_table,552 GHashTable *desktop_file_table,
523 GHashTable *desktop_id_table)553 GHashTable *desktop_id_table,
554 GHashTable *desktop_class_table)
524{555{
525 GFile *file;556 GFile *file;
526 GFileInputStream *stream;557 GFileInputStream *stream;
@@ -569,6 +600,7 @@
569 g_string_truncate (desktop_id, desktop_id->len - 8);600 g_string_truncate (desktop_id, desktop_id->len - 8);
570 601
571 insert_data_into_tables (self, filename->str, exec, desktop_id->str, desktop_file_table, desktop_id_table);602 insert_data_into_tables (self, filename->str, exec, desktop_id->str, desktop_file_table, desktop_id_table);
603 insert_desktop_file_class_into_table (self, filename->str, desktop_class_table);
572604
573 g_string_free (desktop_id, TRUE);605 g_string_free (desktop_id, TRUE);
574 length = 0;606 length = 0;
@@ -612,7 +644,7 @@
612 if (!g_list_find_custom (dirs, "/usr/local/share/applications", (GCompareFunc) g_strcmp0))644 if (!g_list_find_custom (dirs, "/usr/local/share/applications", (GCompareFunc) g_strcmp0))
613 dirs = g_list_prepend (dirs, g_strdup ("/usr/local/share/applications"));645 dirs = g_list_prepend (dirs, g_strdup ("/usr/local/share/applications"));
614 646
615 dirs = g_list_prepend (dirs, g_strdup (g_build_filename (g_get_home_dir (), ".share/applications", NULL)));647 dirs = g_list_prepend (dirs, g_strdup (g_build_filename (g_get_home_dir (), ".local/share/applications", NULL)));
616 648
617 if (data_dirs)649 if (data_dirs)
618 g_strfreev (data_dirs);650 g_strfreev (data_dirs);
@@ -690,6 +722,7 @@
690 {722 {
691 g_hash_table_foreach_remove (self->priv->desktop_id_table, (GHRFunc) hash_table_remove_values, path);723 g_hash_table_foreach_remove (self->priv->desktop_id_table, (GHRFunc) hash_table_remove_values, path);
692 g_hash_table_foreach_remove (self->priv->desktop_file_table, (GHRFunc) hash_table_remove_values, path);724 g_hash_table_foreach_remove (self->priv->desktop_file_table, (GHRFunc) hash_table_remove_values, path);
725 g_hash_table_remove (self->priv->desktop_class_table, path);
693 }726 }
694727
695out:728out:
@@ -697,7 +730,10 @@
697}730}
698731
699static void732static void
700create_desktop_file_table (BamfMatcher * self, GHashTable **desktop_file_table, GHashTable **desktop_id_table)733create_desktop_file_table (BamfMatcher * self,
734 GHashTable **desktop_file_table,
735 GHashTable **desktop_id_table,
736 GHashTable **desktop_class_table)
701{737{
702 GList *directories;738 GList *directories;
703 GList *l;739 GList *l;
@@ -718,6 +754,12 @@
718 (GDestroyNotify) g_free,754 (GDestroyNotify) g_free,
719 NULL);755 NULL);
720756
757 *desktop_class_table =
758 g_hash_table_new_full ((GHashFunc) g_str_hash,
759 (GEqualFunc) g_str_equal,
760 (GDestroyNotify) g_free,
761 (GDestroyNotify) g_free);
762
721 g_return_if_fail (BAMF_IS_MATCHER (self));763 g_return_if_fail (BAMF_IS_MATCHER (self));
722764
723 directories = get_desktop_file_directories (self);765 directories = get_desktop_file_directories (self);
@@ -740,11 +782,13 @@
740782
741 if (g_file_test (bamf_file, G_FILE_TEST_EXISTS))783 if (g_file_test (bamf_file, G_FILE_TEST_EXISTS))
742 {784 {
743 load_index_file_to_table (self, bamf_file, *desktop_file_table, *desktop_id_table);785 load_index_file_to_table (self, bamf_file, *desktop_file_table,
786 *desktop_id_table, *desktop_class_table);
744 }787 }
745 else788 else
746 {789 {
747 load_directory_to_table (self, directory, *desktop_file_table, *desktop_id_table);790 load_directory_to_table (self, directory, *desktop_file_table,
791 *desktop_id_table, *desktop_class_table);
748 }792 }
749793
750 g_free (directory);794 g_free (directory);
@@ -993,38 +1037,81 @@
993 }1037 }
994 else1038 else
995 {1039 {
996 char *class_name = window_class_name (window);1040 char *window_class = window_class_name (window);
9971041
998 if (class_name)1042 char *desktop_file;
1043 char *desktop_class;
1044
1045 if (window_class)
999 {1046 {
1000 class_name = g_ascii_strdown (class_name, -1);1047 char *window_class_down = g_ascii_strdown (g_strdup(window_class), -1);
1001 l = g_hash_table_lookup (priv->desktop_id_table, class_name);1048 l = g_hash_table_lookup (priv->desktop_id_table, window_class_down);
1049 g_free (window_class_down);
10021050
1003 for (; l; l = l->next)1051 for (; l; l = l->next)
1004 {1052 {
1005 if (l->data && !g_list_find_custom (desktop_files, l->data, (GCompareFunc) g_strcmp0))1053 desktop_file = l->data;
1006 desktop_files = g_list_prepend (desktop_files, g_strdup (l->data));1054 if (desktop_file)
1007 }1055 {
10081056 desktop_class = g_hash_table_lookup (priv->desktop_class_table, desktop_file);
1009 desktop_files = g_list_reverse (desktop_files);1057 if ((desktop_class == NULL || g_strcmp0 (desktop_class, window_class) == 0) &&
1010 g_free (class_name);1058 !g_list_find_custom (desktop_files, desktop_file,
1011 }1059 (GCompareFunc) g_strcmp0))
1060 {
1061 desktop_files = g_list_prepend (desktop_files, g_strdup (desktop_file));
1062 }
1063 }
1064 }
1065
1066 desktop_files = g_list_reverse (desktop_files);
1067 }
1068
1069 /* Iterate over the desktop class table, and add matching desktop files */
1070 gpointer key;
1071 gpointer value;
1072 GHashTableIter iter;
1073 g_hash_table_iter_init (&iter, priv->desktop_class_table);
1074
1075 while (g_hash_table_iter_next (&iter, &key, &value))
1076 {
1077 desktop_file = g_strdup (key);
1078 desktop_class = value;
1079 if (g_strcmp0 (desktop_class, window_class) == 0 &&
1080 !g_list_find_custom (desktop_files, desktop_file, (GCompareFunc) g_strcmp0))
1081 {
1082 desktop_files = g_list_prepend (desktop_files, desktop_file);
1083 }
1084 }
10121085
1013 pid = bamf_legacy_window_get_pid (window);1086 pid = bamf_legacy_window_get_pid (window);
1014
1015 pid_list = bamf_matcher_possible_applications_for_pid (self, pid);1087 pid_list = bamf_matcher_possible_applications_for_pid (self, pid);
1016 1088
1017 /* Append these files to the end to give preference to class_name style picking.1089 /* Append these files to the end to give preference to window_class style picking.
1018 This style of matching is prefered and used by GNOME Shell however does not work1090 This style of matching is prefered and used by GNOME Shell however does not work
1019 very well in practice, thus requiring the fallback here */1091 very well in practice, thus requiring the fallback here */
1020 for (l = pid_list; l; l = l->next)1092 for (l = pid_list; l; l = l->next)
1021 {1093 {
1094 desktop_file = l->data;
1022 if (g_list_find_custom (desktop_files, l->data, (GCompareFunc) g_strcmp0))1095 if (g_list_find_custom (desktop_files, l->data, (GCompareFunc) g_strcmp0))
1023 g_free (l->data);1096 g_free (desktop_file);
1024 else1097 else
1025 desktop_files = g_list_append (desktop_files, l->data);1098 {
1099 if (window_class)
1100 {
1101 desktop_class = g_hash_table_lookup (priv->desktop_class_table, desktop_file);
1102 if ((desktop_class == NULL || g_strcmp0 (desktop_class, window_class) == 0) &&
1103 !g_list_find_custom (desktop_files, desktop_file,
1104 (GCompareFunc) g_strcmp0))
1105 {
1106 desktop_files = g_list_append (desktop_files, desktop_file);
1107 }
1108 }
1109 else
1110 desktop_files = g_list_append (desktop_files, desktop_file);
1111 }
1026 }1112 }
1027 1113
1114 g_free (window_class);
1028 g_list_free (pid_list);1115 g_list_free (pid_list);
1029 }1116 }
1030 1117
@@ -1039,6 +1126,8 @@
1039 BamfLegacyWindow *window;1126 BamfLegacyWindow *window;
1040 GList *views, *a;1127 GList *views, *a;
1041 char *desktop_file;1128 char *desktop_file;
1129 char *win_class;
1130 char *app_class;
1042 BamfApplication *app = NULL, *best = NULL;1131 BamfApplication *app = NULL, *best = NULL;
1043 BamfView *view;1132 BamfView *view;
10441133
@@ -1049,6 +1138,7 @@
1049 views = self->priv->views;1138 views = self->priv->views;
10501139
1051 possible_apps = bamf_matcher_possible_applications_for_window (self, bamf_window);1140 possible_apps = bamf_matcher_possible_applications_for_window (self, bamf_window);
1141 win_class = window_class_name(window);
10521142
1053 /* Loop over every application, inside that application see if its .desktop file1143 /* Loop over every application, inside that application see if its .desktop file
1054 * matches with any of our possible hits. If so we match it. If we have no possible hits1144 * matches with any of our possible hits. If so we match it. If we have no possible hits
@@ -1062,8 +1152,16 @@
1062 continue;1152 continue;
10631153
1064 app = BAMF_APPLICATION (view);1154 app = BAMF_APPLICATION (view);
1155 app_class = bamf_application_get_wmclass (app);
1156
1157 if (app_class != NULL && g_strcmp0 (win_class, app_class) != 0)
1158 {
1159 g_free (app_class);
1160 continue;
1161 }
1162
1065 desktop_file = bamf_application_get_desktop_file (app);1163 desktop_file = bamf_application_get_desktop_file (app);
1066 1164
1067 if (possible_apps)1165 if (possible_apps)
1068 {1166 {
1069 /* primary matching */1167 /* primary matching */
@@ -1084,7 +1182,8 @@
1084 if (bamf_application_contains_similar_to_window (app, bamf_window))1182 if (bamf_application_contains_similar_to_window (app, bamf_window))
1085 best = app;1183 best = app;
1086 }1184 }
1087 1185
1186 g_free (app_class);
1088 g_free (desktop_file);1187 g_free (desktop_file);
1089 }1188 }
10901189
@@ -1095,16 +1194,19 @@
1095 else1194 else
1096 best = bamf_application_new ();1195 best = bamf_application_new ();
10971196
1197 bamf_application_set_wmclass (best, win_class);
1198
1098 bamf_matcher_register_view (self, BAMF_VIEW (best));1199 bamf_matcher_register_view (self, BAMF_VIEW (best));
1099 g_object_unref (best);1200 g_object_unref (best);
1100 }1201 }
11011202
1102 for (l = possible_apps; l; l = l->next)1203 g_free (win_class);
1103 {
1104 char *str = l->data;
1105 g_free (str);
1106 }
11071204
1205 for (l = possible_apps; l; l = l->next)
1206 {
1207 char *str = l->data;
1208 g_free (str);
1209 }
11081210
1109 g_list_free (possible_apps);1211 g_list_free (possible_apps);
11101212
@@ -1340,7 +1442,8 @@
1340 load_desktop_file_to_table (self,1442 load_desktop_file_to_table (self,
1341 desktop_file,1443 desktop_file,
1342 self->priv->desktop_file_table,1444 self->priv->desktop_file_table,
1343 self->priv->desktop_id_table);1445 self->priv->desktop_id_table,
1446 self->priv->desktop_class_table);
1344}1447}
13451448
1346void1449void
@@ -1731,11 +1834,13 @@
17311834
1732 g_array_free (prefixstrings, TRUE);1835 g_array_free (prefixstrings, TRUE);
17331836
1734 create_desktop_file_table (self, &(priv->desktop_file_table), &(priv->desktop_id_table));1837 create_desktop_file_table (self, &(priv->desktop_file_table),
1838 &(priv->desktop_id_table),
1839 &(priv->desktop_class_table));
17351840
1736 screen = bamf_legacy_screen_get_default ();1841 screen = bamf_legacy_screen_get_default ();
1737 g_signal_connect (G_OBJECT (screen), "window-opened",1842 g_signal_connect (G_OBJECT (screen), "window-opened",
1738 (GCallback) handle_window_opened, self);1843 (GCallback) handle_window_opened, self);
17391844
1740 approver = bamf_indicator_source_get_default ();1845 approver = bamf_indicator_source_get_default ();
1741 g_signal_connect (G_OBJECT (approver), "indicator-opened",1846 g_signal_connect (G_OBJECT (approver), "indicator-opened",

Subscribers

People subscribed via source and target branches