diff --git a/libmenu/entry-directories.c b/libmenu/entry-directories.c
index c459ff5..1a1b898 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);
     }
 }
 
@@ -451,7 +517,7 @@ handle_cached_dir_changed (MenuMonitor      *monitor,
 
   if (handled)
     {
-      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);
         }
