Merge lp:~3v1n0/bamf/fixes into lp:bamf/0.4

Proposed by Marco Trevisan (Treviño)
Status: Merged
Merged at revision: 412
Proposed branch: lp:~3v1n0/bamf/fixes
Merge into: lp:bamf/0.4
Diff against target: 1121 lines (+555/-236)
3 files modified
src/bamf-application.c (+27/-14)
src/bamf-application.h (+4/-4)
src/bamf-matcher.c (+524/-218)
To merge this branch: bzr merge lp:~3v1n0/bamf/fixes
Reviewer Review Type Date Requested Status
Jason Smith (community) Approve
Unity Community Hackers Pending
Review via email: mp+65434@code.launchpad.net

Description of the change

This is a branch I'm working on during my spare time since some weeks; it includes some BAMF miscellaneous fixes.

 - Improved desktop folders monitoring support (fix bug #676593) supporting monitoring
   newly added .desktop files, newly added folders containing .desktop files
   (recursively), edited .desktop files (reducing the rate limit, to save CPU)
 - Correctly clear from BAMF cache .desktop files that are removed from system
 - Order correctly the .desktop file keeping their priority
 - Support the ~/Desktop folder and $XDG_DATA_HOME as .desktop storages (with
   highest priority, the order will be kept when adding new files) bug #768636
 - Some memory leaks and coding style fixes...

I would have added also the support for dynamically update a bamf_application when a .desktop file (that matches it) is removed, but I guess that it's not vital... On next application reload the user will notice the change (however, if it is requested, I've already done something in it).

For more informations, look at the logs [1]; I've wrote anything there.

[1] http://bazaar.launchpad.net/~3v1n0/bamf/fixes/changes

To post a comment you must log in.
lp:~3v1n0/bamf/fixes updated
423. By Marco Trevisan (Treviño)

compare_sub_values optimization.

Generate the "prefix" string just once, and not for every sub-folder
.desktop item compared. This should save many allocations/copies...

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

+1 looks good :)

runs well too!

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-04-18 17:34:28 +0000
+++ src/bamf-application.c 2011-06-26 22:21:13 +0000
@@ -237,21 +237,30 @@
237237
238void238void
239bamf_application_set_desktop_file (BamfApplication *application,239bamf_application_set_desktop_file (BamfApplication *application,
240 char * desktop_file)240 const char * desktop_file)
241{241{
242 g_return_if_fail (BAMF_IS_APPLICATION (application));242 g_return_if_fail (BAMF_IS_APPLICATION (application));
243243
244 application->priv->desktop_file = g_strdup (desktop_file);244 if (application->priv->desktop_file)
245 g_free (application->priv->desktop_file);
246
247 if (desktop_file && desktop_file[0] != '\0')
248 application->priv->desktop_file = g_strdup (desktop_file);
249 else
250 application->priv->desktop_file = NULL;
245251
246 bamf_application_setup_icon_and_name (application);252 bamf_application_setup_icon_and_name (application);
247}253}
248254
249void255void
250bamf_application_set_wmclass (BamfApplication *application,256bamf_application_set_wmclass (BamfApplication *application,
251 char *wmclass)257 const char *wmclass)
252{258{
253 g_return_if_fail (BAMF_IS_APPLICATION (application));259 g_return_if_fail (BAMF_IS_APPLICATION (application));
254260
261 if (application->priv->wmclass)
262 g_free (application->priv->wmclass);
263
255 if (wmclass && wmclass[0] != '\0')264 if (wmclass && wmclass[0] != '\0')
256 application->priv->wmclass = g_strdup (wmclass);265 application->priv->wmclass = g_strdup (wmclass);
257 else266 else
@@ -517,16 +526,24 @@
517 g_return_if_fail (list);526 g_return_if_fail (list);
518527
519 priv = self->priv;528 priv = self->priv;
520 529
530 if (priv->desktop_file_list)
531 {
532 g_list_free_full (priv->desktop_file_list, g_free);
533 priv->desktop_file_list = NULL;
534 }
535
521 for (l = list; l; l = l->next)536 for (l = list; l; l = l->next)
522 priv->desktop_file_list = g_list_prepend (priv->desktop_file_list, g_strdup (l->data));537 priv->desktop_file_list = g_list_prepend (priv->desktop_file_list, g_strdup (l->data));
523 538
539 priv->desktop_file_list = g_list_reverse (priv->desktop_file_list);
540
524 desktop_file = bamf_application_favorite_from_list (self, priv->desktop_file_list);541 desktop_file = bamf_application_favorite_from_list (self, priv->desktop_file_list);
525 542
526 /* items come in priority order */543 /* items, after reversing them, are in priority order */
527 if (!desktop_file)544 if (!desktop_file)
528 desktop_file = list->data;545 desktop_file = list->data;
529 546
530 bamf_application_set_desktop_file (self, desktop_file);547 bamf_application_set_desktop_file (self, desktop_file);
531}548}
532549
@@ -576,7 +593,6 @@
576{593{
577 BamfApplication *app;594 BamfApplication *app;
578 BamfApplicationPrivate *priv;595 BamfApplicationPrivate *priv;
579 GList *l;
580596
581 app = BAMF_APPLICATION (object);597 app = BAMF_APPLICATION (object);
582 priv = app->priv;598 priv = app->priv;
@@ -589,10 +605,7 @@
589 605
590 if (priv->desktop_file_list)606 if (priv->desktop_file_list)
591 {607 {
592 for (l = priv->desktop_file_list; l; l = l->next)608 g_list_free_full (priv->desktop_file_list, g_free);
593 g_free (l->data);
594
595 g_list_free (priv->desktop_file_list);
596 priv->desktop_file_list = NULL;609 priv->desktop_file_list = NULL;
597 }610 }
598611
@@ -676,7 +689,7 @@
676}689}
677690
678BamfApplication *691BamfApplication *
679bamf_application_new_from_desktop_file (char * desktop_file)692bamf_application_new_from_desktop_file (const char * desktop_file)
680{693{
681 BamfApplication *application;694 BamfApplication *application;
682 application = (BamfApplication *) g_object_new (BAMF_TYPE_APPLICATION, NULL);695 application = (BamfApplication *) g_object_new (BAMF_TYPE_APPLICATION, NULL);
@@ -698,7 +711,7 @@
698}711}
699712
700BamfApplication *713BamfApplication *
701bamf_application_new_with_wmclass (char *wmclass)714bamf_application_new_with_wmclass (const char *wmclass)
702{715{
703 BamfApplication *application;716 BamfApplication *application;
704 application = (BamfApplication *) g_object_new (BAMF_TYPE_APPLICATION, NULL);717 application = (BamfApplication *) g_object_new (BAMF_TYPE_APPLICATION, NULL);
705718
=== modified file 'src/bamf-application.h'
--- src/bamf-application.h 2011-03-29 09:37:44 +0000
+++ src/bamf-application.h 2011-06-26 22:21:13 +0000
@@ -56,7 +56,7 @@
5656
57char * bamf_application_get_desktop_file (BamfApplication *application);57char * bamf_application_get_desktop_file (BamfApplication *application);
58void bamf_application_set_desktop_file (BamfApplication *application,58void bamf_application_set_desktop_file (BamfApplication *application,
59 char * desktop_file);59 const char * desktop_file);
6060
61GArray * bamf_application_get_xids (BamfApplication *application);61GArray * bamf_application_get_xids (BamfApplication *application);
6262
@@ -68,15 +68,15 @@
6868
69char * bamf_application_get_wmclass (BamfApplication *application);69char * bamf_application_get_wmclass (BamfApplication *application);
70void bamf_application_set_wmclass (BamfApplication *application,70void bamf_application_set_wmclass (BamfApplication *application,
71 char *wmclass);71 const char *wmclass);
7272
73BamfApplication * bamf_application_new (void);73BamfApplication * bamf_application_new (void);
7474
75BamfApplication * bamf_application_new_from_desktop_file (char * desktop_file);75BamfApplication * bamf_application_new_from_desktop_file (const char * desktop_file);
76gboolean bamf_application_get_show_stubs (BamfApplication *application);76gboolean bamf_application_get_show_stubs (BamfApplication *application);
7777
78BamfApplication * bamf_application_new_from_desktop_files (GList * desktop_files);78BamfApplication * bamf_application_new_from_desktop_files (GList * desktop_files);
7979
80BamfApplication * bamf_application_new_with_wmclass (char *wmclass);80BamfApplication * bamf_application_new_with_wmclass (const char *wmclass);
8181
82#endif82#endif
8383
=== modified file 'src/bamf-matcher.c'
--- src/bamf-matcher.c 2011-04-27 16:48:14 +0000
+++ src/bamf-matcher.c 2011-06-26 22:21:13 +0000
@@ -150,7 +150,7 @@
150 type = bamf_view_get_view_type (view);150 type = bamf_view_get_view_type (view);
151151
152 g_signal_connect (G_OBJECT (view), "closed-internal",152 g_signal_connect (G_OBJECT (view), "closed-internal",
153 (GCallback) on_view_closed, self);153 (GCallback) on_view_closed, self);
154 g_signal_connect (G_OBJECT (view), "active-changed",154 g_signal_connect (G_OBJECT (view), "active-changed",
155 (GCallback) on_view_active_changed, self);155 (GCallback) on_view_active_changed, self);
156156
@@ -275,28 +275,28 @@
275 part = parts[i];275 part = parts[i];
276276
277 if (!g_str_has_prefix (part, "-"))277 if (!g_str_has_prefix (part, "-"))
278 {278 {
279 tmp = g_utf8_strrchr (part, -1, '/');279 tmp = g_utf8_strrchr (part, -1, G_DIR_SEPARATOR);
280 if (tmp)280 if (tmp)
281 part = tmp + 1;281 part = tmp + 1;
282282
283 regexFail = FALSE;283 regexFail = FALSE;
284 for (j = 0; j < self->priv->bad_prefixes->len; j++)284 for (j = 0; j < self->priv->bad_prefixes->len; j++)
285 {285 {
286 regex = g_array_index (self->priv->bad_prefixes, GRegex *, j);286 regex = g_array_index (self->priv->bad_prefixes, GRegex *, j);
287 if (g_regex_match (regex, part, 0, NULL))287 if (g_regex_match (regex, part, 0, NULL))
288 {288 {
289 regexFail = TRUE;289 regexFail = TRUE;
290 break;290 break;
291 }291 }
292 }292 }
293293
294 if (!regexFail)294 if (!regexFail)
295 {295 {
296 result = g_strdup (part);296 result = g_strdup (part);
297 break;297 break;
298 }298 }
299 }299 }
300 i++;300 i++;
301 }301 }
302302
@@ -404,6 +404,34 @@
404 return !g_str_has_prefix (exec, "ooffice") && !g_str_has_prefix (exec, "libreoffice");404 return !g_str_has_prefix (exec, "ooffice") && !g_str_has_prefix (exec, "libreoffice");
405}405}
406406
407static gboolean
408is_desktop_folder_item (const char *desktop_file_path, gssize max_len)
409{
410 gsize len;
411 const char *desktop_folder;
412
413 g_return_val_if_fail (desktop_file_path, FALSE);
414
415 if (max_len > 0)
416 {
417 len = max_len;
418 }
419 else
420 {
421 char *tmp;
422 tmp = strrchr (desktop_file_path, G_DIR_SEPARATOR);
423 g_return_val_if_fail (tmp, FALSE);
424 len = tmp - desktop_file_path;
425 }
426
427 desktop_folder = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
428
429 if (strncmp (desktop_folder, desktop_file_path, len) == 0)
430 return TRUE;
431
432 return FALSE;
433}
434
407static void435static void
408insert_data_into_tables (BamfMatcher *self,436insert_data_into_tables (BamfMatcher *self,
409 const char *data,437 const char *data,
@@ -421,20 +449,60 @@
421 file_list = g_hash_table_lookup (desktop_file_table, exec);449 file_list = g_hash_table_lookup (desktop_file_table, exec);
422 id_list = g_hash_table_lookup (desktop_id_table, desktop_id);450 id_list = g_hash_table_lookup (desktop_id_table, desktop_id);
423451
452 if (g_list_find_custom (file_list, data, (GCompareFunc) g_strcmp0) &&
453 g_list_find_custom (id_list, data, (GCompareFunc) g_strcmp0))
454 {
455 return;
456 }
457
424 datadup = g_strdup (data);458 datadup = g_strdup (data);
425 459
426 /* order so that items whose desktop_id == exec string are first in the list */460 /* order so that items whose desktop_id == exec string are first in the list */
427 if (g_strcmp0 (exec, desktop_id) == 0)461
462 if (g_strcmp0 (exec, desktop_id) == 0 || is_desktop_folder_item (datadup, -1))
428 {463 {
429 file_list = g_list_prepend (file_list, datadup);464 GList *l, *last;
430 id_list = g_list_prepend (id_list, datadup);465 last = NULL;
466
467 for (l = file_list; l; l = l->next)
468 {
469 char *dpath;
470 char *dname_start, *dname_end;
471 size_t len;
472
473 dpath = l->data;
474 dname_start = strrchr (dpath, G_DIR_SEPARATOR);
475 if (!dname_start)
476 {
477 continue;
478 }
479
480 dname_start++;
481 dname_end = strrchr (dname_start, '.');
482 len = dname_end - dname_start;
483
484 if (!dname_end || len < 1)
485 {
486 continue;
487 }
488
489 if (strncmp (desktop_id, dname_start, len) != 0 &&
490 !is_desktop_folder_item (dpath, (dname_start - dpath - 1)))
491 {
492 last = l;
493 break;
494 }
495 }
496
497 file_list = g_list_insert_before (file_list, last, datadup);
431 }498 }
432 else499 else
433 {500 {
434 file_list = g_list_append (file_list, datadup);501 file_list = g_list_append (file_list, datadup);
435 id_list = g_list_append (id_list, datadup);
436 }502 }
437503
504 id_list = g_list_append (id_list, datadup);
505
438 g_hash_table_insert (desktop_file_table, g_strdup (exec), file_list);506 g_hash_table_insert (desktop_file_table, g_strdup (exec), file_list);
439 g_hash_table_insert (desktop_id_table, g_strdup (desktop_id), id_list);507 g_hash_table_insert (desktop_id_table, g_strdup (desktop_id), id_list);
440}508}
@@ -530,8 +598,8 @@
530 GFile *dir;598 GFile *dir;
531 GFileEnumerator *enumerator;599 GFileEnumerator *enumerator;
532 GFileInfo *info;600 GFileInfo *info;
533 const char* name;601 const char *name;
534 const char *path;602 char *path;
535603
536 dir = g_file_new_for_path (directory);604 dir = g_file_new_for_path (directory);
537605
@@ -558,7 +626,7 @@
558 desktop_id_table,626 desktop_id_table,
559 desktop_class_table);627 desktop_class_table);
560628
561 g_free ((gpointer) path);629 g_free (path);
562 g_object_unref (info);630 g_object_unref (info);
563 }631 }
564632
@@ -599,8 +667,8 @@
599 while ((line = g_data_input_stream_read_line (input, &length, NULL, NULL)) != NULL)667 while ((line = g_data_input_stream_read_line (input, &length, NULL, NULL)) != NULL)
600 {668 {
601 char *exec;669 char *exec;
670 char *filename;
602 GString *desktop_id;671 GString *desktop_id;
603 GString *filename;
604672
605 gchar **parts = g_strsplit (line, "\t", 3);673 gchar **parts = g_strsplit (line, "\t", 3);
606674
@@ -612,64 +680,37 @@
612 exec = tmp;680 exec = tmp;
613 }681 }
614682
615 char *name = g_build_filename (directory, parts[0], NULL);683 filename = g_build_filename (directory, parts[0], NULL);
616 filename = g_string_new (name);
617 g_free ((gpointer) name);
618684
619 desktop_id = g_string_new (parts[0]);685 desktop_id = g_string_new (parts[0]);
620 g_string_truncate (desktop_id, desktop_id->len - 8);686 g_string_truncate (desktop_id, desktop_id->len - 8);
621 687
622 insert_data_into_tables (self, filename->str, exec, desktop_id->str, desktop_file_table, desktop_id_table);688 insert_data_into_tables (self, filename, exec, desktop_id->str, desktop_file_table, desktop_id_table);
623 insert_desktop_file_class_into_table (self, filename->str, desktop_class_table);689 insert_desktop_file_class_into_table (self, filename, desktop_class_table);
624690
625 g_string_free (desktop_id, TRUE);691 g_string_free (desktop_id, TRUE);
692 g_free (filename);
693 g_strfreev (parts);
626 length = 0;694 length = 0;
627 g_strfreev (parts);
628 }695 }
629 g_free ((gpointer) directory);696
697 g_object_unref (input);
698 g_object_unref (stream);
699 g_object_unref (file);
700 g_free (directory);
630}701}
631702
703static GList * get_directory_tree_list (GList *) G_GNUC_WARN_UNUSED_RESULT;
704
632static GList *705static GList *
633get_desktop_file_directories (BamfMatcher *self)706get_directory_tree_list (GList *dirs)
634{707{
708 GList *l;
635 GFile *file;709 GFile *file;
710 GFileEnumerator *enumerator;
636 GFileInfo *info;711 GFileInfo *info;
637 GFileEnumerator *enumerator;712 gchar *path, *subpath;
638 GList *dirs = NULL, *l;713
639 const char *env;
640 char *path;
641 char *subpath;
642 char **data_dirs = NULL;
643 char **data;
644
645 env = g_getenv ("XDG_DATA_DIRS");
646
647 if (env)
648 {
649 data_dirs = g_strsplit (env, ":", 0);
650
651 for (data = data_dirs; *data; data++)
652 {
653 path = g_build_filename (*data, "applications", NULL);
654 if (g_file_test (path, G_FILE_TEST_IS_DIR))
655 dirs = g_list_prepend (dirs, path);
656 else
657 g_free (path);
658 }
659 }
660
661 if (!g_list_find_custom (dirs, "/usr/share/applications", (GCompareFunc) g_strcmp0))
662 dirs = g_list_prepend (dirs, g_strdup ("/usr/share/applications"));
663
664 if (!g_list_find_custom (dirs, "/usr/local/share/applications", (GCompareFunc) g_strcmp0))
665 dirs = g_list_prepend (dirs, g_strdup ("/usr/local/share/applications"));
666
667 dirs = g_list_prepend (dirs, g_strdup (g_build_filename (g_get_home_dir (), ".local/share/applications", NULL)));
668
669 if (data_dirs)
670 g_strfreev (data_dirs);
671
672 /* include subdirs */
673 for (l = dirs; l; l = l->next)714 for (l = dirs; l; l = l->next)
674 {715 {
675 path = l->data;716 path = l->data;
@@ -698,8 +739,10 @@
698 continue;739 continue;
699 740
700 subpath = g_build_filename (path, g_file_info_get_name (info), NULL);741 subpath = g_build_filename (path, g_file_info_get_name (info), NULL);
701 /* append for non-recursive recursion love */742 /* append after the current list item for non-recursive recursion love
702 dirs = g_list_append (dirs, subpath);743 * and to keep the priorities (hierarchy) of the .desktop directories.
744 */
745 dirs = g_list_insert_before (dirs, l->next, subpath);
703746
704 g_object_unref (info);747 g_object_unref (info);
705 }748 }
@@ -707,42 +750,255 @@
707 g_object_unref (enumerator);750 g_object_unref (enumerator);
708 g_object_unref (file);751 g_object_unref (file);
709 }752 }
710 753
711 return dirs;754 return dirs;
755}
756
757static GList * get_desktop_file_env_directories (GList *, const gchar *) G_GNUC_WARN_UNUSED_RESULT;
758
759static GList *
760get_desktop_file_env_directories (GList *dirs, const gchar *varname)
761{
762 g_return_val_if_fail (varname, dirs);
763
764 const gchar *env;
765 char *path;
766 char **data_dirs = NULL;
767 char **data;
768
769 env = g_getenv (varname);
770
771 if (env)
772 {
773 data_dirs = g_strsplit (env, ":", 0);
774
775 for (data = data_dirs; *data; data++)
776 {
777 path = g_build_filename (*data, "applications", NULL);
778 if (g_file_test (path, G_FILE_TEST_IS_DIR) &&
779 !g_list_find_custom (dirs, path, (GCompareFunc) g_strcmp0))
780 {
781 dirs = g_list_prepend (dirs, path);
782 }
783 else
784 {
785 g_free (path);
786 }
787 }
788
789 if (data_dirs)
790 g_strfreev (data_dirs);
791 }
792
793 return dirs;
794}
795
796static GList *
797get_desktop_file_directories (BamfMatcher *self)
798{
799 GList *dirs = NULL;
800 char *path;
801
802 dirs = get_desktop_file_env_directories(dirs, "XDG_DATA_DIRS");
803
804 if (!g_list_find_custom (dirs, "/usr/share/applications", (GCompareFunc) g_strcmp0))
805 dirs = g_list_prepend (dirs, g_strdup ("/usr/share/applications"));
806
807 if (!g_list_find_custom (dirs, "/usr/local/share/applications", (GCompareFunc) g_strcmp0))
808 dirs = g_list_prepend (dirs, g_strdup ("/usr/local/share/applications"));
809
810 dirs = get_desktop_file_env_directories(dirs, "XDG_DATA_HOME");
811
812 path = g_build_filename (g_get_home_dir (), ".local/share/applications", NULL);
813
814 if (!g_list_find_custom (dirs, path, (GCompareFunc) g_strcmp0))
815 dirs = g_list_prepend (dirs, path);
816 else
817 g_free (path);
818
819 /* include subdirs */
820 dirs = get_directory_tree_list (dirs);
821
822 /* Include also the user desktop folder, but without its subfolders */
823 dirs = g_list_prepend (dirs, g_strdup (g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP)));
824
825 return dirs;
826}
827
828static gint
829compare_sub_values (gconstpointer desktop_path, gconstpointer desktop_file)
830{
831 return !g_str_has_prefix (desktop_file, desktop_path);
832}
833
834static void
835hash_table_remove_sub_values (GHashTable *htable, GCompareFunc compare_func,
836 GFreeFunc free_func, gpointer target, gboolean search_all)
837{
838 g_return_if_fail (htable);
839 g_return_if_fail (compare_func);
840
841 GHashTableIter iter;
842 gpointer key;
843 gpointer value;
844
845 g_hash_table_iter_init (&iter, htable);
846
847 while (g_hash_table_iter_next (&iter, &key, &value))
848 {
849 GList *list, *l;
850 gboolean found;
851
852 list = value;
853 found = FALSE;
854
855 l = list;
856 while (l)
857 {
858 GList *next = l->next;
859
860 if (compare_func (target, l->data) == 0)
861 {
862 found = TRUE;
863
864 if (!l->prev && !l->next)
865 {
866 if (free_func)
867 g_list_free_full (list, free_func);
868 else
869 g_list_free (list);
870
871 g_hash_table_iter_remove (&iter);
872
873 next = NULL;
874 break;
875 }
876 else
877 {
878 if (free_func)
879 free_func (l->data);
880
881 /* If the target is the first element of the list (and thanks to
882- * the previous check we're also sure that it's not the only one),
883 * simply switch it with its follower, not to change the first
884 * pointer and the hash table value for key
885 */
886 if (l == list)
887 {
888 l->data = next->data;
889 l = next;
890 next = list;
891 }
892
893 list = g_list_delete_link (list, l);
894 }
895
896 if (!search_all)
897 break;
898 }
899 l = next;
900 }
901
902 if (found && !search_all)
903 break;
904 }
712}905}
713906
714static gboolean907static gboolean
715hash_table_remove_values (gpointer key, gpointer value, gpointer target)908hash_table_compare_sub_values (gpointer desktop_path, gpointer desktop_class, gpointer target_path)
716{909{
717 return g_strcmp0 ((char *) value, (char *) target) == 0;910 return !compare_sub_values (target_path, desktop_path);
718}911}
719912
913static void fill_desktop_file_table (BamfMatcher *, GList *, GHashTable *, GHashTable *, GHashTable *);
914
720static void915static void
721on_monitor_changed (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent type, BamfMatcher *self)916on_monitor_changed (GFileMonitor *monitor, GFile *file, GFile *other_file, GFileMonitorEvent type, BamfMatcher *self)
722{917{
723 char *path;918 char *path;
919 const char *monitored_dir;
920 GFileType filetype;
724921
725 g_return_if_fail (G_IS_FILE_MONITOR (monitor));922 g_return_if_fail (G_IS_FILE_MONITOR (monitor));
726 g_return_if_fail (BAMF_IS_MATCHER (self));
727
728 if (type != G_FILE_MONITOR_EVENT_CHANGED && type != G_FILE_MONITOR_EVENT_DELETED)
729 return;
730
731 g_return_if_fail (G_IS_FILE (file));923 g_return_if_fail (G_IS_FILE (file));
924 g_return_if_fail (BAMF_IS_MATCHER (self));
925
926 if (type != G_FILE_MONITOR_EVENT_CREATED &&
927 type != G_FILE_MONITOR_EVENT_DELETED &&
928 type != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
929 return;
930
732 path = g_file_get_path (file);931 path = g_file_get_path (file);
932 filetype = g_file_query_file_type (file, G_FILE_QUERY_INFO_NONE, NULL);
933 monitored_dir = g_object_get_data (G_OBJECT (monitor), "root");
733 934
734 if (!g_str_has_suffix (path, ".desktop"))935 if (!g_str_has_suffix (path, ".desktop") &&
936 filetype != G_FILE_TYPE_DIRECTORY &&
937 type != G_FILE_MONITOR_EVENT_DELETED)
735 goto out;938 goto out;
939
940 if (type == G_FILE_MONITOR_EVENT_DELETED ||
941 type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
942 {
943 if (g_str_has_suffix (path, ".desktop"))
944 {
945 /* Remove all the .desktop file referencies from the hash tables.
946 * Free the string itself only on the 2nd pass (tables share the same
947 * string instance)
948 */
949 hash_table_remove_sub_values (self->priv->desktop_id_table,
950 (GCompareFunc) g_strcmp0, NULL, path, FALSE);
951 hash_table_remove_sub_values (self->priv->desktop_file_table,
952 (GCompareFunc) g_strcmp0, g_free, path, FALSE);
953 g_hash_table_remove (self->priv->desktop_class_table, path);
954 }
955 else if (g_strcmp0 (monitored_dir, path) == 0)
956 {
957 /* Remove all the referencies to the .desktop files placed in subfolders
958 * of the current path. Free the strings itself only on the 2nd pass
959 * (as before, the tables share the same string instance)
960 */
961 char *prefix = g_strconcat (path, G_DIR_SEPARATOR_S, NULL);
962
963 hash_table_remove_sub_values (self->priv->desktop_id_table,
964 compare_sub_values, NULL, prefix, TRUE);
965 hash_table_remove_sub_values (self->priv->desktop_file_table,
966 compare_sub_values, g_free, prefix, TRUE);
967 g_hash_table_foreach_remove (self->priv->desktop_class_table,
968 hash_table_compare_sub_values, prefix);
969
970 g_signal_handlers_disconnect_by_func (monitor, on_monitor_changed, self);
971 self->priv->monitors = g_list_remove (self->priv->monitors, monitor);
972 g_object_unref (monitor);
973 g_free (prefix);
974 }
975 }
976
977 if (type == G_FILE_MONITOR_EVENT_CREATED ||
978 type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
979 {
980 if (filetype == G_FILE_TYPE_DIRECTORY)
981 {
982 const char *desktop_dir;
983 desktop_dir = g_get_user_special_dir (G_USER_DIRECTORY_DESKTOP);
984
985 if (g_strcmp0 (monitored_dir, desktop_dir) != 0)
986 {
987 GList *dirs = NULL;
988 dirs = g_list_prepend (dirs, g_strdup (path));
989 dirs = get_directory_tree_list (dirs);
990 fill_desktop_file_table (self, dirs,
991 self->priv->desktop_file_table,
992 self->priv->desktop_id_table,
993 self->priv->desktop_class_table);
736 994
737 if (type == G_FILE_MONITOR_EVENT_CREATED)995 g_list_free_full (dirs, (GDestroyNotify) g_free);
738 {996 }
739 bamf_matcher_load_desktop_file (self, path);997 }
740 }998 else if (filetype != G_FILE_TYPE_UNKNOWN)
741 else if (type == G_FILE_MONITOR_EVENT_DELETED)999 {
742 {1000 bamf_matcher_load_desktop_file (self, path);
743 g_hash_table_foreach_remove (self->priv->desktop_id_table, (GHRFunc) hash_table_remove_values, path);1001 }
744 g_hash_table_foreach_remove (self->priv->desktop_file_table, (GHRFunc) hash_table_remove_values, path);
745 g_hash_table_remove (self->priv->desktop_class_table, path);
746 }1002 }
7471003
748out:1004out:
@@ -750,17 +1006,71 @@
750}1006}
7511007
752static void1008static void
1009bamf_add_new_monitored_directory (BamfMatcher * self, const gchar *directory)
1010{
1011 g_return_if_fail (BAMF_IS_MATCHER (self));
1012
1013 GFile *file;
1014 GFileMonitor *monitor;
1015
1016 file = g_file_new_for_path (directory);
1017 monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
1018 g_file_monitor_set_rate_limit (monitor, 1000);
1019 g_object_set_data_full (G_OBJECT (monitor), "root", g_strdup (directory), g_free);
1020 g_signal_connect (monitor, "changed", (GCallback) on_monitor_changed, self);
1021 self->priv->monitors = g_list_prepend (self->priv->monitors, monitor);
1022
1023 g_object_unref (file);
1024}
1025
1026static void
1027fill_desktop_file_table (BamfMatcher * self,
1028 GList *directories,
1029 GHashTable *desktop_file_table,
1030 GHashTable *desktop_id_table,
1031 GHashTable *desktop_class_table)
1032{
1033 g_return_if_fail (BAMF_IS_MATCHER (self));
1034
1035 GList *l;
1036 char *directory;
1037 char *bamf_file;
1038
1039 for (l = directories; l; l = l->next)
1040 {
1041 directory = l->data;
1042
1043 if (!g_file_test (directory, G_FILE_TEST_IS_DIR))
1044 continue;
1045
1046 bamf_add_new_monitored_directory (self, directory);
1047
1048 bamf_file = g_build_filename (directory, "bamf.index", NULL);
1049
1050 if (g_file_test (bamf_file, G_FILE_TEST_EXISTS))
1051 {
1052 load_index_file_to_table (self, bamf_file, desktop_file_table,
1053 desktop_id_table, desktop_class_table);
1054 }
1055 else
1056 {
1057 load_directory_to_table (self, directory, desktop_file_table,
1058 desktop_id_table, desktop_class_table);
1059 }
1060
1061 g_free (bamf_file);
1062 }
1063}
1064
1065static void
753create_desktop_file_table (BamfMatcher * self,1066create_desktop_file_table (BamfMatcher * self,
754 GHashTable **desktop_file_table,1067 GHashTable **desktop_file_table,
755 GHashTable **desktop_id_table,1068 GHashTable **desktop_id_table,
756 GHashTable **desktop_class_table)1069 GHashTable **desktop_class_table)
757{1070{
1071 g_return_if_fail (BAMF_IS_MATCHER (self));
1072
758 GList *directories;1073 GList *directories;
759 GList *l;
760 char *directory;
761 const char *bamf_file;
762 GFile *file;
763 GFileMonitor *monitor;
7641074
765 *desktop_file_table =1075 *desktop_file_table =
766 g_hash_table_new_full ((GHashFunc) g_str_hash,1076 g_hash_table_new_full ((GHashFunc) g_str_hash,
@@ -778,44 +1088,14 @@
778 g_hash_table_new_full ((GHashFunc) g_str_hash,1088 g_hash_table_new_full ((GHashFunc) g_str_hash,
779 (GEqualFunc) g_str_equal,1089 (GEqualFunc) g_str_equal,
780 (GDestroyNotify) g_free,1090 (GDestroyNotify) g_free,
781 (GDestroyNotify) g_free);1091 (GDestroyNotify) g_free);
782
783 g_return_if_fail (BAMF_IS_MATCHER (self));
7841092
785 directories = get_desktop_file_directories (self);1093 directories = get_desktop_file_directories (self);
7861094
787 for (l = directories; l; l = l->next)1095 fill_desktop_file_table (self, directories, *desktop_file_table,
788 {1096 *desktop_id_table, *desktop_class_table);
789 directory = l->data;
790
791 if (!g_file_test (directory, G_FILE_TEST_IS_DIR))
792 continue;
793
794 file = g_file_new_for_path (directory);
795 monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
796
797 self->priv->monitors = g_list_prepend (self->priv->monitors, monitor);
798
799 g_signal_connect (monitor, "changed", (GCallback) on_monitor_changed, self);
800
801 bamf_file = g_build_filename (directory, "bamf.index", NULL);
802
803 if (g_file_test (bamf_file, G_FILE_TEST_EXISTS))
804 {
805 load_index_file_to_table (self, bamf_file, *desktop_file_table,
806 *desktop_id_table, *desktop_class_table);
807 }
808 else
809 {
810 load_directory_to_table (self, directory, *desktop_file_table,
811 *desktop_id_table, *desktop_class_table);
812 }
813
814 g_free (directory);
815 g_free ((gpointer) bamf_file);
816 }
817 1097
818 g_list_free (directories);1098 g_list_free_full (directories, (GDestroyNotify) g_free);
819}1099}
8201100
821static gboolean1101static gboolean
@@ -861,17 +1141,17 @@
861 atom = XInternAtom (XDisplay, atom_name, FALSE);1141 atom = XInternAtom (XDisplay, atom_name, FALSE);
8621142
863 int result = XGetWindowProperty (XDisplay,1143 int result = XGetWindowProperty (XDisplay,
864 (gulong) bamf_legacy_window_get_xid (window),1144 (gulong) bamf_legacy_window_get_xid (window),
865 atom,1145 atom,
866 0,1146 0,
867 G_MAXINT,1147 G_MAXINT,
868 FALSE,1148 FALSE,
869 XA_STRING,1149 XA_STRING,
870 &type,1150 &type,
871 &format,1151 &format,
872 &numItems,1152 &numItems,
873 &bytesAfter,1153 &bytesAfter,
874 &buffer);1154 &buffer);
8751155
876 if (close_display)1156 if (close_display)
877 XCloseDisplay (XDisplay);1157 XCloseDisplay (XDisplay);
@@ -912,24 +1192,18 @@
912 }1192 }
9131193
914 XChangeProperty (XDisplay,1194 XChangeProperty (XDisplay,
915 bamf_legacy_window_get_xid (window),1195 bamf_legacy_window_get_xid (window),
916 XInternAtom (XDisplay,1196 XInternAtom (XDisplay,
917 atom_name,1197 atom_name,
918 FALSE),1198 FALSE),
919 XA_STRING,1199 XA_STRING,
920 8,1200 8,
921 PropModeReplace,1201 PropModeReplace,
922 (unsigned char *) data,1202 (unsigned char *) data,
923 strlen (data));1203 strlen (data));
9241204
925 if (close_display)1205 if (close_display)
926 XCloseDisplay (XDisplay);1206 XCloseDisplay (XDisplay);
927}
928
929static char*
930window_class_name (BamfLegacyWindow *window)
931{
932 return g_strdup (bamf_legacy_window_get_class_name (window));
933}1207}
9341208
935static char *1209static char *
@@ -951,7 +1225,7 @@
951 {1225 {
952 g_string_append (exec, argv[i]);1226 g_string_append (exec, argv[i]);
953 if (argv[i + 1] != NULL)1227 if (argv[i + 1] != NULL)
954 g_string_append (exec, " ");1228 g_string_append (exec, " ");
955 g_free (argv[i]);1229 g_free (argv[i]);
956 i++;1230 i++;
957 }1231 }
@@ -1084,7 +1358,7 @@
1084 }1358 }
1085 else1359 else
1086 {1360 {
1087 char *window_class = window_class_name (window);1361 const char *window_class = bamf_legacy_window_get_class_name (window);
1088 1362
1089 char *desktop_file;1363 char *desktop_file;
1090 char *desktop_class;1364 char *desktop_class;
@@ -1098,6 +1372,7 @@
1098 for (; l; l = l->next)1372 for (; l; l = l->next)
1099 {1373 {
1100 desktop_file = l->data;1374 desktop_file = l->data;
1375
1101 if (desktop_file)1376 if (desktop_file)
1102 {1377 {
1103 desktop_class = g_hash_table_lookup (priv->desktop_class_table, desktop_file);1378 desktop_class = g_hash_table_lookup (priv->desktop_class_table, desktop_file);
@@ -1128,6 +1403,10 @@
1128 {1403 {
1129 desktop_files = g_list_prepend (desktop_files, desktop_file);1404 desktop_files = g_list_prepend (desktop_files, desktop_file);
1130 }1405 }
1406 else
1407 {
1408 g_free (desktop_file);
1409 }
1131 }1410 }
11321411
1133 pid = bamf_legacy_window_get_pid (window);1412 pid = bamf_legacy_window_get_pid (window);
@@ -1139,26 +1418,56 @@
1139 for (l = pid_list; l; l = l->next)1418 for (l = pid_list; l; l = l->next)
1140 {1419 {
1141 desktop_file = l->data;1420 desktop_file = l->data;
1142 if (g_list_find_custom (desktop_files, l->data, (GCompareFunc) g_strcmp0))1421 if (g_list_find_custom (desktop_files, desktop_file, (GCompareFunc) g_strcmp0))
1143 g_free (desktop_file);1422 {
1423 g_free (desktop_file);
1424 }
1144 else1425 else
1145 {1426 {
1427 gboolean append = FALSE;
1428
1146 if (window_class)1429 if (window_class)
1147 {1430 {
1148 desktop_class = g_hash_table_lookup (priv->desktop_class_table, desktop_file);1431 desktop_class = g_hash_table_lookup (priv->desktop_class_table, desktop_file);
1149 if ((desktop_class == NULL || g_strcmp0 (desktop_class, window_class) == 0) &&1432 if (desktop_class == NULL || g_strcmp0 (desktop_class, window_class) == 0)
1150 !g_list_find_custom (desktop_files, desktop_file,1433 {
1151 (GCompareFunc) g_strcmp0))1434 append = TRUE;
1152 {1435 }
1153 desktop_files = g_list_append (desktop_files, desktop_file);1436 }
1154 }1437 else
1155 }1438 {
1156 else1439 append = TRUE;
1157 desktop_files = g_list_append (desktop_files, desktop_file);1440 }
1441
1442 if (append)
1443 {
1444 /* If we're adding a .desktop file stored in the desktop folder,
1445 give it the priority it should have. */
1446 GList *last = NULL;
1447
1448 if (is_desktop_folder_item (desktop_file, -1))
1449 {
1450 GList *ll;
1451
1452 for (ll = desktop_files; ll; ll = ll->next)
1453 {
1454 if (!is_desktop_folder_item (ll->data, -1))
1455 {
1456 last = ll;
1457 break;
1458 }
1459 }
1460 }
1461
1462 desktop_files = g_list_insert_before (desktop_files, last, desktop_file);
1463 }
1464 else
1465 {
1466 g_free (desktop_file);
1467 }
1158 }1468 }
1159 }1469 }
11601470
1161 g_free (window_class);
1162 g_list_free (pid_list);1471 g_list_free (pid_list);
1163 }1472 }
1164 1473
@@ -1172,8 +1481,8 @@
1172 GList *possible_apps, *l;1481 GList *possible_apps, *l;
1173 BamfLegacyWindow *window;1482 BamfLegacyWindow *window;
1174 GList *views, *a;1483 GList *views, *a;
1484 const char *win_class;
1175 char *desktop_file;1485 char *desktop_file;
1176 char *win_class;
1177 char *app_class;1486 char *app_class;
1178 BamfApplication *app = NULL, *best = NULL;1487 BamfApplication *app = NULL, *best = NULL;
1179 BamfView *view;1488 BamfView *view;
@@ -1185,7 +1494,7 @@
1185 views = self->priv->views;1494 views = self->priv->views;
11861495
1187 possible_apps = bamf_matcher_possible_applications_for_window (self, bamf_window);1496 possible_apps = bamf_matcher_possible_applications_for_window (self, bamf_window);
1188 win_class = window_class_name(window);1497 win_class = bamf_legacy_window_get_class_name (window);
11891498
1190 /* Loop over every application, inside that application see if its .desktop file1499 /* Loop over every application, inside that application see if its .desktop file
1191 * matches with any of our possible hits. If so we match it. If we have no possible hits1500 * matches with any of our possible hits. If so we match it. If we have no possible hits
@@ -1200,7 +1509,6 @@
12001509
1201 app = BAMF_APPLICATION (view);1510 app = BAMF_APPLICATION (view);
1202 app_class = bamf_application_get_wmclass (app);1511 app_class = bamf_application_get_wmclass (app);
1203
1204 desktop_file = bamf_application_get_desktop_file (app);1512 desktop_file = bamf_application_get_desktop_file (app);
12051513
1206 if (possible_apps)1514 if (possible_apps)
@@ -1242,8 +1550,6 @@
1242 g_object_unref (best);1550 g_object_unref (best);
1243 }1551 }
12441552
1245 g_free (win_class);
1246
1247 for (l = possible_apps; l; l = l->next)1553 for (l = possible_apps; l; l = l->next)
1248 {1554 {
1249 char *str = l->data;1555 char *str = l->data;
@@ -1912,51 +2218,51 @@
1912 g_type_class_add_private (klass, sizeof (BamfMatcherPrivate));2218 g_type_class_add_private (klass, sizeof (BamfMatcherPrivate));
19132219
1914 dbus_g_object_type_install_info (BAMF_TYPE_MATCHER,2220 dbus_g_object_type_install_info (BAMF_TYPE_MATCHER,
1915 &dbus_glib_bamf_matcher_object_info);2221 &dbus_glib_bamf_matcher_object_info);
19162222
1917 matcher_signals [VIEW_OPENED] =2223 matcher_signals [VIEW_OPENED] =
1918 g_signal_new ("view-opened",2224 g_signal_new ("view-opened",
1919 G_OBJECT_CLASS_TYPE (klass),2225 G_OBJECT_CLASS_TYPE (klass),
1920 0,2226 0,
1921 0, NULL, NULL,2227 0, NULL, NULL,
1922 bamf_marshal_VOID__STRING_STRING,2228 bamf_marshal_VOID__STRING_STRING,
1923 G_TYPE_NONE, 2,2229 G_TYPE_NONE, 2,
1924 G_TYPE_STRING, G_TYPE_STRING);2230 G_TYPE_STRING, G_TYPE_STRING);
19252231
1926 matcher_signals [VIEW_CLOSED] =2232 matcher_signals [VIEW_CLOSED] =
1927 g_signal_new ("view-closed",2233 g_signal_new ("view-closed",
1928 G_OBJECT_CLASS_TYPE (klass),2234 G_OBJECT_CLASS_TYPE (klass),
1929 0,2235 0,
1930 0, NULL, NULL,2236 0, NULL, NULL,
1931 bamf_marshal_VOID__STRING_STRING,2237 bamf_marshal_VOID__STRING_STRING,
1932 G_TYPE_NONE, 2,2238 G_TYPE_NONE, 2,
1933 G_TYPE_STRING, G_TYPE_STRING);2239 G_TYPE_STRING, G_TYPE_STRING);
19342240
1935 matcher_signals [ACTIVE_APPLICATION_CHANGED] =2241 matcher_signals [ACTIVE_APPLICATION_CHANGED] =
1936 g_signal_new ("active-application-changed",2242 g_signal_new ("active-application-changed",
1937 G_OBJECT_CLASS_TYPE (klass),2243 G_OBJECT_CLASS_TYPE (klass),
1938 0,2244 0,
1939 0, NULL, NULL,2245 0, NULL, NULL,
1940 bamf_marshal_VOID__STRING_STRING,2246 bamf_marshal_VOID__STRING_STRING,
1941 G_TYPE_NONE, 2,2247 G_TYPE_NONE, 2,
1942 G_TYPE_STRING, G_TYPE_STRING);2248 G_TYPE_STRING, G_TYPE_STRING);
19432249
1944 matcher_signals [ACTIVE_WINDOW_CHANGED] =2250 matcher_signals [ACTIVE_WINDOW_CHANGED] =
1945 g_signal_new ("active-window-changed",2251 g_signal_new ("active-window-changed",
1946 G_OBJECT_CLASS_TYPE (klass),2252 G_OBJECT_CLASS_TYPE (klass),
1947 0,2253 0,
1948 0, NULL, NULL,2254 0, NULL, NULL,
1949 bamf_marshal_VOID__STRING_STRING,2255 bamf_marshal_VOID__STRING_STRING,
1950 G_TYPE_NONE, 2,2256 G_TYPE_NONE, 2,
1951 G_TYPE_STRING, G_TYPE_STRING);2257 G_TYPE_STRING, G_TYPE_STRING);
1952 2258
1953 matcher_signals [FAVORITES_CHANGED] =2259 matcher_signals [FAVORITES_CHANGED] =
1954 g_signal_new ("favorites-changed",2260 g_signal_new ("favorites-changed",
1955 G_OBJECT_CLASS_TYPE (klass),2261 G_OBJECT_CLASS_TYPE (klass),
1956 0,2262 0,
1957 0, NULL, NULL,2263 0, NULL, NULL,
1958 g_cclosure_marshal_VOID__VOID,2264 g_cclosure_marshal_VOID__VOID,
1959 G_TYPE_NONE, 0);2265 G_TYPE_NONE, 0);
1960}2266}
19612267
1962BamfMatcher *2268BamfMatcher *

Subscribers

People subscribed via source and target branches