terminal/src/cascadia/TerminalSettingsEditor/Launch.xaml
Schuyler Rosefield 13e9546bab
Persist window layout on window close (#10972)
This commit adds initial support for saving window layout on application
close.

Done:
- Add user setting for if tabs should be maintained.
- Added events to track the number of open windows for the monarch, and
  then save if you are the last window closing.
- Saves layout when the user explicitly hits the "Close Window" button.
- If the user manually closed all of their tabs (through the tab x
  button or through closing all panes on the tab) then remove any saved
  state.
- Saves in the ApplicationState file a list of actions the terminal can
  perform to restore its layout and the window size/position
  information.
- This saves an action to focus the correct pane, but this won't
  actually work without #10978. Note that if you have a pane zoomed, it
  does still zoom the correct pane, but when you unzoom it will have a
  different pane selected.

Todo:
- multiple windows? Right now it can only handle loading/saving one
  window.
   - PR #11083 will save multiple windows.
- This also sometimes runs into the existing bug where multiple tabs
  appear to be focused on opening.

Next Steps:
- The business logic of when the save is triggered can be adjusted as
  necessary.
- Right now I am taking the pragmatic approach and just saving the state
  as an array of objects, but only ever populate it with 1, that way
  saving multiple windows in the future could be added without breaking
  schema compatibility. Selfishly I'm hoping that handling multiple
  windows could be spun off into another pr/feature for now.
- One possible thing that can maybe be done is that the commandline can
  be augmented with a "--saved ##" attribute that would load from the
  nth saved state if it exists. e.g. if there are 3 saved windows, on
  first load it can spawn three wt --saved {0,1,2} that would reopen the
  windows? This way there also exists a way to load a copy of a previous
  window (if it is in the saved state).
- Is the application state something that is planned to be public/user
  editable? In theory the user could since it is just json, but I don't
  know what it buys them over just modifying their settings and
  startupActions.

Validation Steps Performed:
- The happy path: open terminal -> set setting to true -> close terminal
  -> reopen and see tabs. Tested with powershell/cmd/wsl windows.
- That closing all panes/tabs on their own will remove the saved
  session.
- Open multiple windows, close windows and confirm that the last window
  closed saves its state.

The generated file stores a sequence of actions that will be executed to
restore the terminal to its saved form.

References #8324
This is also one of the items on microsoft/terminal#5000
Closes #766
2021-09-08 22:44:53 +00:00

181 lines
9.8 KiB
XML

<!--
Copyright (c) Microsoft Corporation. All rights reserved. Licensed under
the MIT License. See LICENSE in the project root for license information.
-->
<Page x:Class="Microsoft.Terminal.Settings.Editor.Launch"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:SettingsModel="using:Microsoft.Terminal.Settings.Model"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Microsoft.Terminal.Settings.Editor"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
mc:Ignorable="d">
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="CommonResources.xaml" />
</ResourceDictionary.MergedDictionaries>
<DataTemplate x:Key="EnumRadioButtonTemplate"
x:DataType="local:EnumEntry">
<RadioButton Content="{x:Bind EnumName, Mode=OneWay}" />
</DataTemplate>
<SettingsModel:IconPathConverter x:Key="IconSourceConverter" />
<Style x:Key="LaunchSizeNumberBoxStyle"
BasedOn="{StaticResource NumberBoxSettingStyle}"
TargetType="muxc:NumberBox">
<Setter Property="SmallChange" Value="1" />
<Setter Property="LargeChange" Value="10" />
<Setter Property="Minimum" Value="1" />
</Style>
</ResourceDictionary>
</Page.Resources>
<ScrollViewer ViewChanging="ViewChanging">
<StackPanel>
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!-- Default Profile -->
<local:SettingContainer x:Uid="Globals_DefaultProfile"
Margin="0">
<ComboBox x:Name="DefaultProfile"
ItemsSource="{x:Bind DefaultProfiles}"
SelectedItem="{x:Bind CurrentDefaultProfile, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="SettingsModel:Profile">
<Grid HorizontalAlignment="Stretch"
ColumnSpacing="8">
<Grid.ColumnDefinitions>
<!-- icon -->
<ColumnDefinition Width="16" />
<!-- profile name -->
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<IconSourceElement Grid.Column="0"
Width="16"
Height="16"
IconSource="{x:Bind Icon, Mode=OneWay, Converter={StaticResource IconSourceConverter}}" />
<TextBlock Grid.Column="1"
Text="{x:Bind Name}" />
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</local:SettingContainer>
<!-- Default Terminal -->
<local:SettingContainer x:Name="DefaultTerminalDropdown"
x:Uid="Globals_DefaultTerminal"
x:Load="false">
<ComboBox x:Name="DefaultTerminal"
ItemsSource="{x:Bind State.Settings.DefaultTerminals, Mode=OneWay}"
SelectedItem="{x:Bind State.Settings.CurrentDefaultTerminal, Mode=TwoWay}"
Style="{StaticResource ComboBoxSettingStyle}">
<ComboBox.ItemTemplate>
<DataTemplate x:DataType="SettingsModel:DefaultTerminal">
<Grid HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
ColumnSpacing="8">
<Grid.ColumnDefinitions>
<!-- icon -->
<ColumnDefinition Width="24" />
<!-- profile name and author -->
<ColumnDefinition Width="*" />
<!-- version -->
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<!-- profile name -->
<RowDefinition Height="*" />
<!-- author and version -->
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<IconSourceElement Grid.Row="0"
Grid.RowSpan="2"
Grid.Column="0"
Width="24"
Height="24"
VerticalAlignment="Center"
IconSource="{x:Bind Icon, Mode=OneWay, Converter={StaticResource IconSourceConverter}}" />
<TextBlock Grid.Row="0"
Grid.Column="1"
Grid.ColumnSpan="2"
Text="{x:Bind Name}" />
<TextBlock Grid.Row="1"
Grid.Column="1"
Style="{ThemeResource SecondaryTextBlockStyle}"
Text="{x:Bind Author}" />
<TextBlock Grid.Row="1"
Grid.Column="2"
Style="{ThemeResource SecondaryTextBlockStyle}"
Text="{x:Bind Version}" />
</Grid>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</local:SettingContainer>
<!-- Start on User Login -->
<local:SettingContainer x:Uid="Globals_StartOnUserLogin">
<ToggleSwitch IsOn="{x:Bind State.Settings.GlobalSettings.StartOnUserLogin, Mode=TwoWay}" />
</local:SettingContainer>
<!-- First Window Behavior -->
<local:SettingContainer x:Uid="Globals_FirstWindowPreference"
Visibility="{x:Bind ShowFirstWindowPreference}">
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
ItemsSource="{x:Bind FirstWindowPreferenceList}"
SelectedItem="{x:Bind CurrentFirstWindowPreference, Mode=TwoWay}" />
</local:SettingContainer>
<!-- Launch Mode -->
<local:SettingContainer x:Uid="Globals_LaunchMode">
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
ItemsSource="{x:Bind LaunchModeList}"
SelectedItem="{x:Bind CurrentLaunchMode, Mode=TwoWay}" />
</local:SettingContainer>
<!-- Launch Mode -->
<local:SettingContainer x:Uid="Globals_WindowingBehavior">
<muxc:RadioButtons ItemTemplate="{StaticResource EnumRadioButtonTemplate}"
ItemsSource="{x:Bind WindowingBehaviorList}"
SelectedItem="{x:Bind CurrentWindowingBehavior, Mode=TwoWay}" />
</local:SettingContainer>
</StackPanel>
<!-- Launch Size -->
<StackPanel Style="{StaticResource SettingsStackStyle}">
<!-- Header -->
<TextBlock x:Uid="Globals_LaunchSize"
Style="{StaticResource SubtitleTextBlockStyle}" />
<!-- Columns -->
<local:SettingContainer x:Uid="Globals_InitialCols"
Margin="0">
<muxc:NumberBox Style="{StaticResource LaunchSizeNumberBoxStyle}"
Value="{x:Bind State.Settings.GlobalSettings.InitialCols, Mode=TwoWay}" />
</local:SettingContainer>
<!-- Rows -->
<local:SettingContainer x:Uid="Globals_InitialRows">
<muxc:NumberBox Style="{StaticResource LaunchSizeNumberBoxStyle}"
Value="{x:Bind State.Settings.GlobalSettings.InitialRows, Mode=TwoWay}" />
</local:SettingContainer>
</StackPanel>
</StackPanel>
</ScrollViewer>
</Page>