[nautilus] window, window-slot: Save and restore navigation history



commit 691f1cf1bde256c94e126c1a2bb111aaff630b72
Author: Sachin Daluja <30343-sachindaluja users noreply gitlab gnome org>
Date:   Sun May 10 22:30:03 2020 -0400

    window, window-slot: Save and restore navigation history
    
    When a new window slot instance replaces the existing one to handle the new
    location.
    
    This allows back and forward history lists to be preserved when the window
    switches between instances of different window slot classes.
    
    Closes https://gitlab.gnome.org/GNOME/nautilus/-/issues/32

 src/nautilus-window-slot.c | 48 ++++++++++++++++++++++----
 src/nautilus-window-slot.h | 13 +++++++
 src/nautilus-window.c      | 84 +++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 138 insertions(+), 7 deletions(-)
---
diff --git a/src/nautilus-window-slot.c b/src/nautilus-window-slot.c
index 2747b1754..ada81a9f1 100644
--- a/src/nautilus-window-slot.c
+++ b/src/nautilus-window-slot.c
@@ -198,6 +198,9 @@ nautilus_window_slot_restore_navigation_state (NautilusWindowSlot      *self,
 
     priv = nautilus_window_slot_get_instance_private (self);
 
+    /* We are restoring saved history to newly created slot with no history. */
+    g_warn_if_fail (priv->back_list == NULL && priv->forward_list == NULL);
+
     priv->back_list = g_steal_pointer (&data->back_list);
 
     priv->forward_list = g_steal_pointer (&data->forward_list);
@@ -2280,12 +2283,11 @@ nautilus_window_slot_set_content_view (NautilusWindowSlot *self,
 }
 
 void
-nautilus_window_back_or_forward (NautilusWindow          *window,
-                                 gboolean                 back,
-                                 guint                    distance,
-                                 NautilusWindowOpenFlags  flags)
+nautilus_window_slot_back_or_forward (NautilusWindowSlot      *self,
+                                      gboolean                 back,
+                                      guint                    distance,
+                                      NautilusWindowOpenFlags  flags)
 {
-    NautilusWindowSlot *self;
     GList *list;
     GFile *location;
     guint len;
@@ -2293,7 +2295,6 @@ nautilus_window_back_or_forward (NautilusWindow          *window,
     GFile *old_location;
     NautilusWindowSlotPrivate *priv;
 
-    self = nautilus_window_get_active_slot (window);
     priv = nautilus_window_slot_get_instance_private (self);
     list = back ? priv->back_list : priv->forward_list;
 
@@ -3728,3 +3729,38 @@ nautilus_window_slot_get_query_editor (NautilusWindowSlot *self)
 
     return priv->query_editor;
 }
+
+/*
+ * Open the specified location and set up the navigation history including the
+ * back and forward lists. This function is intended to be called when switching
+ * between NautilusWindowSlot and NautilusOtherLocationsWindowSlot. It allows
+ * the navigation history accumulated in the slot being replaced to be loaded
+ * into the replacing slot.
+ *
+ * The 'location' member variable is set to the new location before calling
+ * begin_location_change() to ensure that it matches the
+ * 'current_location_bookmark' member as expected by the location change
+ * pipeline.
+ */
+void
+nautilus_window_slot_open_location_set_navigation_state (NautilusWindowSlot         *self,
+                                                         GFile                      *location,
+                                                         NautilusWindowOpenFlags     flags,
+                                                         GList                      *new_selection,
+                                                         NautilusLocationChangeType  change_type,
+                                                         NautilusNavigationState    *navigation_state,
+                                                         guint                       distance)
+{
+    NautilusWindowSlotPrivate *priv;
+
+    priv = nautilus_window_slot_get_instance_private (self);
+
+    nautilus_window_slot_restore_navigation_state (self, navigation_state);
+
+    g_clear_object (&priv->location);
+
+    priv->location = nautilus_file_get_location (navigation_state->file);
+
+    begin_location_change (self, location, NULL, new_selection,
+                           change_type, distance, NULL);
+}
diff --git a/src/nautilus-window-slot.h b/src/nautilus-window-slot.h
index bdb9dccfa..3518c948c 100644
--- a/src/nautilus-window-slot.h
+++ b/src/nautilus-window-slot.h
@@ -77,6 +77,14 @@ void nautilus_window_slot_open_location_full              (NautilusWindowSlot
                                                            NautilusWindowOpenFlags  flags,
                                                            GList                   *new_selection);
 
+void nautilus_window_slot_open_location_set_navigation_state (NautilusWindowSlot         *slot,
+                                                              GFile                      *location,
+                                                              NautilusWindowOpenFlags     flags,
+                                                              GList                      *new_selection,
+                                                              NautilusLocationChangeType  change_type,
+                                                              NautilusNavigationState    *navigation_state,
+                                                              guint                       distance);
+
 GFile * nautilus_window_slot_get_location                 (NautilusWindowSlot *slot);
 GFile * nautilus_window_slot_get_pending_location          (NautilusWindowSlot *slot);
 
@@ -134,4 +142,9 @@ NautilusQueryEditor *nautilus_window_slot_get_query_editor (NautilusWindowSlot *
 /* Only used by slot-dnd */
 NautilusView*  nautilus_window_slot_get_current_view       (NautilusWindowSlot *slot);
 
+void nautilus_window_slot_back_or_forward                  (NautilusWindowSlot     *slot,
+                                                            gboolean                back,
+                                                            guint                   distance,
+                                                            NautilusWindowOpenFlags flags);
+
 void free_navigation_state                                 (gpointer data);
diff --git a/src/nautilus-window.c b/src/nautilus-window.c
index ee5b16051..c81d150d1 100644
--- a/src/nautilus-window.c
+++ b/src/nautilus-window.c
@@ -610,6 +610,7 @@ nautilus_window_open_location_full (NautilusWindow          *window,
 {
     NautilusWindowSlot *active_slot;
     gboolean new_tab_at_end;
+    NautilusNavigationState *navigation_state = NULL;
 
     /* The location owner can be one of the slots requesting to handle an
      * unhandled location. But this slot can be destroyed when switching to
@@ -641,6 +642,8 @@ nautilus_window_open_location_full (NautilusWindow          *window,
     }
     else if (!nautilus_window_slot_handles_location (target_slot, location))
     {
+        navigation_state = nautilus_window_slot_get_navigation_state (active_slot);
+
         target_slot = replace_active_slot (window, location, flags);
     }
 
@@ -652,7 +655,19 @@ nautilus_window_open_location_full (NautilusWindow          *window,
         nautilus_window_set_active_slot (window, target_slot);
     }
 
-    nautilus_window_slot_open_location_full (target_slot, location, flags, selection);
+    if (navigation_state != NULL)
+    {
+        nautilus_window_slot_open_location_set_navigation_state (target_slot,
+                                                                 location, flags, selection,
+                                                                 NAUTILUS_LOCATION_CHANGE_STANDARD,
+                                                                 navigation_state, 0);
+
+        free_navigation_state (navigation_state);
+    }
+    else
+    {
+        nautilus_window_slot_open_location_full (target_slot, location, flags, selection);
+    }
 
     g_object_unref (location);
 }
@@ -3016,3 +3031,70 @@ nautilus_window_search (NautilusWindow *window,
         g_warning ("Trying search on a slot but no active slot present");
     }
 }
+
+/* Ideally, this method should be a simple wrapper for the slot method. However,
+ * going back or forward can result in a new slot (or another subclass), so we
+ * workaround that by duplicating part of nautilus_window_slot_back_or_forward()
+ */
+void
+nautilus_window_back_or_forward (NautilusWindow          *window,
+                                 gboolean                 back,
+                                 guint                    distance,
+                                 NautilusWindowOpenFlags  flags)
+{
+    NautilusWindowSlot *slot;
+    GList *next_location_list, *back_list, *forward_list;
+    GFile *next_location;
+    guint len;
+    NautilusBookmark *next_location_bookmark;
+    gboolean active_slot_handles_location;
+
+    slot = nautilus_window_get_active_slot (window);
+    back_list = nautilus_window_slot_get_back_history (slot);
+    forward_list = nautilus_window_slot_get_forward_history (slot);
+
+    next_location_list = back ? back_list : forward_list;
+
+    len = (guint) g_list_length (next_location_list);
+
+    /* If we can't move in the direction at all, just return. */
+    if (len == 0)
+    {
+        return;
+    }
+
+    /* If the distance to move is off the end of the list, go to the end
+     *  of the list. */
+    if (distance >= len)
+    {
+        distance = len - 1;
+    }
+
+    next_location_bookmark = g_list_nth_data (next_location_list, distance);
+    next_location = nautilus_bookmark_get_location (next_location_bookmark);
+
+    active_slot_handles_location = nautilus_window_slot_handles_location (slot, next_location);
+
+    if (!active_slot_handles_location)
+    {
+        NautilusNavigationState *navigation_state;
+        NautilusLocationChangeType location_change_type;
+
+        navigation_state = nautilus_window_slot_get_navigation_state (slot);
+
+        location_change_type = back ? NAUTILUS_LOCATION_CHANGE_BACK : NAUTILUS_LOCATION_CHANGE_FORWARD;
+
+        slot = replace_active_slot (window, next_location, flags);
+
+        nautilus_window_slot_open_location_set_navigation_state (slot,
+                                                                 next_location, flags, NULL,
+                                                                 location_change_type,
+                                                                 navigation_state, distance);
+
+        free_navigation_state (navigation_state);
+    }
+    else
+    {
+        nautilus_window_slot_back_or_forward (slot, back, distance, flags);
+    }
+}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]