Add the ability to show the tab bar in fullscreen (#18171)

This PR allows users to enable the tab bar in fullscreen mode.

A new setting; "showTabsFullscreen"; has been added which accepts a
boolean value. When `true`, then the tab bar will remain visible when
the terminal app is fullscreen. If the value is `false` (default), then
the tab bar is hidden in fullscreen.

When the tab bar is visible in fullscreen, the min/max/close controls
are hidden to maintain the expected behaviour of a fullscreen app.

## Validation Steps Performed
All unit tests are passing.

Manually verified that when the "launchMode" setting is "fullscreen" and
the "showTabsFullscreen" setting is `true`, the tab bar is visible on
launch.

Manually verified that changing the setting at runtime causes the tab
bar to be shown/hidden immediately (if the terminal is currently
fullscreen).

Manually verified that the new "showTabsFullscreen" setting is honoured
regardless of whether "showTabsInTitlebar" is set to `true` or `false`.

Closes #11130
This commit is contained in:
Josh Johnson 2025-01-30 21:53:43 +00:00 committed by GitHub
parent 4da527c9b8
commit 27f775ee9e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 133 additions and 13 deletions

View File

@ -2532,6 +2532,11 @@
"description": "When set to true, the Terminal's tab row will display a shield icon when the Terminal is running with administrator privileges",
"type": "boolean"
},
"showTabsFullscreen": {
"default": false,
"description": "When set to true, tabs remain visible in fullscreen mode. When set to false, tabs will be hidden when entering fullscreen mode.",
"type": "boolean"
},
"useAcrylicInTabRow": {
"default": false,
"description": "When set to true, the tab row will have an acrylic material background with 50% opacity.",

View File

@ -243,10 +243,12 @@ namespace winrt::TerminalApp::implementation
// - Handle changes in tab layout.
void TerminalPage::_UpdateTabView()
{
// Never show the tab row when we're fullscreen. Otherwise:
// Show tabs when there's more than 1, or the user has chosen to always
// show the tab bar.
const auto isVisible = (!_isFullscreen && !_isInFocusMode) &&
// The tab row should only be visible if:
// - we're not in focus mode
// - we're not in full screen, or the user has enabled fullscreen tabs
// - there is more than one tab, or the user has chosen to always show tabs
const auto isVisible = !_isInFocusMode &&
(!_isFullscreen || _showTabsFullscreen) &&
(_settings.GlobalSettings().ShowTabsInTitlebar() ||
(_tabs.Size() > 1) ||
_settings.GlobalSettings().AlwaysShowTabs());

View File

@ -269,6 +269,7 @@ namespace winrt::TerminalApp::implementation
_layoutUpdatedRevoker = _tabContent.LayoutUpdated(winrt::auto_revoke, { this, &TerminalPage::_OnFirstLayout });
_isAlwaysOnTop = _settings.GlobalSettings().AlwaysOnTop();
_showTabsFullscreen = _settings.GlobalSettings().ShowTabsFullscreen();
// DON'T set up Toasts/TeachingTips here. They should be loaded and
// initialized the first time they're opened, in whatever method opens
@ -3599,6 +3600,8 @@ namespace winrt::TerminalApp::implementation
_isAlwaysOnTop = _settings.GlobalSettings().AlwaysOnTop();
AlwaysOnTopChanged.raise(*this, nullptr);
_showTabsFullscreen = _settings.GlobalSettings().ShowTabsFullscreen();
// Settings AllowDependentAnimations will affect whether animations are
// enabled application-wide, so we don't need to check it each time we
// want to create an animation.
@ -4023,6 +4026,37 @@ namespace winrt::TerminalApp::implementation
return _isAlwaysOnTop;
}
// Method Description:
// - Returns true if the tab row should be visible when we're in full screen
// state.
// Arguments:
// - <none>
// Return Value:
// - true if the tab row should be visible in full screen state
bool TerminalPage::ShowTabsFullscreen() const
{
return _showTabsFullscreen;
}
// Method Description:
// - Updates the visibility of the tab row when in fullscreen state.
void TerminalPage::SetShowTabsFullscreen(bool newShowTabsFullscreen)
{
if (_showTabsFullscreen == newShowTabsFullscreen)
{
return;
}
_showTabsFullscreen = newShowTabsFullscreen;
// if we're currently in fullscreen, update tab view to make
// sure tabs are given the correct visibility
if (_isFullscreen)
{
_UpdateTabView();
}
}
void TerminalPage::SetFullscreen(bool newFullscreen)
{
if (_isFullscreen == newFullscreen)

View File

@ -121,6 +121,8 @@ namespace winrt::TerminalApp::implementation
bool FocusMode() const;
bool Fullscreen() const;
bool AlwaysOnTop() const;
bool ShowTabsFullscreen() const;
void SetShowTabsFullscreen(bool newShowTabsFullscreen);
void SetFullscreen(bool);
void SetFocusMode(const bool inFocusMode);
void Maximized(bool newMaximized);
@ -228,6 +230,7 @@ namespace winrt::TerminalApp::implementation
bool _isFullscreen{ false };
bool _isMaximized{ false };
bool _isAlwaysOnTop{ false };
bool _showTabsFullscreen{ false };
std::optional<uint32_t> _loadFromPersistedLayoutIdx{};

View File

@ -289,6 +289,11 @@ namespace winrt::TerminalApp::implementation
return _settings.GlobalSettings().AlwaysOnTop();
}
bool TerminalWindow::GetInitialShowTabsFullscreen()
{
return _settings.GlobalSettings().ShowTabsFullscreen();
}
bool TerminalWindow::GetMinimizeToNotificationArea()
{
return _settings.GlobalSettings().MinimizeToNotificationArea();
@ -981,6 +986,11 @@ namespace winrt::TerminalApp::implementation
return _root ? _root->AlwaysOnTop() : false;
}
bool TerminalWindow::ShowTabsFullscreen() const
{
return _root ? _root->ShowTabsFullscreen() : false;
}
void TerminalWindow::SetSettingsStartupArgs(const std::vector<ActionAndArgs>& actions)
{
for (const auto& action : actions)

View File

@ -89,6 +89,7 @@ namespace winrt::TerminalApp::implementation
bool Fullscreen() const;
void Maximized(bool newMaximized);
bool AlwaysOnTop() const;
bool ShowTabsFullscreen() const;
bool AutoHideWindow();
void IdentifyWindow();
@ -106,6 +107,7 @@ namespace winrt::TerminalApp::implementation
Microsoft::Terminal::Settings::Model::LaunchMode GetLaunchMode();
bool GetShowTabsInTitlebar();
bool GetInitialAlwaysOnTop();
bool GetInitialShowTabsFullscreen();
float CalcSnappedDimension(const bool widthOrHeight, const float dimension) const;
Windows::UI::Xaml::UIElement GetRoot() noexcept;

View File

@ -69,6 +69,7 @@ namespace TerminalApp
void Maximized(Boolean newMaximized);
Boolean AlwaysOnTop { get; };
Boolean AutoHideWindow { get; };
Boolean ShowTabsFullscreen { get; };
void IdentifyWindow();
void SetPersistedLayoutIdx(UInt32 idx);
@ -82,6 +83,7 @@ namespace TerminalApp
Microsoft.Terminal.Settings.Model.LaunchMode GetLaunchMode();
Boolean GetShowTabsInTitlebar();
Boolean GetInitialAlwaysOnTop();
Boolean GetInitialShowTabsFullscreen();
Single CalcSnappedDimension(Boolean widthOrHeight, Single dimension);
void TitlebarClicked();
void CloseWindow();

View File

@ -12,6 +12,8 @@
#include "TitlebarControl.g.cpp"
using namespace winrt::Windows::UI::Xaml;
namespace winrt::TerminalApp::implementation
{
TitlebarControl::TitlebarControl(uint64_t handle) :
@ -77,6 +79,11 @@ namespace winrt::TerminalApp::implementation
}
}
void TitlebarControl::FullscreenChanged(const bool fullscreen)
{
MinMaxCloseControl().Visibility(fullscreen ? Visibility::Collapsed : Visibility::Visible);
}
void TitlebarControl::_OnMaximizeOrRestore(byte flag)
{
POINT point1 = {};

View File

@ -22,6 +22,7 @@ namespace winrt::TerminalApp::implementation
void SetWindowVisualState(WindowVisualState visualState);
void Root_SizeChanged(const IInspectable& sender, const Windows::UI::Xaml::SizeChangedEventArgs& e);
void FullscreenChanged(const bool fullscreen);
void Minimize_Click(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& e);
void Maximize_Click(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& e);

View File

@ -22,6 +22,7 @@ namespace TerminalApp
{
TitlebarControl(UInt64 parentWindowHandle);
void SetWindowVisualState(WindowVisualState visualState);
void FullscreenChanged(Boolean fullscreen);
void HoverButton(CaptionButton button);
void PressButton(CaptionButton button);

View File

@ -64,6 +64,12 @@
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Show tabs in full screen -->
<local:SettingContainer x:Uid="Globals_ShowTabsFullscreen">
<ToggleSwitch IsOn="{x:Bind ViewModel.ShowTabsFullscreen, Mode=TwoWay}"
Style="{StaticResource ToggleSwitchInExpanderStyle}" />
</local:SettingContainer>
<!-- Show Acrylic in Tab Row -->
<local:SettingContainer x:Uid="Globals_AcrylicTabRow">
<ToggleSwitch IsOn="{x:Bind ViewModel.UseAcrylicInTabRow, Mode=TwoWay}"

View File

@ -32,6 +32,7 @@ namespace winrt::Microsoft::Terminal::Settings::Editor::implementation
void ShowTitlebarToggled(const winrt::Windows::Foundation::IInspectable& sender, const winrt::Windows::UI::Xaml::RoutedEventArgs& args);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, AlwaysShowTabs);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, ShowTabsFullscreen);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, ShowTabsInTitlebar);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, UseAcrylicInTabRow);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(_GlobalSettings, ShowTitleInTitlebar);

View File

@ -26,6 +26,7 @@ namespace Microsoft.Terminal.Settings.Editor
void ShowTitlebarToggled(IInspectable sender, Windows.UI.Xaml.RoutedEventArgs args);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, AlwaysShowTabs);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, ShowTabsFullscreen);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, ShowTabsInTitlebar);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, UseAcrylicInTabRow);
PERMANENT_OBSERVABLE_PROJECTED_SETTING(Boolean, ShowTitleInTitlebar);

View File

@ -2280,6 +2280,14 @@
<value>Display a shield in the title bar when Windows Terminal is running as Administrator</value>
<comment>Header for a control to toggle displaying a shield in the title bar of the app. "Admin" refers to elevated sessions like "run as Admin"</comment>
</data>
<data name="Globals_ShowTabsFullscreen.Header" xml:space="preserve">
<value>Show tabs in full screen</value>
<comment>Header for a control to toggle if the app should show the tabs when in full screen state.</comment>
</data>
<data name="Globals_ShowTabsFullscreen.HelpText" xml:space="preserve">
<value>When enabled, the tab bar will be visible when the app is full screen.</value>
<comment>A description for what the "show tabs in full screen" setting does.</comment>
</data>
<data name="Profile_PathTranslationStyle.[using:Windows.UI.Xaml.Automation]AutomationProperties.Name" xml:space="preserve">
<value>Path translation</value>
<comment>Name for a control to select how file and directory paths are translated.</comment>

View File

@ -57,6 +57,7 @@ namespace Microsoft.Terminal.Settings.Model
INHERITABLE_SETTING(Int32, InitialRows);
INHERITABLE_SETTING(Int32, InitialCols);
INHERITABLE_SETTING(Boolean, AlwaysShowTabs);
INHERITABLE_SETTING(Boolean, ShowTabsFullscreen);
INHERITABLE_SETTING(NewTabPosition, NewTabPosition);
INHERITABLE_SETTING(Boolean, ShowTitleInTitlebar);
INHERITABLE_SETTING(Boolean, ConfirmCloseAllTabs);

View File

@ -68,7 +68,8 @@ Author(s):
X(bool, EnableUnfocusedAcrylic, "compatibility.enableUnfocusedAcrylic", true) \
X(winrt::Windows::Foundation::Collections::IVector<Model::NewTabMenuEntry>, NewTabMenu, "newTabMenu", winrt::single_threaded_vector<Model::NewTabMenuEntry>({ Model::RemainingProfilesEntry{} })) \
X(bool, AllowHeadless, "compatibility.allowHeadless", false) \
X(hstring, SearchWebDefaultQueryUrl, "searchWebDefaultQueryUrl", L"https://www.bing.com/search?q=%22%s%22")
X(hstring, SearchWebDefaultQueryUrl, "searchWebDefaultQueryUrl", L"https://www.bing.com/search?q=%22%s%22") \
X(bool, ShowTabsFullscreen, "showTabsFullscreen", false)
// Also add these settings to:
// * Profile.idl

View File

@ -193,6 +193,7 @@ void AppHost::Initialize()
_window->SetAlwaysOnTop(_windowLogic.GetInitialAlwaysOnTop());
_window->SetAutoHideWindow(_windowLogic.AutoHideWindow());
_window->SetShowTabsFullscreen(_windowLogic.GetInitialShowTabsFullscreen());
// MORE EVENT HANDLERS HERE!
// MAKE SURE THEY ARE ALL:
@ -1020,6 +1021,7 @@ void AppHost::_HandleSettingsChanged(const winrt::Windows::Foundation::IInspecta
_window->SetMinimizeToNotificationAreaBehavior(_windowLogic.GetMinimizeToNotificationArea());
_window->SetAutoHideWindow(_windowLogic.AutoHideWindow());
_window->SetShowTabsFullscreen(_windowLogic.ShowTabsFullscreen());
_updateTheme();
}

View File

@ -895,6 +895,11 @@ void IslandWindow::ShowWindowChanged(const bool showOrHide)
}
}
void IslandWindow::SetShowTabsFullscreen(const bool newShowTabsFullscreen)
{
_showTabsFullscreen = newShowTabsFullscreen;
}
// Method Description
// - Flash the taskbar icon, indicating to the user that something needs their attention
void IslandWindow::FlashTaskbar()

View File

@ -50,6 +50,7 @@ public:
void FullscreenChanged(const bool fullscreen);
void SetAlwaysOnTop(const bool alwaysOnTop);
void ShowWindowChanged(const bool showOrHide);
virtual void SetShowTabsFullscreen(const bool newShowTabsFullscreen);
void FlashTaskbar();
void SetTaskbarProgress(const size_t state, const size_t progress);
@ -109,6 +110,7 @@ protected:
bool _borderless{ false };
bool _alwaysOnTop{ false };
bool _fullscreen{ false };
bool _showTabsFullscreen{ false };
bool _fWasMaximizedBeforeFullscreen{ false };
RECT _rcWindowBeforeFullscreen{};
RECT _rcWorkBeforeFullscreen{};
@ -116,6 +118,7 @@ protected:
virtual void _SetIsBorderless(const bool borderlessEnabled);
virtual void _SetIsFullscreen(const bool fullscreenEnabled);
void _RestoreFullscreenPosition(const RECT& rcWork);
void _SetFullscreenPosition(const RECT& rcMonitor, const RECT& rcWork);

View File

@ -1129,7 +1129,7 @@ void NonClientIslandWindow::_SetIsBorderless(const bool borderlessEnabled)
// Method Description:
// - Enable or disable fullscreen mode. When entering fullscreen mode, we'll
// need to manually hide the entire titlebar.
// need to check whether to hide the titlebar.
// - See also IslandWindow::_SetIsFullscreen, which does additional work.
// Arguments:
// - fullscreenEnabled: If true, we're entering fullscreen mode. If false, we're leaving.
@ -1138,10 +1138,7 @@ void NonClientIslandWindow::_SetIsBorderless(const bool borderlessEnabled)
void NonClientIslandWindow::_SetIsFullscreen(const bool fullscreenEnabled)
{
IslandWindow::_SetIsFullscreen(fullscreenEnabled);
if (_titlebar)
{
_titlebar.Visibility(_IsTitlebarVisible() ? Visibility::Visible : Visibility::Collapsed);
}
_UpdateTitlebarVisibility();
// GH#4224 - When the auto-hide taskbar setting is enabled, then we don't
// always get another window message to trigger us to remove the drag bar.
// So, make sure to update the size of the drag region here, so that it
@ -1149,16 +1146,42 @@ void NonClientIslandWindow::_SetIsFullscreen(const bool fullscreenEnabled)
_ResizeDragBarWindow();
}
void NonClientIslandWindow::SetShowTabsFullscreen(const bool newShowTabsFullscreen)
{
IslandWindow::SetShowTabsFullscreen(newShowTabsFullscreen);
// don't waste time recalculating UI elements if we're not
// in fullscreen state - this setting doesn't affect other
// window states
if (_fullscreen)
{
_UpdateTitlebarVisibility();
}
}
void NonClientIslandWindow::_UpdateTitlebarVisibility()
{
if (!_titlebar)
{
return;
}
const auto showTitlebar = _IsTitlebarVisible();
_titlebar.Visibility(showTitlebar ? Visibility::Visible : Visibility::Collapsed);
_titlebar.FullscreenChanged(_fullscreen);
}
// Method Description:
// - Returns true if the titlebar is visible. For things like fullscreen mode,
// borderless mode (aka "focus mode"), this will return false.
// - Returns true if the titlebar is visible. For borderless mode (aka "focus mode"),
// this will return false. For fullscreen, this will return false unless the user
// has enabled fullscreen tabs.
// Arguments:
// - <none>
// Return Value:
// - true iff the titlebar is visible
bool NonClientIslandWindow::_IsTitlebarVisible() const
{
return !(_fullscreen || _borderless);
return !_borderless && (!_fullscreen || _showTabsFullscreen);
}
void NonClientIslandWindow::SetTitlebarBackground(winrt::Windows::UI::Xaml::Media::Brush brush)

View File

@ -46,6 +46,7 @@ public:
void OnApplicationThemeChanged(const winrt::Windows::UI::Xaml::ElementTheme& requestedTheme) override;
void SetTitlebarBackground(winrt::Windows::UI::Xaml::Media::Brush brush);
void SetShowTabsFullscreen(const bool newShowTabsFullscreen) override;
virtual void UseMica(const bool newValue, const double titlebarOpacity) override;
@ -92,6 +93,7 @@ private:
void _UpdateFrameMargins() const noexcept;
void _UpdateMaximizedState();
void _UpdateIslandPosition(const UINT windowWidth, const UINT windowHeight);
void _UpdateTitlebarVisibility();
struct Revokers
{