]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkfilechooserdefault.c
Fix make check
[~andy/gtk] / gtk / gtkfilechooserdefault.c
index 3f4064148490acec60b26d3409f145d8c9a7d5a0..498efd135d717907af781658c4c8758a055ab3ba 100644 (file)
@@ -14,9 +14,7 @@
  * Lesser General Public License for more details.
  *
  * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include "config.h"
 #include "gtkfilesystem.h"
 #include "gtkfilesystemmodel.h"
 #include "gtkframe.h"
-#include "gtkpaned.h"
+#include "gtkgrid.h"
 #include "gtkiconfactory.h"
 #include "gtkicontheme.h"
 #include "gtkimage.h"
 #include "gtkimagemenuitem.h"
+#include "gtkinfobar.h"
 #include "gtklabel.h"
 #include "gtkmarshalers.h"
 #include "gtkmessagedialog.h"
 #include "gtkmountoperation.h"
+#include "gtkpaned.h"
 #include "gtkpathbar.h"
 #include "gtkprivate.h"
 #include "gtkradiobutton.h"
 #include "gtkrecentmanager.h"
 #include "gtkscrolledwindow.h"
 #include "gtkseparatormenuitem.h"
+#include "gtksettings.h"
 #include "gtksizegroup.h"
 #include "gtksizerequest.h"
 #include "gtkstock.h"
-#include "gtktable.h"
 #include "gtktoolbar.h"
 #include "gtktoolbutton.h"
 #include "gtktooltip.h"
 #include <io.h>
 #endif
 
+/* Values for GtkSelection-related "info" fields */
+#define SELECTION_TEXT 0
+#define SELECTION_URI  1
+
 /* Profiling stuff */
 #undef PROFILE_FILE_CHOOSER
 #ifdef PROFILE_FILE_CHOOSER
@@ -95,6 +99,7 @@
 #endif
 
 #define PROFILE_INDENT 4
+
 static int profile_indent;
 
 static void
@@ -201,6 +206,7 @@ enum {
   MODEL_COL_FILE,
   MODEL_COL_NAME_COLLATED,
   MODEL_COL_IS_FOLDER,
+  MODEL_COL_IS_SENSITIVE,
   MODEL_COL_PIXBUF,
   MODEL_COL_SIZE_TEXT,
   MODEL_COL_MTIME_TEXT,
@@ -217,6 +223,7 @@ enum {
        G_TYPE_FILE,              /* MODEL_COL_FILE */          \
        G_TYPE_STRING,            /* MODEL_COL_NAME_COLLATED */ \
        G_TYPE_BOOLEAN,           /* MODEL_COL_IS_FOLDER */     \
+       G_TYPE_BOOLEAN,           /* MODEL_COL_IS_SENSITIVE */  \
        GDK_TYPE_PIXBUF,          /* MODEL_COL_PIXBUF */        \
        G_TYPE_STRING,            /* MODEL_COL_SIZE_TEXT */     \
        G_TYPE_STRING,            /* MODEL_COL_MTIME_TEXT */    \
@@ -249,15 +256,6 @@ typedef enum {
 #define NUM_LINES 45
 #define NUM_CHARS 60
 
-#define SETTINGS_KEY_LAST_FOLDER_URI     "last-folder-uri"
-#define SETTINGS_KEY_LOCATION_MODE       "location-mode"
-#define SETTINGS_KEY_SHOW_HIDDEN         "show-hidden"
-#define SETTINGS_KEY_SHOW_SIZE_COLUMN    "show-size-column"
-#define SETTINGS_KEY_SORT_COLUMN         "sort-column"
-#define SETTINGS_KEY_SORT_ORDER          "sort-order"
-#define SETTINGS_KEY_WINDOW_POSITION     "window-position"
-#define SETTINGS_KEY_WINDOW_SIZE         "window-size"
-
 static void gtk_file_chooser_default_iface_init       (GtkFileChooserIface        *iface);
 static void gtk_file_chooser_embed_default_iface_init (GtkFileChooserEmbedIface   *iface);
 
@@ -283,8 +281,6 @@ static void     gtk_file_chooser_default_hierarchy_changed (GtkWidget          *
 static void     gtk_file_chooser_default_style_updated  (GtkWidget             *widget);
 static void     gtk_file_chooser_default_screen_changed (GtkWidget             *widget,
                                                         GdkScreen             *previous_screen);
-static void     gtk_file_chooser_default_size_allocate  (GtkWidget             *widget,
-                                                        GtkAllocation         *allocation);
 
 static gboolean       gtk_file_chooser_default_set_current_folder         (GtkFileChooser    *chooser,
                                                                            GFile             *folder,
@@ -326,6 +322,8 @@ static void           gtk_file_chooser_default_get_default_size       (GtkFileCh
 static gboolean       gtk_file_chooser_default_should_respond         (GtkFileChooserEmbed *chooser_embed);
 static void           gtk_file_chooser_default_initial_focus          (GtkFileChooserEmbed *chooser_embed);
 
+static void add_selection_to_recent_list (GtkFileChooserDefault *impl);
+
 static void location_popup_handler  (GtkFileChooserDefault *impl,
                                     const gchar           *path);
 static void location_popup_on_paste_handler (GtkFileChooserDefault *impl);
@@ -394,7 +392,7 @@ static void remove_bookmark_button_clicked_cb (GtkButton             *button,
 
 static void update_cell_renderer_attributes (GtkFileChooserDefault *impl);
 
-static void load_remove_timer (GtkFileChooserDefault *impl);
+static void load_remove_timer (GtkFileChooserDefault *impl, LoadState new_load_state);
 static void browse_files_center_selected_row (GtkFileChooserDefault *impl);
 
 static void location_button_toggled_cb (GtkToggleButton *toggle,
@@ -403,22 +401,23 @@ static void location_switch_to_path_bar (GtkFileChooserDefault *impl);
 
 static void stop_loading_and_clear_list_model (GtkFileChooserDefault *impl,
                                                gboolean remove_from_treeview);
+
+static void     search_setup_widgets         (GtkFileChooserDefault *impl);
 static void     search_stop_searching        (GtkFileChooserDefault *impl,
                                               gboolean               remove_query);
 static void     search_clear_model           (GtkFileChooserDefault *impl, 
                                              gboolean               remove_from_treeview);
 static gboolean search_should_respond        (GtkFileChooserDefault *impl);
-static void     search_switch_to_browse_mode (GtkFileChooserDefault *impl);
 static GSList  *search_get_selected_files    (GtkFileChooserDefault *impl);
 static void     search_entry_activate_cb     (GtkEntry              *entry, 
                                              gpointer               data);
 static void     settings_load                (GtkFileChooserDefault *impl);
 
+static void     recent_start_loading         (GtkFileChooserDefault *impl);
 static void     recent_stop_loading          (GtkFileChooserDefault *impl);
 static void     recent_clear_model           (GtkFileChooserDefault *impl,
                                               gboolean               remove_from_treeview);
 static gboolean recent_should_respond        (GtkFileChooserDefault *impl);
-static void     recent_switch_to_browse_mode (GtkFileChooserDefault *impl);
 static GSList * recent_get_selected_files    (GtkFileChooserDefault *impl);
 static void     set_file_system_backend      (GtkFileChooserDefault *impl);
 static void     unset_file_system_backend    (GtkFileChooserDefault *impl);
@@ -444,6 +443,8 @@ typedef struct {
 
 static void shortcuts_pane_model_filter_drag_source_iface_init (GtkTreeDragSourceIface *iface);
 
+GType _shortcuts_pane_model_filter_get_type (void);
+
 G_DEFINE_TYPE_WITH_CODE (ShortcutsPaneModelFilter,
                         _shortcuts_pane_model_filter,
                         GTK_TYPE_TREE_MODEL_FILTER,
@@ -502,7 +503,6 @@ _gtk_file_chooser_default_class_init (GtkFileChooserDefaultClass *class)
   widget_class->hierarchy_changed = gtk_file_chooser_default_hierarchy_changed;
   widget_class->style_updated = gtk_file_chooser_default_style_updated;
   widget_class->screen_changed = gtk_file_chooser_default_screen_changed;
-  widget_class->size_allocate = gtk_file_chooser_default_size_allocate;
 
   signals[LOCATION_POPUP] =
     g_signal_new_class_handler (I_("location-popup"),
@@ -630,10 +630,6 @@ _gtk_file_chooser_default_class_init (GtkFileChooserDefaultClass *class)
                                GDK_KEY_v, GDK_CONTROL_MASK,
                                "location-popup-on-paste",
                                0);
-  gtk_binding_entry_add_signal (binding_set,
-                               GDK_KEY_BackSpace, 0,
-                               "up-folder",
-                               0);
 
   add_normal_and_shifted_binding (binding_set,
                                  GDK_KEY_Up, GDK_MOD1_MASK,
@@ -811,8 +807,7 @@ shortcuts_free (GtkFileChooserDefault *impl)
 static void
 pending_select_files_free (GtkFileChooserDefault *impl)
 {
-  g_slist_foreach (impl->pending_select_files, (GFunc) g_object_unref, NULL);
-  g_slist_free (impl->pending_select_files);
+  g_slist_free_full (impl->pending_select_files, g_object_unref);
   impl->pending_select_files = NULL;
 }
 
@@ -1451,7 +1446,6 @@ get_file_info_finished (GCancellable *cancellable,
                        const GError *error,
                        gpointer      data)
 {
-  gint pos = -1;
   gboolean cancelled = g_cancellable_is_cancelled (cancellable);
   GdkPixbuf *pixbuf;
   GtkTreePath *path;
@@ -1464,7 +1458,6 @@ get_file_info_finished (GCancellable *cancellable,
     /* Handle doesn't exist anymore in the model */
     goto out;
 
-  pos = gtk_tree_path_get_indices (path)[0];
   gtk_tree_model_get_iter (GTK_TREE_MODEL (request->impl->shortcuts_model),
                           &iter, path);
   gtk_tree_path_free (path);
@@ -1740,11 +1733,31 @@ shortcuts_append_search (GtkFileChooserDefault *impl)
   impl->has_search = TRUE;
 }
 
+static gboolean
+shortcuts_get_recent_enabled (GtkWidget *widget)
+{
+  GtkSettings *settings;
+  gboolean enabled;
+
+  if (gtk_widget_has_screen (widget))
+    settings = gtk_settings_get_for_screen (gtk_widget_get_screen (widget));
+  else
+    settings = gtk_settings_get_default ();
+
+  g_object_get (settings, "gtk-recent-files-enabled", &enabled, NULL);
+  return enabled;
+}
+
 static void
 shortcuts_append_recent (GtkFileChooserDefault *impl)
 {
   GdkPixbuf *pixbuf;
   GtkTreeIter iter;
+  gboolean enabled;
+
+  enabled = shortcuts_get_recent_enabled (GTK_WIDGET (impl));
+  if (!enabled)
+    return;
 
   pixbuf = render_recent_icon (impl);
 
@@ -1760,6 +1773,8 @@ shortcuts_append_recent (GtkFileChooserDefault *impl)
   
   if (pixbuf)
     g_object_unref (pixbuf);
+
+  impl->has_recent = TRUE;
 }
 
 /* Appends an item for the user's home directory to the shortcuts model */
@@ -1875,7 +1890,7 @@ shortcuts_get_index (GtkFileChooserDefault *impl,
   if (where == SHORTCUTS_RECENT)
     goto out;
 
-  n += 1; /* we always have the recently-used item */
+  n += impl->has_recent ? 1 : 0;
 
   if (where == SHORTCUTS_RECENT_SEPARATOR)
     goto out;
@@ -2242,7 +2257,7 @@ add_idle_while_impl_is_alive (GtkFileChooserDefault *impl, GCallback callback)
 static gboolean
 edited_idle_cb (GtkFileChooserDefault *impl)
 {
-  GDK_THREADS_ENTER ();
+  gdk_threads_enter ();
   
   g_source_destroy (impl->edited_idle);
   impl->edited_idle = NULL;
@@ -2280,7 +2295,7 @@ edited_idle_cb (GtkFileChooserDefault *impl)
       impl->edited_new_text = NULL;
     }
 
-  GDK_THREADS_LEAVE ();
+  gdk_threads_leave ();
 
   return FALSE;
 }
@@ -3376,7 +3391,7 @@ shortcuts_build_popup_menu (GtkFileChooserDefault *impl)
   gtk_widget_show (item);
   gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_shortcuts_popup_menu), item);
 
-  item = gtk_menu_item_new_with_label (_("Rename..."));
+  item = gtk_menu_item_new_with_label (_("Rename"));
   impl->browse_shortcuts_popup_menu_rename_item = item;
   g_signal_connect (item, "activate",
                    G_CALLBACK (rename_shortcut_cb), impl);
@@ -3441,7 +3456,7 @@ shortcuts_button_press_event_cb (GtkWidget             *widget,
   if (in_press)
     return FALSE;
 
-  if (event->button != 3)
+  if (!gdk_event_triggers_context_menu ((GdkEvent *) event))
     return FALSE;
 
   in_press = TRUE;
@@ -3656,6 +3671,7 @@ shortcuts_pane_create (GtkFileChooserDefault *impl,
   /* Box for buttons */
 
   toolbar = gtk_toolbar_new ();
+  gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS);
   gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_MENU);
 
   context = gtk_widget_get_style_context (toolbar);
@@ -3709,7 +3725,7 @@ key_is_left_or_right (GdkEventKey *event)
 
 /* Handles key press events on the file list, so that we can trap Enter to
  * activate the default button on our own.  Also, checks to see if '/' has been
- * pressed.  See comment by tree_view_keybinding_cb() for more details.
+ * pressed.
  */
 static gboolean
 browse_files_key_press_event_cb (GtkWidget   *widget,
@@ -3717,18 +3733,19 @@ browse_files_key_press_event_cb (GtkWidget   *widget,
                                 gpointer     data)
 {
   GtkFileChooserDefault *impl;
-  int modifiers;
+  GdkModifierType no_text_input_mask;
 
   impl = (GtkFileChooserDefault *) data;
 
-  modifiers = gtk_accelerator_get_default_mod_mask ();
+  no_text_input_mask =
+    gtk_widget_get_modifier_mask (widget, GDK_MODIFIER_INTENT_NO_TEXT_INPUT);
 
   if ((event->keyval == GDK_KEY_slash
        || event->keyval == GDK_KEY_KP_Divide
 #ifdef G_OS_UNIX
        || event->keyval == GDK_KEY_asciitilde
 #endif
-       ) && ! (event->state & (~GDK_SHIFT_MASK & modifiers)))
+       ) && !(event->state & no_text_input_mask))
     {
       location_popup_handler (impl, event->string);
       return TRUE;
@@ -3745,7 +3762,7 @@ browse_files_key_press_event_cb (GtkWidget   *widget,
        || event->keyval == GDK_KEY_KP_Enter
        || event->keyval == GDK_KEY_space
        || event->keyval == GDK_KEY_KP_Space)
-      && ((event->state & modifiers) == 0)
+      && !(event->state & gtk_accelerator_get_default_mod_mask ())
       && !(impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
           impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
     {
@@ -3785,6 +3802,7 @@ popup_menu_detach_cb (GtkWidget *attach_widget,
   impl->browse_files_popup_menu = NULL;
   impl->browse_files_popup_menu_add_shortcut_item = NULL;
   impl->browse_files_popup_menu_hidden_files_item = NULL;
+  impl->browse_files_popup_menu_copy_file_location_item = NULL;
 }
 
 /* Callback used when the "Add to Bookmarks" menu item is activated */
@@ -3795,7 +3813,119 @@ add_to_shortcuts_cb (GtkMenuItem           *item,
   bookmarks_add_selected_folder (impl);
 }
 
-/* Callback used when the "Show Hidden Files" menu item is toggled */
+/* callback used to set data to clipboard */
+static void
+copy_file_get_cb  (GtkClipboard     *clipboard,
+                   GtkSelectionData *selection_data,
+                   guint             info,
+                   gpointer          data)
+{
+  GSList *selected_files = data;
+
+  if (selected_files)
+    {
+      gint num_files = g_slist_length (selected_files);
+      gchar **uris;
+      gint i;
+      GSList *l;
+
+      uris = g_new (gchar *, num_files + 1);
+      uris[num_files] = NULL; /* null terminator */
+
+      i = 0;
+
+      for (l = selected_files; l; l = l->next)
+        {
+          GFile *file = (GFile *) l->data;
+
+         if (info == SELECTION_URI)
+           uris[i] = g_file_get_uri (file);
+         else /* if (info == SELECTION_TEXT) - let this be the fallback */
+           uris[i] = g_file_get_parse_name (file);
+
+          i++;
+        }
+
+      if (info == SELECTION_URI)
+       gtk_selection_data_set_uris (selection_data, uris);
+      else /* if (info == SELECTION_TEXT) - let this be the fallback */
+       {
+         char *str = g_strjoinv (" ", uris);
+         gtk_selection_data_set_text (selection_data, str, -1);
+         g_free (str);
+       }
+
+      g_strfreev (uris);
+    }
+}
+
+/* callback used to clear the clipboard data */
+static void
+copy_file_clear_cb (GtkClipboard *clipboard,
+                    gpointer      data)
+{
+  GSList *selected_files = data;
+
+  g_slist_foreach (selected_files, (GFunc) g_object_unref, NULL);
+  g_slist_free (selected_files);
+}
+
+/* Callback used when the "Copy file’s location" menu item is activated */
+static void
+copy_file_location_cb (GtkMenuItem           *item,
+                       GtkFileChooserDefault *impl)
+{
+  GSList *selected_files = NULL;
+
+  selected_files = search_get_selected_files (impl);
+
+  if (selected_files)
+    {
+      GtkClipboard *clipboard;
+      GtkTargetList *target_list;
+      GtkTargetEntry *targets;
+      int n_targets;
+
+      clipboard = gtk_widget_get_clipboard (GTK_WIDGET (impl), GDK_SELECTION_CLIPBOARD);
+
+      target_list = gtk_target_list_new (NULL, 0);
+      gtk_target_list_add_text_targets (target_list, SELECTION_TEXT);
+      gtk_target_list_add_uri_targets (target_list, SELECTION_URI);
+
+      targets = gtk_target_table_new_from_list (target_list, &n_targets);
+      gtk_target_list_unref (target_list);
+
+      gtk_clipboard_set_with_data (clipboard, targets, n_targets,
+                                  copy_file_get_cb,
+                                   copy_file_clear_cb,
+                                  selected_files);
+
+      gtk_target_table_free (targets, n_targets);
+    }
+}
+
+/* Callback used when the "Visit this file" menu item is activated */
+static void
+visit_file_cb (GtkMenuItem *item,
+              GtkFileChooserDefault *impl)
+{
+  GSList *files;
+
+  files = search_get_selected_files (impl);
+
+  /* Sigh, just use the first one */
+  if (files)
+    {
+      GFile *file = files->data;
+
+      gtk_file_chooser_default_select_file (GTK_FILE_CHOOSER (impl), file, NULL); /* NULL-GError */
+    }
+
+  g_slist_foreach (files, (GFunc) g_object_unref, NULL);
+  g_slist_free (files);
+}
+
+/* callback used when the "Show Hidden Files" menu item is toggled */
 static void
 show_hidden_toggled_cb (GtkCheckMenuItem      *item,
                        GtkFileChooserDefault *impl)
@@ -3982,6 +4112,58 @@ file_list_drag_motion_cb (GtkWidget             *widget,
   return TRUE;
 }
 
+/* Sensitizes the "Copy file’s location" context menu item if there is actually
+ * a selection active.
+ */
+static void
+check_copy_file_location_sensitivity (GtkFileChooserDefault *impl)
+{
+  GtkTreeSelection *selection;
+  gboolean active;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+  if (gtk_tree_selection_count_selected_rows (selection) == 0)
+    active = FALSE;
+  else
+    active = TRUE;
+
+  if (impl->browse_files_popup_menu_copy_file_location_item)
+    gtk_widget_set_sensitive (impl->browse_files_popup_menu_copy_file_location_item, active);
+}
+
+static GtkWidget *
+file_list_add_image_menu_item (GtkFileChooserDefault *impl,
+                              const char *stock_name,
+                              const char *mnemonic_label,
+                              GCallback callback)
+{
+  GtkWidget *item;
+
+  item = gtk_image_menu_item_new_with_mnemonic (mnemonic_label);
+  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
+                                 gtk_image_new_from_stock (stock_name, GTK_ICON_SIZE_MENU));
+  g_signal_connect (item, "activate", callback, impl);
+  gtk_widget_show (item);
+  gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
+  
+  return item;
+}
+
+static GtkWidget *
+file_list_add_check_menu_item (GtkFileChooserDefault *impl,
+                              const char *mnemonic_label,
+                              GCallback callback)
+{
+  GtkWidget *item;
+
+  item = gtk_check_menu_item_new_with_mnemonic (mnemonic_label);
+  g_signal_connect (item, "toggled", callback, impl);
+  gtk_widget_show (item);
+  gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
+
+  return item;
+}
+
 /* Constructs the popup menu for the file list if needed */
 static void
 file_list_build_popup_menu (GtkFileChooserDefault *impl)
@@ -3996,34 +4178,27 @@ file_list_build_popup_menu (GtkFileChooserDefault *impl)
                             impl->browse_files_tree_view,
                             popup_menu_detach_cb);
 
-  item = gtk_image_menu_item_new_with_mnemonic (_("_Add to Bookmarks"));
-  impl->browse_files_popup_menu_add_shortcut_item = item;
-  gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
-                                gtk_image_new_from_stock (GTK_STOCK_ADD, GTK_ICON_SIZE_MENU));
-  g_signal_connect (item, "activate",
-                   G_CALLBACK (add_to_shortcuts_cb), impl);
-  gtk_widget_show (item);
-  gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
+  impl->browse_files_popup_menu_visit_file_item                = file_list_add_image_menu_item (impl, GTK_STOCK_DIRECTORY, _("_Visit this file"),
+                                                                                        G_CALLBACK (visit_file_cb));
+
+  impl->browse_files_popup_menu_copy_file_location_item        = file_list_add_image_menu_item (impl, GTK_STOCK_COPY, _("_Copy file’s location"),
+                                                                                        G_CALLBACK (copy_file_location_cb));
+
+  impl->browse_files_popup_menu_add_shortcut_item      = file_list_add_image_menu_item (impl, GTK_STOCK_ADD, _("_Add to Bookmarks"),
+                                                                                        G_CALLBACK (add_to_shortcuts_cb));
 
   item = gtk_separator_menu_item_new ();
   gtk_widget_show (item);
   gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
 
-  item = gtk_check_menu_item_new_with_mnemonic (_("Show _Hidden Files"));
-  impl->browse_files_popup_menu_hidden_files_item = item;
-  g_signal_connect (item, "toggled",
-                   G_CALLBACK (show_hidden_toggled_cb), impl);
-  gtk_widget_show (item);
-  gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
+  impl->browse_files_popup_menu_hidden_files_item      = file_list_add_check_menu_item (impl, _("Show _Hidden Files"),
+                                                                                        G_CALLBACK (show_hidden_toggled_cb));
 
-  item = gtk_check_menu_item_new_with_mnemonic (_("Show _Size Column"));
-  impl->browse_files_popup_menu_size_column_item = item;
-  g_signal_connect (item, "toggled",
-                    G_CALLBACK (show_size_column_toggled_cb), impl);
-  gtk_widget_show (item);
-  gtk_menu_shell_append (GTK_MENU_SHELL (impl->browse_files_popup_menu), item);
+  impl->browse_files_popup_menu_size_column_item       = file_list_add_check_menu_item (impl, _("Show _Size Column"),
+                                                                                        G_CALLBACK (show_size_column_toggled_cb));
 
   bookmarks_check_add_sensitivity (impl);
+  check_copy_file_location_sensitivity (impl);
 }
 
 /* Updates the popup menu for the file list, creating it if necessary */
@@ -4032,12 +4207,13 @@ file_list_update_popup_menu (GtkFileChooserDefault *impl)
 {
   file_list_build_popup_menu (impl);
 
-  /* FIXME - handle OPERATION_MODE_SEARCH and OPERATION_MODE_RECENT */
-
   /* The sensitivity of the Add to Bookmarks item is set in
    * bookmarks_check_add_sensitivity()
    */
 
+  /* 'Visit this file' */
+  gtk_widget_set_visible (impl->browse_files_popup_menu_visit_file_item, (impl->operation_mode != OPERATION_MODE_BROWSE));
+
   /* 'Show Hidden Files' */
   g_signal_handlers_block_by_func (impl->browse_files_popup_menu_hidden_files_item,
                                   G_CALLBACK (show_hidden_toggled_cb), impl);
@@ -4082,7 +4258,7 @@ popup_position_func (GtkMenu   *menu,
 
   monitor_num = gdk_screen_get_monitor_at_point (screen, *x, *y);
   gtk_menu_set_monitor (menu, monitor_num);
-  gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
+  gdk_screen_get_monitor_workarea (screen, monitor_num, &monitor);
 
   *x = CLAMP (*x, monitor.x, monitor.x + MAX (0, monitor.width - req.width));
   *y = CLAMP (*y, monitor.y, monitor.y + MAX (0, monitor.height - req.height));
@@ -4133,7 +4309,7 @@ list_button_press_event_cb (GtkWidget             *widget,
   if (in_press)
     return FALSE;
 
-  if (event->button != 3)
+  if (!gdk_event_triggers_context_menu ((GdkEvent *) event))
     return FALSE;
 
   in_press = TRUE;
@@ -4150,7 +4326,9 @@ typedef struct {
   gint model_column;
 } ColumnMap;
 
-/* Sets the sort column IDs for the file list based on the operation mode */
+/* Sets the sort column IDs for the file list; needs to be done whenever we
+ * change the model on the treeview.
+ */
 static void
 file_list_set_sort_column_ids (GtkFileChooserDefault *impl)
 {
@@ -4344,17 +4522,6 @@ create_file_list (GtkFileChooserDefault *impl)
   return swin;
 }
 
-static GtkWidget *
-create_path_bar (GtkFileChooserDefault *impl)
-{
-  GtkWidget *path_bar;
-
-  path_bar = g_object_new (GTK_TYPE_PATH_BAR, NULL);
-  _gtk_path_bar_set_file_system (GTK_PATH_BAR (path_bar), impl->file_system);
-
-  return path_bar;
-}
-
 /* Creates the widgets for the files/folders pane */
 static GtkWidget *
 file_pane_create (GtkFileChooserDefault *impl,
@@ -4399,6 +4566,18 @@ file_pane_create (GtkFileChooserDefault *impl,
   return vbox;
 }
 
+static void
+location_entry_create (GtkFileChooserDefault *impl)
+{
+  if (!impl->location_entry)
+    impl->location_entry = _gtk_file_chooser_entry_new (TRUE);
+
+  _gtk_file_chooser_entry_set_local_only (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->local_only);
+  _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->action);
+  gtk_entry_set_width_chars (GTK_ENTRY (impl->location_entry), 45);
+  gtk_entry_set_activates_default (GTK_ENTRY (impl->location_entry), TRUE);
+}
+
 /* Creates the widgets specific to Save mode */
 static void
 save_widgets_create (GtkFileChooserDefault *impl)
@@ -4413,35 +4592,25 @@ save_widgets_create (GtkFileChooserDefault *impl)
 
   vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
 
-  impl->save_widgets_table = gtk_table_new (2, 2, FALSE);
+  impl->save_widgets_table = gtk_grid_new ();
   gtk_box_pack_start (GTK_BOX (vbox), impl->save_widgets_table, FALSE, FALSE, 0);
   gtk_widget_show (impl->save_widgets_table);
-  gtk_table_set_row_spacings (GTK_TABLE (impl->save_widgets_table), 12);
-  gtk_table_set_col_spacings (GTK_TABLE (impl->save_widgets_table), 12);
+  gtk_grid_set_row_spacing (GTK_GRID (impl->save_widgets_table), 12);
+  gtk_grid_set_column_spacing (GTK_GRID (impl->save_widgets_table), 12);
 
   /* Label */
 
   widget = gtk_label_new_with_mnemonic (_("_Name:"));
   gtk_widget_set_halign (widget, GTK_ALIGN_START);
   gtk_widget_set_valign (widget, GTK_ALIGN_CENTER);
-  gtk_table_attach (GTK_TABLE (impl->save_widgets_table), widget,
-                   0, 1, 0, 1,
-                   GTK_FILL, GTK_FILL,
-                   0, 0);
+  gtk_grid_attach (GTK_GRID (impl->save_widgets_table), widget, 0, 0, 1, 1);
   gtk_widget_show (widget);
 
   /* Location entry */
 
-  impl->location_entry = _gtk_file_chooser_entry_new (TRUE);
-  _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (impl->location_entry),
-                                          impl->file_system);
-  _gtk_file_chooser_entry_set_local_only (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->local_only);
-  gtk_entry_set_width_chars (GTK_ENTRY (impl->location_entry), 45);
-  gtk_entry_set_activates_default (GTK_ENTRY (impl->location_entry), TRUE);
-  gtk_table_attach (GTK_TABLE (impl->save_widgets_table), impl->location_entry,
-                   1, 2, 0, 1,
-                   GTK_EXPAND | GTK_FILL, 0,
-                   0, 0);
+  location_entry_create (impl);
+  gtk_widget_set_hexpand (impl->location_entry, TRUE);
+  gtk_grid_attach (GTK_GRID (impl->save_widgets_table), impl->location_entry, 1, 0, 1, 1);
   gtk_widget_show (impl->location_entry);
   gtk_label_set_mnemonic_widget (GTK_LABEL (widget), impl->location_entry);
 
@@ -4449,10 +4618,7 @@ save_widgets_create (GtkFileChooserDefault *impl)
   impl->save_folder_label = gtk_label_new (NULL);
   gtk_widget_set_halign (impl->save_folder_label, GTK_ALIGN_START);
   gtk_widget_set_valign (impl->save_folder_label, GTK_ALIGN_CENTER);
-  gtk_table_attach (GTK_TABLE (impl->save_widgets_table), impl->save_folder_label,
-                   0, 1, 1, 2,
-                   GTK_FILL, GTK_FILL,
-                   0, 0);
+  gtk_grid_attach (GTK_GRID (impl->save_widgets_table), impl->save_folder_label, 0, 1, 1, 1);
   gtk_widget_show (impl->save_folder_label);
 
   impl->save_widgets = vbox;
@@ -4490,53 +4656,6 @@ location_switch_to_path_bar (GtkFileChooserDefault *impl)
   gtk_widget_hide (impl->location_entry_box);
 }
 
-/* Sets the full path of the current folder as the text in the location entry. */
-static void
-location_entry_set_initial_text (GtkFileChooserDefault *impl)
-{
-  gchar *text, *filename;
-
-  if (!impl->current_folder)
-    return;
-
-  filename = g_file_get_path (impl->current_folder);
-
-  if (filename)
-    {
-      text = g_filename_to_utf8 (filename, -1, NULL, NULL, NULL);
-      g_free (filename);
-    }
-  else
-    text = g_file_get_uri (impl->current_folder);
-
-  if (text)
-    {
-      gboolean need_slash;
-      int len;
-
-      len = strlen (text);
-      need_slash = (text[len - 1] != G_DIR_SEPARATOR);
-
-      if (need_slash)
-       {
-         char *slash_text;
-
-         slash_text = g_new (char, len + 2);
-         strcpy (slash_text, text);
-         slash_text[len] = G_DIR_SEPARATOR;
-         slash_text[len + 1] = 0;
-
-         g_free (text);
-         text = slash_text;
-       }
-
-      _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), text);
-      g_free (text);
-    }
-
-  g_free (filename);
-}
-
 /* Turns on the location entry.  Can be called even if we are already in that
  * mode.
  */
@@ -4551,28 +4670,22 @@ location_switch_to_filename_entry (GtkFileChooserDefault *impl)
       impl->operation_mode == OPERATION_MODE_RECENT)
     return;
 
-  if (impl->location_entry)
-    gtk_widget_destroy (impl->location_entry);
-
   /* Box */
 
   gtk_widget_show (impl->location_entry_box);
 
   /* Entry */
 
-  impl->location_entry = _gtk_file_chooser_entry_new (TRUE);
-  _gtk_file_chooser_entry_set_file_system (GTK_FILE_CHOOSER_ENTRY (impl->location_entry),
-                                          impl->file_system);
-  gtk_entry_set_activates_default (GTK_ENTRY (impl->location_entry), TRUE);
-  _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->action);
-
-  gtk_box_pack_start (GTK_BOX (impl->location_entry_box), impl->location_entry, TRUE, TRUE, 0);
-  gtk_label_set_mnemonic_widget (GTK_LABEL (impl->location_label), impl->location_entry);
+  if (!impl->location_entry)
+    {
+      location_entry_create (impl);
+      gtk_box_pack_start (GTK_BOX (impl->location_entry_box), impl->location_entry, TRUE, TRUE, 0);
+      gtk_label_set_mnemonic_widget (GTK_LABEL (impl->location_label), impl->location_entry);
+    }
 
   /* Configure the entry */
 
   _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->current_folder);
-  _gtk_file_chooser_entry_set_local_only (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->local_only);
 
   /* Done */
 
@@ -4724,18 +4837,94 @@ location_button_create (GtkFileChooserDefault *impl)
   atk_object_set_name (gtk_widget_get_accessible (impl->location_button), str);
 }
 
-/* Creates the main hpaned with the widgets shared by Open and Save mode */
+typedef enum {
+  PATH_BAR_FOLDER_PATH,
+  PATH_BAR_SELECT_A_FOLDER,
+  PATH_BAR_ERROR_NO_FILENAME,
+  PATH_BAR_ERROR_NO_FOLDER,
+  PATH_BAR_RECENTLY_USED,
+  PATH_BAR_SEARCH
+} PathBarMode;
+
+/* Creates the info bar for informational messages or warnings, with its icon and label */
 static void
-browse_widgets_create (GtkFileChooserDefault *impl)
+info_bar_create (GtkFileChooserDefault *impl)
 {
-  GtkWidget *hpaned;
-  GtkWidget *widget;
-  GtkSizeGroup *size_group;
+  GtkWidget *content_area;
 
-  /* size group is used by the scrolled windows of the panes */
-  size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
-  impl->browse_widgets_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+  impl->browse_select_a_folder_info_bar = gtk_info_bar_new ();
+  impl->browse_select_a_folder_icon = gtk_image_new_from_stock (GTK_STOCK_DIRECTORY, GTK_ICON_SIZE_MENU);
+  impl->browse_select_a_folder_label = gtk_label_new (NULL);
+
+  content_area = gtk_info_bar_get_content_area (GTK_INFO_BAR (impl->browse_select_a_folder_info_bar));
+
+  gtk_box_pack_start (GTK_BOX (content_area), impl->browse_select_a_folder_icon, FALSE, FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (content_area), impl->browse_select_a_folder_label, FALSE, FALSE, 0);
+
+  gtk_widget_show (impl->browse_select_a_folder_icon);
+  gtk_widget_show (impl->browse_select_a_folder_label);
+}
+
+/* Sets the info bar to show the appropriate informational or warning message */
+static void
+info_bar_set (GtkFileChooserDefault *impl, PathBarMode mode)
+{
+  char *str;
+  gboolean free_str;
+  GtkMessageType message_type;
+
+  free_str = FALSE;
+
+  switch (mode)
+    {
+    case PATH_BAR_SELECT_A_FOLDER:
+      str = g_strconcat ("<i>", _("Please select a folder below"), "</i>", NULL);
+      free_str = TRUE;
+      message_type = GTK_MESSAGE_OTHER;
+      break;
+
+    case PATH_BAR_ERROR_NO_FILENAME:
+      str = _("Please type a file name");
+      message_type = GTK_MESSAGE_WARNING;
+      break;
 
+    case PATH_BAR_ERROR_NO_FOLDER:
+      str = _("Please select a folder below");
+      message_type = GTK_MESSAGE_WARNING;
+      break;
+
+    default:
+      g_assert_not_reached ();
+      return;
+    }
+
+  gtk_info_bar_set_message_type (GTK_INFO_BAR (impl->browse_select_a_folder_info_bar), message_type);
+  gtk_image_set_from_stock (GTK_IMAGE (impl->browse_select_a_folder_icon),
+                           (message_type == GTK_MESSAGE_WARNING) ? GTK_STOCK_DIALOG_WARNING : GTK_STOCK_DIRECTORY,
+                           GTK_ICON_SIZE_MENU);
+  gtk_label_set_markup (GTK_LABEL (impl->browse_select_a_folder_label), str);
+
+  if (free_str)
+    g_free (str);
+}
+
+/* Creates the icon and label used to show that the file chooser is in Search or Recently-used mode */
+static void
+special_mode_widgets_create (GtkFileChooserDefault *impl)
+{
+  impl->browse_special_mode_icon = gtk_image_new ();
+  gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->browse_special_mode_icon);
+  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->browse_special_mode_icon, FALSE, FALSE, 0);
+
+  impl->browse_special_mode_label = gtk_label_new (NULL);
+  gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->browse_special_mode_label);
+  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->browse_special_mode_label, FALSE, FALSE, 0);
+}
+
+/* Creates the path bar's container and eveyrthing that goes in it: location button, pathbar, info bar, and Create Folder button */
+static void
+path_bar_widgets_create (GtkFileChooserDefault *impl)
+{
   /* Location widgets - note browse_path_bar_hbox is packed in the right place until switch_path_bar() */
   impl->browse_path_bar_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
   gtk_widget_show (impl->browse_path_bar_hbox);
@@ -4745,62 +4934,160 @@ browse_widgets_create (GtkFileChooserDefault *impl)
   gtk_size_group_set_ignore_hidden (impl->browse_path_bar_size_group, FALSE);
 
   /* Location button */
-
   location_button_create (impl);
-  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->location_button, FALSE, FALSE, 0);
   gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->location_button);
+  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->location_button, FALSE, FALSE, 0);
 
   /* Path bar */
-
-  impl->browse_path_bar = create_path_bar (impl);
+  impl->browse_path_bar = g_object_new (GTK_TYPE_PATH_BAR, NULL);
+  _gtk_path_bar_set_file_system (GTK_PATH_BAR (impl->browse_path_bar), impl->file_system);
   g_signal_connect (impl->browse_path_bar, "path-clicked", G_CALLBACK (path_bar_clicked), impl);
-  gtk_widget_show_all (impl->browse_path_bar);
-  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->browse_path_bar, TRUE, TRUE, 0);
+
   gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->browse_path_bar);
+  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->browse_path_bar, TRUE, TRUE, 0);
+
+  /* Info bar */
+  info_bar_create (impl);
+  gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->browse_select_a_folder_info_bar);
+  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->browse_select_a_folder_info_bar, TRUE, TRUE, 0);
+
+  /* Widgets for special modes (recently-used in Open mode, Search mode) */
+  special_mode_widgets_create (impl);
 
   /* Create Folder */
   impl->browse_new_folder_button = gtk_button_new_with_mnemonic (_("Create Fo_lder"));
   g_signal_connect (impl->browse_new_folder_button, "clicked",
                    G_CALLBACK (new_folder_button_clicked), impl);
+  gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->browse_new_folder_button);
   gtk_box_pack_end (GTK_BOX (impl->browse_path_bar_hbox), impl->browse_new_folder_button, FALSE, FALSE, 0);
+}
 
-  /* Box for the location label and entry */
+/* Sets the path bar's mode to show a label, the actual folder path, or a
+ * warning message.  You may call this function with PATH_BAR_ERROR_* directly
+ * if the pathbar is already showing the widgets you expect; otherwise, call
+ * path_bar_update() instead to set the appropriate widgets automatically.
+ */
+static void
+path_bar_set_mode (GtkFileChooserDefault *impl, PathBarMode mode)
+{
+  gboolean path_bar_visible            = FALSE;
+  gboolean special_mode_widgets_visible = FALSE;
+  gboolean info_bar_visible            = FALSE;
+  gboolean create_folder_visible        = FALSE;
 
-  impl->location_entry_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
-  gtk_box_pack_start (GTK_BOX (impl->browse_widgets_box), impl->location_entry_box, FALSE, FALSE, 0);
+  char *tmp;
 
-  impl->location_label = gtk_label_new_with_mnemonic (_("_Location:"));
-  gtk_widget_show (impl->location_label);
-  gtk_box_pack_start (GTK_BOX (impl->location_entry_box), impl->location_label, FALSE, FALSE, 0);
+  switch (mode)
+    {
+    case PATH_BAR_FOLDER_PATH:
+      path_bar_visible = TRUE;
+      break;
 
-  /* Paned widget */
+    case PATH_BAR_SELECT_A_FOLDER:
+    case PATH_BAR_ERROR_NO_FILENAME:
+    case PATH_BAR_ERROR_NO_FOLDER:
+      info_bar_set (impl, mode);
+      info_bar_visible = TRUE;
+      break;
 
-  hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
-  gtk_widget_show (hpaned);
-  gtk_box_pack_start (GTK_BOX (impl->browse_widgets_box), hpaned, TRUE, TRUE, 0);
+    case PATH_BAR_RECENTLY_USED:
+      gtk_image_set_from_icon_name (GTK_IMAGE (impl->browse_special_mode_icon), "document-open-recent", GTK_ICON_SIZE_BUTTON);
 
-  widget = shortcuts_pane_create (impl, size_group);
-  gtk_paned_pack1 (GTK_PANED (hpaned), widget, FALSE, FALSE);
-  widget = file_pane_create (impl, size_group);
-  gtk_paned_pack2 (GTK_PANED (hpaned), widget, TRUE, FALSE);
-  gtk_paned_set_position (GTK_PANED (hpaned), 148);
-  g_object_unref (size_group);
-}
+      tmp = g_strdup_printf ("<b>%s</b>", _("Recently Used"));
+      gtk_label_set_markup (GTK_LABEL (impl->browse_special_mode_label), tmp);
+      g_free (tmp);
 
-static GObject*
-gtk_file_chooser_default_constructor (GType                  type,
-                                     guint                  n_construct_properties,
-                                     GObjectConstructParam *construct_params)
-{
-  GtkFileChooserDefault *impl;
-  GObject *object;
+      special_mode_widgets_visible = TRUE;
+      break;
 
-  profile_start ("start", NULL);
+    case PATH_BAR_SEARCH:
+      gtk_image_set_from_stock (GTK_IMAGE (impl->browse_special_mode_icon), GTK_STOCK_FIND, GTK_ICON_SIZE_BUTTON);
 
-  object = G_OBJECT_CLASS (_gtk_file_chooser_default_parent_class)->constructor (type,
-                                                                               n_construct_properties,
-                                                                               construct_params);
-  impl = GTK_FILE_CHOOSER_DEFAULT (object);
+      tmp = g_strdup_printf ("<b>%s</b>", _("Search:"));
+      gtk_label_set_markup (GTK_LABEL (impl->browse_special_mode_label), tmp);
+      g_free (tmp);
+
+      special_mode_widgets_visible = TRUE;
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+
+  gtk_widget_set_visible (impl->browse_path_bar,                       path_bar_visible);
+  gtk_widget_set_visible (impl->browse_special_mode_icon,              special_mode_widgets_visible);
+  gtk_widget_set_visible (impl->browse_special_mode_label,             special_mode_widgets_visible);
+  gtk_widget_set_visible (impl->browse_select_a_folder_info_bar,       info_bar_visible);
+
+  if (path_bar_visible)
+    {
+      if (impl->create_folders
+         && impl->action != GTK_FILE_CHOOSER_ACTION_OPEN
+         && impl->operation_mode != OPERATION_MODE_RECENT)
+       create_folder_visible = TRUE;
+    }
+
+  gtk_widget_set_visible (impl->browse_new_folder_button,              create_folder_visible);
+}
+
+/* Creates the main hpaned with the widgets shared by Open and Save mode */
+static void
+browse_widgets_create (GtkFileChooserDefault *impl)
+{
+  GtkWidget *hpaned;
+  GtkWidget *widget;
+  GtkSizeGroup *size_group;
+
+  impl->browse_widgets_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+  gtk_box_pack_start (GTK_BOX (impl), impl->browse_widgets_box, TRUE, TRUE, 0);
+  gtk_widget_show (impl->browse_widgets_box);
+
+  impl->browse_header_box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 12);
+  gtk_box_pack_start (GTK_BOX (impl->browse_widgets_box), impl->browse_header_box, FALSE, FALSE, 0);
+  gtk_widget_show (impl->browse_header_box);
+
+  /* Path bar, info bar, and their respective machinery - the browse_path_bar_hbox will get packed elsewhere */
+  path_bar_widgets_create (impl);
+
+  /* Box for the location label and entry */
+
+  impl->location_entry_box = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
+  gtk_box_pack_start (GTK_BOX (impl->browse_header_box), impl->location_entry_box, FALSE, FALSE, 0);
+
+  impl->location_label = gtk_label_new_with_mnemonic (_("_Location:"));
+  gtk_widget_show (impl->location_label);
+  gtk_box_pack_start (GTK_BOX (impl->location_entry_box), impl->location_label, FALSE, FALSE, 0);
+
+  /* size group is used by the scrolled windows of the panes */
+  size_group = gtk_size_group_new (GTK_SIZE_GROUP_VERTICAL);
+
+  /* Paned widget */
+
+  hpaned = impl->browse_widgets_hpaned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
+  gtk_widget_show (hpaned);
+  gtk_box_pack_start (GTK_BOX (impl->browse_widgets_box), hpaned, TRUE, TRUE, 0);
+
+  widget = shortcuts_pane_create (impl, size_group);
+  gtk_paned_pack1 (GTK_PANED (hpaned), widget, FALSE, FALSE);
+  widget = file_pane_create (impl, size_group);
+  gtk_paned_pack2 (GTK_PANED (hpaned), widget, TRUE, FALSE);
+  g_object_unref (size_group);
+}
+
+static GObject*
+gtk_file_chooser_default_constructor (GType                  type,
+                                     guint                  n_construct_properties,
+                                     GObjectConstructParam *construct_params)
+{
+  GtkFileChooserDefault *impl;
+  GObject *object;
+
+  profile_start ("start", NULL);
+
+  object = G_OBJECT_CLASS (_gtk_file_chooser_default_parent_class)->constructor (type,
+                                                                               n_construct_properties,
+                                                                               construct_params);
+  impl = GTK_FILE_CHOOSER_DEFAULT (object);
 
   g_assert (impl->file_system);
 
@@ -4811,7 +5098,6 @@ gtk_file_chooser_default_constructor (GType                  type,
 
   /* The browse widgets */
   browse_widgets_create (impl);
-  gtk_box_pack_start (GTK_BOX (impl), impl->browse_widgets_box, TRUE, TRUE, 0);
 
   /* Alignment to hold extra widget */
   impl->extra_align = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
@@ -4918,7 +5204,7 @@ set_select_multiple (GtkFileChooserDefault *impl,
   if (select_multiple == impl->select_multiple)
     return;
 
-  mode = select_multiple ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_BROWSE;
+  mode = select_multiple ? GTK_SELECTION_MULTIPLE : GTK_SELECTION_SINGLE;
 
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
   gtk_tree_selection_set_mode (selection, mode);
@@ -4984,16 +5270,14 @@ restore_path_bar (GtkFileChooserDefault *impl)
   if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN
       || impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
     {
-      gtk_box_pack_start (GTK_BOX (impl->browse_widgets_box), impl->browse_path_bar_hbox, FALSE, FALSE, 0);
-      gtk_box_reorder_child (GTK_BOX (impl->browse_widgets_box), impl->browse_path_bar_hbox, 0);
+      gtk_box_pack_start (GTK_BOX (impl->browse_header_box), impl->browse_path_bar_hbox, FALSE, FALSE, 0);
+      gtk_box_reorder_child (GTK_BOX (impl->browse_header_box), impl->browse_path_bar_hbox, 0);
     }
   else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
           || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
     {
-      gtk_table_attach (GTK_TABLE (impl->save_widgets_table), impl->browse_path_bar_hbox,
-                       1, 2, 1, 2,
-                       GTK_EXPAND | GTK_FILL, GTK_FILL,
-                       0, 0);
+      gtk_widget_set_hexpand (impl->browse_path_bar_hbox, TRUE);
+      gtk_grid_attach (GTK_GRID (impl->save_widgets_table), impl->browse_path_bar_hbox, 1, 1, 1, 1);
       gtk_label_set_mnemonic_widget (GTK_LABEL (impl->save_folder_label), impl->browse_path_bar);
     }
   else
@@ -5011,38 +5295,194 @@ put_recent_folder_in_pathbar (GtkFileChooserDefault *impl, GtkTreeIter *iter)
   gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), iter,
                      MODEL_COL_FILE, &file,
                      -1);
-  _gtk_path_bar_set_file (GTK_PATH_BAR (impl->browse_path_bar), file, FALSE, NULL); /* NULL-GError */
+  _gtk_path_bar_set_file (GTK_PATH_BAR (impl->browse_path_bar), file, FALSE);
   g_object_unref (file);
 }
 
-/* For recently-used mode, updates the path in the pathbar with the currently-selected item */
+/* Sets the pathbar in the appropriate mode according to the current operation mode and action.  This is the central function for
+ * dealing with the pathbar's widgets; as long as impl->action and impl->operation_mode are set correctly, then calling this
+ * function will update all the pathbar's widgets.
+ */
 static void
-update_path_bar (GtkFileChooserDefault *impl)
+path_bar_update (GtkFileChooserDefault *impl)
 {
-  if (impl->operation_mode == OPERATION_MODE_RECENT
-      && impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+  PathBarMode mode;
+
+  switch (impl->operation_mode)
     {
-      GtkTreeSelection *selection;
-      gboolean have_selected;
-      GtkTreeIter iter;
+    case OPERATION_MODE_BROWSE:
+      mode = PATH_BAR_FOLDER_PATH;
+      break;
 
-      selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
+    case OPERATION_MODE_RECENT:
+      if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+       {
+         GtkTreeSelection *selection;
+         gboolean have_selected;
+         GtkTreeIter iter;
 
-      /* Save mode means single-selection mode, so the following is valid */
-      have_selected = gtk_tree_selection_get_selected (selection, NULL, &iter);
+         selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
 
-      if (have_selected)
-       {
-         put_recent_folder_in_pathbar (impl, &iter);
-         gtk_widget_show (impl->browse_path_bar);
-         gtk_widget_hide (impl->browse_select_a_folder_label);
+         /* Save mode means single-selection mode, so the following is valid */
+         have_selected = gtk_tree_selection_get_selected (selection, NULL, &iter);
+
+         if (have_selected)
+           {
+             mode = PATH_BAR_FOLDER_PATH;
+             put_recent_folder_in_pathbar (impl, &iter);
+           }
+         else
+           mode = PATH_BAR_SELECT_A_FOLDER;
        }
       else
-       {
-         gtk_widget_hide (impl->browse_path_bar);
-         gtk_widget_show (impl->browse_select_a_folder_label);
-       }
+       mode = PATH_BAR_RECENTLY_USED;
+
+      break;
+
+    case OPERATION_MODE_SEARCH:
+      mode = PATH_BAR_SEARCH;
+      break;
+
+    default:
+      g_assert_not_reached ();
+      return;
     }
+
+  path_bar_set_mode (impl, mode);
+}
+
+static void
+operation_mode_discard_search_widgets (GtkFileChooserDefault *impl)
+{
+  if (impl->search_hbox)
+    {
+      gtk_widget_destroy (impl->search_hbox);
+
+      impl->search_hbox = NULL;
+      impl->search_entry = NULL;
+    }
+}
+
+/* Stops running operations like populating the browse model, searches, and the recent-files model */
+static void
+operation_mode_stop (GtkFileChooserDefault *impl, OperationMode mode)
+{
+  switch (mode)
+    {
+    case OPERATION_MODE_BROWSE:
+      stop_loading_and_clear_list_model (impl, TRUE);
+      break;
+
+    case OPERATION_MODE_SEARCH:
+      search_stop_searching (impl, FALSE);
+      search_clear_model (impl, TRUE);
+
+      operation_mode_discard_search_widgets (impl);
+      break;
+
+    case OPERATION_MODE_RECENT:
+      recent_stop_loading (impl);
+      recent_clear_model (impl, TRUE);
+      break;
+
+    default:
+      g_assert_not_reached ();
+    }
+}
+
+static void
+operation_mode_set_browse (GtkFileChooserDefault *impl)
+{
+  path_bar_update (impl);
+
+  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+      impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+    {
+      gtk_widget_show (impl->location_button);
+      location_mode_set (impl, impl->location_mode, TRUE);
+
+      if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
+       gtk_widget_show (impl->location_entry_box);
+    }
+}
+
+static void
+operation_mode_set_search (GtkFileChooserDefault *impl)
+{
+  g_assert (impl->search_hbox == NULL);
+  g_assert (impl->search_entry == NULL);
+  g_assert (impl->search_model == NULL);
+
+  search_setup_widgets (impl);
+}
+
+static void
+operation_mode_set_recent (GtkFileChooserDefault *impl)
+{
+  path_bar_update (impl);
+
+  /* Hide the location widgets temporarily */
+  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
+      impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
+    {
+      gtk_widget_hide (impl->location_button);
+      gtk_widget_hide (impl->location_entry_box);
+    }
+
+  recent_start_loading (impl);
+}
+
+/* Sometimes we need to frob the selection in the shortcuts list manually */
+static void
+shortcuts_select_item_without_activating (GtkFileChooserDefault *impl, int pos)
+{
+  GtkTreeSelection *selection;
+  GtkTreePath *path;
+
+  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view));
+
+  g_signal_handlers_block_by_func (selection, G_CALLBACK (shortcuts_selection_changed_cb), impl);
+
+  path = gtk_tree_path_new_from_indices (pos, -1);
+  gtk_tree_selection_select_path (selection, path);
+  gtk_tree_path_free (path);
+
+  g_signal_handlers_unblock_by_func (selection, G_CALLBACK (shortcuts_selection_changed_cb), impl);
+}
+
+static void
+operation_mode_set (GtkFileChooserDefault *impl, OperationMode mode)
+{
+  ShortcutsIndex shortcut_to_select;
+
+  operation_mode_stop (impl, impl->operation_mode);
+
+  impl->operation_mode = mode;
+
+  switch (impl->operation_mode)
+    {
+    case OPERATION_MODE_BROWSE:
+      operation_mode_set_browse (impl);
+      shortcut_to_select = SHORTCUTS_CURRENT_FOLDER;
+      break;
+
+    case OPERATION_MODE_SEARCH:
+      operation_mode_set_search (impl);
+      shortcut_to_select = SHORTCUTS_SEARCH;
+      break;
+
+    case OPERATION_MODE_RECENT:
+      operation_mode_set_recent (impl);
+      shortcut_to_select = SHORTCUTS_RECENT;
+      break;
+
+    default:
+      g_assert_not_reached ();
+      return;
+    }
+
+  if (shortcut_to_select != SHORTCUTS_CURRENT_FOLDER)
+    shortcuts_select_item_without_activating (impl, shortcuts_get_index (impl, shortcut_to_select));
 }
 
 /* This function is basically a do_all function.
@@ -5082,7 +5522,6 @@ update_appearance (GtkFileChooserDefault *impl)
     {
       gtk_widget_show (impl->location_button);
       save_widgets_destroy (impl);
-      gtk_widget_show (impl->browse_widgets_box);
       location_mode_set (impl, impl->location_mode, TRUE);
     }
 
@@ -5090,12 +5529,7 @@ update_appearance (GtkFileChooserDefault *impl)
     _gtk_file_chooser_entry_set_action (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->action);
 
   restore_path_bar (impl);
-  update_path_bar (impl);
-
-  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || !impl->create_folders)
-    gtk_widget_hide (impl->browse_new_folder_button);
-  else
-    gtk_widget_show (impl->browse_new_folder_button);
+  path_bar_update (impl);
 
   /* This *is* needed; we need to redraw the file list because the "sensitivity"
    * of files may change depending whether we are in a file or folder-only mode.
@@ -5286,18 +5720,6 @@ cancel_all_operations (GtkFileChooserDefault *impl)
 
   pending_select_files_free (impl);
 
-  /* cancel all pending operations */
-  if (impl->pending_cancellables)
-    {
-      for (l = impl->pending_cancellables; l; l = l->next)
-        {
-         GCancellable *cancellable = G_CANCELLABLE (l->data);
-         g_cancellable_cancel (cancellable);
-        }
-      g_slist_free (impl->pending_cancellables);
-      impl->pending_cancellables = NULL;
-    }
-
   if (impl->reload_icon_cancellables)
     {
       for (l = impl->reload_icon_cancellables; l; l = l->next)
@@ -5338,6 +5760,12 @@ cancel_all_operations (GtkFileChooserDefault *impl)
       impl->should_respond_get_info_cancellable = NULL;
     }
 
+  if (impl->file_exists_get_info_cancellable)
+    {
+      g_cancellable_cancel (impl->file_exists_get_info_cancellable);
+      impl->file_exists_get_info_cancellable = NULL;
+    }
+
   if (impl->update_from_entry_cancellable)
     {
       g_cancellable_cancel (impl->update_from_entry_cancellable);
@@ -5566,13 +5994,6 @@ gtk_file_chooser_default_screen_changed (GtkWidget *widget,
   profile_end ("end", NULL);
 }
 
-static void
-gtk_file_chooser_default_size_allocate (GtkWidget     *widget,
-                                        GtkAllocation *allocation)
-{
-  GTK_WIDGET_CLASS (_gtk_file_chooser_default_parent_class)->size_allocate (widget, allocation);
-}
-
 static void
 set_sort_column (GtkFileChooserDefault *impl)
 {
@@ -5589,17 +6010,6 @@ set_sort_column (GtkFileChooserDefault *impl)
                                         impl->sort_order);
 }
 
-static void
-settings_ensure (GtkFileChooserDefault *impl)
-{
-  if (impl->settings != NULL)
-    return;
-
-  impl->settings = g_settings_new_with_path ("org.gtk.Settings.FileChooser",
-                                             "/org/gtk/settings/file-chooser/");
-  g_settings_delay (impl->settings);
-}
-
 static void
 settings_load (GtkFileChooserDefault *impl)
 {
@@ -5608,14 +6018,17 @@ settings_load (GtkFileChooserDefault *impl)
   gboolean show_size_column;
   gint sort_column;
   GtkSortType sort_order;
+  gint sidebar_width;
+  GSettings *settings;
 
-  settings_ensure (impl);
+  settings = _gtk_file_chooser_get_settings_for_widget (GTK_WIDGET (impl));
 
-  location_mode = g_settings_get_enum (impl->settings, SETTINGS_KEY_LOCATION_MODE);
-  show_hidden = g_settings_get_boolean (impl->settings, SETTINGS_KEY_SHOW_HIDDEN);
-  show_size_column = g_settings_get_boolean (impl->settings, SETTINGS_KEY_SHOW_SIZE_COLUMN);
-  sort_column = g_settings_get_enum (impl->settings, SETTINGS_KEY_SORT_COLUMN);
-  sort_order = g_settings_get_enum (impl->settings, SETTINGS_KEY_SORT_ORDER);
+  location_mode = g_settings_get_enum (settings, SETTINGS_KEY_LOCATION_MODE);
+  show_hidden = g_settings_get_boolean (settings, SETTINGS_KEY_SHOW_HIDDEN);
+  show_size_column = g_settings_get_boolean (settings, SETTINGS_KEY_SHOW_SIZE_COLUMN);
+  sort_column = g_settings_get_enum (settings, SETTINGS_KEY_SORT_COLUMN);
+  sort_order = g_settings_get_enum (settings, SETTINGS_KEY_SORT_ORDER);
+  sidebar_width = g_settings_get_int (settings, SETTINGS_KEY_SIDEBAR_WIDTH);
 
   location_mode_set (impl, location_mode, TRUE);
 
@@ -5630,61 +6043,30 @@ settings_load (GtkFileChooserDefault *impl)
    * created yet.  The individual functions that create and set the models will
    * call set_sort_column() themselves.
    */
-}
 
-static void
-save_dialog_geometry (GtkFileChooserDefault *impl)
-{
-  GtkWindow *toplevel;
-  int x, y, width, height;
-
-  toplevel = get_toplevel (GTK_WIDGET (impl));
-
-  if (!(toplevel && GTK_IS_FILE_CHOOSER_DIALOG (toplevel)))
-    return;
-
-  gtk_window_get_position (toplevel, &x, &y);
-  gtk_window_get_size (toplevel, &width, &height);
-
-  g_settings_set (impl->settings, "window-position", "(ii)", x, y);
-  g_settings_set (impl->settings, "window-size", "(ii)", width, height);
+  gtk_paned_set_position (GTK_PANED (impl->browse_widgets_hpaned), sidebar_width);
 }
 
 static void
 settings_save (GtkFileChooserDefault *impl)
 {
-  char *current_folder_uri;
-
-  settings_ensure (impl);
+  GSettings *settings;
 
-  /* Current folder */
-
-  if (impl->current_folder)
-    current_folder_uri = g_file_get_uri (impl->current_folder);
-  else
-    current_folder_uri = "";
-
-  g_settings_set_string (impl->settings, SETTINGS_KEY_LAST_FOLDER_URI, current_folder_uri);
-
-  if (impl->current_folder)
-    g_free (current_folder_uri);
+  settings = _gtk_file_chooser_get_settings_for_widget (GTK_WIDGET (impl));
 
   /* All the other state */
 
-  g_settings_set_enum (impl->settings, SETTINGS_KEY_LOCATION_MODE, impl->location_mode);
-  g_settings_set_boolean (impl->settings, SETTINGS_KEY_SHOW_HIDDEN,
+  g_settings_set_enum (settings, SETTINGS_KEY_LOCATION_MODE, impl->location_mode);
+  g_settings_set_boolean (settings, SETTINGS_KEY_SHOW_HIDDEN,
                           gtk_file_chooser_get_show_hidden (GTK_FILE_CHOOSER (impl)));
-  g_settings_set_boolean (impl->settings, SETTINGS_KEY_SHOW_SIZE_COLUMN, impl->show_size_column);
-  g_settings_set_enum (impl->settings, SETTINGS_KEY_SORT_COLUMN, impl->sort_column);
-  g_settings_set_enum (impl->settings, SETTINGS_KEY_SORT_ORDER, impl->sort_order);
-
-  save_dialog_geometry (impl);
+  g_settings_set_boolean (settings, SETTINGS_KEY_SHOW_SIZE_COLUMN, impl->show_size_column);
+  g_settings_set_enum (settings, SETTINGS_KEY_SORT_COLUMN, impl->sort_column);
+  g_settings_set_enum (settings, SETTINGS_KEY_SORT_ORDER, impl->sort_order);
+  g_settings_set_int (settings, SETTINGS_KEY_SIDEBAR_WIDTH,
+                     gtk_paned_get_position (GTK_PANED (impl->browse_widgets_hpaned)));
 
   /* Now apply the settings */
-  g_settings_apply (impl->settings);
-
-  g_object_unref (impl->settings);
-  impl->settings = NULL;
+  g_settings_apply (settings);
 }
 
 /* GtkWidget::realize method */
@@ -5700,29 +6082,6 @@ gtk_file_chooser_default_realize (GtkWidget *widget)
   emit_default_size_changed (impl);
 }
 
-static GFile *
-get_file_for_last_folder_opened (GtkFileChooserDefault *impl)
-{
-  char *last_folder_uri;
-  GFile *file;
-
-  settings_ensure (impl);
-
-  last_folder_uri = g_settings_get_string (impl->settings, SETTINGS_KEY_LAST_FOLDER_URI);
-
-  /* If no last folder is set, we use the user's home directory, since
-   * this is the starting point for most documents.
-   */
-  if (last_folder_uri[0] == '\0')
-    file = g_file_new_for_path (g_get_home_dir ());
-  else
-    file = g_file_new_for_uri (last_folder_uri);
-
-  g_free (last_folder_uri);
-
-  return file;
-}
-
 /* GtkWidget::map method */
 static void
 gtk_file_chooser_default_map (GtkWidget *widget)
@@ -5777,13 +6136,6 @@ gtk_file_chooser_default_unmap (GtkWidget *widget)
   GTK_WIDGET_CLASS (_gtk_file_chooser_default_parent_class)->unmap (widget);
 }
 
-static void
-install_list_model_filter (GtkFileChooserDefault *impl)
-{
-  _gtk_file_system_model_set_filter (impl->browse_files_model,
-                                     impl->current_filter);
-}
-
 #define COMPARE_DIRECTORIES                                                                                   \
   GtkFileChooserDefault *impl = user_data;                                                                    \
   GtkFileSystemModel *fs_model = GTK_FILE_SYSTEM_MODEL (model);                                                \
@@ -5922,6 +6274,7 @@ load_set_model (GtkFileChooserDefault *impl)
   gtk_tree_view_columns_autosize (GTK_TREE_VIEW (impl->browse_files_tree_view));
   gtk_tree_view_set_search_column (GTK_TREE_VIEW (impl->browse_files_tree_view),
                                   MODEL_COL_NAME);
+  file_list_set_sort_column_ids (impl);
   set_sort_column (impl);
   profile_msg ("    gtk_tree_view_set_model end", NULL);
   impl->list_sort_ascending = TRUE;
@@ -5963,9 +6316,9 @@ load_setup_timer (GtkFileChooserDefault *impl)
   impl->load_state = LOAD_PRELOAD;
 }
 
-/* Removes the load timeout and switches to the LOAD_FINISHED state */
+/* Removes the load timeout; changes the impl->load_state to the specified value. */
 static void
-load_remove_timer (GtkFileChooserDefault *impl)
+load_remove_timer (GtkFileChooserDefault *impl, LoadState new_load_state)
 {
   if (impl->load_timeout_id != 0)
     {
@@ -5973,12 +6326,16 @@ load_remove_timer (GtkFileChooserDefault *impl)
 
       g_source_remove (impl->load_timeout_id);
       impl->load_timeout_id = 0;
-      impl->load_state = LOAD_EMPTY;
     }
   else
     g_assert (impl->load_state == LOAD_EMPTY ||
              impl->load_state == LOAD_LOADING ||
              impl->load_state == LOAD_FINISHED);
+
+  g_assert (new_load_state == LOAD_EMPTY ||
+           new_load_state == LOAD_LOADING ||
+           new_load_state == LOAD_FINISHED);
+  impl->load_state = new_load_state;
 }
 
 /* Selects the first row in the file list */
@@ -6051,9 +6408,14 @@ show_and_select_files (GtkFileChooserDefault *impl,
   gboolean selected_a_file;
   GSList *walk;
 
+  g_assert (impl->load_state == LOAD_FINISHED);
+  g_assert (impl->browse_files_model != NULL);
+
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
   fsmodel = GTK_FILE_SYSTEM_MODEL (gtk_tree_view_get_model (GTK_TREE_VIEW (impl->browse_files_tree_view)));
 
+  g_assert (fsmodel == impl->browse_files_model);
+
   enabled_hidden = impl->show_hidden;
   removed_filters = (impl->current_filter == NULL);
 
@@ -6188,7 +6550,7 @@ browse_files_model_finished_loading_cb (GtkFileSystemModel    *model,
 
   if (impl->load_state == LOAD_PRELOAD)
     {
-      load_remove_timer (impl);
+      load_remove_timer (impl, LOAD_FINISHED);
       load_set_model (impl);
     }
   else if (impl->load_state == LOAD_LOADING)
@@ -6221,7 +6583,7 @@ static void
 stop_loading_and_clear_list_model (GtkFileChooserDefault *impl,
                                    gboolean remove_from_treeview)
 {
-  load_remove_timer (impl); /* This changes the state to LOAD_EMPTY */
+  load_remove_timer (impl, LOAD_EMPTY);
   
   if (impl->browse_files_model)
     {
@@ -6358,14 +6720,14 @@ file_system_model_got_thumbnail (GObject *object, GAsyncResult *res, gpointer da
   if (queried == NULL)
     return;
 
-  GDK_THREADS_ENTER ();
+  gdk_threads_enter ();
 
   /* now we know model is valid */
 
   /* file was deleted */
   if (!_gtk_file_system_model_get_iter_for_file (model, &iter, file))
     {
-      GDK_THREADS_LEAVE ();
+      gdk_threads_leave ();
       return;
     }
 
@@ -6375,11 +6737,11 @@ file_system_model_got_thumbnail (GObject *object, GAsyncResult *res, gpointer da
   copy_attribute (info, queried, G_FILE_ATTRIBUTE_THUMBNAILING_FAILED);
   copy_attribute (info, queried, G_FILE_ATTRIBUTE_STANDARD_ICON);
 
-  _gtk_file_system_model_update_file (model, file, info, FALSE);
+  _gtk_file_system_model_update_file (model, file, info);
 
   g_object_unref (info);
 
-  GDK_THREADS_LEAVE ();
+  gdk_threads_leave ();
 }
 
 static gboolean
@@ -6412,6 +6774,34 @@ file_system_model_set (GtkFileSystemModel *model,
     case MODEL_COL_IS_FOLDER:
       g_value_set_boolean (value, info == NULL || _gtk_file_info_consider_as_directory (info));
       break;
+    case MODEL_COL_IS_SENSITIVE:
+      if (info)
+        {
+          gboolean sensitive = TRUE;
+
+          if (!(impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
+               || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
+            {
+              sensitive = TRUE; /* for file modes... */
+            }
+          else if (!_gtk_file_info_consider_as_directory (info))
+            {
+              sensitive = FALSE; /* for folder modes, files are not sensitive... */
+            }
+          else
+            {
+             /* ... and for folder modes, folders are sensitive only if the filter says so */
+              GtkTreeIter iter;
+              if (!_gtk_file_system_model_get_iter_for_file (model, &iter, file))
+                g_assert_not_reached ();
+              sensitive = !_gtk_file_system_model_iter_is_filtered_out (model, &iter);
+            }
+
+          g_value_set_boolean (value, sensitive);
+        }
+      else
+        g_value_set_boolean (value, TRUE);
+      break;
     case MODEL_COL_PIXBUF:
       if (info)
         {
@@ -6470,7 +6860,7 @@ file_system_model_set (GtkFileSystemModel *model,
       if (info == NULL || _gtk_file_info_consider_as_directory (info))
         g_value_set_string (value, NULL);
       else
-        g_value_take_string (value, g_format_size_for_display (g_file_info_get_size (info)));
+        g_value_take_string (value, g_format_size (g_file_info_get_size (info)));
       break;
     case MODEL_COL_MTIME:
     case MODEL_COL_MTIME_TEXT:
@@ -6535,7 +6925,7 @@ set_list_model (GtkFileChooserDefault *impl,
   g_signal_connect (impl->browse_files_model, "finished-loading",
                    G_CALLBACK (browse_files_model_finished_loading_cb), impl);
 
-  install_list_model_filter (impl);
+  _gtk_file_system_model_set_filter (impl->browse_files_model, impl->current_filter);
 
   profile_end ("end", NULL);
 
@@ -6588,7 +6978,6 @@ update_chooser_entry (GtkFileChooserDefault *impl)
 
   /* no need to update the file chooser's entry if there's no entry */
   if (impl->operation_mode == OPERATION_MODE_SEARCH ||
-      impl->operation_mode == OPERATION_MODE_RECENT ||
       !impl->location_entry)
     return;
 
@@ -6607,7 +6996,10 @@ update_chooser_entry (GtkFileChooserDefault *impl)
 
   if (closure.num_selected == 0)
     {
-      goto maybe_clear_entry;
+      if (impl->operation_mode == OPERATION_MODE_RECENT)
+       _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), NULL);
+      else
+       goto maybe_clear_entry;
     }
   else if (closure.num_selected == 1)
     {
@@ -6640,7 +7032,7 @@ update_chooser_entry (GtkFileChooserDefault *impl)
 
           if (change_entry)
             {
-              _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), impl->browse_files_last_selected_name);
+              gtk_entry_set_text (GTK_ENTRY (impl->location_entry), impl->browse_files_last_selected_name);
 
               if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
                 _gtk_file_chooser_entry_select_filename (GTK_FILE_CHOOSER_ENTRY (impl->location_entry));
@@ -6648,6 +7040,20 @@ update_chooser_entry (GtkFileChooserDefault *impl)
 
           return;
         }
+      else if (impl->operation_mode == OPERATION_MODE_RECENT
+              && impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+       {
+         GFile *folder;
+
+         /* Set the base folder on the name entry, so it will do completion relative to the correct recent-folder */
+
+         gtk_tree_model_get (GTK_TREE_MODEL (impl->recent_model), &closure.first_selected_iter,
+                             MODEL_COL_FILE, &folder,
+                             -1);
+         _gtk_file_chooser_entry_set_base_folder (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), folder);
+         g_object_unref (folder);
+         return;
+       }
     }
   else
     {
@@ -6658,7 +7064,7 @@ update_chooser_entry (GtkFileChooserDefault *impl)
       g_free (impl->browse_files_last_selected_name);
       impl->browse_files_last_selected_name = NULL;
 
-      _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), "");
+      gtk_entry_set_text (GTK_ENTRY (impl->location_entry), "");
       return;
     }
 
@@ -6693,7 +7099,7 @@ update_chooser_entry (GtkFileChooserDefault *impl)
         clear_entry = FALSE;
 
       if (clear_entry)
-        _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), "");
+        gtk_entry_set_text (GTK_ENTRY (impl->location_entry), "");
     }
 }
 
@@ -6858,8 +7264,7 @@ update_current_folder_get_info_cb (GCancellable *cancellable,
   if (! _gtk_file_info_consider_as_directory (info))
     goto out;
 
-  if (!_gtk_path_bar_set_file (GTK_PATH_BAR (impl->browse_path_bar), data->file, data->keep_trail, NULL))
-    goto out;
+  _gtk_path_bar_set_file (GTK_PATH_BAR (impl->browse_path_bar), data->file, data->keep_trail);
 
   if (impl->current_folder != data->file)
     {
@@ -6890,7 +7295,7 @@ update_current_folder_get_info_cb (GCancellable *cancellable,
                                               impl->current_folder);
 
       if (data->clear_entry)
-       _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), "");
+        gtk_entry_set_text (GTK_ENTRY (impl->location_entry), "");
     }
 
   /* Create a new list model.  This is slightly evil; we store the result value
@@ -6931,17 +7336,7 @@ gtk_file_chooser_default_update_current_folder (GtkFileChooser    *chooser,
 
   g_object_ref (file);
 
-  switch (impl->operation_mode)
-    {
-    case OPERATION_MODE_SEARCH:
-      search_switch_to_browse_mode (impl);
-      break;
-    case OPERATION_MODE_RECENT:
-      recent_switch_to_browse_mode (impl);
-      break;
-    case OPERATION_MODE_BROWSE:
-      break;
-    }
+  operation_mode_set (impl, OPERATION_MODE_BROWSE);
 
   if (impl->local_only && !g_file_is_native (file))
     {
@@ -6989,16 +7384,6 @@ gtk_file_chooser_default_get_current_folder (GtkFileChooser *chooser)
       impl->operation_mode == OPERATION_MODE_RECENT)
     return NULL;
  
-  if (impl->reload_state == RELOAD_EMPTY)
-    {
-      /* We are unmapped, or we had an error while loading the last folder.
-       * We'll return the folder used by the last invocation of the file chooser
-       * since once we get (re)mapped, we'll load *that* folder anyway unless
-       * the caller explicitly calls set_current_folder() on us.
-       */
-      return get_file_for_last_folder_opened (impl);
-    }
-
   if (impl->current_folder)
     return g_object_ref (impl->current_folder);
 
@@ -7015,7 +7400,7 @@ gtk_file_chooser_default_set_current_name (GtkFileChooser *chooser,
                    impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
 
   pending_select_files_free (impl);
-  _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), name);
+  gtk_entry_set_text (GTK_ENTRY (impl->location_entry), name);
 }
 
 static gboolean
@@ -7101,16 +7486,19 @@ maybe_select (GtkTreeModel *model,
 {
   GtkFileChooserDefault *impl = GTK_FILE_CHOOSER_DEFAULT (data);
   GtkTreeSelection *selection;
+  gboolean is_sensitive;
   gboolean is_folder;
   
   selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_files_tree_view));
   
   gtk_tree_model_get (model, iter,
                       MODEL_COL_IS_FOLDER, &is_folder,
+                      MODEL_COL_IS_SENSITIVE, &is_sensitive,
                       -1);
 
-  if ((is_folder && impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) ||
-      (!is_folder && impl->action == GTK_FILE_CHOOSER_ACTION_OPEN))
+  if (is_sensitive &&
+      ((is_folder && impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER) ||
+       (!is_folder && impl->action == GTK_FILE_CHOOSER_ACTION_OPEN)))
     gtk_tree_selection_select_iter (selection, iter);
   else
     gtk_tree_selection_unselect_iter (selection, iter);
@@ -7207,7 +7595,7 @@ check_save_entry (GtkFileChooserDefault *impl,
 
   if (!file_part || file_part[0] == '\0')
     {
-      *file_ret = g_object_ref (current_folder);
+      *file_ret = current_folder;
       *is_well_formed_ret = TRUE;
       *is_file_part_empty_ret = TRUE;
       *is_folder = TRUE;
@@ -7219,6 +7607,7 @@ check_save_entry (GtkFileChooserDefault *impl,
 
   error = NULL;
   file = g_file_get_child_for_display_name (current_folder, file_part, &error);
+  g_object_unref (current_folder);
 
   if (!file)
     {
@@ -7271,15 +7660,23 @@ gtk_file_chooser_default_get_files (GtkFileChooser *chooser)
   GtkWidget *current_focus;
   gboolean file_list_seen;
 
+  info.impl = impl;
+  info.result = NULL;
+  info.file_from_entry = NULL;
+
   if (impl->operation_mode == OPERATION_MODE_SEARCH)
     return search_get_selected_files (impl);
 
   if (impl->operation_mode == OPERATION_MODE_RECENT)
-    return recent_get_selected_files (impl);
-
-  info.impl = impl;
-  info.result = NULL;
-  info.file_from_entry = NULL;
+    {
+      if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+       {
+         file_list_seen = TRUE;
+         goto file_entry;
+       }
+      else
+       return recent_get_selected_files (impl);
+    }
 
   toplevel = get_toplevel (GTK_WIDGET (impl));
   if (toplevel)
@@ -7510,6 +7907,9 @@ add_shortcut_get_info_cb (GCancellable *cancellable,
 
   shortcuts_insert_file (data->impl, pos, SHORTCUT_TYPE_FILE, NULL, data->file, NULL, FALSE, SHORTCUTS_SHORTCUTS);
 
+  /* need to call shortcuts_add_bookmarks to flush out any duplicates bug #577806 */
+  shortcuts_add_bookmarks (data->impl);
+
 out:
   g_object_unref (data->impl);
   g_object_unref (data->file);
@@ -7710,7 +8110,7 @@ find_good_size_from_style (GtkWidget *widget,
 {
   GtkStyleContext *context;
   GtkStateFlags state;
-  int font_size;
+  double font_size;
   GdkScreen *screen;
   double resolution;
 
@@ -7727,8 +8127,8 @@ find_good_size_from_style (GtkWidget *widget,
   else
     resolution = 96.0; /* wheeee */
 
-  font_size = pango_font_description_get_size (gtk_style_context_get_font (context, state));
-  font_size = PANGO_PIXELS (font_size) * resolution / 72.0;
+  gtk_style_context_get (context, state, "font-size", &font_size, NULL);
+  font_size = font_size * resolution / 72.0 + 0.5;
 
   *width = font_size * NUM_CHARS;
   *height = font_size * NUM_LINES;
@@ -7742,13 +8142,14 @@ gtk_file_chooser_default_get_default_size (GtkFileChooserEmbed *chooser_embed,
   GtkFileChooserDefault *impl;
   GtkRequisition req;
   int x, y, width, height;
+  GSettings *settings;
 
   impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
 
-  settings_ensure (impl);
+  settings = _gtk_file_chooser_get_settings_for_widget (GTK_WIDGET (impl));
 
-  g_settings_get (impl->settings, SETTINGS_KEY_WINDOW_POSITION, "(ii)", &x, &y);
-  g_settings_get (impl->settings, SETTINGS_KEY_WINDOW_SIZE, "(ii)", &width, &height);
+  g_settings_get (settings, SETTINGS_KEY_WINDOW_POSITION, "(ii)", &x, &y);
+  g_settings_get (settings, SETTINGS_KEY_WINDOW_SIZE, "(ii)", &width, &height);
 
   if (x >= 0 && y >= 0 && width > 0 && height > 0)
     {
@@ -7930,6 +8331,16 @@ struct GetDisplayNameData
   gchar *file_part;
 };
 
+/* Every time we request a response explicitly, we need to save the selection to the recently-used list,
+ * as requesting a response means, "the dialog is confirmed".
+ */
+static void
+request_response_and_add_to_recent_list (GtkFileChooserDefault *impl)
+{
+  g_signal_emit_by_name (impl, "response-requested");
+  add_selection_to_recent_list (impl);
+}
+
 static void
 confirmation_confirm_get_info_cb (GCancellable *cancellable,
                                  GFileInfo    *info,
@@ -7956,7 +8367,7 @@ confirmation_confirm_get_info_cb (GCancellable *cancellable,
 
   set_busy_cursor (data->impl, FALSE);
   if (should_respond)
-    g_signal_emit_by_name (data->impl, "response-requested");
+    request_response_and_add_to_recent_list (data->impl);
 
 out:
   g_object_unref (data->impl);
@@ -8056,7 +8467,7 @@ name_entry_get_parent_info_cb (GCancellable *cancellable,
     {
       if (data->impl->action == GTK_FILE_CHOOSER_ACTION_OPEN)
        {
-         g_signal_emit_by_name (data->impl, "response-requested"); /* even if the file doesn't exist, apps can make good use of that (e.g. Emacs) */
+         request_response_and_add_to_recent_list (data->impl); /* even if the file doesn't exist, apps can make good use of that (e.g. Emacs) */
        }
       else if (data->impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
         {
@@ -8074,10 +8485,10 @@ name_entry_get_parent_info_cb (GCancellable *cancellable,
               g_free (file_part);
 
              if (retval)
-               g_signal_emit_by_name (data->impl, "response-requested");
+               request_response_and_add_to_recent_list (data->impl);
            }
          else
-           g_signal_emit_by_name (data->impl, "response-requested");
+           request_response_and_add_to_recent_list (data->impl);
        }
       else if (data->impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER
               || data->impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
@@ -8093,7 +8504,7 @@ name_entry_get_parent_info_cb (GCancellable *cancellable,
          set_busy_cursor (data->impl, FALSE);
 
          if (!mkdir_error)
-           g_signal_emit_by_name (data->impl, "response-requested");
+           request_response_and_add_to_recent_list (data->impl);
          else
            error_creating_folder_dialog (data->impl, data->file, mkdir_error);
         }
@@ -8160,7 +8571,7 @@ file_exists_get_info_cb (GCancellable *cancellable,
       else
        {
          if (file_exists)
-           g_signal_emit_by_name (data->impl, "response-requested"); /* user typed an existing filename; we are done */
+           request_response_and_add_to_recent_list (data->impl); /* user typed an existing filename; we are done */
          else
            needs_parent_check = TRUE; /* file doesn't exist; see if its parent exists */
        }
@@ -8191,7 +8602,7 @@ file_exists_get_info_cb (GCancellable *cancellable,
          if (is_folder)
            {
              /* User typed a folder; we are done */
-             g_signal_emit_by_name (data->impl, "response-requested");
+             request_response_and_add_to_recent_list (data->impl);
            }
          else
            error_selecting_folder_over_existing_file_dialog (data->impl, data->file);
@@ -8268,20 +8679,47 @@ location_popup_on_paste_handler (GtkFileChooserDefault *impl)
                              impl);
 }
 
-
 /* Implementation for GtkFileChooserEmbed::should_respond() */
+static void
+add_selection_to_recent_list (GtkFileChooserDefault *impl)
+{
+  GSList *files;
+  GSList *l;
+
+  files = gtk_file_chooser_default_get_files (GTK_FILE_CHOOSER (impl));
+
+  for (l = files; l; l = l->next)
+    {
+      GFile *file = l->data;
+      char *uri;
+
+      uri = g_file_get_uri (file);
+      if (uri)
+       {
+         gtk_recent_manager_add_item (impl->recent_manager, uri);
+         g_free (uri);
+       }
+    }
+
+  g_slist_foreach (files, (GFunc) g_object_unref, NULL);
+  g_slist_free (files);
+}
+
 static gboolean
 gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
 {
   GtkFileChooserDefault *impl;
   GtkWidget *toplevel;
   GtkWidget *current_focus;
+  gboolean retval;
 
   impl = GTK_FILE_CHOOSER_DEFAULT (chooser_embed);
 
   toplevel = gtk_widget_get_toplevel (GTK_WIDGET (impl));
   g_assert (GTK_IS_WINDOW (toplevel));
 
+  retval = FALSE;
+
   current_focus = gtk_window_get_focus (GTK_WINDOW (toplevel));
 
   if (current_focus == impl->browse_files_tree_view)
@@ -8316,10 +8754,21 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
       g_assert (impl->action >= GTK_FILE_CHOOSER_ACTION_OPEN && impl->action <= GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER);
 
       if (impl->operation_mode == OPERATION_MODE_SEARCH)
-       return search_should_respond (impl);
+       {
+         retval = search_should_respond (impl);
+         goto out;
+       }
 
       if (impl->operation_mode == OPERATION_MODE_RECENT)
-        return recent_should_respond (impl);
+       {
+         if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
+           goto save_entry;
+         else
+           {
+             retval = recent_should_respond (impl);
+             goto out;
+           }
+       }
 
       selection_check (impl, &num_selected, &all_files, &all_folders);
 
@@ -8336,7 +8785,8 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
          return FALSE;
 
        case RESPOND:
-         return TRUE;
+         retval = TRUE;
+         goto out;
 
        case RESPOND_OR_SWITCH:
          g_assert (num_selected == 1);
@@ -8347,17 +8797,25 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
              return FALSE;
            }
          else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
-           return should_respond_after_confirm_overwrite (impl,
-                                                          get_display_name_from_file_list (impl),
-                                                          impl->current_folder);
+           {
+             retval = should_respond_after_confirm_overwrite (impl,
+                                                              get_display_name_from_file_list (impl),
+                                                              impl->current_folder);
+             goto out;
+           }
          else
-           return TRUE;
+           {
+             retval = TRUE;
+             goto out;
+           }
 
        case ALL_FILES:
-         return all_files;
+         retval = all_files;
+         goto out;
 
        case ALL_FOLDERS:
-         return all_folders;
+         retval = all_folders;
+         goto out;
 
        case SAVE_ENTRY:
          goto save_entry;
@@ -8371,7 +8829,6 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
       GFile *file;
       gboolean is_well_formed, is_empty, is_file_part_empty;
       gboolean is_folder;
-      gboolean retval;
       GtkFileChooserEntry *entry;
       GError *error;
 
@@ -8387,13 +8844,35 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
       check_save_entry (impl, &file, &is_well_formed, &is_empty, &is_file_part_empty, &is_folder);
 
       if (!is_well_formed)
-        return FALSE;
+       {
+         if (!is_empty
+             && impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
+             && impl->operation_mode == OPERATION_MODE_RECENT)
+           {
+             path_bar_set_mode (impl, PATH_BAR_ERROR_NO_FOLDER);
+#if 0
+             /* We'll #ifdef this out, as the fucking treeview selects its first row,
+              * thus changing our assumption that no selection is present - setting
+              * a selection causes the error message from path_bar_set_mode() to go away,
+              * but we want the user to see that message!
+              */
+             gtk_widget_grab_focus (impl->browse_files_tree_view);
+#endif
+           }
+         /* FIXME: else show an "invalid filename" error as the pathbar mode? */
+
+         return FALSE;
+       }
 
       if (is_empty)
         {
           if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
              || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
-            return FALSE;
+           {
+             path_bar_set_mode (impl, PATH_BAR_ERROR_NO_FILENAME);
+             gtk_widget_grab_focus (impl->location_entry);
+             return FALSE;
+           }
 
           goto file_list;
         }
@@ -8407,7 +8886,6 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
              impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
            {
              change_folder_and_display_error (impl, file, TRUE);
-             retval = FALSE;
            }
          else if (impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER ||
                   impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
@@ -8420,7 +8898,6 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
          else
            {
              g_assert_not_reached ();
-             retval = FALSE;
            }
        }
       else
@@ -8436,7 +8913,7 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
          data = g_new0 (struct FileExistsData, 1);
          data->impl = g_object_ref (impl);
          data->file = g_object_ref (file);
-         data->parent_file = g_object_ref (_gtk_file_chooser_entry_get_current_folder (entry));
+         data->parent_file = _gtk_file_chooser_entry_get_current_folder (entry);
 
          if (impl->file_exists_get_info_cancellable)
            g_cancellable_cancel (impl->file_exists_get_info_cancellable);
@@ -8448,14 +8925,12 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
                                       data);
 
          set_busy_cursor (impl, TRUE);
-         retval = FALSE;
 
          if (error != NULL)
            g_error_free (error);
        }
 
       g_object_unref (file);
-      return retval;
     }
   else if (impl->toplevel_last_focus_widget == impl->browse_files_tree_view)
     {
@@ -8483,9 +8958,13 @@ gtk_file_chooser_default_should_respond (GtkFileChooserEmbed *chooser_embed)
       goto save_entry;
     else
       goto file_list; 
-  
-  g_assert_not_reached ();
-  return FALSE;
+
+ out:
+
+  if (retval)
+    add_selection_to_recent_list (impl);
+
+  return retval;
 }
 
 /* Implementation for GtkFileChooserEmbed::initial_focus() */
@@ -8500,7 +8979,8 @@ gtk_file_chooser_default_initial_focus (GtkFileChooserEmbed *chooser_embed)
   if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
       impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
     {
-      if (impl->location_mode == LOCATION_MODE_PATH_BAR)
+      if (impl->location_mode == LOCATION_MODE_PATH_BAR
+         || impl->operation_mode == OPERATION_MODE_RECENT)
        widget = impl->browse_files_tree_view;
       else
        widget = impl->location_entry;
@@ -8618,6 +9098,7 @@ search_engine_finished_cb (GtkSearchEngine *engine,
    */
   gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view),
                            GTK_TREE_MODEL (impl->search_model));
+  file_list_set_sort_column_ids (impl);
 #endif
 
   /* FMQ: if search was empty, say that we got no hits */
@@ -8687,40 +9168,6 @@ search_stop_searching (GtkFileChooserDefault *impl,
     }
 }
 
-/* Stops any pending searches, clears the file list, and switches back to OPERATION_MODE_BROWSE */
-static void
-search_switch_to_browse_mode (GtkFileChooserDefault *impl)
-{
-  g_assert (impl->operation_mode != OPERATION_MODE_BROWSE);
-
-  search_stop_searching (impl, FALSE);
-  search_clear_model (impl, TRUE);
-
-  gtk_widget_destroy (impl->search_hbox);
-  impl->search_hbox = NULL;
-  impl->search_entry = NULL;
-
-  gtk_widget_show (impl->browse_path_bar);
-  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || !impl->create_folders)
-    gtk_widget_hide (impl->browse_new_folder_button);
-  else
-    gtk_widget_show (impl->browse_new_folder_button);
-
-
-  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
-      impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
-    {
-      gtk_widget_show (impl->location_button);
-
-      if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
-       gtk_widget_show (impl->location_entry_box);
-    }
-
-  impl->operation_mode = OPERATION_MODE_BROWSE;
-
-  file_list_set_sort_column_ids (impl);
-}
-
 /* Creates the search_model and puts it in the tree view */
 static void
 search_setup_model (GtkFileChooserDefault *impl)
@@ -8751,6 +9198,7 @@ search_setup_model (GtkFileChooserDefault *impl)
    */
   gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view),
                            GTK_TREE_MODEL (impl->search_model));
+  file_list_set_sort_column_ids (impl);
 }
 
 /* Creates a new query with the specified text and launches it */
@@ -8820,7 +9268,7 @@ search_entry_activate_cb (GtkEntry *entry,
 static gboolean
 focus_entry_idle_cb (GtkFileChooserDefault *impl)
 {
-  GDK_THREADS_ENTER ();
+  gdk_threads_enter ();
   
   g_source_destroy (impl->focus_entry_idle);
   impl->focus_entry_idle = NULL;
@@ -8828,7 +9276,7 @@ focus_entry_idle_cb (GtkFileChooserDefault *impl)
   if (impl->search_entry)
     gtk_widget_grab_focus (impl->search_entry);
 
-  GDK_THREADS_LEAVE ();
+  gdk_threads_leave ();
 
   return FALSE;
 }
@@ -8852,29 +9300,11 @@ focus_search_entry_in_idle (GtkFileChooserDefault *impl)
 static void
 search_setup_widgets (GtkFileChooserDefault *impl)
 {
-  GtkWidget *label;
-  GtkWidget *image;
-  gchar *tmp;
-
   impl->search_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
 
-  /* Image */
-
-  image = gtk_image_new_from_stock (GTK_STOCK_FIND, GTK_ICON_SIZE_BUTTON);
-  gtk_box_pack_start (GTK_BOX (impl->search_hbox), image, FALSE, FALSE, 5);
-
-  /* Label */
-
-  label = gtk_label_new (NULL);
-  tmp = g_strdup_printf ("<b>%s</b>", _("Search:"));
-  gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), tmp);
-  gtk_box_pack_start (GTK_BOX (impl->search_hbox), label, FALSE, FALSE, 0);
-  g_free (tmp);
-
-  /* Entry */
+  path_bar_update (impl);
 
   impl->search_entry = gtk_entry_new ();
-  gtk_label_set_mnemonic_widget (GTK_LABEL (label), impl->search_entry);
   g_signal_connect (impl->search_entry, "activate",
                    G_CALLBACK (search_entry_activate_cb),
                    impl);
@@ -8899,9 +9329,6 @@ search_setup_widgets (GtkFileChooserDefault *impl)
         }
     }
 
-  gtk_widget_hide (impl->browse_path_bar);
-  gtk_widget_hide (impl->browse_new_folder_button);
-
   /* Box for search widgets */
   gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->search_hbox, TRUE, TRUE, 0);
   gtk_widget_show_all (impl->search_hbox);
@@ -8921,82 +9348,6 @@ search_setup_widgets (GtkFileChooserDefault *impl)
   /* FMQ: hide the filter combo? */
 }
 
-/* Stops running operations like populating the browse model, searches, and the recent-files model */
-static void
-stop_operation (GtkFileChooserDefault *impl, OperationMode mode)
-{
-  switch (mode)
-    {
-    case OPERATION_MODE_BROWSE:
-      stop_loading_and_clear_list_model (impl, TRUE);
-      break;
-
-    case OPERATION_MODE_SEARCH:
-      search_stop_searching (impl, FALSE);
-      search_clear_model (impl, TRUE);
-
-      gtk_widget_destroy (impl->search_hbox);
-      impl->search_hbox = NULL;
-      impl->search_entry = NULL;
-      break;
-
-    case OPERATION_MODE_RECENT:
-      recent_stop_loading (impl);
-      recent_clear_model (impl, TRUE);
-
-      gtk_widget_destroy (impl->recent_hbox);
-      impl->recent_hbox = NULL;
-      break;
-    }
-}
-
-/* Sometimes we need to frob the selection in the shortcuts list manually */
-static void
-shortcuts_select_item_without_activating (GtkFileChooserDefault *impl, int pos)
-{
-  GtkTreeSelection *selection;
-  GtkTreePath *path;
-
-  selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (impl->browse_shortcuts_tree_view));
-
-  g_signal_handlers_block_by_func (selection, G_CALLBACK (shortcuts_selection_changed_cb), impl);
-
-  path = gtk_tree_path_new_from_indices (pos, -1);
-  gtk_tree_selection_select_path (selection, path);
-  gtk_tree_path_free (path);
-
-  g_signal_handlers_unblock_by_func (selection, G_CALLBACK (shortcuts_selection_changed_cb), impl);
-}
-
-/* Main entry point to the searching functions; this gets called when the user
- * activates the Search shortcut.
- */
-static void
-search_activate (GtkFileChooserDefault *impl)
-{
-  OperationMode previous_mode;
-  
-  if (impl->operation_mode == OPERATION_MODE_SEARCH)
-    {
-      focus_search_entry_in_idle (impl);
-      return;
-    }
-
-  previous_mode = impl->operation_mode;
-  impl->operation_mode = OPERATION_MODE_SEARCH;
-
-  shortcuts_select_item_without_activating (impl, shortcuts_get_index (impl, SHORTCUTS_SEARCH));
-
-  stop_operation (impl, previous_mode);
-
-  g_assert (impl->search_hbox == NULL);
-  g_assert (impl->search_entry == NULL);
-  g_assert (impl->search_model == NULL);
-
-  search_setup_widgets (impl);
-  file_list_set_sort_column_ids (impl);
-}
-
 /*
  * Recent files support
  */
@@ -9029,42 +9380,6 @@ recent_stop_loading (GtkFileChooserDefault *impl)
     }
 }
 
-/* Stops any pending load, clears the file list, and switches
- * back to OPERATION_MODE_BROWSE
- */
-static void
-recent_switch_to_browse_mode (GtkFileChooserDefault *impl)
-{
-  g_assert (impl->operation_mode != OPERATION_MODE_BROWSE);
-
-  recent_stop_loading (impl);
-  recent_clear_model (impl, TRUE);
-
-  gtk_widget_destroy (impl->recent_hbox);
-  impl->recent_hbox = NULL;
-
-  gtk_widget_show (impl->browse_path_bar);
-  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN || !impl->create_folders)
-    gtk_widget_hide (impl->browse_new_folder_button);
-  else
-    gtk_widget_show (impl->browse_new_folder_button);
-
-  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
-      impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
-    {
-      gtk_widget_show (impl->location_button);
-
-      if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
-       gtk_widget_show (impl->location_entry_box);
-    }
-
-  gtk_tree_view_column_set_visible (impl->list_size_column, impl->show_size_column);
-
-  impl->operation_mode = OPERATION_MODE_BROWSE;
-
-  file_list_set_sort_column_ids (impl);
-}
-
 static void
 recent_setup_model (GtkFileChooserDefault *impl)
 {
@@ -9095,7 +9410,6 @@ typedef struct
 {
   GtkFileChooserDefault *impl;
   GList *items;
-  guint needs_sorting : 1;
 } RecentLoadData;
 
 static void
@@ -9106,6 +9420,8 @@ recent_idle_cleanup (gpointer data)
 
   gtk_tree_view_set_model (GTK_TREE_VIEW (impl->browse_files_tree_view),
                            GTK_TREE_MODEL (impl->recent_model));
+  file_list_set_sort_column_ids (impl);
+  gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (impl->recent_model), MODEL_COL_MTIME, GTK_SORT_DESCENDING);
 
   set_busy_cursor (impl, FALSE);
   
@@ -9114,16 +9430,6 @@ recent_idle_cleanup (gpointer data)
   g_free (load_data);
 }
 
-static gint
-recent_sort_mru (gconstpointer a,
-                 gconstpointer b)
-{
-  GtkRecentInfo *info_a = (GtkRecentInfo *) a;
-  GtkRecentInfo *info_b = (GtkRecentInfo *) b;
-
-  return (gtk_recent_info_get_modified (info_b) - gtk_recent_info_get_modified (info_a));
-}
-
 static gint
 get_recent_files_limit (GtkWidget *widget)
 {
@@ -9199,32 +9505,18 @@ recent_idle_load (gpointer data)
   if (!impl->recent_manager)
     return FALSE;
 
-  /* first iteration: load all the items */
+  load_data->items = gtk_recent_manager_get_items (impl->recent_manager);
   if (!load_data->items)
-    {
-      load_data->items = gtk_recent_manager_get_items (impl->recent_manager);
-      if (!load_data->items)
-        return FALSE;
-
-      load_data->needs_sorting = TRUE;
-
-      return TRUE;
-    }
-  
-  /* second iteration: MRU sorting and clamping, and populating the model */
-  if (load_data->needs_sorting)
-    {
-      load_data->items = g_list_sort (load_data->items, recent_sort_mru);
+    return FALSE;
 
-      if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN)
-       populate_model_with_recent_items (impl, load_data->items);
-      else
-       populate_model_with_folders (impl, load_data->items);
+  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN)
+    populate_model_with_recent_items (impl, load_data->items);
+  else
+    populate_model_with_folders (impl, load_data->items);
 
-      g_list_foreach (load_data->items, (GFunc) gtk_recent_info_unref, NULL);
-      g_list_free (load_data->items);
-      load_data->items = NULL;
-    }
+  g_list_foreach (load_data->items, (GFunc) gtk_recent_info_unref, NULL);
+  g_list_free (load_data->items);
+  load_data->items = NULL;
 
   return FALSE;
 }
@@ -9244,7 +9536,6 @@ recent_start_loading (GtkFileChooserDefault *impl)
   load_data = g_new (RecentLoadData, 1);
   load_data->impl = impl;
   load_data->items = NULL;
-  load_data->needs_sorting = TRUE;
 
   /* begin lazy loading the recent files into the model */
   impl->load_recent_id = gdk_threads_add_idle_full (G_PRIORITY_HIGH_IDLE + 30,
@@ -9298,84 +9589,6 @@ recent_should_respond (GtkFileChooserDefault *impl)
   return (gtk_tree_selection_count_selected_rows (selection) != 0);
 }
 
-/* Hide the location widgets temporarily */
-static void
-recent_hide_entry (GtkFileChooserDefault *impl)
-{
-  GtkWidget *label;
-  GtkWidget *image;
-  gchar *tmp;
-
-  /* Box for recent widgets */
-  impl->recent_hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 12);
-
-  gtk_box_pack_start (GTK_BOX (impl->browse_path_bar_hbox), impl->recent_hbox, TRUE, TRUE, 0);
-  gtk_size_group_add_widget (impl->browse_path_bar_size_group, impl->recent_hbox);
-  gtk_widget_show (impl->recent_hbox);
-
-  /* For Save mode, we don't want this icon/label - we want update_path_bar() to do its thing instead */
-  if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE)
-    {
-      char *str;
-
-      str = g_strconcat ("<i>", _("Please select a folder below"), "</i>", NULL);
-      impl->browse_select_a_folder_label = gtk_label_new (NULL);
-      gtk_label_set_markup (GTK_LABEL (impl->browse_select_a_folder_label), str);
-      g_free (str);
-      gtk_box_pack_start (GTK_BOX (impl->recent_hbox), impl->browse_select_a_folder_label, FALSE, FALSE, 0);
-    }
-  else
-    {
-      /* Image */
-      image = gtk_image_new_from_icon_name ("document-open-recent", GTK_ICON_SIZE_BUTTON);
-      gtk_box_pack_start (GTK_BOX (impl->recent_hbox), image, FALSE, FALSE, 5);
-      gtk_widget_show (image);
-
-      /* Label */
-      label = gtk_label_new (NULL);
-      tmp = g_strdup_printf ("<b>%s</b>", _("Recently Used"));
-      gtk_label_set_markup_with_mnemonic (GTK_LABEL (label), tmp);
-      gtk_box_pack_start (GTK_BOX (impl->recent_hbox), label, FALSE, FALSE, 0);
-      gtk_widget_show (label);
-      g_free (tmp);
-    }
-
-  gtk_widget_hide (impl->browse_path_bar);
-  gtk_widget_hide (impl->browse_new_folder_button);
-  
-  /* Hide the location widgets temporarily */
-  if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
-      impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
-    {
-      gtk_widget_hide (impl->location_button);
-      gtk_widget_hide (impl->location_entry_box);
-    }
-}
-
-/* Main entry point to the recent files functions; this gets called when
- * the user activates the Recently Used shortcut.
- */
-static void
-recent_activate (GtkFileChooserDefault *impl)
-{
-  OperationMode previous_mode;
-
-  if (impl->operation_mode == OPERATION_MODE_RECENT)
-    return;
-
-  previous_mode = impl->operation_mode;
-  impl->operation_mode = OPERATION_MODE_RECENT;
-
-  shortcuts_select_item_without_activating (impl, shortcuts_get_index (impl, SHORTCUTS_RECENT));
-
-  stop_operation (impl, previous_mode);
-
-  recent_hide_entry (impl);
-
-  file_list_set_sort_column_ids (impl);
-  recent_start_loading (impl);
-}
-
 static void
 set_current_filter (GtkFileChooserDefault *impl,
                    GtkFileFilter         *filter)
@@ -9403,13 +9616,22 @@ set_current_filter (GtkFileChooserDefault *impl,
                                  filter_index);
 
       if (impl->browse_files_model)
-       install_list_model_filter (impl);
+        {
+          _gtk_file_system_model_set_filter (impl->browse_files_model, impl->current_filter);
+          _gtk_file_system_model_clear_cache (impl->browse_files_model, MODEL_COL_IS_SENSITIVE);
+        }
 
       if (impl->search_model)
-        _gtk_file_system_model_set_filter (impl->search_model, filter);
+        {
+          _gtk_file_system_model_set_filter (impl->search_model, filter);
+          _gtk_file_system_model_clear_cache (impl->search_model, MODEL_COL_IS_SENSITIVE);
+        }
 
       if (impl->recent_model)
-        _gtk_file_system_model_set_filter (impl->recent_model, filter);
+        {
+          _gtk_file_system_model_set_filter (impl->recent_model, filter);
+          _gtk_file_system_model_clear_cache (impl->recent_model, MODEL_COL_IS_SENSITIVE);
+        }
 
       g_object_notify (G_OBJECT (impl), "filter");
     }
@@ -9549,17 +9771,7 @@ shortcuts_activate_volume (GtkFileChooserDefault *impl,
 {
   GFile *file;
 
-  switch (impl->operation_mode)
-    {
-    case OPERATION_MODE_BROWSE:
-      break;
-    case OPERATION_MODE_SEARCH:
-      search_switch_to_browse_mode (impl);
-      break;
-    case OPERATION_MODE_RECENT:
-      recent_switch_to_browse_mode (impl);
-      break;
-    }
+  operation_mode_set (impl, OPERATION_MODE_BROWSE);
 
   /* We ref the file chooser since volume_mount() may run a main loop, and the
    * user could close the file chooser window in the meantime.
@@ -9666,10 +9878,13 @@ shortcuts_activate_iter (GtkFileChooserDefault *impl,
   gpointer col_data;
   ShortcutType shortcut_type;
 
-  if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY
+  /* In the Save modes, we want to preserve what the uesr typed in the filename
+   * entry, so that he may choose another folder without erasing his typed name.
+   */
+  if (impl->location_entry
       && !(impl->action == GTK_FILE_CHOOSER_ACTION_SAVE
           || impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER))
-    _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), "");
+    gtk_entry_set_text (GTK_ENTRY (impl->location_entry), "");
 
   gtk_tree_model_get (GTK_TREE_MODEL (impl->shortcuts_model), iter,
                      SHORTCUTS_COL_DATA, &col_data,
@@ -9690,6 +9905,8 @@ shortcuts_activate_iter (GtkFileChooserDefault *impl,
 
       volume = col_data;
 
+      operation_mode_set (impl, OPERATION_MODE_BROWSE);
+
       shortcuts_activate_volume (impl, volume);
     }
   else if (shortcut_type == SHORTCUT_TYPE_FILE)
@@ -9697,6 +9914,8 @@ shortcuts_activate_iter (GtkFileChooserDefault *impl,
       struct ShortcutsActivateData *data;
       GtkFileSystemVolume *volume;
 
+      operation_mode_set (impl, OPERATION_MODE_BROWSE);
+
       volume = _gtk_file_system_get_volume_for_file (impl->file_system, col_data);
 
       data = g_new0 (struct ShortcutsActivateData, 1);
@@ -9728,11 +9947,11 @@ shortcuts_activate_iter (GtkFileChooserDefault *impl,
     }
   else if (shortcut_type == SHORTCUT_TYPE_SEARCH)
     {
-      search_activate (impl);
+      operation_mode_set (impl, OPERATION_MODE_SEARCH);
     }
   else if (shortcut_type == SHORTCUT_TYPE_RECENT)
     {
-      recent_activate (impl);
+      operation_mode_set (impl, OPERATION_MODE_RECENT);
     }
 }
 
@@ -9803,14 +10022,16 @@ list_select_func  (GtkTreeSelection  *selection,
       impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)
     {
       GtkTreeIter iter;
+      gboolean is_sensitive;
       gboolean is_folder;
 
       if (!gtk_tree_model_get_iter (model, &iter, path))
         return FALSE;
       gtk_tree_model_get (model, &iter,
+                          MODEL_COL_IS_SENSITIVE, &is_sensitive,
                           MODEL_COL_IS_FOLDER, &is_folder,
                           -1);
-      if (!is_folder)
+      if (!is_sensitive || !is_folder)
         return FALSE;
     }
     
@@ -9841,10 +10062,11 @@ list_selection_changed (GtkTreeSelection      *selection,
   if (impl->location_entry)
     update_chooser_entry (impl);
 
-  update_path_bar (impl);
+  path_bar_update (impl);
 
   check_preview_change (impl);
   bookmarks_check_add_sensitivity (impl);
+  check_copy_file_location_sensitivity (impl);
 
   g_signal_emit_by_name (impl, "selection-changed", 0);
 }
@@ -9860,6 +10082,7 @@ list_row_activated (GtkTreeView           *tree_view,
   GtkTreeIter iter;
   GtkTreeModel *model;
   gboolean is_folder;
+  gboolean is_sensitive;
 
   model = gtk_tree_view_get_model (tree_view);
 
@@ -9869,12 +10092,12 @@ list_row_activated (GtkTreeView           *tree_view,
   gtk_tree_model_get (model, &iter,
                       MODEL_COL_FILE, &file,
                       MODEL_COL_IS_FOLDER, &is_folder,
+                      MODEL_COL_IS_SENSITIVE, &is_sensitive,
                       -1);
         
-  if (is_folder && file)
+  if (is_sensitive && is_folder && file)
     {
       change_folder_and_display_error (impl, file, FALSE);
-      g_object_unref (file);
       goto out;
     }
 
@@ -9915,10 +10138,6 @@ update_cell_renderer_attributes (GtkFileChooserDefault *impl)
   GtkTreeViewColumn *column;
   GtkCellRenderer *renderer;
   GList *walk, *list;
-  gboolean always_sensitive;
-
-  always_sensitive = impl->action != GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER &&
-                     impl->action != GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER;
 
   /* Keep the following column numbers in sync with create_file_list() */
 
@@ -9941,10 +10160,8 @@ update_cell_renderer_attributes (GtkFileChooserDefault *impl)
                                                "ellipsize", MODEL_COL_ELLIPSIZE,
                                                NULL);
         }
-      if (always_sensitive)
-        g_object_set (renderer, "sensitive", TRUE, NULL);
-      else
-        gtk_tree_view_column_add_attribute (column, renderer, "sensitive", MODEL_COL_IS_FOLDER);
+
+      gtk_tree_view_column_add_attribute (column, renderer, "sensitive", MODEL_COL_IS_SENSITIVE);
     }
   g_list_free (list);
 
@@ -9955,10 +10172,8 @@ update_cell_renderer_attributes (GtkFileChooserDefault *impl)
   gtk_tree_view_column_set_attributes (column, renderer, 
                                        "text", MODEL_COL_SIZE_TEXT,
                                        NULL);
-  if (always_sensitive)
-    g_object_set (renderer, "sensitive", TRUE, NULL);
-  else
-    gtk_tree_view_column_add_attribute (column, renderer, "sensitive", MODEL_COL_IS_FOLDER);
+
+  gtk_tree_view_column_add_attribute (column, renderer, "sensitive", MODEL_COL_IS_SENSITIVE);
   g_list_free (list);
 
   /* mtime */
@@ -9968,10 +10183,7 @@ update_cell_renderer_attributes (GtkFileChooserDefault *impl)
   gtk_tree_view_column_set_attributes (column, renderer, 
                                        "text", MODEL_COL_MTIME_TEXT,
                                        NULL);
-  if (always_sensitive)
-    g_object_set (renderer, "sensitive", TRUE, NULL);
-  else
-    gtk_tree_view_column_add_attribute (column, renderer, "sensitive", MODEL_COL_IS_FOLDER);
+  gtk_tree_view_column_add_attribute (column, renderer, "sensitive", MODEL_COL_IS_SENSITIVE);
   g_list_free (list);
 }
 
@@ -9985,7 +10197,7 @@ static void
 location_set_user_text (GtkFileChooserDefault *impl,
                        const gchar           *path)
 {
-  _gtk_file_chooser_entry_set_file_part (GTK_FILE_CHOOSER_ENTRY (impl->location_entry), path);
+  gtk_entry_set_text (GTK_ENTRY (impl->location_entry), path);
   gtk_editable_set_position (GTK_EDITABLE (impl->location_entry), -1);
 }
 
@@ -9996,21 +10208,9 @@ location_popup_handler (GtkFileChooserDefault *impl,
   if (impl->operation_mode != OPERATION_MODE_BROWSE)
     {
       GtkWidget *widget_to_focus;
-      
-      /* This will give us the location widgets back */
-      switch (impl->operation_mode)
-        {
-        case OPERATION_MODE_SEARCH:
-          search_switch_to_browse_mode (impl);
-          break;
-        case OPERATION_MODE_RECENT:
-          recent_switch_to_browse_mode (impl);
-          break;
-        case OPERATION_MODE_BROWSE:
-          g_assert_not_reached ();
-          break;
-        }
 
+      operation_mode_set (impl, OPERATION_MODE_BROWSE);
+      
       if (impl->current_folder)
         change_folder_and_display_error (impl, impl->current_folder, FALSE);
 
@@ -10026,34 +10226,11 @@ location_popup_handler (GtkFileChooserDefault *impl,
   if (impl->action == GTK_FILE_CHOOSER_ACTION_OPEN ||
       impl->action == GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER)
     {
-      LocationMode new_mode;
-
-      if (path != NULL)
-       {
-         /* since the user typed something, we unconditionally want to turn on the entry */
-         new_mode = LOCATION_MODE_FILENAME_ENTRY;
-       }
-      else if (impl->location_mode == LOCATION_MODE_PATH_BAR)
-       new_mode = LOCATION_MODE_FILENAME_ENTRY;
-      else if (impl->location_mode == LOCATION_MODE_FILENAME_ENTRY)
-       new_mode = LOCATION_MODE_PATH_BAR;
-      else
-       {
-         g_assert_not_reached ();
-         return;
-       }
+      if (!path)
+       return;
 
-      location_mode_set (impl, new_mode, TRUE);
-      if (new_mode == LOCATION_MODE_FILENAME_ENTRY)
-       {
-         if (path != NULL)
-           location_set_user_text (impl, path);
-         else
-           {
-             location_entry_set_initial_text (impl);
-             gtk_editable_select_region (GTK_EDITABLE (impl->location_entry), 0, -1);
-           }
-       }
+      location_mode_set (impl, LOCATION_MODE_FILENAME_ENTRY, TRUE);
+      location_set_user_text (impl, path);
     }
   else if (impl->action == GTK_FILE_CHOOSER_ACTION_SAVE ||
           impl->action == GTK_FILE_CHOOSER_ACTION_CREATE_FOLDER)