diff --git a/src/Application.vala b/src/Application.vala index 311dc0a5b8..619874f9d5 100644 --- a/src/Application.vala +++ b/src/Application.vala @@ -107,9 +107,9 @@ public class Terminal.Application : Gtk.Application { if (options.lookup ("working-directory", "^&ay", out working_directory)) { if (working_directory != "\0") { Environment.set_current_dir (working_directory); // will be sent via platform-data + // Need to know in commandline () whether this option was present and valid so do not remove + // options.remove ("working-directory"); } - - options.remove ("working-directory"); } if (options.lookup (OPTION_REMAINING, "^a&ay", out args)) { @@ -217,17 +217,15 @@ public class Terminal.Application : Gtk.Application { unowned var options = command_line.get_options_dict (); var window = (MainWindow) active_window; bool new_window; - - if (window == null || options.lookup ("new-window", "b", out new_window) && new_window) { - /* Uncertain whether tabs should be restored when app is launched with working directory from commandline. - * Currently they are set to restore (subject to the restore-tabs setting). - * If it is desired that tabs should never be restored in these circimstances add another check below. - */ - bool restore_tabs = !("commandline" in options || "execute" in options) || window == null; - window = new MainWindow (this, restore_tabs); + if (window == null || + options.lookup ("new-window", "b", out new_window) && new_window) { + window = new MainWindow (this); } - unowned var working_directory = command_line.get_cwd (); + unowned string working_directory; + var wd_was_requested = options.lookup ("working-directory", "^&ay", out working_directory); + working_directory = command_line.get_cwd (); + unowned string[] commands; unowned string command; bool new_tab, minimized; @@ -237,15 +235,20 @@ public class Terminal.Application : Gtk.Application { if (options.lookup ("execute", "^a&ay", out commands)) { for (var i = 0; commands[i] != null; i++) { if (commands[i] != "\0") { - window.add_tab_with_working_directory (working_directory, commands[i], new_tab); + window.add_tab_with_working_directory (working_directory, commands[i]); } } } else if (options.lookup ("commandline", "^&ay", out command) && command != "\0") { - window.add_tab_with_working_directory (working_directory, command, new_tab); - } else { - window.add_tab_with_working_directory (working_directory, null, new_tab); + window.add_tab_with_working_directory (working_directory, command); + } else if (wd_was_requested) { + window.add_tab_with_working_directory (working_directory, null); + } else if (new_tab) { + window.add_tab_with_working_directory (working_directory, null); //FIXME Should we honor "follow-last-tab" setting? } + // Only if no other tabs, add default tab (can happen if trying to execute invalid commands) + add_default_tab (window, false); + if (options.lookup ("minimized", "b", out minimized) && minimized) { window.iconify (); } else { @@ -264,7 +267,15 @@ public class Terminal.Application : Gtk.Application { } private void new_window () { - new MainWindow (this, active_window == null).present (); + var window = new MainWindow (this); + add_default_tab (window, false); + window.present (); + } + + private void add_default_tab (MainWindow window, bool force) { + if (force || window.terminals.length () == 0) { + window.actions.activate_action (window.ACTION_NEW_TAB, null); + } } private void close () { diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 34622dc090..d3a8e80f3f 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -28,6 +28,7 @@ namespace Terminal { private Gtk.ToggleButton search_button; private Dialogs.ColorPreferences? color_preferences_dialog; private Granite.AccelLabel open_in_browser_menuitem_label; + private bool tabs_were_restored = false; private HashTable restorable_terminals; private bool is_fullscreen = false; @@ -41,7 +42,6 @@ namespace Terminal { public bool unsafe_ignored; public bool focus_restored_tabs { get; construct; default = true; } - public bool recreate_tabs { get; construct; default = true; } public bool restore_pos { get; construct; default = true; } public uint focus_timeout { get; private set; default = 0;} public Gtk.Menu menu { get; private set; } @@ -105,30 +105,19 @@ namespace Terminal { { ACTION_OPEN_IN_BROWSER, action_open_in_browser } }; - public MainWindow (Terminal.Application app, bool recreate_tabs = true) { + public MainWindow (Terminal.Application app) { Object ( - app: app, - recreate_tabs: recreate_tabs + app: app ); - - if (!recreate_tabs) { - new_tab (""); - } } - public MainWindow.with_coords (Terminal.Application app, int x, int y, - bool recreate_tabs, bool ensure_tab) { + public MainWindow.with_coords (Terminal.Application app, int x, int y) { Object ( app: app, - restore_pos: false, - recreate_tabs: recreate_tabs + restore_pos: false ); move (x, y); - - if (!recreate_tabs && ensure_tab) { - new_tab (""); - } } static construct { @@ -259,28 +248,17 @@ namespace Terminal { restorable_terminals = new HashTable (str_hash, str_equal); - if (recreate_tabs) { - open_tabs (); + if (app.get_windows ().length () == 1) { + open_saved_tabs (); } } - public void add_tab_with_working_directory (string? directory, string? command = null, bool create_new_tab = false) { + public void add_tab_with_working_directory (string location, string? command = null) { /* This requires all restored tabs to be initialized first so that the shell location is available */ - /* Do not add a new tab if location is already open in existing tab */ - string? location = null; - - if (directory == null || directory == "") { - if (notebook.tabs.first () == null || command != null || create_new_tab) { //Ensure at least one tab - new_tab ("", command); - } - - return; - } else { - location = directory; - } + /* Does not add a new tab if location is already open in existing tab */ /* We can match existing tabs only if there is no command and create_new_tab == false */ - if (command == null && !create_new_tab) { + if (command == null && location != null) { var file = File.new_for_commandline_arg (location); foreach (Granite.Widgets.Tab tab in notebook.tabs) { var terminal_widget = get_term_widget (tab); @@ -295,7 +273,7 @@ namespace Terminal { } } - new_tab (location, command); + new_tab (location, command); // Always execute command in new tab } /** Returns true if the code parameter matches the keycode of the keyval parameter for @@ -550,7 +528,8 @@ namespace Terminal { } private void restore_saved_state (bool restore_pos = true) { - if (Granite.Services.System.history_is_enabled () && + if (!tabs_were_restored && // Only restore tabs once + Granite.Services.System.history_is_enabled () && Application.settings.get_boolean ("remember-tabs")) { saved_tabs = Terminal.Application.saved_state.get_strv ("tabs"); @@ -659,9 +638,7 @@ namespace Terminal { var new_window = new MainWindow.with_coords ( app, x, - y, - false, - false + y ); var terminal_widget = get_term_widget (tab); @@ -822,7 +799,7 @@ namespace Terminal { current_terminal.grab_focus (); } - private void open_tabs () { + private void open_saved_tabs () { string[] tabs = {}; double[] zooms = {}; int focus = 0; @@ -831,12 +808,12 @@ namespace Terminal { if (Granite.Services.System.history_is_enabled () && Application.settings.get_boolean ("remember-tabs")) { + tabs_were_restored = true; // An attempt was made to restore. tabs = saved_tabs; var n_tabs = tabs.length; if (n_tabs == 0) { - tabs += Environment.get_home_dir (); - zooms += default_zoom; + return; } else { foreach (unowned string zoom_s in saved_zooms) { var zoom = double.parse (zoom_s); // Locale independent @@ -854,9 +831,6 @@ namespace Terminal { } focus = Terminal.Application.saved_state.get_int ("focused-tab"); - } else { - tabs += Environment.get_current_dir (); - zooms += default_zoom; } assert (zooms.length == tabs.length); @@ -869,10 +843,6 @@ namespace Terminal { null_dirs++; tabs[i] = ""; } - - if (null_dirs == tabs.length) { - tabs[0] = Environment.get_current_dir (); - } } Terminal.Application.saved_state.set_strv ("tabs", {}); @@ -896,7 +866,7 @@ namespace Terminal { index++; } - if (focus_restored_tabs) { + if (index > 0 && focus_restored_tabs) { var tab = notebook.get_tab_by_index (focus.clamp (0, notebook.n_tabs - 1)); notebook.current = tab; get_term_widget (tab).grab_focus (); @@ -920,8 +890,10 @@ namespace Terminal { var tab = create_tab ( - location != null ? Path.get_basename (location) : TerminalWidget.DEFAULT_LABEL, - null, terminal_widget); //Set correct label now to avoid race when spawning shell + Path.get_basename (location), + null, + terminal_widget + ); //Set correct label now to avoid race when spawning shell terminal_widget.child_exited.connect (() => { if (!terminal_widget.killed) { @@ -1189,7 +1161,11 @@ namespace Terminal { private void action_new_tab () { if (Application.settings.get_boolean ("follow-last-tab")) { - new_tab (current_terminal.get_shell_location ()); + if (current_terminal != null) { + new_tab (current_terminal.get_shell_location ()); + } else { + new_tab (Environment.get_current_dir ()); + } } else { new_tab (Environment.get_home_dir ()); } @@ -1348,8 +1324,8 @@ namespace Terminal { string[] opened_tabs = {}; string[] zooms = {}; + // The last closed window will override the settings for any previously closed window Application.saved_state.set_double ("zoom", current_terminal.font_scale); - if (Granite.Services.System.history_is_enabled () && Application.settings.get_boolean ("remember-tabs")) { @@ -1362,22 +1338,22 @@ namespace Terminal { } } }); - } - Terminal.Application.saved_state.set_strv ( - "tabs", - opened_tabs - ); + Terminal.Application.saved_state.set_strv ( + "tabs", + opened_tabs + ); - Terminal.Application.saved_state.set_strv ( - "tab-zooms", - zooms - ); + Terminal.Application.saved_state.set_strv ( + "tab-zooms", + zooms + ); - Terminal.Application.saved_state.set_int ( - "focused-tab", - notebook.current != null ? notebook.get_tab_position (notebook.current) : 0 - ); + Terminal.Application.saved_state.set_int ( + "focused-tab", + notebook.current != null ? notebook.get_tab_position (notebook.current) : 0 + ); + } } /** Return enough of @path to distinguish it from @conflict_path **/ diff --git a/src/tests/Application.vala b/src/tests/Application.vala index df88c9dd62..3e6733a2bc 100644 --- a/src/tests/Application.vala +++ b/src/tests/Application.vala @@ -47,13 +47,20 @@ namespace Terminal.Test.Application { } } - private void option (string options, string platform_data, CommandLineCallback callback) { + private void option ( + string options, + string platform_data, + CommandLineCallback callback, + bool create_default_window_first = true + ) { ulong oneshot = 0; setup (); oneshot = application.command_line.connect ((nil) => { application.disconnect (oneshot); - application.command_line (nil); + if (create_default_window_first) { + application.command_line (nil); + } var cmdline = (ApplicationCommandLine) Object.new ( typeof (ApplicationCommandLine), @@ -145,39 +152,40 @@ namespace Terminal.Test.Application { unowned var window = (MainWindow) application.active_window; assert_nonnull (window); var n_tabs = (int) window.terminals.length (); - assert_cmpint (n_tabs, CompareOperator.EQ, 2); - }); + assert_cmpint (n_tabs, CompareOperator.EQ, 1); + }, false); option ("{'new-tab':}", "@a{sv} {}", () => { unowned var window = (MainWindow) application.active_window; assert_nonnull (window); var n_tabs = (int) window.terminals.length (); assert_cmpint (n_tabs, CompareOperator.EQ, 1); - }); + }, false); }); GLib.Test.add_func ("/application/command-line/new-window", () => { option ("{'new-window':}", "@a{sv} {}", () => { var n_windows = (int) application.get_windows ().length (); assert_cmpint (n_windows, CompareOperator.EQ, 2); - }); + }, true); option ("{'new-window':}", "@a{sv} {}", () => { var n_windows = (int) application.get_windows ().length (); assert_cmpint (n_windows, CompareOperator.EQ, 1); - }); + }, false); }); GLib.Test.add_func ("/application/command-line/execute", () => { - string[] execute = { "true", "echo test", "echo -e te\\tst", "false" }; + string[] execute = { "true", "echo test", "echo -e te\\tst", "false" }; // 4 commands // valid option ("{'execute':<[b'%s']>}".printf (string.joinv ("',b'", execute)), "@a{sv} {}", () => { + debug ("execute callback"); unowned var window = (MainWindow) application.active_window; assert_nonnull (window); var n_tabs = (int) window.terminals.length (); - assert_cmpint (n_tabs, CompareOperator.EQ, 5); // include the guaranted extra tab - }); + assert_cmpint (n_tabs, CompareOperator.EQ, 4); + }, false); // invalid option ("{'execute':<[b'',b'',b'']>}", "@a{sv} {}", () => { @@ -185,7 +193,7 @@ namespace Terminal.Test.Application { assert_nonnull (window); var n_tabs = (int) window.terminals.length (); assert_cmpint (n_tabs, CompareOperator.EQ, 1); - }); + }, false); }); //FIXME: cannot test the commandline option without a way to get the terminal command