Updating branch refs/heads/master to e9cf76d8adcbc9eceab9a3c00a8213bbb54b6891 (commit) from 53a350d9380b89e062c7f122c16a493e972341ce (commit)
commit e9cf76d8adcbc9eceab9a3c00a8213bbb54b6891 Author: Jannis Pohlmann <jan...@xfce.org> Date: Fri Nov 5 19:01:31 2010 +0100 Merge consecutive file change events using an idle handler. In combination with handling G_FILE_MONITOR_EVENT_CREATED, this properly picks up all changes to application directories now. An idle handler is used together with a GFile list to avoid processing the same file multiple times, e.g. when receiving three consecutive CREATED, CHANGES_DONE and ATTRIBUTE_CHANGED events. garcon/garcon-menu.c | 99 +++++++++++++++++++++++++++++++++++++++++++++----- 1 files changed, 90 insertions(+), 9 deletions(-) diff --git a/garcon/garcon-menu.c b/garcon/garcon-menu.c index b4c3b2e..8a4cd30 100644 --- a/garcon/garcon-menu.c +++ b/garcon/garcon-menu.c @@ -221,6 +221,10 @@ struct _GarconMenuPrivate /* Shared menu item cache */ GarconMenuItemCache *cache; + /* List to merge consecutive file changes into a a single event */ + GList *changed_files; + guint file_changed_idle; + /* Flag for marking custom path menus */ guint uses_custom_path : 1; }; @@ -336,6 +340,7 @@ garcon_menu_init (GarconMenu *menu) menu->priv->parent = NULL; menu->priv->pool = garcon_menu_item_pool_new (); menu->priv->uses_custom_path = TRUE; + menu->priv->changed_files = NULL; /* Take reference on the menu item cache */ menu->priv->cache = garcon_menu_item_cache_get_default (); @@ -1760,6 +1765,12 @@ garcon_menu_start_monitoring (GarconMenu *menu) /* Let only the root menu monitor menu files, merge files/directories and app dirs */ if (menu->priv->parent == NULL) { + /* Create the list for merging consecutive file change events */ + menu->priv->changed_files = NULL; + + /* Reset the idle source for handling file changes */ + menu->priv->file_changed_idle = 0; + garcon_menu_monitor_menu_files (menu); garcon_menu_monitor_files (menu, menu->priv->merge_files, @@ -1803,6 +1814,15 @@ garcon_menu_stop_monitoring (GarconMenu *menu) /* Free the monitor list */ g_list_free (menu->priv->monitors); menu->priv->monitors = NULL; + + /* Stop the idle source for handling file changes from being invoked */ + if (menu->priv->file_changed_idle != 0) + g_source_remove (menu->priv->file_changed_idle); + + /* Free the hash table for merging consecutive file change events */ + g_list_foreach (menu->priv->changed_files, (GFunc) g_object_unref, NULL); + g_list_free (menu->priv->changed_files); + menu->priv->changed_files = NULL; } @@ -2100,23 +2120,24 @@ garcon_menu_merge_dir_changed (GarconMenu *menu, -static void -garcon_menu_app_dir_changed (GarconMenu *menu, - GFile *file, - GFile *other_file, - GFileMonitorEvent event_type, - GFileMonitor *monitor) +static gboolean +garcon_menu_process_file_changes (GarconMenu *menu) { GarconMenuItem *item; GFileType file_type; gboolean affects_the_outside = FALSE; + gboolean stop_processing = FALSE; + GFile *file; + GList *lp; gchar *path; - g_return_if_fail (GARCON_IS_MENU (menu)); - g_return_if_fail (menu->priv->parent == NULL); + g_return_val_if_fail (GARCON_IS_MENU (menu), FALSE); + g_return_val_if_fail (menu->priv->parent == NULL, FALSE); - if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT) + for (lp = menu->priv->changed_files; !stop_processing && lp != NULL; lp = lp->next) { + file = G_FILE (lp->data); + /* query the type of the changed file */ file_type = g_file_query_file_type (file, G_FILE_QUERY_INFO_NONE, NULL); @@ -2129,6 +2150,7 @@ garcon_menu_app_dir_changed (GarconMenu *menu, * this is not trivial to handle, so we simply enforce a * menu reload to deal with the changes */ g_signal_emit (menu, menu_signals[RELOAD_REQUIRED], 0); + stop_processing = TRUE; } else { @@ -2149,6 +2171,7 @@ garcon_menu_app_dir_changed (GarconMenu *menu, * more complicated than one would first think, so just * enforce a complete menu reload for now */ g_signal_emit (menu, menu_signals[RELOAD_REQUIRED], 0); + stop_processing = TRUE; } else { @@ -2172,6 +2195,7 @@ garcon_menu_app_dir_changed (GarconMenu *menu, * tricky, so, again, we just enfore a menu reload until we have * something better */ g_signal_emit (menu, menu_signals[RELOAD_REQUIRED], 0); + stop_processing = TRUE; } } else @@ -2180,11 +2204,68 @@ garcon_menu_app_dir_changed (GarconMenu *menu, * stuff is complicated. for now, simply enforce a complete reload * of the menu structure */ g_signal_emit (menu, menu_signals[RELOAD_REQUIRED], 0); + stop_processing = TRUE; } } g_free (path); } } + + /* reset the changed files list, all events processed */ + g_list_foreach (menu->priv->changed_files, (GFunc) g_object_unref, NULL); + g_list_free (menu->priv->changed_files); + menu->priv->changed_files = NULL; + + /* reset the idle source ID */ + menu->priv->file_changed_idle = 0; + + /* remove the idle source */ + return FALSE; +} + + + +static gint +compare_files (gconstpointer a, + gconstpointer b) +{ + return g_file_equal (G_FILE (a), G_FILE (b)) ? 0 : 1; +} + + + +static void +garcon_menu_app_dir_changed (GarconMenu *menu, + GFile *file, + GFile *other_file, + GFileMonitorEvent event_type, + GFileMonitor *monitor) +{ + GarconMenuItem *item; + GFileType file_type; + + g_return_if_fail (GARCON_IS_MENU (menu)); + g_return_if_fail (menu->priv->parent == NULL); + + if (event_type == G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT + || event_type == G_FILE_MONITOR_EVENT_CREATED + || event_type == G_FILE_MONITOR_EVENT_ATTRIBUTE_CHANGED) + { + /* add the file to the changed files queue if we have no change event for + * it queued yet */ + if (g_list_find_custom (menu->priv->changed_files, file, compare_files) == NULL) + { + menu->priv->changed_files = g_list_append (menu->priv->changed_files, + g_object_ref (file)); + + /* register the idle handler if it is not active yet */ + if (menu->priv->file_changed_idle == 0) + { + menu->priv->file_changed_idle = + g_idle_add ((GSourceFunc) garcon_menu_process_file_changes, menu); + } + } + } else if (event_type == G_FILE_MONITOR_EVENT_DELETED) { /* query the type of the changed file */ _______________________________________________ Xfce4-commits mailing list Xfce4-commits@xfce.org http://foo-projects.org/mailman/listinfo/xfce4-commits