diff --git a/src/cascadia/TerminalApp/AppLogic.h b/src/cascadia/TerminalApp/AppLogic.h index 1a71f5c1a28..1c7e6b91e21 100644 --- a/src/cascadia/TerminalApp/AppLogic.h +++ b/src/cascadia/TerminalApp/AppLogic.h @@ -159,6 +159,7 @@ namespace winrt::TerminalApp::implementation FORWARDED_TYPED_EVENT(SetTaskbarProgress, winrt::Windows::Foundation::IInspectable, winrt::Windows::Foundation::IInspectable, _root, SetTaskbarProgress); FORWARDED_TYPED_EVENT(IdentifyWindowsRequested, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IdentifyWindowsRequested); FORWARDED_TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs, _root, RenameWindowRequested); + FORWARDED_TYPED_EVENT(IsQuakeWindowChanged, Windows::Foundation::IInspectable, Windows::Foundation::IInspectable, _root, IsQuakeWindowChanged); #ifdef UNIT_TESTING friend class TerminalAppLocalTests::CommandlineTest; diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index 6313f5e765f..6bbd2a5d1e4 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -86,5 +86,6 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler SetTaskbarProgress; event Windows.Foundation.TypedEventHandler IdentifyWindowsRequested; event Windows.Foundation.TypedEventHandler RenameWindowRequested; + event Windows.Foundation.TypedEventHandler IsQuakeWindowChanged; } } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index cbeae8d2722..cb85f4a7b7b 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -2049,9 +2049,17 @@ namespace winrt::TerminalApp::implementation // - void TerminalPage::ToggleFocusMode() { - _isInFocusMode = !_isInFocusMode || IsQuakeWindow(); - _UpdateTabView(); - _FocusModeChangedHandlers(*this, nullptr); + _SetFocusMode(!_isInFocusMode); + } + + void TerminalPage::_SetFocusMode(const bool inFocusMode) + { + if (inFocusMode != FocusMode()) + { + _isInFocusMode = inFocusMode || IsQuakeWindow(); + _UpdateTabView(); + _FocusModeChangedHandlers(*this, nullptr); + } } // Method Description: @@ -2596,10 +2604,21 @@ namespace winrt::TerminalApp::implementation } void TerminalPage::WindowName(const winrt::hstring& value) { + const bool oldIsQuakeMode = IsQuakeWindow(); if (_WindowName != value) { _WindowName = value; _PropertyChangedHandlers(*this, WUX::Data::PropertyChangedEventArgs{ L"WindowNameForDisplay" }); + + // If we're entering quake mode, or leaving it + if (IsQuakeWindow() != oldIsQuakeMode) + { + // If we're entering QM from ~FM, then this will enter FM + // If we're entering QM from FM, then this will do nothing + // If we're leaving QM (we're already in FM), then this will do nothing + _SetFocusMode(_isInFocusMode); + _IsQuakeWindowChangedHandlers(*this, nullptr); + } } } diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 0a6c0f18475..a918f9c4997 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -123,6 +123,7 @@ namespace winrt::TerminalApp::implementation TYPED_EVENT(Initialized, IInspectable, winrt::Windows::UI::Xaml::RoutedEventArgs); TYPED_EVENT(IdentifyWindowsRequested, IInspectable, IInspectable); TYPED_EVENT(RenameWindowRequested, Windows::Foundation::IInspectable, winrt::TerminalApp::RenameWindowRequestedArgs); + TYPED_EVENT(IsQuakeWindowChanged, IInspectable, IInspectable); private: friend struct TerminalPageT; // for Xaml to bind events @@ -331,6 +332,8 @@ namespace winrt::TerminalApp::implementation void _UpdateTeachingTipTheme(winrt::Windows::UI::Xaml::FrameworkElement element); + void _SetFocusMode(const bool inFocusMode); + #pragma region ActionHandlers // These are all defined in AppActionHandlers.cpp #define ON_ALL_ACTIONS(action) DECLARE_ACTION_HANDLER(action); diff --git a/src/cascadia/TerminalApp/TerminalPage.idl b/src/cascadia/TerminalApp/TerminalPage.idl index 0fb382634f1..f1c1e55fc15 100644 --- a/src/cascadia/TerminalApp/TerminalPage.idl +++ b/src/cascadia/TerminalApp/TerminalPage.idl @@ -55,5 +55,6 @@ namespace TerminalApp event Windows.Foundation.TypedEventHandler SetTaskbarProgress; event Windows.Foundation.TypedEventHandler IdentifyWindowsRequested; event Windows.Foundation.TypedEventHandler RenameWindowRequested; + event Windows.Foundation.TypedEventHandler IsQuakeWindowChanged; } } diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index e837cf8fdfb..3deaa9107c2 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -244,7 +244,6 @@ void AppHost::Initialize() _logic.FullscreenChanged({ this, &AppHost::_FullscreenChanged }); _logic.FocusModeChanged({ this, &AppHost::_FocusModeChanged }); _logic.AlwaysOnTopChanged({ this, &AppHost::_AlwaysOnTopChanged }); - _logic.RaiseVisualBell({ this, &AppHost::_RaiseVisualBell }); _logic.Create(); @@ -253,6 +252,7 @@ void AppHost::Initialize() _logic.SetTaskbarProgress({ this, &AppHost::SetTaskbarProgress }); _logic.IdentifyWindowsRequested({ this, &AppHost::_IdentifyWindowsRequested }); _logic.RenameWindowRequested({ this, &AppHost::_RenameWindowRequested }); + _logic.IsQuakeWindowChanged({ this, &AppHost::_IsQuakeWindowChanged }); _window->UpdateTitle(_logic.Title()); @@ -687,3 +687,9 @@ winrt::fire_and_forget AppHost::_RenameWindowRequested(const winrt::Windows::Fou } } } + +void AppHost::_IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectable&, + const winrt::Windows::Foundation::IInspectable&) +{ + _window->IsQuakeWindow(_logic.IsQuakeWindow()); +} diff --git a/src/cascadia/WindowsTerminal/AppHost.h b/src/cascadia/WindowsTerminal/AppHost.h index a3a22603adb..3c32af7190a 100644 --- a/src/cascadia/WindowsTerminal/AppHost.h +++ b/src/cascadia/WindowsTerminal/AppHost.h @@ -59,4 +59,7 @@ class AppHost const winrt::TerminalApp::RenameWindowRequestedArgs args); GUID _CurrentDesktopGuid(); + + void _IsQuakeWindowChanged(const winrt::Windows::Foundation::IInspectable& sender, + const winrt::Windows::Foundation::IInspectable& args); }; diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 4b6419ccd13..2a4ad606c1d 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -197,7 +197,7 @@ LRESULT IslandWindow::_OnSizing(const WPARAM wParam, const LPARAM lParam) // If we're the quake window, prevent resizing on all sides except the // bottom. This also applies to resising with the Alt+Space menu - if (_IsQuakeWindow && wParam != WMSZ_BOTTOM) + if (IsQuakeWindow() && wParam != WMSZ_BOTTOM) { // Stuff our current window size into the lParam, and return true. This // will tell User32 to use our current dimensions to resize to. @@ -271,7 +271,7 @@ LRESULT IslandWindow::_OnMoving(const WPARAM /*wParam*/, const LPARAM lParam) { LPRECT winRect = reinterpret_cast(lParam); // If we're the quake window, prevent moving the window - if (_IsQuakeWindow) + if (IsQuakeWindow()) { // Stuff our current window into the lParam, and return true. This // will tell User32 to use our current position to move to. @@ -787,6 +787,7 @@ void IslandWindow::_SetIsBorderless(const bool borderlessEnabled) // 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(), @@ -918,5 +919,52 @@ winrt::fire_and_forget IslandWindow::SummonWindow() LOG_IF_WIN32_BOOL_FALSE(ShowWindow(_window.get(), SW_SHOW)); } +bool IslandWindow::IsQuakeWindow() const noexcept +{ + return _isQuakeWindow; +} + +void IslandWindow::IsQuakeWindow(bool isQuakeWindow) noexcept +{ + if (_isQuakeWindow != isQuakeWindow) + { + _isQuakeWindow = isQuakeWindow; + if (IsQuakeWindow()) + { + _enterQuakeMode(); + } + } +} + +void IslandWindow::_enterQuakeMode() +{ + RECT windowRect = GetWindowRect(); + HMONITOR hmon = MonitorFromRect(&windowRect, MONITOR_DEFAULTTONEAREST); + MONITORINFO nearestMonitorInfo; + nearestMonitorInfo.cbSize = sizeof(MONITORINFO); + // Get monitor dimensions: + GetMonitorInfo(hmon, &nearestMonitorInfo); + const COORD desktopDimensions{ gsl::narrow(nearestMonitorInfo.rcWork.right - nearestMonitorInfo.rcWork.left), + gsl::narrow(nearestMonitorInfo.rcWork.bottom - nearestMonitorInfo.rcWork.top) }; + + const til::point origin{ + ::base::saturated_cast(nearestMonitorInfo.rcWork.left), + ::base::saturated_cast(nearestMonitorInfo.rcWork.top) + }; + const til::size dimensions{ + desktopDimensions.X, + desktopDimensions.Y / 2 + }; + + const til::rectangle newRect{ origin, dimensions }; + SetWindowPos(GetHandle(), + HWND_TOP, + newRect.left(), + newRect.top(), + newRect.width(), + newRect.height(), + SWP_SHOWWINDOW | SWP_FRAMECHANGED | SWP_NOACTIVATE); +} + DEFINE_EVENT(IslandWindow, DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>); DEFINE_EVENT(IslandWindow, WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>); diff --git a/src/cascadia/WindowsTerminal/IslandWindow.h b/src/cascadia/WindowsTerminal/IslandWindow.h index 7b24f6f50a6..abd7f755df8 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.h +++ b/src/cascadia/WindowsTerminal/IslandWindow.h @@ -40,7 +40,8 @@ class IslandWindow : winrt::fire_and_forget SummonWindow(); - WINRT_PROPERTY(bool, IsQuakeWindow, false); + bool IsQuakeWindow() const noexcept; + void IsQuakeWindow(bool isQuakeWindow) noexcept; DECLARE_EVENT(DragRegionClicked, _DragRegionClickedHandlers, winrt::delegate<>); DECLARE_EVENT(WindowCloseButtonClicked, _windowCloseButtonClickedHandler, winrt::delegate<>); @@ -86,6 +87,9 @@ class IslandWindow : void _OnGetMinMaxInfo(const WPARAM wParam, const LPARAM lParam); long _calculateTotalSize(const bool isWidth, const long clientSize, const long nonClientSize); + bool _isQuakeWindow{ false }; + void _enterQuakeMode(); + private: // This minimum width allows for width the tabs fit static constexpr long minimumWidth = 460L;