Index: ChangeLog =================================================================== RCS file: /cvs/gnome/gnome-menus/ChangeLog,v retrieving revision 1.146 diff -u -p -r1.146 ChangeLog --- ChangeLog 6 Sep 2005 09:15:30 -0000 1.146 +++ ChangeLog 30 Sep 2005 14:14:04 -0000 @@ -0,0 +1,12 @@ +2005-09-30 Mark McLoughlin + + Hopefully fix issue where menus wouldn't be completely + reloaded after a spew of file change events (#313833) + + Detailed analysis from Frederic Crozat + + * libmenu/menu-monitor.c: make the pending_events list global + rather than per-monitor and don't try and coalesce events for + the same path so that we can guarantee that we emit all the + events in the same order as we receive them from FAM. + Index: libmenu/menu-monitor.c =================================================================== RCS file: /cvs/gnome/gnome-menus/libmenu/menu-monitor.c,v retrieving revision 1.7 diff -u -p -r1.7 menu-monitor.c --- libmenu/menu-monitor.c 24 Aug 2005 14:53:25 -0000 1.7 +++ libmenu/menu-monitor.c 30 Sep 2005 14:14:04 -0000 @@ -37,7 +37,6 @@ struct MenuMonitor #ifdef HAVE_FAM FAMRequest request; - GSList *pending_events; #endif /* HAVE_FAM */ guint is_directory : 1; @@ -70,6 +69,7 @@ static gboolean opened_connection static gboolean failed_to_connect = FALSE; static guint fam_io_watch = 0; static guint events_idle_handler = 0; +static GSList *pending_events = NULL; static void invoke_notifies (MenuMonitor *monitor, @@ -83,7 +83,6 @@ invoke_notifies (MenuMonitor *monit g_slist_foreach (copy, (GFunc) menu_monitor_notify_ref, NULL); - tmp = copy; while (tmp != NULL) @@ -104,62 +103,50 @@ invoke_notifies (MenuMonitor *monit g_slist_free (copy); } -static void -list_pending_events_foreach (const char *key, - MenuMonitor *monitor, - GSList **pending_events) +static gboolean +emit_events_in_idle (void) { + GSList *events_to_emit; GSList *tmp; - tmp = monitor->pending_events; + events_to_emit = pending_events; + + pending_events = NULL; + events_idle_handler = 0; + + tmp = events_to_emit; while (tmp != NULL) { - MenuMonitorEventInfo *event = tmp->data; + MenuMonitorEventInfo *event_info = tmp->data; - menu_monitor_ref (event->monitor); + menu_monitor_ref (event_info->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; - - events_idle_handler = 0; - g_hash_table_foreach (monitors_registry, - (GHFunc) list_pending_events_foreach, - &pending_events); - - tmp = pending_events; + tmp = events_to_emit; while (tmp != NULL) { - MenuMonitorEventInfo *event = tmp->data; + MenuMonitorEventInfo *event_info = tmp->data; - invoke_notifies (event->monitor, event->event, event->path); + invoke_notifies (event_info->monitor, + event_info->event, + event_info->path); - menu_monitor_unref (event->monitor); - event->monitor = NULL; + menu_monitor_unref (event_info->monitor); + event_info->monitor = NULL; - g_free (event->path); - event->path = NULL; + g_free (event_info->path); + event_info->path = NULL; - event->event = MENU_MONITOR_EVENT_INVALID; + event_info->event = MENU_MONITOR_EVENT_INVALID; - g_free (event); + g_free (event_info); tmp = tmp->next; } - g_slist_free (pending_events); + g_slist_free (events_to_emit); return FALSE; } @@ -168,10 +155,10 @@ static void queue_fam_event (MenuMonitor *monitor, FAMEvent *fam_event) { - MenuMonitorEventInfo *event; + MenuMonitorEventInfo *event_info; + MenuMonitorEvent event; const char *path; char *freeme; - GSList *tmp; freeme = NULL; if (fam_event->filename[0] == '/') @@ -185,43 +172,19 @@ queue_fam_event (MenuMonitor *monitor, 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->path = g_strdup (path); - event->monitor = monitor; - - monitor->pending_events = g_slist_append (monitor->pending_events, - event); - } - + event = MENU_MONITOR_EVENT_INVALID; switch (fam_event->code) { case FAMChanged: - event->event = MENU_MONITOR_EVENT_CHANGED; + event = MENU_MONITOR_EVENT_CHANGED; break; case FAMCreated: - event->event = MENU_MONITOR_EVENT_CREATED; + event = MENU_MONITOR_EVENT_CREATED; break; case FAMDeleted: - event->event = MENU_MONITOR_EVENT_DELETED; + event = MENU_MONITOR_EVENT_DELETED; break; default: @@ -229,6 +192,14 @@ queue_fam_event (MenuMonitor *monitor, break; } + event_info = g_new0 (MenuMonitorEventInfo, 1); + + event_info->path = g_strdup (path); + event_info->event = event; + event_info->monitor = monitor; + + pending_events = g_slist_append (pending_events, event_info); + if (events_idle_handler == 0) { events_idle_handler = g_idle_add ((GSourceFunc) emit_events_in_idle, NULL); @@ -513,15 +484,31 @@ menu_monitor_ref (MenuMonitor *monitor) #ifdef HAVE_FAM static void -free_event_info (MenuMonitorEventInfo *event) +menu_monitor_clear_pending_events (MenuMonitor *monitor) { - g_free (event->path); - event->path = NULL; + GSList *tmp; - event->monitor = NULL; - event->event = MENU_MONITOR_EVENT_INVALID; + tmp = pending_events; + while (tmp != NULL) + { + MenuMonitorEventInfo *event_info = tmp->data; + GSList *next = tmp->next; + + if (event_info->monitor == monitor) + { + pending_events = g_slist_delete_link (pending_events, tmp); + + g_free (event_info->path); + event_info->path = NULL; + + event_info->monitor = NULL; + event_info->event = MENU_MONITOR_EVENT_INVALID; - g_free (event); + g_free (event_info); + } + + tmp = next; + } } #endif /* HAVE_FAM */ @@ -547,10 +534,8 @@ menu_monitor_unref (MenuMonitor *monitor 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 */ + menu_monitor_clear_pending_events (monitor); +#endif g_free (monitor->path); monitor->path = NULL;