Skip to content

Commit

Permalink
Add the ability to show the tab bar in fullscreen (#18171)
Browse files Browse the repository at this point in the history
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
  • Loading branch information
GeekJosh authored Jan 30, 2025
1 parent 4da527c commit 27f775e
Show file tree
Hide file tree
Showing 21 changed files with 133 additions and 13 deletions.
5 changes: 5 additions & 0 deletions doc/cascadia/profiles.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
Expand Down
10 changes: 6 additions & 4 deletions src/cascadia/TerminalApp/TabManagement.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down
34 changes: 34 additions & 0 deletions src/cascadia/TerminalApp/TerminalPage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/TerminalApp/TerminalPage.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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{};

Expand Down
10 changes: 10 additions & 0 deletions src/cascadia/TerminalApp/TerminalWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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)
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/TerminalWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/TerminalApp/TerminalWindow.idl
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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();
Expand Down
7 changes: 7 additions & 0 deletions src/cascadia/TerminalApp/TitlebarControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@

#include "TitlebarControl.g.cpp"

using namespace winrt::Windows::UI::Xaml;

namespace winrt::TerminalApp::implementation
{
TitlebarControl::TitlebarControl(uint64_t handle) :
Expand Down Expand Up @@ -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 = {};
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/TitlebarControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalApp/TitlebarControl.idl
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
6 changes: 6 additions & 0 deletions src/cascadia/TerminalSettingsEditor/GlobalAppearance.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -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}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
1 change: 1 addition & 0 deletions src/cascadia/TerminalSettingsModel/GlobalAppSettings.idl
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion src/cascadia/TerminalSettingsModel/MTSMSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/WindowsTerminal/AppHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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();
}

Expand Down
5 changes: 5 additions & 0 deletions src/cascadia/WindowsTerminal/IslandWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down
3 changes: 3 additions & 0 deletions src/cascadia/WindowsTerminal/IslandWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class IslandWindow :
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);
Expand Down Expand Up @@ -109,13 +110,15 @@ class IslandWindow :
bool _borderless{ false };
bool _alwaysOnTop{ false };
bool _fullscreen{ false };
bool _showTabsFullscreen{ false };
bool _fWasMaximizedBeforeFullscreen{ false };
RECT _rcWindowBeforeFullscreen{};
RECT _rcWorkBeforeFullscreen{};
UINT _dpiBeforeFullscreen{ 96 };

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);

Expand Down
39 changes: 31 additions & 8 deletions src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -1138,27 +1138,50 @@ 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
// _definitely_ goes away.
_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)
Expand Down
2 changes: 2 additions & 0 deletions src/cascadia/WindowsTerminal/NonClientIslandWindow.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ class NonClientIslandWindow : public IslandWindow
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;

Expand Down Expand Up @@ -92,6 +93,7 @@ class NonClientIslandWindow : public IslandWindow
void _UpdateFrameMargins() const noexcept;
void _UpdateMaximizedState();
void _UpdateIslandPosition(const UINT windowWidth, const UINT windowHeight);
void _UpdateTitlebarVisibility();

struct Revokers
{
Expand Down

0 comments on commit 27f775e

Please sign in to comment.