Skip to content

Commit 8fd292a

Browse files
kavehtehranismpl-os
authored andcommitted
Restore Last Window Tabs on Startup (linuxmint#3661)
* Restore last closed window tabs Save split view and tab URIs on window close and restore them when starting Nemo with no explicit locations. * adding tabs * adding tabs * adding tabs * adding tabs * adding tabs * adding tabs * adding tabs * option under 'behaviour' in preferences to toggle on restoring tabs * simplified sessions save logic to only save the window that exits * addressing pr comments regarding last window logic
1 parent ad10fda commit 8fd292a

8 files changed

Lines changed: 461 additions & 11 deletions

gresources/nemo-file-management-properties.glade

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1269,6 +1269,24 @@ along with . If not, see <http://www.gnu.org/licenses/>.
12691269
<packing>
12701270
<property name="expand">False</property>
12711271
<property name="fill">False</property>
1272+
<property name="padding">3</property>
1273+
<property name="position">3</property>
1274+
</packing>
1275+
</child>
1276+
<child>
1277+
<object class="GtkCheckButton" id="restore_tabs_on_startup_checkbutton">
1278+
<property name="label" translatable="yes">Restore last window tabs on startup</property>
1279+
<property name="visible">True</property>
1280+
<property name="can-focus">True</property>
1281+
<property name="receives-default">False</property>
1282+
<property name="use-underline">True</property>
1283+
<property name="xalign">0</property>
1284+
<property name="draw-indicator">True</property>
1285+
</object>
1286+
<packing>
1287+
<property name="expand">False</property>
1288+
<property name="fill">False</property>
1289+
<property name="padding">3</property>
12721290
<property name="position">4</property>
12731291
</packing>
12741292
</child>

libnemo-private/nemo-global-preferences.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,13 @@ typedef enum
126126
#define NEMO_WINDOW_STATE_DEVICES_EXPANDED "devices-expanded"
127127
#define NEMO_WINDOW_STATE_NETWORK_EXPANDED "network-expanded"
128128

129+
/* Saved session (last closed window) */
130+
#define NEMO_WINDOW_STATE_SAVED_SPLIT_VIEW "saved-split-view"
131+
#define NEMO_WINDOW_STATE_SAVED_TABS_LEFT "saved-tabs-left"
132+
#define NEMO_WINDOW_STATE_SAVED_TABS_RIGHT "saved-tabs-right"
133+
#define NEMO_WINDOW_STATE_SAVED_ACTIVE_TAB_LEFT "saved-active-tab-left"
134+
#define NEMO_WINDOW_STATE_SAVED_ACTIVE_TAB_RIGHT "saved-active-tab-right"
135+
129136
/* Sorting order */
130137
#define NEMO_PREFERENCES_SORT_DIRECTORIES_FIRST "sort-directories-first"
131138
#define NEMO_PREFERENCES_SORT_FAVORITES_FIRST "sort-favorites-first"
@@ -142,6 +149,7 @@ typedef enum
142149

143150
#define NEMO_PREFERENCES_START_WITH_DUAL_PANE "start-with-dual-pane"
144151
#define NEMO_PREFERENCES_SHOW_DUAL_PANE_LOCATION_LABELS "show-dual-pane-location-labels"
152+
#define NEMO_PREFERENCES_RESTORE_TABS_ON_STARTUP "restore-tabs-on-startup"
145153
#define NEMO_PREFERENCES_IGNORE_VIEW_METADATA "ignore-view-metadata"
146154
#define NEMO_PREFERENCES_SHOW_BOOKMARKS_IN_TO_MENUS "show-bookmarks-in-to-menus"
147155
#define NEMO_PREFERENCES_SHOW_PLACES_IN_TO_MENUS "show-places-in-to-menus"

libnemo-private/org.nemo.gschema.xml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,11 @@
362362
<summary>Whether to show per-pane location labels in dual-pane mode</summary>
363363
<description>If set to true, each pane in dual-pane mode will show a compact path label above its file list</description>
364364
</key>
365+
<key name="restore-tabs-on-startup" type="b">
366+
<default>false</default>
367+
<summary>Restore the previous window tabs on startup</summary>
368+
<description>If set to true, Nemo will restore the last saved window tab state when launched without explicit locations.</description>
369+
</key>
365370
<key name="ignore-view-metadata" type="b">
366371
<default>false</default>
367372
<summary>Whether to ignore folder metadata for view zoom levels and layouts</summary>
@@ -718,6 +723,33 @@
718723
<summary>Side pane view</summary>
719724
<description>The side pane view to show in newly opened windows.</description>
720725
</key>
726+
727+
<!-- Saved session (last closed window) -->
728+
<key name="saved-split-view" type="b">
729+
<default>false</default>
730+
<summary>Whether split view was enabled when the last window was closed</summary>
731+
<description>Internal setting used to restore the last closed window's split view and tabs.</description>
732+
</key>
733+
<key name="saved-tabs-left" type="as">
734+
<default>[]</default>
735+
<summary>Saved tab URIs for the left pane</summary>
736+
<description>Internal setting used to restore the last closed window's tabs for the left pane.</description>
737+
</key>
738+
<key name="saved-tabs-right" type="as">
739+
<default>[]</default>
740+
<summary>Saved tab URIs for the right pane</summary>
741+
<description>Internal setting used to restore the last closed window's tabs for the right pane.</description>
742+
</key>
743+
<key name="saved-active-tab-left" type="i">
744+
<default>0</default>
745+
<summary>Index of the active tab in the left pane</summary>
746+
<description>Internal setting used to restore which tab was active in the left pane.</description>
747+
</key>
748+
<key name="saved-active-tab-right" type="i">
749+
<default>0</default>
750+
<summary>Index of the active tab in the right pane</summary>
751+
<description>Internal setting used to restore which tab was active in the right pane.</description>
752+
</key>
721753
</schema>
722754

723755
<schema id="org.nemo.plugins" path="/org/nemo/plugins/" gettext-domain="nemo">

src/nemo-application.c

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030

3131
#include "nemo-application.h"
3232

33+
#include "nemo-desktop-window.h"
34+
3335
#if (defined(ENABLE_EMPTY_VIEW) && ENABLE_EMPTY_VIEW)
3436
#include "nemo-empty-view.h"
3537
#endif /* ENABLE_EMPTY_VIEW */
@@ -638,6 +640,33 @@ nemo_application_quit (NemoApplication *self)
638640
GList *windows;
639641

640642
windows = gtk_application_get_windows (GTK_APPLICATION (app));
643+
644+
/* Save session state once, before we destroy all windows.
645+
* Save the last non-desktop window we find. */
646+
{
647+
NemoWindow *last_window = NULL;
648+
649+
for (GList *l = windows; l != NULL; l = l->next) {
650+
GtkWindow *w = GTK_WINDOW (l->data);
651+
652+
if (!NEMO_IS_WINDOW (w)) {
653+
continue;
654+
}
655+
656+
/* Avoid saving the desktop window */
657+
if (NEMO_IS_DESKTOP_WINDOW (w)) {
658+
continue;
659+
}
660+
661+
last_window = NEMO_WINDOW (w);
662+
break;
663+
}
664+
665+
if (last_window != NULL) {
666+
nemo_window_save_session_state (last_window);
667+
}
668+
}
669+
641670
g_list_foreach (windows, (GFunc) gtk_widget_destroy, NULL);
642671

643672
/* we have been asked to force quit */

src/nemo-file-management-properties.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
#define NEMO_FILE_MANAGEMENT_PROPERTIES_SHOW_ADVANCED_PERMISSIONS_WIDGET "show_advanced_permissions_checkbutton"
102102
#define NEMO_FILE_MANAGEMENT_PROPERTIES_START_WITH_DUAL_PANE_WIDGET "start_with_dual_pane_checkbutton"
103103
#define NEMO_FILE_MANAGEMENT_PROPERTIES_SHOW_DUAL_PANE_LOCATION_LABELS_WIDGET "show_dual_pane_location_labels_checkbutton"
104+
#define NEMO_FILE_MANAGEMENT_PROPERTIES_RESTORE_TABS_ON_STARTUP_WIDGET "restore_tabs_on_startup_checkbutton"
104105
#define NEMO_FILE_MANAGEMENT_PROPERTIES_IGNORE_VIEW_METADATA_WIDGET "ignore_view_metadata_checkbutton"
105106
#define NEMO_FILE_MANAGEMENT_PROPERTIES_BOOKMARKS_IN_TO_MENUS_WIDGET "bookmarks_in_to_checkbutton"
106107
#define NEMO_FILE_MANAGEMENT_PROPERTIES_PLACES_IN_TO_MENUS_WIDGET "places_in_to_checkbutton"
@@ -1097,6 +1098,10 @@ nemo_file_management_properties_dialog_setup (GtkBuilder *builder,
10971098
NEMO_FILE_MANAGEMENT_PROPERTIES_SHOW_DUAL_PANE_LOCATION_LABELS_WIDGET,
10981099
NEMO_PREFERENCES_SHOW_DUAL_PANE_LOCATION_LABELS);
10991100

1101+
bind_builder_bool (builder, nemo_preferences,
1102+
NEMO_FILE_MANAGEMENT_PROPERTIES_RESTORE_TABS_ON_STARTUP_WIDGET,
1103+
NEMO_PREFERENCES_RESTORE_TABS_ON_STARTUP);
1104+
11001105
bind_builder_bool (builder, nemo_preferences,
11011106
NEMO_FILE_MANAGEMENT_PROPERTIES_IGNORE_VIEW_METADATA_WIDGET,
11021107
NEMO_PREFERENCES_IGNORE_VIEW_METADATA);

src/nemo-main-application.c

Lines changed: 68 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -483,8 +483,34 @@ open_windows (NemoMainApplication *application,
483483
gint i;
484484

485485
if (files == NULL || files[0] == NULL) {
486-
/* Open a window pointing at the default location. */
487-
open_window (application, NULL, screen, geometry);
486+
/* No explicit locations requested: try restoring the last session. */
487+
NemoWindow *window;
488+
gboolean have_geometry;
489+
gboolean do_restore;
490+
491+
window = nemo_main_application_create_window (NEMO_APPLICATION (application), screen);
492+
493+
have_geometry = geometry != NULL && strcmp (geometry, "") != 0;
494+
if (have_geometry && !gtk_widget_get_visible (GTK_WIDGET (window))) {
495+
/* never maximize windows opened from shell if a
496+
* custom geometry has been requested.
497+
*/
498+
gtk_window_unmaximize (GTK_WINDOW (window));
499+
eel_gtk_window_set_initial_geometry_from_string (GTK_WINDOW (window),
500+
geometry,
501+
APPLICATION_WINDOW_MIN_WIDTH,
502+
APPLICATION_WINDOW_MIN_HEIGHT,
503+
FALSE);
504+
}
505+
506+
do_restore = g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_RESTORE_TABS_ON_STARTUP);
507+
508+
if (!do_restore || !nemo_window_restore_saved_tabs (window)) {
509+
/* Fall back to a safe default location */
510+
GFile *home = g_file_new_for_path (g_get_home_dir ());
511+
nemo_window_go_to (window, home);
512+
g_object_unref (home);
513+
}
488514
} else {
489515
if (open_in_existing_window) {
490516
/* Open one tab at each requested location in an existing window */
@@ -552,6 +578,7 @@ nemo_main_application_open (GApplication *app,
552578
gboolean open_in_tabs = FALSE;
553579
gchar *geometry = NULL;
554580
gboolean open_in_existing_window = strcmp (options, "EXISTING_WINDOW") == 0;
581+
gboolean default_no_args = FALSE;
555582
const char splitter = '=';
556583

557584
g_debug ("Open called on the GApplication instance; %d files", n_files);
@@ -560,7 +587,12 @@ nemo_main_application_open (GApplication *app,
560587
/* Check if local command line passed --geometry or --tabs */
561588
if (strlen (options) > 0) {
562589
gchar** split_options = g_strsplit (options, &splitter, 2);
563-
if (strcmp (split_options[0], "NULL") != 0) {
590+
if (g_str_has_prefix (split_options[0], "DEFAULT")) {
591+
default_no_args = TRUE;
592+
if (g_str_has_prefix (split_options[0], "DEFAULT+")) {
593+
geometry = g_strdup (split_options[0] + strlen ("DEFAULT+"));
594+
}
595+
} else if (strcmp (split_options[0], "NULL") != 0) {
564596
geometry = g_strdup (split_options[0]);
565597
}
566598
sscanf (split_options[1], "%d", &open_in_tabs);
@@ -575,7 +607,13 @@ nemo_main_application_open (GApplication *app,
575607
geometry ? geometry : "none",
576608
open_in_existing_window ? "yes" : "no");
577609

578-
open_windows (self, files, n_files, gdk_screen_get_default (), geometry, open_in_tabs, open_in_existing_window);
610+
if (default_no_args) {
611+
/* Treat this as a no-arg launch; open_windows() will attempt session restore
612+
* and fall back to Home if restore isn't possible. */
613+
open_windows (self, NULL, 0, gdk_screen_get_default (), geometry, open_in_tabs, open_in_existing_window);
614+
} else {
615+
open_windows (self, files, n_files, gdk_screen_get_default (), geometry, open_in_tabs, open_in_existing_window);
616+
}
579617

580618
g_clear_pointer (&geometry, g_free);
581619
}
@@ -820,9 +858,11 @@ nemo_main_application_local_command_line (GApplication *application,
820858

821859
GFile **files;
822860
gint idx, len;
861+
gboolean used_default_location;
823862

824863
len = 0;
825864
files = NULL;
865+
used_default_location = FALSE;
826866

827867
/* Convert args to GFiles */
828868
if (remaining != NULL) {
@@ -844,11 +884,15 @@ nemo_main_application_local_command_line (GApplication *application,
844884
}
845885

846886
if (files == NULL && !no_default_window) {
887+
/* Original behavior: default to Home when no URIs are provided. */
847888
files = g_malloc0 (2 * sizeof (GFile *));
848889
len = 1;
849890

850891
files[0] = g_file_new_for_path (g_get_home_dir ());
851892
files[1] = NULL;
893+
894+
/* Mark that this was a no-arg launch, not an explicit URI. */
895+
used_default_location = TRUE;
852896
}
853897
/* --select: open the parent dir and highlight the requested file */
854898
if (select_uri != NULL) {
@@ -868,27 +912,40 @@ nemo_main_application_local_command_line (GApplication *application,
868912
goto out_free_files;
869913
}
870914

871-
/* Invoke "Open" to open in existing window or create new windows */
915+
/* Invoke "Open" to open in existing window or create new windows.
916+
*/
872917
if (len > 0) {
873918
gchar* concatOptions = g_malloc0(64);
874919
if (open_in_existing_window) {
875920
g_stpcpy (concatOptions, "EXISTING_WINDOW");
876921
} else {
877922
if (self->priv->geometry == NULL) {
878-
g_snprintf (concatOptions, 64, "NULL=%d", open_in_tabs);
923+
/* If Home was synthesized because no URIs were passed, signal that
924+
* to the primary instance so it can attempt session restore. */
925+
if (used_default_location) {
926+
g_snprintf (concatOptions, 64, "DEFAULT=%d", open_in_tabs);
927+
} else {
928+
g_snprintf (concatOptions, 64, "NULL=%d", open_in_tabs);
929+
}
879930
} else {
880-
g_snprintf (concatOptions, 64, "%s=%d", self->priv->geometry, open_in_tabs);
931+
if (used_default_location) {
932+
g_snprintf (concatOptions, 64, "DEFAULT+%s=%d", self->priv->geometry, open_in_tabs);
933+
} else {
934+
g_snprintf (concatOptions, 64, "%s=%d", self->priv->geometry, open_in_tabs);
935+
}
881936
}
882937
}
883938
g_application_open (application, files, len, concatOptions);
884939
g_free (concatOptions);
885940
}
886941

887-
out_free_files:
888-
for (idx = 0; idx < len; idx++) {
889-
g_object_unref (files[idx]);
942+
out_free_files:
943+
if (files != NULL) {
944+
for (idx = 0; idx < len; idx++) {
945+
g_object_unref (files[idx]);
946+
}
947+
g_free (files);
890948
}
891-
g_free (files);
892949

893950
out:
894951
g_option_context_free (context);

src/nemo-window-private.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,9 @@ void nemo_window_set_active_pane (NemoWindow
160160
NemoWindowPane *new_pane);
161161
NemoWindowPane * nemo_window_get_active_pane (NemoWindow *window);
162162

163+
gboolean nemo_window_restore_saved_tabs (NemoWindow *window);
164+
void nemo_window_save_session_state (NemoWindow *window);
165+
163166

164167
/* sync window GUI with current slot. Used when changing slots,
165168
* and when updating the slot state.

0 commit comments

Comments
 (0)