Skip to content
Open
2 changes: 2 additions & 0 deletions libnemo-private/nemo-global-preferences.h
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,8 @@ typedef enum
#define NEMO_WINDOW_STATE_SAVED_SPLIT_VIEW "saved-split-view"
#define NEMO_WINDOW_STATE_SAVED_TABS_LEFT "saved-tabs-left"
#define NEMO_WINDOW_STATE_SAVED_TABS_RIGHT "saved-tabs-right"
#define NEMO_WINDOW_STATE_SAVED_TAB_LOCKS_LEFT "saved-tab-locks-left"
#define NEMO_WINDOW_STATE_SAVED_TAB_LOCKS_RIGHT "saved-tab-locks-right"
#define NEMO_WINDOW_STATE_SAVED_ACTIVE_TAB_LEFT "saved-active-tab-left"
#define NEMO_WINDOW_STATE_SAVED_ACTIVE_TAB_RIGHT "saved-active-tab-right"

Expand Down
14 changes: 12 additions & 2 deletions libnemo-private/org.nemo.gschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -717,12 +717,22 @@
<key name="saved-tabs-left" type="as">
<default>[]</default>
<summary>Saved tab URIs for the left pane</summary>
<description>Internal setting used to restore the last closed window's tabs for the left pane.</description>
<description>Internal setting used to restore the last closed window's tabs for the left pane. A locked tab is saved at its locked folder rather than at the last folder it visited.</description>
</key>
<key name="saved-tabs-right" type="as">
<default>[]</default>
<summary>Saved tab URIs for the right pane</summary>
<description>Internal setting used to restore the last closed window's tabs for the right pane.</description>
<description>Internal setting used to restore the last closed window's tabs for the right pane. A locked tab is saved at its locked folder rather than at the last folder it visited.</description>
</key>
<key name="saved-tab-locks-left" type="ai">
<default>[]</default>
<summary>Saved tab lock modes for the left pane</summary>
<description>Internal setting used to restore the lock mode of each tab in saved-tabs-left, position by position: 0 for an unlocked tab, 1 for a tab that returns to its locked folder when reselected, and 2 for a tab whose folder changes open in a new tab. Entries missing from the end of this list default to 0, so a saved-tabs-left written by a Nemo without tab locking restores as all-unlocked.</description>
</key>
<key name="saved-tab-locks-right" type="ai">
<default>[]</default>
<summary>Saved tab lock modes for the right pane</summary>
<description>Internal setting used to restore the lock mode of each tab in saved-tabs-right, position by position: 0 for an unlocked tab, 1 for a tab that returns to its locked folder when reselected, and 2 for a tab whose folder changes open in a new tab. Entries missing from the end of this list default to 0, so a saved-tabs-right written by a Nemo without tab locking restores as all-unlocked.</description>
</key>
<key name="saved-active-tab-left" type="i">
<default>0</default>
Expand Down
89 changes: 62 additions & 27 deletions src/nemo-application.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@
#include <errno.h>
#include <glib/gstdio.h>
#include <glib/gi18n.h>
#include <glib-unix.h>
#include <gio/gio.h>
#include <eel/eel-gtk-extensions.h>
#include <eel/eel-stock-dialogs.h>
Expand Down Expand Up @@ -534,6 +535,60 @@ nemo_application_init (NemoApplication *application)
g_object_unref (action);
}

/* Save session state once, from the last non-desktop window we find, and flush
* it: both callers are on their way out of the process, and an unflushed
* GSettings write dies with us.
*/
static void
save_last_window_session_state (NemoApplication *self)
{
GList *windows;
NemoWindow *last_window = NULL;

windows = gtk_application_get_windows (GTK_APPLICATION (self));

for (GList *l = windows; l != NULL; l = l->next) {
GtkWindow *w = GTK_WINDOW (l->data);

if (!NEMO_IS_WINDOW (w)) {
continue;
}

/* Avoid saving the desktop window */
if (NEMO_IS_DESKTOP_WINDOW (w)) {
continue;
}

last_window = NEMO_WINDOW (w);
break;
}

if (last_window != NULL) {
nemo_window_save_session_state (last_window);
g_settings_sync ();
}
}

/* Logging out terminates us with SIGTERM (SIGHUP if the session's terminal
* goes away first). Without this the session is never saved, because the
* window close and Quit paths never run.
*/
static gboolean
session_end_signal_cb (gpointer user_data)
{
static gboolean ending = FALSE;

/* Both signals can arrive; tear down once. */
if (ending) {
return G_SOURCE_REMOVE;
}
ending = TRUE;

nemo_application_quit (NEMO_APPLICATION (user_data));

return G_SOURCE_REMOVE;
}

void
nemo_application_quit (NemoApplication *self)
{
Expand All @@ -547,34 +602,10 @@ nemo_application_quit (NemoApplication *self)

GList *windows;

windows = gtk_application_get_windows (GTK_APPLICATION (app));

/* Save session state once, before we destroy all windows.
* Save the last non-desktop window we find. */
{
NemoWindow *last_window = NULL;

for (GList *l = windows; l != NULL; l = l->next) {
GtkWindow *w = GTK_WINDOW (l->data);

if (!NEMO_IS_WINDOW (w)) {
continue;
}

/* Avoid saving the desktop window */
if (NEMO_IS_DESKTOP_WINDOW (w)) {
continue;
}

last_window = NEMO_WINDOW (w);
break;
}

if (last_window != NULL) {
nemo_window_save_session_state (last_window);
}
}
/* Before we destroy all windows. */
save_last_window_session_state (self);

windows = gtk_application_get_windows (GTK_APPLICATION (app));
g_list_foreach (windows, (GFunc) gtk_widget_destroy, NULL);

/* we have been asked to force quit */
Expand All @@ -596,6 +627,10 @@ nemo_application_startup (GApplication *app)
/* initialize preferences and create the global GSettings objects */
nemo_global_preferences_init ();

/* save the session when the session manager ends it */
g_unix_signal_add (SIGTERM, session_end_signal_cb, self);
g_unix_signal_add (SIGHUP, session_end_signal_cb, self);

/* Run desktop- or main- specific things */
NEMO_APPLICATION_CLASS (G_OBJECT_GET_CLASS (self))->continue_startup (self);

Expand Down
40 changes: 39 additions & 1 deletion src/nemo-notebook.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,6 +316,39 @@ nemo_notebook_sync_tab_label (NemoNotebook *notebook,
}
}

void
nemo_notebook_sync_lock (NemoNotebook *notebook,
NemoWindowSlot *slot)
{
GtkWidget *tab_label, *lock_icon, *close_button;
gboolean locked;

g_return_if_fail (NEMO_IS_NOTEBOOK (notebook));
g_return_if_fail (NEMO_IS_WINDOW_SLOT (slot));

tab_label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (notebook),
GTK_WIDGET (slot));
if (tab_label == NULL) {
return;
}

lock_icon = GTK_WIDGET (g_object_get_data (G_OBJECT (tab_label), "lock-icon"));
close_button = GTK_WIDGET (g_object_get_data (G_OBJECT (tab_label), "close-button"));
g_return_if_fail (lock_icon != NULL && close_button != NULL);

locked = nemo_window_slot_is_locked (slot);

if (locked) {
gtk_widget_set_tooltip_text (lock_icon,
slot->lock_mode == NEMO_TAB_LOCK_NEW_TAB ?
_("Locked: folder changes open in a new tab") :
_("Locked: returns to this folder when reselected"));
}

gtk_widget_set_visible (lock_icon, locked);
gtk_widget_set_visible (close_button, !locked);
}

static void
close_button_clicked_cb (GtkWidget *widget,
NemoWindowSlot *slot)
Expand All @@ -331,7 +364,7 @@ close_button_clicked_cb (GtkWidget *widget,
static GtkWidget *
build_tab_label (NemoNotebook *nb, NemoWindowSlot *slot)
{
GtkWidget *hbox, *label, *close_button, *image, *spinner, *icon;
GtkWidget *hbox, *label, *close_button, *image, *spinner, *icon, *lock_icon;

/* set hbox spacing and label padding (see below) so that there's an
* equal amount of space around the label */
Expand All @@ -347,6 +380,10 @@ build_tab_label (NemoNotebook *nb, NemoWindowSlot *slot)
gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
/* don't show the icon */

/* setup padlock icon for locked tabs, hidden by default */
lock_icon = gtk_image_new_from_icon_name ("changes-prevent-symbolic", GTK_ICON_SIZE_MENU);
gtk_box_pack_start (GTK_BOX (hbox), lock_icon, FALSE, FALSE, 0);

/* setup label */
label = gtk_label_new (NULL);
gtk_label_set_width_chars (GTK_LABEL (label), 8);
Expand Down Expand Up @@ -383,6 +420,7 @@ build_tab_label (NemoNotebook *nb, NemoWindowSlot *slot)
g_object_set_data (G_OBJECT (hbox), "spinner", spinner);
g_object_set_data (G_OBJECT (hbox), "icon", icon);
g_object_set_data (G_OBJECT (hbox), "close-button", close_button);
g_object_set_data (G_OBJECT (hbox), "lock-icon", lock_icon);

return hbox;
}
Expand Down
2 changes: 2 additions & 0 deletions src/nemo-notebook.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ void nemo_notebook_sync_tab_label (NemoNotebook *nb,
NemoWindowSlot *slot);
void nemo_notebook_sync_loading (NemoNotebook *nb,
NemoWindowSlot *slot);
void nemo_notebook_sync_lock (NemoNotebook *nb,
NemoWindowSlot *slot);

void nemo_notebook_reorder_child_relative (NemoNotebook *notebook,
int page_num,
Expand Down
23 changes: 22 additions & 1 deletion src/nemo-window-manage-views.c
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,23 @@ nemo_window_slot_open_location_full (NemoWindowSlot *slot,
}
} else {
use_same |= g_settings_get_boolean (nemo_preferences, NEMO_PREFERENCES_ALWAYS_USE_BROWSER);

/* A tab locked in "new tab" mode never leaves its folder: divert the
* new location into a fresh, unlocked tab and leave this one alone.
*
* Search is exempt. It is a view of the locked folder rather than a
* move away from it, and its completion callback assumes the search
* landed in the slot that started it.
*/
if (nemo_window_slot_get_lock_mode (slot) == NEMO_TAB_LOCK_NEW_TAB &&
(flags & (NEMO_WINDOW_OPEN_FLAG_NEW_TAB |
NEMO_WINDOW_OPEN_FLAG_NEW_WINDOW |
NEMO_WINDOW_OPEN_FLAG_SEARCH)) == 0 &&
slot->location != NULL &&
!g_file_equal (slot->location, location)) {
flags |= NEMO_WINDOW_OPEN_FLAG_NEW_TAB;
use_same = TRUE;
}
}

g_assert (!((flags & NEMO_WINDOW_OPEN_FLAG_NEW_WINDOW) != 0 &&
Expand Down Expand Up @@ -1904,7 +1921,11 @@ nemo_window_back_or_forward (NemoWindow *window,
bookmark = g_list_nth_data (list, distance);
location = nemo_bookmark_get_location (bookmark);

if (flags != 0) {
/* Route a "new tab" locked slot through open_location, whose guard turns
* the history step into a new tab rather than moving the locked one.
*/
if (flags != 0 ||
nemo_window_slot_get_lock_mode (slot) == NEMO_TAB_LOCK_NEW_TAB) {
nemo_window_slot_open_location (slot, location, flags);
} else {
char *scroll_pos;
Expand Down
4 changes: 4 additions & 0 deletions src/nemo-window-menus.c
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ action_close_window_slot_callback (GtkAction *action,
window = NEMO_WINDOW (user_data);
slot = nemo_window_get_active_slot (window);

if (nemo_window_slot_is_locked (slot)) {
return;
}

nemo_window_pane_close_slot (slot->pane, slot);
}

Expand Down
Loading