From d5fe6514eb842116ed3194a754ac70a3b0eca016 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 26 Jun 2020 11:25:37 -0500 Subject: [PATCH 01/13] Proof of concept, borderless for the NCIW. Need to do IW, and borderless<->Fullscreen still --- src/cascadia/TerminalApp/ActionAndArgs.cpp | 2 + .../TerminalApp/AppActionHandlers.cpp | 7 +++ src/cascadia/TerminalApp/AppLogic.h | 1 + src/cascadia/TerminalApp/AppLogic.idl | 1 + .../TerminalApp/ShortcutActionDispatch.cpp | 5 ++ .../TerminalApp/ShortcutActionDispatch.h | 1 + .../TerminalApp/ShortcutActionDispatch.idl | 2 + src/cascadia/TerminalApp/TerminalPage.cpp | 20 ++++++- src/cascadia/TerminalApp/TerminalPage.h | 4 ++ src/cascadia/TerminalApp/TerminalPage.idl | 2 + src/cascadia/WindowsTerminal/AppHost.cpp | 7 +++ src/cascadia/WindowsTerminal/AppHost.h | 2 + src/cascadia/WindowsTerminal/IslandWindow.cpp | 54 +++++++++++++++++++ src/cascadia/WindowsTerminal/IslandWindow.h | 3 ++ .../WindowsTerminal/NonClientIslandWindow.cpp | 22 ++++++-- .../WindowsTerminal/NonClientIslandWindow.h | 3 +- 16 files changed, 131 insertions(+), 5 deletions(-) diff --git a/src/cascadia/TerminalApp/ActionAndArgs.cpp b/src/cascadia/TerminalApp/ActionAndArgs.cpp index b69dd978694..30f081b9dbb 100644 --- a/src/cascadia/TerminalApp/ActionAndArgs.cpp +++ b/src/cascadia/TerminalApp/ActionAndArgs.cpp @@ -32,6 +32,7 @@ static constexpr std::string_view SplitPaneKey{ "splitPane" }; static constexpr std::string_view ResizePaneKey{ "resizePane" }; static constexpr std::string_view MoveFocusKey{ "moveFocus" }; static constexpr std::string_view FindKey{ "find" }; +static constexpr std::string_view ToggleBorderlessKey{ "toggleBorderless" }; static constexpr std::string_view ToggleFullscreenKey{ "toggleFullscreen" }; static constexpr std::string_view SetTabColorKey{ "setTabColor" }; static constexpr std::string_view OpenTabColorPickerKey{ "openTabColorPicker" }; @@ -69,6 +70,7 @@ namespace winrt::TerminalApp::implementation { ResizePaneKey, ShortcutAction::ResizePane }, { MoveFocusKey, ShortcutAction::MoveFocus }, { OpenSettingsKey, ShortcutAction::OpenSettings }, + { ToggleBorderlessKey, ShortcutAction::ToggleBorderless }, { ToggleFullscreenKey, ShortcutAction::ToggleFullscreen }, { SplitPaneKey, ShortcutAction::SplitPane }, { SetTabColorKey, ShortcutAction::SetTabColor }, diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 1f1ab072416..ec59c92dabe 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -231,6 +231,13 @@ namespace winrt::TerminalApp::implementation args.Handled(true); } + void TerminalPage::_HandleToggleBorderless(const IInspectable& /*sender*/, + const TerminalApp::ActionEventArgs& args) + { + ToggleBorderless(); + args.Handled(true); + } + void TerminalPage::_HandleToggleFullscreen(const IInspectable& /*sender*/, const TerminalApp::ActionEventArgs& args) { diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index 1d1641ba3d0..6f1ab794733 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -103,6 +103,7 @@ namespace winrt::TerminalApp::implementation FORWARDED_TYPED_EVENT(SetTitleBarContent, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::UIElement, _root, SetTitleBarContent); FORWARDED_TYPED_EVENT(TitleChanged, winrt::Windows::Foundation::IInspectable, winrt::hstring, _root, TitleChanged); FORWARDED_TYPED_EVENT(LastTabClosed, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs, _root, LastTabClosed); + FORWARDED_TYPED_EVENT(ToggleBorderless, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleBorderlessEventArgs, _root, ToggleBorderless); FORWARDED_TYPED_EVENT(ToggleFullscreen, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleFullscreenEventArgs, _root, ToggleFullscreen); }; } diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index 3c8a4fedf66..f08fba8b119 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -55,5 +55,6 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler LastTabClosed; event Windows.Foundation.TypedEventHandler RequestedThemeChanged; event Windows.Foundation.TypedEventHandler ToggleFullscreen; + event Windows.Foundation.TypedEventHandler ToggleBorderless; } } diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp index 682b2a4594a..c94135b5375 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp @@ -154,6 +154,11 @@ namespace winrt::TerminalApp::implementation _ResetFontSizeHandlers(*this, *eventArgs); break; } + case ShortcutAction::ToggleBorderless: + { + _ToggleBorderlessHandlers(*this, *eventArgs); + break; + } case ShortcutAction::ToggleFullscreen: { _ToggleFullscreenHandlers(*this, *eventArgs); diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.h b/src/cascadia/TerminalApp/ShortcutActionDispatch.h index 422858a0e17..40233f25728 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.h +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.h @@ -46,6 +46,7 @@ namespace winrt::TerminalApp::implementation TYPED_EVENT(ResizePane, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(Find, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(MoveFocus, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(ToggleBorderless, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(ToggleFullscreen, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(SetTabColor, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(OpenTabColorPicker,TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl index a09390ebaee..cbd4a2c962d 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl @@ -31,6 +31,7 @@ namespace TerminalApp ResizePane, MoveFocus, Find, + ToggleBorderless, ToggleFullscreen, SetTabColor, OpenTabColorPicker, @@ -72,6 +73,7 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler ResizePane; event Windows.Foundation.TypedEventHandler Find; event Windows.Foundation.TypedEventHandler MoveFocus; + event Windows.Foundation.TypedEventHandler ToggleBorderless; event Windows.Foundation.TypedEventHandler ToggleFullscreen; event Windows.Foundation.TypedEventHandler SetTabColor; event Windows.Foundation.TypedEventHandler OpenTabColorPicker; diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index ccb7cbcd124..f1202d45f69 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -764,6 +764,7 @@ namespace winrt::TerminalApp::implementation _actionDispatch->AdjustFontSize({ this, &TerminalPage::_HandleAdjustFontSize }); _actionDispatch->Find({ this, &TerminalPage::_HandleFind }); _actionDispatch->ResetFontSize({ this, &TerminalPage::_HandleResetFontSize }); + _actionDispatch->ToggleBorderless({ this, &TerminalPage::_HandleToggleBorderless }); _actionDispatch->ToggleFullscreen({ this, &TerminalPage::_HandleToggleFullscreen }); _actionDispatch->SetTabColor({ this, &TerminalPage::_HandleSetTabColor }); _actionDispatch->OpenTabColorPicker({ this, &TerminalPage::_HandleOpenTabColorPicker }); @@ -824,7 +825,7 @@ namespace winrt::TerminalApp::implementation // 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 bool isVisible = (!_isFullscreen) && + const bool isVisible = (!_isFullscreen && !_isBorderless) && (_settings->GlobalSettings().ShowTabsInTitlebar() || (_tabs.Size() > 1) || _settings->GlobalSettings().AlwaysShowTabs()); @@ -1847,6 +1848,22 @@ namespace winrt::TerminalApp::implementation termControl.CreateSearchBoxControl(); } + // Method Description: + // - Toggles borderless mode. Hides the tab row, and raises our + // ToggleBorderless event. + // Arguments: + // - + // Return Value: + // - + void TerminalPage::ToggleBorderless() + { + _toggleBorderlessHandlers(*this, nullptr); + + _isBorderless = !_isBorderless; + + _UpdateTabView(); + } + // Method Description: // - Toggles fullscreen mode. Hides the tab row, and raises our // ToggleFullscreen event. @@ -2048,5 +2065,6 @@ namespace winrt::TerminalApp::implementation DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, LastTabClosed, _lastTabClosedHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs); DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, SetTitleBarContent, _setTitleBarContentHandlers, winrt::Windows::Foundation::IInspectable, UIElement); DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, ShowDialog, _showDialogHandlers, winrt::Windows::Foundation::IInspectable, WUX::Controls::ContentDialog); + DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, ToggleBorderless, _toggleBorderlessHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleBorderlessEventArgs); DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, ToggleFullscreen, _toggleFullscreenHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleFullscreenEventArgs); } diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index e6eb55d63d3..27c6c7a0d32 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -49,6 +49,7 @@ namespace winrt::TerminalApp::implementation void CloseWindow(); + void ToggleBorderless(); void ToggleFullscreen(); void SetStartupActions(std::deque& actions); @@ -58,6 +59,7 @@ namespace winrt::TerminalApp::implementation DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(LastTabClosed, _lastTabClosedHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTitleBarContent, _setTitleBarContentHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::UIElement); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(ShowDialog, _showDialogHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::Controls::ContentDialog); + DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(ToggleBorderless, _toggleBorderlessHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleBorderlessEventArgs); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(ToggleFullscreen, _toggleFullscreenHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleFullscreenEventArgs); TYPED_EVENT(Initialized, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::RoutedEventArgs); @@ -81,6 +83,7 @@ namespace winrt::TerminalApp::implementation winrt::com_ptr _GetStrongTabImpl(const uint32_t index) const; winrt::com_ptr _GetStrongTabImpl(const ::winrt::TerminalApp::Tab& tab) const; + bool _isBorderless{ false }; bool _isFullscreen{ false }; bool _rearranging; @@ -197,6 +200,7 @@ namespace winrt::TerminalApp::implementation void _HandleAdjustFontSize(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleFind(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleResetFontSize(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); + void _HandleToggleBorderless(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleToggleFullscreen(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleSetTabColor(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleOpenTabColorPicker(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); diff --git a/src/cascadia/TerminalApp/TerminalPage.idl b/src/cascadia/TerminalApp/TerminalPage.idl index d02450fa04e..ab0b41e28ec 100644 --- a/src/cascadia/TerminalApp/TerminalPage.idl +++ b/src/cascadia/TerminalApp/TerminalPage.idl @@ -5,6 +5,7 @@ namespace TerminalApp { delegate void LastTabClosedEventArgs(); delegate void ToggleFullscreenEventArgs(); + delegate void ToggleBorderlessEventArgs(); [default_interface] runtimeclass TerminalPage : Windows.UI.Xaml.Controls.Page { @@ -19,6 +20,7 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler SetTitleBarContent; event Windows.Foundation.TypedEventHandler ShowDialog; event Windows.Foundation.TypedEventHandler ToggleFullscreen; + event Windows.Foundation.TypedEventHandler ToggleBorderless; event Windows.Foundation.TypedEventHandler Initialized; } } diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index b88a21cd9e0..397be92772c 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -157,6 +157,7 @@ void AppHost::Initialize() _logic.RequestedThemeChanged({ this, &AppHost::_UpdateTheme }); _logic.ToggleFullscreen({ this, &AppHost::_ToggleFullscreen }); + _logic.ToggleBorderless({ this, &AppHost::_ToggleBorderless }); _logic.Create(); @@ -352,6 +353,12 @@ void AppHost::_UpdateTheme(const winrt::Windows::Foundation::IInspectable&, cons _window->OnApplicationThemeChanged(arg); } +void AppHost::_ToggleBorderless(const winrt::Windows::Foundation::IInspectable&, + const winrt::TerminalApp::ToggleBorderlessEventArgs&) +{ + _window->ToggleBorderless(); +} + void AppHost::_ToggleFullscreen(const winrt::Windows::Foundation::IInspectable&, const winrt::TerminalApp::ToggleFullscreenEventArgs&) { diff --git a/src/cascadia/WindowsTerminal/AppHost.h b/src/cascadia/WindowsTerminal/AppHost.h index 4fefd567a97..3e6288575ec 100644 --- a/src/cascadia/WindowsTerminal/AppHost.h +++ b/src/cascadia/WindowsTerminal/AppHost.h @@ -33,6 +33,8 @@ class AppHost const winrt::Windows::UI::Xaml::UIElement& arg); void _UpdateTheme(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::UI::Xaml::ElementTheme& arg); + void _ToggleBorderless(const winrt::Windows::Foundation::IInspectable& sender, + const winrt::TerminalApp::ToggleBorderlessEventArgs& arg); void _ToggleFullscreen(const winrt::Windows::Foundation::IInspectable& sender, const winrt::TerminalApp::ToggleFullscreenEventArgs& arg); void _WindowMouseWheeled(const til::point coord, const int32_t delta); diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 59508166e6d..bfdd961bb2b 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -441,6 +441,17 @@ void IslandWindow::OnApplicationThemeChanged(const winrt::Windows::UI::Xaml::Ele ::InvalidateRect(_window.get(), nullptr, false); } +// Method Description: +// - Toggles our fullscreen state. See _SetIsFullscreen for more details. +// Arguments: +// - +// Return Value: +// - +void IslandWindow::ToggleBorderless() +{ + _SetIsBorderless(!_borderless); +} + // Method Description: // - Toggles our fullscreen state. See _SetIsFullscreen for more details. // Arguments: @@ -471,6 +482,49 @@ void _SetWindowLongWHelper(const HWND hWnd, const int nIndex, const LONG dwNewLo } } +void IslandWindow::_SetIsBorderless(const bool borderlessEnabled) +{ + // It is possible to enter _SetIsFullscreen even if we're already in full + // screen. Use the old is in fullscreen flag to gate checks that rely on the + // current state. + // const auto oldIsInBorderless = _borderless; + _borderless = borderlessEnabled; + + HWND const hWnd = GetHandle(); + + // First, modify regular window styles as appropriate + auto windowStyle = GetWindowLongW(hWnd, GWL_STYLE); + + // When moving to fullscreen, remove WS_OVERLAPPEDWINDOW, which specifies + // styles for non-fullscreen windows (e.g. caption bar), and add the + // WS_POPUP style to allow us to size ourselves to the monitor size. + // Do the reverse when restoring from fullscreen. + // Doing these modifications to that window will cause a vista-style + // window frame to briefly appear when entering and exiting fullscreen. + if (_borderless && !_fullscreen) + { + WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); + WI_SetFlag(windowStyle, WS_POPUP); + } + else if (_borderless && !_fullscreen) + { + WI_ClearFlag(windowStyle, WS_POPUP); + WI_SetAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); + } + + _SetWindowLongWHelper(hWnd, GWL_STYLE, windowStyle); + + // Now modify extended window styles as appropriate + // When moving to fullscreen, remove the window edge style to avoid an + // ugly border when not focused. + auto exWindowStyle = GetWindowLongW(hWnd, GWL_EXSTYLE); + WI_UpdateFlag(exWindowStyle, WS_EX_WINDOWEDGE, !_fullscreen); + _SetWindowLongWHelper(hWnd, GWL_EXSTYLE, exWindowStyle); + + // _BackupWindowSizes(oldIsInFullscreen); + // _ApplyWindowSize(); +} + // Method Description: // - Controls setting us into or out of fullscreen mode. Largely taken from // Window::SetIsFullscreen in conhost. diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index 065d9831acc..c6955f42c17 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -32,6 +32,7 @@ class IslandWindow : void SetCreateCallback(std::function pfn) noexcept; void SetSnapDimensionCallback(std::function pfn) noexcept; + void ToggleBorderless(); void ToggleFullscreen(); #pragma endregion @@ -60,10 +61,12 @@ class IslandWindow : void _HandleCreateWindow(const WPARAM wParam, const LPARAM lParam) noexcept; [[nodiscard]] LRESULT _OnSizing(const WPARAM wParam, const LPARAM lParam); + bool _borderless{ false }; bool _fullscreen{ false }; RECT _fullscreenWindowSize; RECT _nonFullscreenWindowSize; + virtual void _SetIsBorderless(const bool borderlessEnabled); virtual void _SetIsFullscreen(const bool fullscreenEnabled); void _BackupWindowSizes(const bool currentIsInFullscreen); void _ApplyWindowSize(); diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp index 2238cf770a3..2bc8c62227c 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp @@ -263,7 +263,7 @@ void NonClientIslandWindow::SetTitlebarContent(winrt::Windows::UI::Xaml::UIEleme // - the height of the border above the title bar or 0 if it's disabled int NonClientIslandWindow::_GetTopBorderHeight() const noexcept { - if (_isMaximized || _fullscreen) + if (_isMaximized || (!_IsTitlebarVisible())) { // no border when maximized return 0; @@ -811,6 +811,22 @@ void NonClientIslandWindow::OnApplicationThemeChanged(const ElementTheme& reques _theme = requestedTheme; } +void NonClientIslandWindow::_SetIsBorderless(const bool borderlessEnabled) +{ + _borderless = borderlessEnabled; + + // IslandWindow::_SetIsBorderless(borderlessEnabled); + if (_titlebar) + { + _titlebar.Visibility(_IsTitlebarVisible() ? Visibility::Visible : Visibility::Collapsed); + } + // 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(); +} + // Method Description: // - Enable or disable fullscreen mode. When entering fullscreen mode, we'll // need to manually hide the entire titlebar. @@ -824,7 +840,7 @@ void NonClientIslandWindow::_SetIsFullscreen(const bool fullscreenEnabled) IslandWindow::_SetIsFullscreen(fullscreenEnabled); if (_titlebar) { - _titlebar.Visibility(!fullscreenEnabled ? Visibility::Visible : Visibility::Collapsed); + _titlebar.Visibility(_IsTitlebarVisible() ? Visibility::Visible : Visibility::Collapsed); } // 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. @@ -844,7 +860,7 @@ bool NonClientIslandWindow::_IsTitlebarVisible() const { // TODO:GH#2238 - When we add support for titlebar-less mode, this should be // updated to include that mode. - return !_fullscreen; + return !(_fullscreen || _borderless); } // Method Description: diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.h b/src/cascadia/WindowsTerminal/NonClientIslandWindow.h index 792ba6272c9..10a39b4fcb1 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.h +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.h @@ -79,7 +79,8 @@ class NonClientIslandWindow : public IslandWindow void _OnMaximizeChange() noexcept; void _OnDragBarSizeChanged(winrt::Windows::Foundation::IInspectable sender, winrt::Windows::UI::Xaml::SizeChangedEventArgs eventArgs); - void _SetIsFullscreen(const bool fFullscreenEnabled) override; + void _SetIsBorderless(const bool borderlessEnabled) override; + void _SetIsFullscreen(const bool fullscreenEnabled) override; bool _IsTitlebarVisible() const; void _UpdateFrameMargins() const noexcept; From e6c8b65e5615fc8832bdc526a3854f73d9e22a2f Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Fri, 26 Jun 2020 11:54:55 -0500 Subject: [PATCH 02/13] Now it works for the IW as well --- src/cascadia/WindowsTerminal/IslandWindow.cpp | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index bfdd961bb2b..0f4d1af4866 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -504,11 +504,15 @@ void IslandWindow::_SetIsBorderless(const bool borderlessEnabled) if (_borderless && !_fullscreen) { WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); - WI_SetFlag(windowStyle, WS_POPUP); + // WI_SetFlag(windowStyle, WS_POPUP); + WI_SetFlag(windowStyle, WS_BORDER); + WI_SetFlag(windowStyle, WS_SIZEBOX); } - else if (_borderless && !_fullscreen) + else if (!_borderless && !_fullscreen) { - WI_ClearFlag(windowStyle, WS_POPUP); + // WI_ClearFlag(windowStyle, WS_POPUP); + WI_ClearFlag(windowStyle, WS_BORDER); + WI_ClearFlag(windowStyle, WS_SIZEBOX); WI_SetAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); } @@ -521,8 +525,16 @@ void IslandWindow::_SetIsBorderless(const bool borderlessEnabled) WI_UpdateFlag(exWindowStyle, WS_EX_WINDOWEDGE, !_fullscreen); _SetWindowLongWHelper(hWnd, GWL_EXSTYLE, exWindowStyle); - // _BackupWindowSizes(oldIsInFullscreen); - // _ApplyWindowSize(); + // Resize the window, with SWP_FRAMECHANGED, to trigger user32 to + // recalculate the non/client areas + const til::rectangle windowPos{ GetWindowRect() }; + SetWindowPos(GetHandle(), + HWND_TOP, + windowPos.left(), + windowPos.top(), + windowPos.width(), + windowPos.height(), + SWP_SHOWWINDOW | SWP_FRAMECHANGED); } // Method Description: @@ -566,8 +578,11 @@ void IslandWindow::_SetIsFullscreen(const bool fullscreenEnabled) else { WI_ClearFlag(windowStyle, WS_POPUP); - WI_SetAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); } + // if (!_borderless) + // { + // WI_SetAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); + // } _SetWindowLongWHelper(hWnd, GWL_STYLE, windowStyle); From 95f4904a3c6f4bcb7f4112783ed7db9e2333ffdd Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 6 Jul 2020 11:09:36 -0500 Subject: [PATCH 03/13] This feels good for all the IW scenarios - toggling both FS and borderless in either mode. Now double check NCIW... --- src/cascadia/WindowsTerminal/IslandWindow.cpp | 115 ++++++++++++------ src/cascadia/WindowsTerminal/IslandWindow.h | 2 + 2 files changed, 77 insertions(+), 40 deletions(-) diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 0f4d1af4866..befbc8dc438 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -482,6 +482,33 @@ void _SetWindowLongWHelper(const HWND hWnd, const int nIndex, const LONG dwNewLo } } +LONG IslandWindow::_getCurrentWindowStyle() const +{ + auto windowStyle = GetWindowLongW(GetHandle(), GWL_STYLE); + + if (_fullscreen) + { + WI_ClearFlag(windowStyle, WS_BORDER); + WI_ClearFlag(windowStyle, WS_SIZEBOX); + WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); + WI_SetFlag(windowStyle, WS_POPUP); + return windowStyle; + } + else if (_borderless && !_fullscreen) + { + WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); + WI_ClearFlag(windowStyle, WS_POPUP); + WI_SetFlag(windowStyle, WS_BORDER); + WI_SetFlag(windowStyle, WS_SIZEBOX); + return windowStyle; + } + WI_ClearFlag(windowStyle, WS_POPUP); + WI_ClearFlag(windowStyle, WS_BORDER); + WI_ClearFlag(windowStyle, WS_SIZEBOX); + WI_SetAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); + return windowStyle; +} + void IslandWindow::_SetIsBorderless(const bool borderlessEnabled) { // It is possible to enter _SetIsFullscreen even if we're already in full @@ -492,30 +519,31 @@ void IslandWindow::_SetIsBorderless(const bool borderlessEnabled) HWND const hWnd = GetHandle(); - // First, modify regular window styles as appropriate - auto windowStyle = GetWindowLongW(hWnd, GWL_STYLE); - - // When moving to fullscreen, remove WS_OVERLAPPEDWINDOW, which specifies - // styles for non-fullscreen windows (e.g. caption bar), and add the - // WS_POPUP style to allow us to size ourselves to the monitor size. - // Do the reverse when restoring from fullscreen. - // Doing these modifications to that window will cause a vista-style - // window frame to briefly appear when entering and exiting fullscreen. - if (_borderless && !_fullscreen) - { - WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); - // WI_SetFlag(windowStyle, WS_POPUP); - WI_SetFlag(windowStyle, WS_BORDER); - WI_SetFlag(windowStyle, WS_SIZEBOX); - } - else if (!_borderless && !_fullscreen) - { - // WI_ClearFlag(windowStyle, WS_POPUP); - WI_ClearFlag(windowStyle, WS_BORDER); - WI_ClearFlag(windowStyle, WS_SIZEBOX); - WI_SetAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); - } + // // First, modify regular window styles as appropriate + // auto windowStyle = GetWindowLongW(hWnd, GWL_STYLE); + + // // When moving to fullscreen, remove WS_OVERLAPPEDWINDOW, which specifies + // // styles for non-fullscreen windows (e.g. caption bar), and add the + // // WS_POPUP style to allow us to size ourselves to the monitor size. + // // Do the reverse when restoring from fullscreen. + // // Doing these modifications to that window will cause a vista-style + // // window frame to briefly appear when entering and exiting fullscreen. + // if (_borderless && !_fullscreen) + // { + // WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); + // // WI_SetFlag(windowStyle, WS_POPUP); + // WI_SetFlag(windowStyle, WS_BORDER); + // WI_SetFlag(windowStyle, WS_SIZEBOX); + // } + // else if (!_borderless && !_fullscreen) + // { + // // WI_ClearFlag(windowStyle, WS_POPUP); + // WI_ClearFlag(windowStyle, WS_BORDER); + // WI_ClearFlag(windowStyle, WS_SIZEBOX); + // WI_SetAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); + // } + auto windowStyle = _getCurrentWindowStyle(); _SetWindowLongWHelper(hWnd, GWL_STYLE, windowStyle); // Now modify extended window styles as appropriate @@ -562,27 +590,34 @@ void IslandWindow::_SetIsFullscreen(const bool fullscreenEnabled) HWND const hWnd = GetHandle(); // First, modify regular window styles as appropriate - auto windowStyle = GetWindowLongW(hWnd, GWL_STYLE); - - // When moving to fullscreen, remove WS_OVERLAPPEDWINDOW, which specifies - // styles for non-fullscreen windows (e.g. caption bar), and add the - // WS_POPUP style to allow us to size ourselves to the monitor size. - // Do the reverse when restoring from fullscreen. - // Doing these modifications to that window will cause a vista-style - // window frame to briefly appear when entering and exiting fullscreen. - if (_fullscreen) - { - WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); - WI_SetFlag(windowStyle, WS_POPUP); - } - else - { - WI_ClearFlag(windowStyle, WS_POPUP); - } + // auto windowStyle = GetWindowLongW(hWnd, GWL_STYLE); + auto windowStyle = _getCurrentWindowStyle(); + // // When moving to fullscreen, remove WS_OVERLAPPEDWINDOW, which specifies + // // styles for non-fullscreen windows (e.g. caption bar), and add the + // // WS_POPUP style to allow us to size ourselves to the monitor size. + // // Do the reverse when restoring from fullscreen. + // // Doing these modifications to that window will cause a vista-style + // // window frame to briefly appear when entering and exiting fullscreen. + // if (_fullscreen) + // { + // WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); + // WI_SetFlag(windowStyle, WS_POPUP); + // } + // else + // { + // WI_ClearFlag(windowStyle, WS_POPUP); + // } // if (!_borderless) // { // WI_SetAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); // } + // else + // { + // WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); + // // WI_SetFlag(windowStyle, WS_POPUP); + // WI_SetFlag(windowStyle, WS_BORDER); + // WI_SetFlag(windowStyle, WS_SIZEBOX); + // } _SetWindowLongWHelper(hWnd, GWL_STYLE, windowStyle); diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index c6955f42c17..6ffd5335801 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -71,6 +71,8 @@ class IslandWindow : void _BackupWindowSizes(const bool currentIsInFullscreen); void _ApplyWindowSize(); + LONG _getCurrentWindowStyle() const; + private: // This minimum width allows for width the tabs fit static constexpr long minimumWidth = 460L; From 6356aaf71a9da35f87ff2ed4b4c73d42345676a6 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 6 Jul 2020 12:02:28 -0500 Subject: [PATCH 04/13] NCIW works _pretty_ well, but loses the top border on resize. This is an acceptable known issue, since the alternative is having a white line on top of the window when it loses focus --- .../WindowsTerminal/NonClientIslandWindow.cpp | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp index 2bc8c62227c..abda5c01cc7 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp @@ -144,11 +144,13 @@ void NonClientIslandWindow::_ResizeDragBarWindow() noexcept { const til::rectangle rect{ _GetDragAreaRect() }; if (_IsTitlebarVisible() && rect.size().area() > 0) + // if ((_IsTitlebarVisible() || _borderless) && rect.size().area() > 0) { SetWindowPos(_dragBarWindow.get(), HWND_TOP, rect.left(), rect.top() + _GetTopBorderHeight(), + // rect.top() + (_borderless ? 1 : _GetTopBorderHeight()), rect.width(), rect.height(), SWP_NOACTIVATE | SWP_SHOWWINDOW); @@ -266,6 +268,7 @@ int NonClientIslandWindow::_GetTopBorderHeight() const noexcept if (_isMaximized || (!_IsTitlebarVisible())) { // no border when maximized + // return (_borderless && !_fullscreen) ? 1 : 0; // This line seems to work really well, but the titlebar is then white when we lose focus, and that's horrible. return 0; } @@ -616,7 +619,8 @@ SIZE NonClientIslandWindow::GetTotalNonClientExclusiveSize(UINT dpi) const noexc // If we have a titlebar, this is being called after we've initialized, and // we can just ask that titlebar how big it wants to be. - const auto titleBarHeight = _titlebar ? static_cast(_titlebar.ActualHeight()) : 0; + auto titleBarHeight = _titlebar ? static_cast(_titlebar.ActualHeight()) : 0; + titleBarHeight += (_borderless && !_fullscreen) ? 1 : 0; return { islandFrame.right - islandFrame.left, @@ -656,6 +660,10 @@ void NonClientIslandWindow::_UpdateFrameMargins() const noexcept // so it should work fine. margins.cyTopHeight = -frame.top; } + // else if (_borderless) + // { + // margins.cyTopHeight = -1; + // } // Extend the frame into the client area. microsoft/terminal#2735 - Just log // the failure here, don't crash. If DWM crashes for any reason, calling @@ -820,11 +828,23 @@ void NonClientIslandWindow::_SetIsBorderless(const bool borderlessEnabled) { _titlebar.Visibility(_IsTitlebarVisible() ? Visibility::Visible : Visibility::Collapsed); } + // 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(); + + // Resize the window, with SWP_FRAMECHANGED, to trigger user32 to + // recalculate the non/client areas + const til::rectangle windowPos{ GetWindowRect() }; + SetWindowPos(GetHandle(), + HWND_TOP, + windowPos.left(), + windowPos.top(), + windowPos.width(), + windowPos.height(), + SWP_SHOWWINDOW | SWP_FRAMECHANGED); } // Method Description: From fcb2d4850c2f6e817a1dc2a2966775bd9a3eece2 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 6 Jul 2020 14:20:51 -0500 Subject: [PATCH 05/13] cleanup for review --- src/cascadia/WindowsTerminal/IslandWindow.cpp | 101 +++++++----------- .../WindowsTerminal/NonClientIslandWindow.cpp | 24 +++-- 2 files changed, 55 insertions(+), 70 deletions(-) diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index befbc8dc438..a362fe501e1 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -482,67 +482,78 @@ void _SetWindowLongWHelper(const HWND hWnd, const int nIndex, const LONG dwNewLo } } +// Method Description: +// - This is a helper to figure out what the window styles should be, given the +// current state of flags like borderless mode and fullscreen mode. +// Arguments: +// - +// Return Value: +// - a LONG with the appropriate flags set for our current window mode, to be used with GWL_STYLE LONG IslandWindow::_getCurrentWindowStyle() const { auto windowStyle = GetWindowLongW(GetHandle(), GWL_STYLE); + // If we're both fullscreen and borderless, fullscreen mode takes precedence. + if (_fullscreen) { + // When moving to fullscreen, remove WS_OVERLAPPEDWINDOW, which specifies + // styles for non-fullscreen windows (e.g. caption bar), and add the + // WS_POPUP style to allow us to size ourselves to the monitor size. + // Do the reverse when restoring from fullscreen. + // Doing these modifications to that window will cause a vista-style + // window frame to briefly appear when entering and exiting fullscreen. WI_ClearFlag(windowStyle, WS_BORDER); WI_ClearFlag(windowStyle, WS_SIZEBOX); WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); + WI_SetFlag(windowStyle, WS_POPUP); return windowStyle; } else if (_borderless && !_fullscreen) { + // When moving to borderless, remove WS_OVERLAPPEDWINDOW, which + // specifies styles for non-fullscreen windows (e.g. caption bar), and + // add the WS_BORDER and WS_SIZEBOX styles. This allows us to still have + // a small resizing frame, but without a full titlebar, nor caption + // buttons. + WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); WI_ClearFlag(windowStyle, WS_POPUP); + WI_SetFlag(windowStyle, WS_BORDER); WI_SetFlag(windowStyle, WS_SIZEBOX); return windowStyle; } + + // Here, we're not in either fullscreen or borderless mode. Return to + // WS_OVERLAPPEDWINDOW. WI_ClearFlag(windowStyle, WS_POPUP); WI_ClearFlag(windowStyle, WS_BORDER); WI_ClearFlag(windowStyle, WS_SIZEBOX); + WI_SetAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); + return windowStyle; } +// Method Description: +// - Enable or disable borderless mode. When entering borderless mode, we'll +// need to manually hide the entire titlebar. +// - When we're entering borderless we need to do some additional modification +// of our window styles. However, the NonClientIslandWindow very explicitly +// _doesn't_ need to do these steps. +// Arguments: +// - borderlessEnabled: If true, we're entering borderless mode. If false, we're leaving. +// Return Value: +// - void IslandWindow::_SetIsBorderless(const bool borderlessEnabled) { - // It is possible to enter _SetIsFullscreen even if we're already in full - // screen. Use the old is in fullscreen flag to gate checks that rely on the - // current state. - // const auto oldIsInBorderless = _borderless; _borderless = borderlessEnabled; HWND const hWnd = GetHandle(); - // // First, modify regular window styles as appropriate - // auto windowStyle = GetWindowLongW(hWnd, GWL_STYLE); - - // // When moving to fullscreen, remove WS_OVERLAPPEDWINDOW, which specifies - // // styles for non-fullscreen windows (e.g. caption bar), and add the - // // WS_POPUP style to allow us to size ourselves to the monitor size. - // // Do the reverse when restoring from fullscreen. - // // Doing these modifications to that window will cause a vista-style - // // window frame to briefly appear when entering and exiting fullscreen. - // if (_borderless && !_fullscreen) - // { - // WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); - // // WI_SetFlag(windowStyle, WS_POPUP); - // WI_SetFlag(windowStyle, WS_BORDER); - // WI_SetFlag(windowStyle, WS_SIZEBOX); - // } - // else if (!_borderless && !_fullscreen) - // { - // // WI_ClearFlag(windowStyle, WS_POPUP); - // WI_ClearFlag(windowStyle, WS_BORDER); - // WI_ClearFlag(windowStyle, WS_SIZEBOX); - // WI_SetAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); - // } - + // First, modify regular window styles as appropriate auto windowStyle = _getCurrentWindowStyle(); _SetWindowLongWHelper(hWnd, GWL_STYLE, windowStyle); @@ -571,10 +582,6 @@ void IslandWindow::_SetIsBorderless(const bool borderlessEnabled) // - When entering fullscreen mode, we'll save the current window size and // location, and expand to take the entire monitor size. When leaving, we'll // use that saved size to restore back to. -// - When we're entering fullscreen we need to do some additional modification -// of our window styles. However, the NonClientIslandWindow very explicitly -// _doesn't_ need to do these steps. Subclasses should override -// _ShouldUpdateStylesOnFullscreen to disable setting these window styles. // Arguments: // - fullscreenEnabled true if we should enable fullscreen mode, false to disable. // Return Value: @@ -590,35 +597,7 @@ void IslandWindow::_SetIsFullscreen(const bool fullscreenEnabled) HWND const hWnd = GetHandle(); // First, modify regular window styles as appropriate - // auto windowStyle = GetWindowLongW(hWnd, GWL_STYLE); auto windowStyle = _getCurrentWindowStyle(); - // // When moving to fullscreen, remove WS_OVERLAPPEDWINDOW, which specifies - // // styles for non-fullscreen windows (e.g. caption bar), and add the - // // WS_POPUP style to allow us to size ourselves to the monitor size. - // // Do the reverse when restoring from fullscreen. - // // Doing these modifications to that window will cause a vista-style - // // window frame to briefly appear when entering and exiting fullscreen. - // if (_fullscreen) - // { - // WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); - // WI_SetFlag(windowStyle, WS_POPUP); - // } - // else - // { - // WI_ClearFlag(windowStyle, WS_POPUP); - // } - // if (!_borderless) - // { - // WI_SetAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); - // } - // else - // { - // WI_ClearAllFlags(windowStyle, WS_OVERLAPPEDWINDOW); - // // WI_SetFlag(windowStyle, WS_POPUP); - // WI_SetFlag(windowStyle, WS_BORDER); - // WI_SetFlag(windowStyle, WS_SIZEBOX); - // } - _SetWindowLongWHelper(hWnd, GWL_STYLE, windowStyle); // Now modify extended window styles as appropriate @@ -628,6 +607,8 @@ void IslandWindow::_SetIsFullscreen(const bool fullscreenEnabled) WI_UpdateFlag(exWindowStyle, WS_EX_WINDOWEDGE, !_fullscreen); _SetWindowLongWHelper(hWnd, GWL_EXSTYLE, exWindowStyle); + // When entering/exiting fullscreen mode, we also need to backup/restore the + // current window size, and resize the window to match the new state. _BackupWindowSizes(oldIsInFullscreen); _ApplyWindowSize(); } diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp index abda5c01cc7..4a86bc4ab6b 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp @@ -144,13 +144,11 @@ void NonClientIslandWindow::_ResizeDragBarWindow() noexcept { const til::rectangle rect{ _GetDragAreaRect() }; if (_IsTitlebarVisible() && rect.size().area() > 0) - // if ((_IsTitlebarVisible() || _borderless) && rect.size().area() > 0) { SetWindowPos(_dragBarWindow.get(), HWND_TOP, rect.left(), rect.top() + _GetTopBorderHeight(), - // rect.top() + (_borderless ? 1 : _GetTopBorderHeight()), rect.width(), rect.height(), SWP_NOACTIVATE | SWP_SHOWWINDOW); @@ -268,7 +266,6 @@ int NonClientIslandWindow::_GetTopBorderHeight() const noexcept if (_isMaximized || (!_IsTitlebarVisible())) { // no border when maximized - // return (_borderless && !_fullscreen) ? 1 : 0; // This line seems to work really well, but the titlebar is then white when we lose focus, and that's horrible. return 0; } @@ -619,8 +616,7 @@ SIZE NonClientIslandWindow::GetTotalNonClientExclusiveSize(UINT dpi) const noexc // If we have a titlebar, this is being called after we've initialized, and // we can just ask that titlebar how big it wants to be. - auto titleBarHeight = _titlebar ? static_cast(_titlebar.ActualHeight()) : 0; - titleBarHeight += (_borderless && !_fullscreen) ? 1 : 0; + const auto titleBarHeight = _titlebar ? static_cast(_titlebar.ActualHeight()) : 0; return { islandFrame.right - islandFrame.left, @@ -660,10 +656,6 @@ void NonClientIslandWindow::_UpdateFrameMargins() const noexcept // so it should work fine. margins.cyTopHeight = -frame.top; } - // else if (_borderless) - // { - // margins.cyTopHeight = -1; - // } // Extend the frame into the client area. microsoft/terminal#2735 - Just log // the failure here, don't crash. If DWM crashes for any reason, calling @@ -819,11 +811,23 @@ void NonClientIslandWindow::OnApplicationThemeChanged(const ElementTheme& reques _theme = requestedTheme; } +// Method Description: +// - Enable or disable borderless mode. When entering borderless mode, we'll +// need to manually hide the entire titlebar. +// - See also IslandWindow::_SetIsBorderless, which does similar, but different work. +// Arguments: +// - borderlessEnabled: If true, we're entering borderless mode. If false, we're leaving. +// Return Value: +// - void NonClientIslandWindow::_SetIsBorderless(const bool borderlessEnabled) { _borderless = borderlessEnabled; - // IslandWindow::_SetIsBorderless(borderlessEnabled); + // Explicitly _don't_ call IslandWindow::_SetIsBorderless. That version will + // change the window styles appropriately for the window with the detault + // titlebar, but for the tabs-in-titlebar mode, we can just get rid of the + // title bar entirely. + if (_titlebar) { _titlebar.Visibility(_IsTitlebarVisible() ? Visibility::Visible : Visibility::Collapsed); From a50d2e9d670597eef06a2278a6aa2b7131772fa0 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 6 Jul 2020 15:37:35 -0500 Subject: [PATCH 06/13] add to defaults.json too, so it'll be picked up as a command automatically --- src/cascadia/TerminalApp/defaults.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/cascadia/TerminalApp/defaults.json b/src/cascadia/TerminalApp/defaults.json index e3df4f19b8f..3f5dcdaa261 100644 --- a/src/cascadia/TerminalApp/defaults.json +++ b/src/cascadia/TerminalApp/defaults.json @@ -277,6 +277,7 @@ { "command": "closeWindow", "keys": "alt+f4" }, { "command": "toggleFullscreen", "keys": "alt+enter" }, { "command": "toggleFullscreen", "keys": "f11" }, + { "command": "toggleBorderless" }, { "command": "openNewTabDropdown", "keys": "ctrl+shift+space" }, { "command": "openSettings", "keys": "ctrl+," }, { "command": { "action": "openSettings", "target": "defaultsFile" }, "keys": "ctrl+alt+," }, From f5a1a684c83f8a1e9700ea4945539166b6669527 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 6 Jul 2020 15:39:36 -0500 Subject: [PATCH 07/13] add to schema --- doc/cascadia/profiles.schema.json | 1 + 1 file changed, 1 insertion(+) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 2817e9dfa4f..7104d0b3bf2 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -54,6 +54,7 @@ "scrollUpPage", "splitPane", "switchToTab", + "toggleBorderless", "toggleFullscreen", "find", "setTabColor", From 06506f2e7f5879596b866817e59c835848080db7 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 6 Jul 2020 15:46:07 -0500 Subject: [PATCH 08/13] good bot --- .github/actions/spell-check/expect/expect.txt | 1 + src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/actions/spell-check/expect/expect.txt b/.github/actions/spell-check/expect/expect.txt index 2ff98f8e894..c979e71938b 100644 --- a/.github/actions/spell-check/expect/expect.txt +++ b/.github/actions/spell-check/expect/expect.txt @@ -2130,6 +2130,7 @@ SIGDN SINGLEFLAG SINGLETHREADED siup +SIZEBOX sizeof SIZESCROLL SKIPFONT diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp index 4a86bc4ab6b..ab4e1483242 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp @@ -824,7 +824,7 @@ void NonClientIslandWindow::_SetIsBorderless(const bool borderlessEnabled) _borderless = borderlessEnabled; // Explicitly _don't_ call IslandWindow::_SetIsBorderless. That version will - // change the window styles appropriately for the window with the detault + // change the window styles appropriately for the window with the default // titlebar, but for the tabs-in-titlebar mode, we can just get rid of the // title bar entirely. From a6b7f03dd525d14919f79ffb4a35d4be585450d5 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 7 Jul 2020 09:21:26 -0500 Subject: [PATCH 09/13] accidentally the whole thing --- src/cascadia/TerminalApp/ActionAndArgs.cpp | 3 ++ .../TerminalApp/AppActionHandlers.cpp | 7 ++++ src/cascadia/TerminalApp/AppLogic.cpp | 5 +++ src/cascadia/TerminalApp/AppLogic.h | 2 + src/cascadia/TerminalApp/AppLogic.idl | 5 ++- .../TerminalApp/GlobalAppSettings.cpp | 3 ++ src/cascadia/TerminalApp/GlobalAppSettings.h | 1 + .../Resources/en-US/Resources.resw | 3 ++ .../TerminalApp/ShortcutActionDispatch.cpp | 5 +++ .../TerminalApp/ShortcutActionDispatch.h | 1 + .../TerminalApp/ShortcutActionDispatch.idl | 2 + src/cascadia/TerminalApp/TerminalPage.cpp | 24 ++++++++--- src/cascadia/TerminalApp/TerminalPage.h | 5 +++ src/cascadia/TerminalApp/TerminalPage.idl | 8 +++- src/cascadia/TerminalApp/defaults.json | 1 + src/cascadia/WindowsTerminal/AppHost.cpp | 8 ++++ src/cascadia/WindowsTerminal/AppHost.h | 2 + src/cascadia/WindowsTerminal/IslandWindow.cpp | 41 ++++++++++++++----- src/cascadia/WindowsTerminal/IslandWindow.h | 2 + .../WindowsTerminal/NonClientIslandWindow.cpp | 3 +- 20 files changed, 110 insertions(+), 21 deletions(-) diff --git a/src/cascadia/TerminalApp/ActionAndArgs.cpp b/src/cascadia/TerminalApp/ActionAndArgs.cpp index 609935937bb..829d3ee7ba6 100644 --- a/src/cascadia/TerminalApp/ActionAndArgs.cpp +++ b/src/cascadia/TerminalApp/ActionAndArgs.cpp @@ -31,6 +31,7 @@ static constexpr std::string_view FindKey{ "find" }; static constexpr std::string_view ToggleRetroEffectKey{ "toggleRetroEffect" }; static constexpr std::string_view ToggleBorderlessKey{ "toggleBorderless" }; static constexpr std::string_view ToggleFullscreenKey{ "toggleFullscreen" }; +static constexpr std::string_view ToggleAlwaysOnTopKey{ "toggleAlwaysOnTop" }; static constexpr std::string_view SetTabColorKey{ "setTabColor" }; static constexpr std::string_view OpenTabColorPickerKey{ "openTabColorPicker" }; static constexpr std::string_view RenameTabKey{ "renameTab" }; @@ -76,6 +77,7 @@ namespace winrt::TerminalApp::implementation { ToggleRetroEffectKey, ShortcutAction::ToggleRetroEffect }, { ToggleBorderlessKey, ShortcutAction::ToggleBorderless }, { ToggleFullscreenKey, ShortcutAction::ToggleFullscreen }, + { ToggleAlwaysOnTopKey, ShortcutAction::ToggleAlwaysOnTop }, { SplitPaneKey, ShortcutAction::SplitPane }, { SetTabColorKey, ShortcutAction::SetTabColor }, { OpenTabColorPickerKey, ShortcutAction::OpenTabColorPicker }, @@ -255,6 +257,7 @@ namespace winrt::TerminalApp::implementation { ShortcutAction::OpenSettings, RS_(L"OpenSettingsCommandKey") }, { ShortcutAction::ToggleBorderless, RS_(L"ToggleBorderlessCommandKey") }, { ShortcutAction::ToggleFullscreen, RS_(L"ToggleFullscreenCommandKey") }, + { ShortcutAction::ToggleAlwaysOnTop, RS_(L"ToggleAlwaysOnTopCommandKey") }, { ShortcutAction::SplitPane, RS_(L"SplitPaneCommandKey") }, { ShortcutAction::Invalid, L"" }, { ShortcutAction::Find, RS_(L"FindCommandKey") }, diff --git a/src/cascadia/TerminalApp/AppActionHandlers.cpp b/src/cascadia/TerminalApp/AppActionHandlers.cpp index 96913460990..669c1950f1c 100644 --- a/src/cascadia/TerminalApp/AppActionHandlers.cpp +++ b/src/cascadia/TerminalApp/AppActionHandlers.cpp @@ -253,6 +253,13 @@ namespace winrt::TerminalApp::implementation args.Handled(true); } + void TerminalPage::_HandleToggleAlwaysOnTop(const IInspectable& /*sender*/, + const TerminalApp::ActionEventArgs& args) + { + ToggleAlwaysOnTop(); + args.Handled(true); + } + void TerminalPage::_HandleToggleCommandPalette(const IInspectable& /*sender*/, const TerminalApp::ActionEventArgs& args) { diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 77f4e4aefef..62401d718e4 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -1121,6 +1121,11 @@ namespace winrt::TerminalApp::implementation return RS_(L"ApplicationVersionUnknown"); } + bool AppLogic::AlwaysOnTop() const + { + return _root ? _root->AlwaysOnTop() : false; + } + // -------------------------------- WinRT Events --------------------------------- // Winrt events need a method for adding a callback to the event and removing the callback. // These macros will define them both for you. diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index b50b1704bdf..3e6dfba5ff9 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -33,6 +33,7 @@ namespace winrt::TerminalApp::implementation winrt::hstring ApplicationDisplayName() const; winrt::hstring ApplicationVersion() const; + bool AlwaysOnTop() const; Windows::Foundation::Point GetLaunchDimensions(uint32_t dpi); winrt::Windows::Foundation::Point GetLaunchInitialPositions(int32_t defaultInitialX, int32_t defaultInitialY); @@ -106,6 +107,7 @@ namespace winrt::TerminalApp::implementation FORWARDED_TYPED_EVENT(LastTabClosed, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs, _root, LastTabClosed); FORWARDED_TYPED_EVENT(ToggleBorderless, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleBorderlessEventArgs, _root, ToggleBorderless); FORWARDED_TYPED_EVENT(ToggleFullscreen, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleFullscreenEventArgs, _root, ToggleFullscreen); + FORWARDED_TYPED_EVENT(AlwaysOnTopChanged, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::AlwaysOnTopChangedEventArgs, _root, AlwaysOnTopChanged); }; } diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index fac75f7ace8..b2c690b652c 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -41,6 +41,8 @@ namespace TerminalApp String ApplicationDisplayName { get; }; String ApplicationVersion { get; }; + Boolean AlwaysOnTop { get; }; + Windows.Foundation.Point GetLaunchDimensions(UInt32 dpi); Windows.Foundation.Point GetLaunchInitialPositions(Int32 defaultInitialX, Int32 defaultInitialY); Windows.UI.Xaml.ElementTheme GetRequestedTheme(); @@ -58,7 +60,8 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler TitleChanged; event Windows.Foundation.TypedEventHandler LastTabClosed; event Windows.Foundation.TypedEventHandler RequestedThemeChanged; - event Windows.Foundation.TypedEventHandler ToggleFullscreen; event Windows.Foundation.TypedEventHandler ToggleBorderless; + event Windows.Foundation.TypedEventHandler ToggleFullscreen; + event Windows.Foundation.TypedEventHandler AlwaysOnTopChanged; } } diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.cpp b/src/cascadia/TerminalApp/GlobalAppSettings.cpp index b1943037766..d76e7966349 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalApp/GlobalAppSettings.cpp @@ -37,6 +37,7 @@ static constexpr std::string_view LaunchModeKey{ "launchMode" }; static constexpr std::string_view ConfirmCloseAllKey{ "confirmCloseAllTabs" }; static constexpr std::string_view SnapToGridOnResizeKey{ "snapToGridOnResize" }; static constexpr std::string_view EnableStartupTaskKey{ "startOnUserLogin" }; +static constexpr std::string_view AlwaysOnTopKey{ "alwaysOnTop" }; static constexpr std::string_view DebugFeaturesKey{ "debugFeatures" }; @@ -223,6 +224,8 @@ void GlobalAppSettings::LayerJson(const Json::Value& json) JsonUtils::GetBool(json, EnableStartupTaskKey, _StartOnUserLogin); + JsonUtils::GetBool(json, AlwaysOnTopKey, _AlwaysOnTop); + // This is a helper lambda to get the keybindings and commands out of both // and array of objects. We'll use this twice, once on the legacy // `keybindings` key, and again on the newer `bindings` key. diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.h b/src/cascadia/TerminalApp/GlobalAppSettings.h index 052dc9827c4..0a5a3480454 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.h +++ b/src/cascadia/TerminalApp/GlobalAppSettings.h @@ -85,6 +85,7 @@ class TerminalApp::GlobalAppSettings final GETSET_PROPERTY(bool, ForceVTInput, false); GETSET_PROPERTY(bool, DebugFeaturesEnabled); // default value set in constructor GETSET_PROPERTY(bool, StartOnUserLogin, false); + GETSET_PROPERTY(bool, AlwaysOnTop, false); private: std::optional _unparsedDefaultProfile; diff --git a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw index 769c3ddeb46..6c35cd87c4a 100644 --- a/src/cascadia/TerminalApp/Resources/en-US/Resources.resw +++ b/src/cascadia/TerminalApp/Resources/en-US/Resources.resw @@ -386,6 +386,9 @@ Toggle fullscreen + + Toggle always on top mode + Open new tab dropdown diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp index fa833856384..86dc94ed9eb 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.cpp @@ -169,6 +169,11 @@ namespace winrt::TerminalApp::implementation _ToggleFullscreenHandlers(*this, *eventArgs); break; } + case ShortcutAction::ToggleAlwaysOnTop: + { + _ToggleAlwaysOnTopHandlers(*this, *eventArgs); + break; + } case ShortcutAction::ToggleCommandPalette: { _ToggleCommandPaletteHandlers(*this, *eventArgs); diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.h b/src/cascadia/TerminalApp/ShortcutActionDispatch.h index 0875b1a8ee0..2a85017b966 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.h +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.h @@ -49,6 +49,7 @@ namespace winrt::TerminalApp::implementation TYPED_EVENT(ToggleRetroEffect, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(ToggleBorderless, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(ToggleFullscreen, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); + TYPED_EVENT(ToggleAlwaysOnTop, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(ToggleCommandPalette, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(SetTabColor, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); TYPED_EVENT(OpenTabColorPicker, TerminalApp::ShortcutActionDispatch, TerminalApp::ActionEventArgs); diff --git a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl index 7482fde84a9..080eff2d80d 100644 --- a/src/cascadia/TerminalApp/ShortcutActionDispatch.idl +++ b/src/cascadia/TerminalApp/ShortcutActionDispatch.idl @@ -34,6 +34,7 @@ namespace TerminalApp ToggleRetroEffect, ToggleBorderless, ToggleFullscreen, + ToggleAlwaysOnTop, SetTabColor, OpenTabColorPicker, OpenSettings, @@ -78,6 +79,7 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler ToggleRetroEffect; event Windows.Foundation.TypedEventHandler ToggleBorderless; event Windows.Foundation.TypedEventHandler ToggleFullscreen; + event Windows.Foundation.TypedEventHandler ToggleAlwaysOnTop; event Windows.Foundation.TypedEventHandler ToggleCommandPalette; event Windows.Foundation.TypedEventHandler SetTabColor; event Windows.Foundation.TypedEventHandler OpenTabColorPicker; diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index c70cb7b11a4..f72abe4612d 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -844,6 +844,7 @@ namespace winrt::TerminalApp::implementation _actionDispatch->ToggleRetroEffect({ this, &TerminalPage::_HandleToggleRetroEffect }); _actionDispatch->ToggleBorderless({ this, &TerminalPage::_HandleToggleBorderless }); _actionDispatch->ToggleFullscreen({ this, &TerminalPage::_HandleToggleFullscreen }); + _actionDispatch->ToggleAlwaysOnTop({ this, &TerminalPage::_HandleToggleAlwaysOnTop }); _actionDispatch->ToggleCommandPalette({ this, &TerminalPage::_HandleToggleCommandPalette }); _actionDispatch->SetTabColor({ this, &TerminalPage::_HandleSetTabColor }); _actionDispatch->OpenTabColorPicker({ this, &TerminalPage::_HandleOpenTabColorPicker }); @@ -1905,6 +1906,9 @@ namespace winrt::TerminalApp::implementation _UpdateTabWidthMode(); _CreateNewTabFlyout(); } + + _isAlwayOnTop = _settings->GlobalSettings().AlwaysOnTop(); + _alwaysOnTopChangedHandlers(*this, nullptr); } // Method Description: @@ -1968,10 +1972,8 @@ namespace winrt::TerminalApp::implementation // - void TerminalPage::ToggleBorderless() { - _toggleBorderlessHandlers(*this, nullptr); - _isBorderless = !_isBorderless; - + _toggleBorderlessHandlers(*this, nullptr); _UpdateTabView(); } @@ -1984,13 +1986,17 @@ namespace winrt::TerminalApp::implementation // - void TerminalPage::ToggleFullscreen() { - _toggleFullscreenHandlers(*this, nullptr); - _isFullscreen = !_isFullscreen; - + _toggleFullscreenHandlers(*this, nullptr); _UpdateTabView(); } + void TerminalPage::ToggleAlwaysOnTop() + { + _isAlwayOnTop = !_isAlwayOnTop; + _alwaysOnTopChangedHandlers(*this, nullptr); + } + // Method Description: // - Returns a com_ptr to the implementation type of the tab at the given index // Arguments: @@ -2179,6 +2185,11 @@ namespace winrt::TerminalApp::implementation } } + bool TerminalPage::AlwaysOnTop() const + { + return _isAlwayOnTop; + } + // -------------------------------- WinRT Events --------------------------------- // Winrt events need a method for adding a callback to the event and removing the callback. // These macros will define them both for you. @@ -2187,4 +2198,5 @@ namespace winrt::TerminalApp::implementation DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, SetTitleBarContent, _setTitleBarContentHandlers, winrt::Windows::Foundation::IInspectable, UIElement); DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, ToggleBorderless, _toggleBorderlessHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleBorderlessEventArgs); DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, ToggleFullscreen, _toggleFullscreenHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleFullscreenEventArgs); + DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, AlwaysOnTopChanged, _alwaysOnTopChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::AlwaysOnTopChangedEventArgs); } diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 741a21f3e53..d8bec8c827c 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -51,6 +51,8 @@ namespace winrt::TerminalApp::implementation void ToggleBorderless(); void ToggleFullscreen(); + void ToggleAlwaysOnTop(); + bool AlwaysOnTop() const; void SetStartupActions(std::deque& actions); @@ -63,6 +65,7 @@ namespace winrt::TerminalApp::implementation DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTitleBarContent, _setTitleBarContentHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::UIElement); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(ToggleBorderless, _toggleBorderlessHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleBorderlessEventArgs); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(ToggleFullscreen, _toggleFullscreenHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleFullscreenEventArgs); + DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(AlwaysOnTopChanged, _alwaysOnTopChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::AlwaysOnTopChangedEventArgs); TYPED_EVENT(Initialized, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::RoutedEventArgs); private: @@ -87,6 +90,7 @@ namespace winrt::TerminalApp::implementation bool _isBorderless{ false }; bool _isFullscreen{ false }; + bool _isAlwayOnTop{ false }; bool _rearranging; std::optional _rearrangeFrom; @@ -211,6 +215,7 @@ namespace winrt::TerminalApp::implementation void _HandleToggleRetroEffect(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleToggleBorderless(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleToggleFullscreen(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); + void _HandleToggleAlwaysOnTop(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleSetTabColor(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleOpenTabColorPicker(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); void _HandleRenameTab(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); diff --git a/src/cascadia/TerminalApp/TerminalPage.idl b/src/cascadia/TerminalApp/TerminalPage.idl index aa41a764da3..50496aed1cb 100644 --- a/src/cascadia/TerminalApp/TerminalPage.idl +++ b/src/cascadia/TerminalApp/TerminalPage.idl @@ -4,8 +4,9 @@ namespace TerminalApp { delegate void LastTabClosedEventArgs(); - delegate void ToggleFullscreenEventArgs(); delegate void ToggleBorderlessEventArgs(); + delegate void ToggleFullscreenEventArgs(); + delegate void AlwaysOnTopChangedEventArgs(); interface IDialogPresenter { @@ -20,6 +21,8 @@ namespace TerminalApp String ApplicationDisplayName { get; }; String ApplicationVersion { get; }; + Boolean AlwaysOnTop { get; }; + // We cannot use the default XAML APIs because we want to make sure // that there's only one application-global dialog visible at a time, // and because of GH#5224. @@ -28,8 +31,9 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler TitleChanged; event Windows.Foundation.TypedEventHandler LastTabClosed; event Windows.Foundation.TypedEventHandler SetTitleBarContent; - event Windows.Foundation.TypedEventHandler ToggleFullscreen; event Windows.Foundation.TypedEventHandler ToggleBorderless; + event Windows.Foundation.TypedEventHandler ToggleFullscreen; + event Windows.Foundation.TypedEventHandler AlwaysOnTopChanged; event Windows.Foundation.TypedEventHandler Initialized; } } diff --git a/src/cascadia/TerminalApp/defaults.json b/src/cascadia/TerminalApp/defaults.json index 3f5dcdaa261..0be643ad95b 100644 --- a/src/cascadia/TerminalApp/defaults.json +++ b/src/cascadia/TerminalApp/defaults.json @@ -278,6 +278,7 @@ { "command": "toggleFullscreen", "keys": "alt+enter" }, { "command": "toggleFullscreen", "keys": "f11" }, { "command": "toggleBorderless" }, + { "command": "toggleAlwaysOnTop" }, { "command": "openNewTabDropdown", "keys": "ctrl+shift+space" }, { "command": "openSettings", "keys": "ctrl+," }, { "command": { "action": "openSettings", "target": "defaultsFile" }, "keys": "ctrl+alt+," }, diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 397be92772c..554ab14a0da 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -52,6 +52,7 @@ AppHost::AppHost() noexcept : std::placeholders::_1, std::placeholders::_2)); _window->MouseScrolled({ this, &AppHost::_WindowMouseWheeled }); + _window->SetAlwaysOnTop(_logic.AlwaysOnTop()); _window->MakeWindow(); } @@ -158,6 +159,7 @@ void AppHost::Initialize() _logic.RequestedThemeChanged({ this, &AppHost::_UpdateTheme }); _logic.ToggleFullscreen({ this, &AppHost::_ToggleFullscreen }); _logic.ToggleBorderless({ this, &AppHost::_ToggleBorderless }); + _logic.AlwaysOnTopChanged({ this, &AppHost::_AlwaysOnTopChanged }); _logic.Create(); @@ -365,6 +367,12 @@ void AppHost::_ToggleFullscreen(const winrt::Windows::Foundation::IInspectable&, _window->ToggleFullscreen(); } +void AppHost::_AlwaysOnTopChanged(const winrt::Windows::Foundation::IInspectable&, + const winrt::TerminalApp::AlwaysOnTopChangedEventArgs&) +{ + _window->SetAlwaysOnTop(_logic.AlwaysOnTop()); +} + // Method Description: // - Called when the IslandWindow has received a WM_MOUSEWHEEL message. This can // happen on some laptops, where their trackpads won't scroll inactive windows diff --git a/src/cascadia/WindowsTerminal/AppHost.h b/src/cascadia/WindowsTerminal/AppHost.h index 3e6288575ec..77eef14cc0c 100644 --- a/src/cascadia/WindowsTerminal/AppHost.h +++ b/src/cascadia/WindowsTerminal/AppHost.h @@ -37,5 +37,7 @@ class AppHost const winrt::TerminalApp::ToggleBorderlessEventArgs& arg); void _ToggleFullscreen(const winrt::Windows::Foundation::IInspectable& sender, const winrt::TerminalApp::ToggleFullscreenEventArgs& arg); + void _AlwaysOnTopChanged(const winrt::Windows::Foundation::IInspectable& sender, + const winrt::TerminalApp::AlwaysOnTopChangedEventArgs& arg); void _WindowMouseWheeled(const til::point coord, const int32_t delta); }; diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index a362fe501e1..801acd3aed7 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -51,17 +51,18 @@ void IslandWindow::MakeWindow() noexcept // Create the window with the default size here - During the creation of the // window, the system will give us a chance to set its size in WM_CREATE. // WM_CREATE will be handled synchronously, before CreateWindow returns. - WINRT_VERIFY(CreateWindow(wc.lpszClassName, - L"Windows Terminal", - WS_OVERLAPPEDWINDOW, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - CW_USEDEFAULT, - nullptr, - nullptr, - wc.hInstance, - this)); + WINRT_VERIFY(CreateWindowEx(_alwaysOnTop ? WS_EX_TOPMOST : 0, + wc.lpszClassName, + L"Windows Terminal", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + CW_USEDEFAULT, + nullptr, + nullptr, + wc.hInstance, + this)); WINRT_ASSERT(_window); } @@ -463,6 +464,24 @@ void IslandWindow::ToggleFullscreen() _SetIsFullscreen(!_fullscreen); } +void IslandWindow::SetAlwaysOnTop(const bool alwaysOnTop) +{ + _alwaysOnTop = alwaysOnTop; + + const auto hwnd = GetHandle(); + if (hwnd) + { + const til::rectangle windowPos{ GetWindowRect() }; + SetWindowPos(GetHandle(), + _alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, + windowPos.left(), + windowPos.top(), + windowPos.width(), + windowPos.height(), + SWP_NOMOVE | SWP_NOSIZE); + } +} + // From GdiEngine::s_SetWindowLongWHelper void _SetWindowLongWHelper(const HWND hWnd, const int nIndex, const LONG dwNewLong) noexcept { diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index 6ffd5335801..eb458ddc744 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -34,6 +34,7 @@ class IslandWindow : void ToggleBorderless(); void ToggleFullscreen(); + void SetAlwaysOnTop(const bool alwaysOnTop); #pragma endregion @@ -63,6 +64,7 @@ class IslandWindow : bool _borderless{ false }; bool _fullscreen{ false }; + bool _alwaysOnTop{ false }; RECT _fullscreenWindowSize; RECT _nonFullscreenWindowSize; diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp index ab4e1483242..a9b252f151e 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp @@ -843,7 +843,8 @@ void NonClientIslandWindow::_SetIsBorderless(const bool borderlessEnabled) // recalculate the non/client areas const til::rectangle windowPos{ GetWindowRect() }; SetWindowPos(GetHandle(), - HWND_TOP, + // _borderless ? HWND_TOPMOST : HWND_NOTOPMOST, + 0, windowPos.left(), windowPos.top(), windowPos.width(), From 8fb257a88bd3b694bc169984fff42c37fca6466c Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 7 Jul 2020 09:34:43 -0500 Subject: [PATCH 10/13] cleanup code for review --- doc/cascadia/profiles.schema.json | 6 ++++++ src/cascadia/TerminalApp/TerminalPage.cpp | 18 ++++++++++++++++++ src/cascadia/TerminalApp/defaults.json | 1 + src/cascadia/WindowsTerminal/IslandWindow.cpp | 11 ++++++++++- 4 files changed, 35 insertions(+), 1 deletion(-) diff --git a/doc/cascadia/profiles.schema.json b/doc/cascadia/profiles.schema.json index 7104d0b3bf2..85852ba57fe 100644 --- a/doc/cascadia/profiles.schema.json +++ b/doc/cascadia/profiles.schema.json @@ -56,6 +56,7 @@ "switchToTab", "toggleBorderless", "toggleFullscreen", + "toggleAlwaysOnTop", "find", "setTabColor", "openTabColorPicker", @@ -321,6 +322,11 @@ "additionalProperties": true, "description": "Properties that affect the entire window, regardless of the profile settings.", "properties": { + "alwaysOnTop": { + "default": false, + "description": "When set to true, the window is created on top of all other windows. If multiple windows are all \"always on top\", the most recently focused one will be the topmost", + "type": "boolean" + }, "alwaysShowTabs": { "default": true, "description": "When set to true, tabs are always displayed. When set to false and \"showTabsInTitlebar\" is set to false, tabs only appear after opening a new tab.", diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index f72abe4612d..2868d38d7e4 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -1907,6 +1907,9 @@ namespace winrt::TerminalApp::implementation _CreateNewTabFlyout(); } + // Reload the current value of alwaysOnTop from the settings file. This + // will let the user hot-reload this setting, but any runtime changes to + // the alwaysOnTop setting will be lost. _isAlwayOnTop = _settings->GlobalSettings().AlwaysOnTop(); _alwaysOnTopChangedHandlers(*this, nullptr); } @@ -1991,6 +1994,12 @@ namespace winrt::TerminalApp::implementation _UpdateTabView(); } + // Method Description: + // - Toggles always on top mode. Raises our AlwaysOnTopChanged event. + // Arguments: + // - + // Return Value: + // - void TerminalPage::ToggleAlwaysOnTop() { _isAlwayOnTop = !_isAlwayOnTop; @@ -2185,6 +2194,15 @@ namespace winrt::TerminalApp::implementation } } + // Method Description: + // - Returns true if we're currently in "Always on top" mode. When we're in + // always on top mode, the window should be on top of all other windows. + // If multiple windows are all "always on top", they'll maintain their own + // z-order, with all the windows on top of all other non-topmost windows. + // Arguments: + // - + // Return Value: + // - true if we should be in "always on top" mode bool TerminalPage::AlwaysOnTop() const { return _isAlwayOnTop; diff --git a/src/cascadia/TerminalApp/defaults.json b/src/cascadia/TerminalApp/defaults.json index 0be643ad95b..fcb95eafa27 100644 --- a/src/cascadia/TerminalApp/defaults.json +++ b/src/cascadia/TerminalApp/defaults.json @@ -6,6 +6,7 @@ "initialCols": 120, "initialRows": 30, "launchMode": "default", + "alwaysOnTop": false, // Selection "copyOnSelect": false, diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 801acd3aed7..9c579504058 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -464,6 +464,15 @@ void IslandWindow::ToggleFullscreen() _SetIsFullscreen(!_fullscreen); } +// Method Description: +// - Enter or exit the "always on top" state. Before the window is created, this +// value will later be used when we create the window to create the window on +// top of all others. After the window is created, it will either enter the +// group of topmost windows, or exit the group of topmost windows. +// Arguments: +// - alwaysOnTop: whether we should be entering or exiting always on top mode. +// Return Value: +// - void IslandWindow::SetAlwaysOnTop(const bool alwaysOnTop) { _alwaysOnTop = alwaysOnTop; @@ -472,7 +481,7 @@ void IslandWindow::SetAlwaysOnTop(const bool alwaysOnTop) if (hwnd) { const til::rectangle windowPos{ GetWindowRect() }; - SetWindowPos(GetHandle(), + SetWindowPos(hwnd, _alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, windowPos.left(), windowPos.top(), From cdc80a7292806952e21a4401073a58b66ecb0a74 Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Mon, 13 Jul 2020 14:11:21 -0500 Subject: [PATCH 11/13] this was missed in the merge --- src/cascadia/WindowsTerminal/IslandWindow.cpp | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index f2efc3c5ebf..de93bcf9d8c 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -453,17 +453,6 @@ void IslandWindow::ToggleFocusMode() _SetIsBorderless(!_borderless); } -// Method Description: -// - Toggles our fullscreen state. See _SetIsFullscreen for more details. -// Arguments: -// - -// Return Value: -// - -void IslandWindow::ToggleBorderless() -{ - _SetIsBorderless(!_borderless); -} - // Method Description: // - Toggles our fullscreen state. See _SetIsFullscreen for more details. // Arguments: From 35f1950155884ee70db3d4aa66a69f234a85f36d Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 14 Jul 2020 09:05:50 -0500 Subject: [PATCH 12/13] feedback from PR --- src/cascadia/TerminalApp/AppLogic.cpp | 10 ++++++ src/cascadia/TerminalApp/AppLogic.h | 8 +++-- src/cascadia/TerminalApp/AppLogic.idl | 8 +++-- src/cascadia/TerminalApp/TerminalPage.cpp | 29 ++++++++++------ src/cascadia/TerminalApp/TerminalPage.h | 10 +++--- src/cascadia/TerminalApp/TerminalPage.idl | 11 +++---- src/cascadia/WindowsTerminal/AppHost.cpp | 18 +++++----- src/cascadia/WindowsTerminal/AppHost.h | 10 +++--- src/cascadia/WindowsTerminal/IslandWindow.cpp | 33 ++++++++++++------- src/cascadia/WindowsTerminal/IslandWindow.h | 4 +-- 10 files changed, 88 insertions(+), 53 deletions(-) diff --git a/src/cascadia/TerminalApp/AppLogic.cpp b/src/cascadia/TerminalApp/AppLogic.cpp index 62401d718e4..e036bd9ee2c 100644 --- a/src/cascadia/TerminalApp/AppLogic.cpp +++ b/src/cascadia/TerminalApp/AppLogic.cpp @@ -1121,6 +1121,16 @@ namespace winrt::TerminalApp::implementation return RS_(L"ApplicationVersionUnknown"); } + bool AppLogic::FocusMode() const + { + return _root ? _root->FocusMode() : false; + } + + bool AppLogic::Fullscreen() const + { + return _root ? _root->Fullscreen() : false; + } + bool AppLogic::AlwaysOnTop() const { return _root ? _root->AlwaysOnTop() : false; diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index e05a61ffcd5..c879a6f1876 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -33,6 +33,8 @@ namespace winrt::TerminalApp::implementation winrt::hstring ApplicationDisplayName() const; winrt::hstring ApplicationVersion() const; + bool FocusMode() const; + bool Fullscreen() const; bool AlwaysOnTop() const; Windows::Foundation::Point GetLaunchDimensions(uint32_t dpi); @@ -105,9 +107,9 @@ namespace winrt::TerminalApp::implementation FORWARDED_TYPED_EVENT(SetTitleBarContent, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::UIElement, _root, SetTitleBarContent); FORWARDED_TYPED_EVENT(TitleChanged, winrt::Windows::Foundation::IInspectable, winrt::hstring, _root, TitleChanged); FORWARDED_TYPED_EVENT(LastTabClosed, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs, _root, LastTabClosed); - FORWARDED_TYPED_EVENT(ToggleFocusMode, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleFocusModeEventArgs, _root, ToggleFocusMode); - FORWARDED_TYPED_EVENT(ToggleFullscreen, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleFullscreenEventArgs, _root, ToggleFullscreen); - FORWARDED_TYPED_EVENT(AlwaysOnTopChanged, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::AlwaysOnTopChangedEventArgs, _root, AlwaysOnTopChanged); + FORWARDED_TYPED_EVENT(FocusModeChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, FocusModeChanged); + FORWARDED_TYPED_EVENT(FullscreenChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, FullscreenChanged); + FORWARDED_TYPED_EVENT(AlwaysOnTopChanged, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, AlwaysOnTopChanged); }; } diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index 13171260265..071a5ce84cc 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -41,6 +41,8 @@ namespace TerminalApp String ApplicationDisplayName { get; }; String ApplicationVersion { get; }; + Boolean FocusMode { get; }; + Boolean Fullscreen { get; }; Boolean AlwaysOnTop { get; }; Windows.Foundation.Point GetLaunchDimensions(UInt32 dpi); @@ -60,8 +62,8 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler TitleChanged; event Windows.Foundation.TypedEventHandler LastTabClosed; event Windows.Foundation.TypedEventHandler RequestedThemeChanged; - event Windows.Foundation.TypedEventHandler ToggleFocusMode; - event Windows.Foundation.TypedEventHandler ToggleFullscreen; - event Windows.Foundation.TypedEventHandler AlwaysOnTopChanged; + event Windows.Foundation.TypedEventHandler FocusModeChanged; + event Windows.Foundation.TypedEventHandler FullscreenChanged; + event Windows.Foundation.TypedEventHandler AlwaysOnTopChanged; } } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index c5f1db0acdd..6ed6d8e9716 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -1918,7 +1918,7 @@ namespace winrt::TerminalApp::implementation // Reload the current value of alwaysOnTop from the settings file. This // will let the user hot-reload this setting, but any runtime changes to // the alwaysOnTop setting will be lost. - _isAlwayOnTop = _settings->GlobalSettings().AlwaysOnTop(); + _isAlwaysOnTop = _settings->GlobalSettings().AlwaysOnTop(); _alwaysOnTopChangedHandlers(*this, nullptr); } @@ -1976,7 +1976,7 @@ namespace winrt::TerminalApp::implementation // Method Description: // - Toggles borderless mode. Hides the tab row, and raises our - // ToggleFocusMode event. + // FocusModeChanged event. // Arguments: // - // Return Value: @@ -1984,13 +1984,13 @@ namespace winrt::TerminalApp::implementation void TerminalPage::ToggleFocusMode() { _isInFocusMode = !_isInFocusMode; - _toggleFocusModeHandlers(*this, nullptr); _UpdateTabView(); + _focusModeChangedHandlers(*this, nullptr); } // Method Description: // - Toggles fullscreen mode. Hides the tab row, and raises our - // ToggleFullscreen event. + // FullscreenChanged event. // Arguments: // - // Return Value: @@ -1998,8 +1998,8 @@ namespace winrt::TerminalApp::implementation void TerminalPage::ToggleFullscreen() { _isFullscreen = !_isFullscreen; - _toggleFullscreenHandlers(*this, nullptr); _UpdateTabView(); + _fullscreenChangedHandlers(*this, nullptr); } // Method Description: @@ -2010,7 +2010,7 @@ namespace winrt::TerminalApp::implementation // - void TerminalPage::ToggleAlwaysOnTop() { - _isAlwayOnTop = !_isAlwayOnTop; + _isAlwaysOnTop = !_isAlwaysOnTop; _alwaysOnTopChangedHandlers(*this, nullptr); } @@ -2202,6 +2202,15 @@ namespace winrt::TerminalApp::implementation } } + bool TerminalPage::FocusMode() const + { + return _isInFocusMode; + } + + bool TerminalPage::Fullscreen() const + { + return _isFullscreen; + } // Method Description: // - Returns true if we're currently in "Always on top" mode. When we're in // always on top mode, the window should be on top of all other windows. @@ -2213,7 +2222,7 @@ namespace winrt::TerminalApp::implementation // - true if we should be in "always on top" mode bool TerminalPage::AlwaysOnTop() const { - return _isAlwayOnTop; + return _isAlwaysOnTop; } // -------------------------------- WinRT Events --------------------------------- @@ -2222,7 +2231,7 @@ namespace winrt::TerminalApp::implementation DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, TitleChanged, _titleChangeHandlers, winrt::Windows::Foundation::IInspectable, winrt::hstring); DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, LastTabClosed, _lastTabClosedHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs); DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, SetTitleBarContent, _setTitleBarContentHandlers, winrt::Windows::Foundation::IInspectable, UIElement); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, ToggleFocusMode, _toggleFocusModeHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleFocusModeEventArgs); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, ToggleFullscreen, _toggleFullscreenHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleFullscreenEventArgs); - DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, AlwaysOnTopChanged, _alwaysOnTopChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::AlwaysOnTopChangedEventArgs); + DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, FocusModeChanged, _focusModeChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); + DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, FullscreenChanged, _fullscreenChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); + DEFINE_EVENT_WITH_TYPED_EVENT_HANDLER(TerminalPage, AlwaysOnTopChanged, _alwaysOnTopChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); } diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index c8944d8dba6..2aa717cfacd 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -52,6 +52,8 @@ namespace winrt::TerminalApp::implementation void ToggleFocusMode(); void ToggleFullscreen(); void ToggleAlwaysOnTop(); + bool FocusMode() const; + bool Fullscreen() const; bool AlwaysOnTop() const; void SetStartupActions(std::deque& actions); @@ -63,9 +65,9 @@ namespace winrt::TerminalApp::implementation DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(TitleChanged, _titleChangeHandlers, winrt::Windows::Foundation::IInspectable, winrt::hstring); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(LastTabClosed, _lastTabClosedHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::LastTabClosedEventArgs); DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(SetTitleBarContent, _setTitleBarContentHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::UIElement); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(ToggleFocusMode, _toggleFocusModeHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleFocusModeEventArgs); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(ToggleFullscreen, _toggleFullscreenHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::ToggleFullscreenEventArgs); - DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(AlwaysOnTopChanged, _alwaysOnTopChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::TerminalApp::AlwaysOnTopChangedEventArgs); + DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(FocusModeChanged, _focusModeChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); + DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(FullscreenChanged, _fullscreenChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); + DECLARE_EVENT_WITH_TYPED_EVENT_HANDLER(AlwaysOnTopChanged, _alwaysOnTopChangedHandlers, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable); TYPED_EVENT(Initialized, winrt::Windows::Foundation::IInspectable, winrt::Windows::UI::Xaml::RoutedEventArgs); private: @@ -90,7 +92,7 @@ namespace winrt::TerminalApp::implementation bool _isInFocusMode{ false }; bool _isFullscreen{ false }; - bool _isAlwayOnTop{ false }; + bool _isAlwaysOnTop{ false }; bool _rearranging; std::optional _rearrangeFrom; diff --git a/src/cascadia/TerminalApp/TerminalPage.idl b/src/cascadia/TerminalApp/TerminalPage.idl index 381d59d890f..7fb5cb29ac1 100644 --- a/src/cascadia/TerminalApp/TerminalPage.idl +++ b/src/cascadia/TerminalApp/TerminalPage.idl @@ -4,9 +4,6 @@ namespace TerminalApp { delegate void LastTabClosedEventArgs(); - delegate void ToggleFocusModeEventArgs(); - delegate void ToggleFullscreenEventArgs(); - delegate void AlwaysOnTopChangedEventArgs(); interface IDialogPresenter { @@ -21,6 +18,8 @@ namespace TerminalApp String ApplicationDisplayName { get; }; String ApplicationVersion { get; }; + Boolean FocusMode { get; }; + Boolean Fullscreen { get; }; Boolean AlwaysOnTop { get; }; // We cannot use the default XAML APIs because we want to make sure @@ -31,9 +30,9 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler TitleChanged; event Windows.Foundation.TypedEventHandler LastTabClosed; event Windows.Foundation.TypedEventHandler SetTitleBarContent; - event Windows.Foundation.TypedEventHandler ToggleFocusMode; - event Windows.Foundation.TypedEventHandler ToggleFullscreen; - event Windows.Foundation.TypedEventHandler AlwaysOnTopChanged; + event Windows.Foundation.TypedEventHandler FocusModeChanged; + event Windows.Foundation.TypedEventHandler FullscreenChanged; + event Windows.Foundation.TypedEventHandler AlwaysOnTopChanged; event Windows.Foundation.TypedEventHandler Initialized; } } diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index bd3ab1857fe..b2c3c32a3b5 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -157,8 +157,8 @@ void AppHost::Initialize() _window->DragRegionClicked([this]() { _logic.TitlebarClicked(); }); _logic.RequestedThemeChanged({ this, &AppHost::_UpdateTheme }); - _logic.ToggleFullscreen({ this, &AppHost::_ToggleFullscreen }); - _logic.ToggleFocusMode({ this, &AppHost::_ToggleFocusMode }); + _logic.FullscreenChanged({ this, &AppHost::_FullscreenChanged }); + _logic.FocusModeChanged({ this, &AppHost::_FocusModeChanged }); _logic.AlwaysOnTopChanged({ this, &AppHost::_AlwaysOnTopChanged }); _logic.Create(); @@ -355,20 +355,20 @@ void AppHost::_UpdateTheme(const winrt::Windows::Foundation::IInspectable&, cons _window->OnApplicationThemeChanged(arg); } -void AppHost::_ToggleFocusMode(const winrt::Windows::Foundation::IInspectable&, - const winrt::TerminalApp::ToggleFocusModeEventArgs&) +void AppHost::_FocusModeChanged(const winrt::Windows::Foundation::IInspectable&, + const winrt::Windows::Foundation::IInspectable&) { - _window->ToggleFocusMode(); + _window->FocusModeChanged(_logic.FocusMode()); } -void AppHost::_ToggleFullscreen(const winrt::Windows::Foundation::IInspectable&, - const winrt::TerminalApp::ToggleFullscreenEventArgs&) +void AppHost::_FullscreenChanged(const winrt::Windows::Foundation::IInspectable&, + const winrt::Windows::Foundation::IInspectable&) { - _window->ToggleFullscreen(); + _window->FullscreenChanged(_logic.Fullscreen()); } void AppHost::_AlwaysOnTopChanged(const winrt::Windows::Foundation::IInspectable&, - const winrt::TerminalApp::AlwaysOnTopChangedEventArgs&) + const winrt::Windows::Foundation::IInspectable&) { _window->SetAlwaysOnTop(_logic.AlwaysOnTop()); } diff --git a/src/cascadia/WindowsTerminal/AppHost.h b/src/cascadia/WindowsTerminal/AppHost.h index 26469e43251..4e072411de8 100644 --- a/src/cascadia/WindowsTerminal/AppHost.h +++ b/src/cascadia/WindowsTerminal/AppHost.h @@ -33,11 +33,11 @@ class AppHost const winrt::Windows::UI::Xaml::UIElement& arg); void _UpdateTheme(const winrt::Windows::Foundation::IInspectable&, const winrt::Windows::UI::Xaml::ElementTheme& arg); - void _ToggleFocusMode(const winrt::Windows::Foundation::IInspectable& sender, - const winrt::TerminalApp::ToggleFocusModeEventArgs& arg); - void _ToggleFullscreen(const winrt::Windows::Foundation::IInspectable& sender, - const winrt::TerminalApp::ToggleFullscreenEventArgs& arg); + void _FocusModeChanged(const winrt::Windows::Foundation::IInspectable& sender, + const winrt::Windows::Foundation::IInspectable& arg); + void _FullscreenChanged(const winrt::Windows::Foundation::IInspectable& sender, + const winrt::Windows::Foundation::IInspectable& arg); void _AlwaysOnTopChanged(const winrt::Windows::Foundation::IInspectable& sender, - const winrt::TerminalApp::AlwaysOnTopChangedEventArgs& arg); + const winrt::Windows::Foundation::IInspectable& arg); void _WindowMouseWheeled(const til::point coord, const int32_t delta); }; diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index de93bcf9d8c..e6497d1d48b 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -443,25 +443,37 @@ void IslandWindow::OnApplicationThemeChanged(const winrt::Windows::UI::Xaml::Ele } // Method Description: -// - Toggles our focus mode state. See _SetIsBorderless for more details. +// - Updates our focus mode state. See _SetIsBorderless for more details. // Arguments: // - // Return Value: // - -void IslandWindow::ToggleFocusMode() +void IslandWindow::FocusModeChanged(const bool focusMode) { - _SetIsBorderless(!_borderless); + // Do nothing if the value was unchanged. + if (focusMode == _borderless) + { + return; + } + + _SetIsBorderless(focusMode); } // Method Description: -// - Toggles our fullscreen state. See _SetIsFullscreen for more details. +// - Updates our fullscreen state. See _SetIsFullscreen for more details. // Arguments: // - // Return Value: // - -void IslandWindow::ToggleFullscreen() +void IslandWindow::FullscreenChanged(const bool fullscreen) { - _SetIsFullscreen(!_fullscreen); + // Do nothing if the value was unchanged. + if (fullscreen == _fullscreen) + { + return; + } + + _SetIsFullscreen(fullscreen); } // Method Description: @@ -480,13 +492,12 @@ void IslandWindow::SetAlwaysOnTop(const bool alwaysOnTop) const auto hwnd = GetHandle(); if (hwnd) { - const til::rectangle windowPos{ GetWindowRect() }; SetWindowPos(hwnd, _alwaysOnTop ? HWND_TOPMOST : HWND_NOTOPMOST, - windowPos.left(), - windowPos.top(), - windowPos.width(), - windowPos.height(), + 0, // the window dimensions are unused, because we're passing SWP_NOSIZE + 0, + 0, + 0, SWP_NOMOVE | SWP_NOSIZE); } } diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index 546fa105a8f..cd593e6663f 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -32,8 +32,8 @@ class IslandWindow : void SetCreateCallback(std::function pfn) noexcept; void SetSnapDimensionCallback(std::function pfn) noexcept; - void ToggleFocusMode(); - void ToggleFullscreen(); + void FocusModeChanged(const bool focusMode); + void FullscreenChanged(const bool fullscreen); void SetAlwaysOnTop(const bool alwaysOnTop); #pragma endregion From 46e478bd7179d75a690ae6f211dcb53b05c1a39b Mon Sep 17 00:00:00 2001 From: Mike Griese Date: Tue, 14 Jul 2020 09:07:25 -0500 Subject: [PATCH 13/13] good bot --- .github/actions/spell-check/expect/expect.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/actions/spell-check/expect/expect.txt b/.github/actions/spell-check/expect/expect.txt index 24efc1f3289..c9f74d196f2 100644 --- a/.github/actions/spell-check/expect/expect.txt +++ b/.github/actions/spell-check/expect/expect.txt @@ -1529,6 +1529,7 @@ nothrow NOTICKS NOTIMPL notin +NOTOPMOST NOTNULL NOTRACK NOTSUPPORTED