[gnome-menus] libmenu: Do not send multiple notifications for one file change
- From: Vincent Untz <vuntz src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-menus] libmenu: Do not send multiple notifications for one file change
- Date: Wed, 6 Oct 2010 13:51:29 +0000 (UTC)
commit 5092245c4fe1449bee93b8923e370d7db339f40f
Author: Vincent Untz <vuntz gnome org>
Date: Wed Oct 6 15:45:31 2010 +0200
libmenu: Do not send multiple notifications for one file change
We emit notifications in the idle loop, which enables us to compress
multiple notifications: this way, we can check if there is already a
notification for a directory.
We do this at the CachedDir level because it enables us to get one
notification for a file rename, for example. But we also need it at the
MenuLayout level to be sure to compress notifications accross multiple
directories. It could be argued that we only need the latter, but I like
it this way :-)
https://bugzilla.gnome.org/show_bug.cgi?id=172046
libmenu/entry-directories.c | 70 +++++++++++++++++++++++++++++++++++++++++-
libmenu/menu-layout.c | 35 +++++++++++++++++----
2 files changed, 96 insertions(+), 9 deletions(-)
---
diff --git a/libmenu/entry-directories.c b/libmenu/entry-directories.c
index b96b845..ee22a55 100644
--- a/libmenu/entry-directories.c
+++ b/libmenu/entry-directories.c
@@ -74,6 +74,8 @@ struct CachedDirMonitor
gpointer user_data;
};
+static void cached_dir_add_reference (CachedDir *dir);
+static void cached_dir_remove_reference (CachedDir *dir);
static void cached_dir_free (CachedDir *dir);
static gboolean cached_dir_load_entries_recursive (CachedDir *dir,
const char *dirname);
@@ -363,6 +365,9 @@ cached_dir_remove_subdir (CachedDir *dir,
return FALSE;
}
+static guint monitors_idle_handler = 0;
+static GSList *pending_monitors_dirs = NULL;
+
static void
cached_dir_invoke_monitors (CachedDir *dir)
{
@@ -379,9 +384,70 @@ cached_dir_invoke_monitors (CachedDir *dir)
tmp = next;
}
+ /* we explicitly don't invoke monitors of the parent since an
+ * event has been queued for it too */
+}
+
+static gboolean
+emit_monitors_in_idle (void)
+{
+ GSList *monitors_to_emit;
+ GSList *tmp;
+
+ monitors_to_emit = pending_monitors_dirs;
+
+ pending_monitors_dirs = NULL;
+ monitors_idle_handler = 0;
+
+ tmp = monitors_to_emit;
+ while (tmp != NULL)
+ {
+ CachedDir *dir = tmp->data;
+
+ cached_dir_invoke_monitors (dir);
+ cached_dir_remove_reference (dir);
+
+ tmp = tmp->next;
+ }
+
+ g_slist_free (monitors_to_emit);
+
+ return FALSE;
+}
+
+static void
+cached_dir_queue_monitor_event (CachedDir *dir)
+{
+ GSList *tmp;
+
+ tmp = pending_monitors_dirs;
+ while (tmp != NULL)
+ {
+ CachedDir *d = tmp->data;
+ GSList *next = tmp->next;
+
+ if (dir->parent == d->parent &&
+ g_strcmp0 (dir->name, d->name) == 0)
+ break;
+
+ tmp = next;
+ }
+
+ /* not found, so let's queue it */
+ if (tmp == NULL)
+ {
+ cached_dir_add_reference (dir);
+ pending_monitors_dirs = g_slist_append (pending_monitors_dirs, dir);
+ }
+
if (dir->parent)
{
- cached_dir_invoke_monitors (dir->parent);
+ cached_dir_queue_monitor_event (dir->parent);
+ }
+
+ if (monitors_idle_handler == 0)
+ {
+ monitors_idle_handler = g_idle_add ((GSourceFunc) emit_monitors_in_idle, NULL);
}
}
@@ -457,7 +523,7 @@ handle_cached_dir_changed (MenuMonitor *monitor,
_entry_directory_list_empty_desktop_cache ();
}
- cached_dir_invoke_monitors (dir);
+ cached_dir_queue_monitor_event (dir);
}
}
diff --git a/libmenu/menu-layout.c b/libmenu/menu-layout.c
index d9b800c..8439bca 100644
--- a/libmenu/menu-layout.c
+++ b/libmenu/menu-layout.c
@@ -65,6 +65,7 @@ struct MenuLayoutNodeRoot
char *name;
GSList *monitors;
+ guint monitors_idle_handler;
};
struct MenuLayoutNodeMenu
@@ -133,16 +134,14 @@ node_next (MenuLayoutNode *node)
return node->next;
}
-static void
-handle_entry_directory_changed (EntryDirectory *dir,
- MenuLayoutNode *node)
+static gboolean
+menu_layout_invoke_monitors (MenuLayoutNodeRoot *nr)
{
- MenuLayoutNodeRoot *nr;
- GSList *tmp;
+ GSList *tmp;
- g_assert (node->type == MENU_LAYOUT_NODE_MENU);
+ g_assert (nr->node.type == MENU_LAYOUT_NODE_ROOT);
- nr = (MenuLayoutNodeRoot *) menu_layout_node_get_root (node);
+ nr->monitors_idle_handler = 0;
tmp = nr->monitors;
while (tmp != NULL)
@@ -154,6 +153,24 @@ handle_entry_directory_changed (EntryDirectory *dir,
tmp = next;
}
+
+ return FALSE;
+}
+
+static void
+handle_entry_directory_changed (EntryDirectory *dir,
+ MenuLayoutNode *node)
+{
+ MenuLayoutNodeRoot *nr;
+
+ g_assert (node->type == MENU_LAYOUT_NODE_MENU);
+
+ nr = (MenuLayoutNodeRoot *) menu_layout_node_get_root (node);
+
+ if (nr->monitors_idle_handler == 0)
+ {
+ nr->monitors_idle_handler = g_idle_add ((GSourceFunc) menu_layout_invoke_monitors, nr);
+ }
}
static void
@@ -224,6 +241,10 @@ menu_layout_node_unref (MenuLayoutNode *node)
g_slist_foreach (nr->monitors, (GFunc) g_free, NULL);
g_slist_free (nr->monitors);
+ if (nr->monitors_idle_handler != 0)
+ g_source_remove (nr->monitors_idle_handler);
+ nr->monitors_idle_handler = 0;
+
g_free (nr->basedir);
g_free (nr->name);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]