--- gnome-menus/libmenu/menu-monitor.c	24 Aug 2005 14:53:25 -0000	1.7
+++ gnome-menus/libmenu/menu-monitor.c	12 Sep 2005 12:26:25 -0000
@@ -37,7 +37,7 @@ struct MenuMonitor
 
 #ifdef HAVE_FAM
   FAMRequest  request;
-  GSList     *pending_events;
+  char *fam_key;
 #endif /* HAVE_FAM */
 
   guint is_directory : 1;
@@ -53,7 +53,7 @@ typedef struct
 #ifdef HAVE_FAM
 typedef struct
 {
-  MenuMonitor      *monitor;
+  char             *monitor_key;
   MenuMonitorEvent  event;
   char             *path;
 } MenuMonitorEventInfo;
@@ -63,6 +63,8 @@ static GHashTable *monitors_registry = N
 
 static MenuMonitorNotify *menu_monitor_notify_ref   (MenuMonitorNotify *notify);
 static void               menu_monitor_notify_unref (MenuMonitorNotify *notify);
+static void               free_event_info           (MenuMonitorEventInfo *event);
+static inline char       *get_registry_key          (const char *path, gboolean    is_directory);
 
 #ifdef HAVE_FAM
 static FAMConnection  fam_connection;
@@ -70,6 +72,7 @@ static gboolean       opened_connection 
 static gboolean       failed_to_connect = FALSE;
 static guint          fam_io_watch = 0;
 static guint          events_idle_handler = 0;
+static GQueue        *event_queue = NULL;
 
 static void
 invoke_notifies (MenuMonitor      *monitor,
@@ -104,74 +107,47 @@ invoke_notifies (MenuMonitor      *monit
   g_slist_free (copy);
 }
 
-static void
-list_pending_events_foreach (const char   *key,
-			     MenuMonitor  *monitor,
-			     GSList      **pending_events)
-{
-  GSList *tmp;
-
-  tmp = monitor->pending_events;
-  while (tmp != NULL)
-    {
-      MenuMonitorEventInfo *event = tmp->data;
-
-      menu_monitor_ref (event->monitor);
-
-      tmp = tmp->next;
-    }
-
-  *pending_events = g_slist_concat (*pending_events,
-				    monitor->pending_events);
-
-  monitor->pending_events = NULL;
-}
 
 static gboolean
 emit_events_in_idle (void)
 {
-  GSList *pending_events = NULL;
-  GSList *tmp;
+  MenuMonitorEventInfo *event;
 
   events_idle_handler = 0;
   
-  g_hash_table_foreach (monitors_registry,
-			(GHFunc) list_pending_events_foreach,
-			&pending_events);
 
-  tmp = pending_events;
-  while (tmp != NULL)
+  while ((event = g_queue_pop_head (event_queue))!= NULL)
     {
-      MenuMonitorEventInfo *event = tmp->data;
+      MenuMonitor *monitor;
 
-      invoke_notifies (event->monitor, event->event, event->path);
+      monitor = g_hash_table_lookup (monitors_registry, event->monitor_key);
 
-      menu_monitor_unref (event->monitor);
-      event->monitor = NULL;
+      if (monitor == NULL)
+	      continue;
 
-      g_free (event->path);
-      event->path = NULL;
+      menu_monitor_ref (monitor);
 
-      event->event = MENU_MONITOR_EVENT_INVALID;
+      invoke_notifies (monitor, event->event, event->path);
 
-      g_free (event);
+      menu_monitor_unref (monitor);
 
-      tmp = tmp->next;
+      free_event_info (event);
     }
 
-  g_slist_free (pending_events);
-
   return FALSE;
 }
 
+static inline char *
+get_registry_key (const char *path,
+		  gboolean    is_directory);
+
 static void
-queue_fam_event (MenuMonitor *monitor,
+queue_fam_event (const char *userdata,
 		 FAMEvent    *fam_event)
 {
   MenuMonitorEventInfo *event;
   const char           *path;
   char                 *freeme;
-  GSList               *tmp;
 
   freeme = NULL;
   if (fam_event->filename[0] == '/')
@@ -180,35 +156,15 @@ queue_fam_event (MenuMonitor *monitor,
     }
   else
     {
-      path = freeme = g_build_filename (monitor->path,
+      path = freeme = g_build_filename (userdata+1,
 					fam_event->filename,
 					NULL);
     }
 
-  event = NULL;
-  tmp = monitor->pending_events;
-  while (tmp != NULL)
-    {
-      event = tmp->data;
-
-      if (strcmp (event->path, path) == 0)
-	break;
-
-      event = NULL;
-
-      tmp = tmp->next;
-    }
-
-  if (event == NULL)
-    {
-      event = g_new0 (MenuMonitorEventInfo, 1);
+  event = g_new0 (MenuMonitorEventInfo, 1);
 
-      event->path    = g_strdup (path);
-      event->monitor = monitor;
-
-      monitor->pending_events = g_slist_append (monitor->pending_events,
-						event);
-    }
+  event->path    = g_strdup (path);
+  event->monitor_key = get_registry_key(userdata+1, userdata[0] == '1');
 
   switch (fam_event->code)
     {
@@ -229,6 +185,8 @@ queue_fam_event (MenuMonitor *monitor,
       break;
     }
 
+  g_queue_push_tail (event_queue, event);
+
   if (events_idle_handler == 0)
     {
       events_idle_handler = g_idle_add ((GSourceFunc) emit_events_in_idle, NULL);
@@ -240,7 +198,7 @@ queue_fam_event (MenuMonitor *monitor,
 static inline void
 debug_event (FAMEvent *event)
 {
-#define PRINT_EVENT(str) menu_verbose ("Got event: %d %s <" str ">\n", event->code, event->filename);
+#define PRINT_EVENT(str) menu_verbose ("Got event: %d %s <" str "> %p\n", event->code, event->filename, event->userdata);
 
   switch (event->code)
     {
@@ -345,6 +303,7 @@ get_fam_connection (void)
 					 (GIOFunc) fam_data_pending,
 					 NULL);
 	  g_io_channel_unref (io_channel);
+	  event_queue = g_queue_new();
 	}
       else
 	{
@@ -388,10 +347,11 @@ register_monitor_with_fam (MenuMonitor *
 
   if (monitor->is_directory)
     {
+      monitor->fam_key = g_strdup_printf("1%s",monitor->path);
       if (FAMMonitorDirectory (fam_connection,
 			       monitor->path,
 			       &monitor->request,
-			       monitor) != 0)
+			       monitor->fam_key) != 0)
 	{
 	  g_warning ("Failed to add directory monitor on '%s': %s",
 		     monitor->path, FamErrlist[FAMErrno]);
@@ -399,10 +359,11 @@ register_monitor_with_fam (MenuMonitor *
     }
   else
     {
+      monitor->fam_key = g_strdup_printf("0%s",monitor->path);
       if (FAMMonitorFile (fam_connection,
 			  monitor->path,
 			  &monitor->request,
-			  monitor) != 0)
+			  monitor->fam_key) != 0)
 	{
 	  g_warning ("Failed to add file monitor on '%s': %s",
 		     monitor->path, FamErrlist[FAMErrno]);
@@ -518,7 +479,8 @@ free_event_info (MenuMonitorEventInfo *e
   g_free (event->path);
   event->path = NULL;
 
-  event->monitor = NULL;
+  g_free (event->monitor_key);
+  event->monitor_key = NULL;
   event->event   = MENU_MONITOR_EVENT_INVALID;
 
   g_free (event);
@@ -546,14 +508,13 @@ menu_monitor_unref (MenuMonitor *monitor
   g_slist_free (monitor->notifies);
   monitor->notifies = NULL;
 
-#ifdef HAVE_FAM
-  g_slist_foreach (monitor->pending_events, (GFunc) free_event_info, NULL);
-  g_slist_free (monitor->pending_events);
-  monitor->pending_events = NULL;
-#endif /* HAVE_FAM */
-
   g_free (monitor->path);
   monitor->path = NULL;
+
+#ifdef HAVE_FAM
+  g_free (monitor->fam_key);
+  monitor->fam_key = NULL;
+#endif
 
   g_free (monitor);
 }
