GNOME Bugzilla – Bug 339273
Possibility for an extension to ask for menu cache refreshing
Last modified: 2006-06-20 13:59:35 UTC
I'm the maintainer of Nautilus-actions [1] which allows to add custom menu item in the popup menu of Nautilus and I have some trouble with the menu cache system (see Bug #325584 [2] ). When a user add an action with my extension, Nautilus doesn't update the menu content every time for obvious performance reasons. There is three differents behaviours : - For the popup menu of a bunch of selected files or folders in a Nautilus' window, the menu is refreshed when the user changes the current selection (not very annoying). - For the popup menu generated on the background of a Nautilus' window, the menu is updated when the user close this window and reopen it (a bit annoying). - For the popup menu generated on the desktop, the menu is updated when the user restart Nautilus (eg. with the command "nautilus -q" ) or log out his gnome session (very annoying) These tests has been made with Nautilus 2.12. So it would be great to have a function to ask Nautilus to refresh its menu cache when an extension is modifying it. [1] http://www.grumz.net/node/4 [2] http://bugzilla.gnome.org/show_bug.cgi?id=325584
Following our discussion[1] on the nautilus mailing list, I took some time to look at the code and try to find a clean solution to this problem. I've maybe found a solution but I miss some details and I would like your opinion about it. I found that the update of the menus are ordered by the function schedule_update_menus() in src/file-manager/fm-directory-view.c This function trigger a timeout function and set the variable view->details->menu_states_untrustworthy to TRUE and then if the user right-click on a selection and this variable still has this state, it ask for menu update in update_menus_if_pending() function, otherwise it is done by the timeout function update_menus_timeout_callback(). So to fix this bug, one solution is to export the schedule_update_menus() function or an equivalent. But we must give it the FMDirectoryView pointer as parameter which the extension doesn't have. So is there a way to find it easily from nautilus (maybe with the parent window)... the function would be something like void ask_for_menu_update (GtkWindow* parent_window) { FMDirectoryView* view = get_current_fm_directory_view_pointer(parent_window); schedule_update_menus(view); } Another solution would be to add a function in the extension API which return true if the item list has changed and we would call it in the function update_menus_if_pending() but it is less efficient and nautilus can't be sure that an extention will not make lots of computation that will slow down the whole process. So the first solution is cleaner, but we have to solve the problem of finding the FMDirectoryView. [1] http://mail.gnome.org/archives/nautilus-list/2006-April/msg00077.html
After digging a bit more in the code, I may have found a way to get the view I need. The function would look like this now : void ask_for_menu_update (GtkWindow* parent_window) { g_assert (NAUTILUS_IS_WINDOW(parent_window)); NautilusWindow *window = NAUTILUS_WINDOW(parent_window); NautilusView *view = nautilus_view_factory_lookup (nautilus_window_get_content_view_id (window)); schedule_update_menu (FM_DIRECTORY_VIEW(view)); } I still have to find a clean way to get all this stuff working in the libnautilus-extentions library. If you have any clue or advice, you are welcome to post them here and if you think I'm in the wrong way, please tell me too :)
Created attachment 67391 [details] [review] First patch proposal to fix this bug So finally, I've found a clean way to fix this bug. I've added a signal "items_updated" to the menu provider interface with a function to emit it easily. Then after loading the modules, nautilus attaches for each menu provider extension this signal to a callback which will update all the currently cached popup menus (current selection, background of each window and the desktop). So when an extension wants menu updating because its config has changed, it just has to call the function nautilus_menu_provider_emit_items_updated_signal() and Nautilus do the job.
Created attachment 67480 [details] [review] New patch proposal following alex review So, here is the new patch proposition. The changes are : - remove the declaration of the signal in the menu provider class to avoid ABI compatibility breakage - remove the need for the window parameter in the item_changed signal - use the NautilusSignaller API to update the menu instead of hardcoding things from different part of nautilus. - precedent patch didn't update all selection's popup menus. Now all the menus are updated correctly.
Created attachment 67484 [details] [review] New patch proposal with move of NautilusSignaller in private lib Here is the new version with the move of the NautilusSignaller class in libnautilus-private as Alex proposed on the mailing list. The patch has been done with the command : diff -ruNP to reflect the move of the nautilus-signaller.[ch] from src folder to libnautilus-private. I change some Makefile.am files but I removed from the patch the changes generated by the autotools scripts (Makefile.in, ...) so don't forget to rerun them after applying it. Hope this one is the good one :)
Commited.