diff --git a/src/cascadia/TerminalApp/AppLogic.idl b/src/cascadia/TerminalApp/AppLogic.idl index 513f6c543e7..12368a8ab10 100644 --- a/src/cascadia/TerminalApp/AppLogic.idl +++ b/src/cascadia/TerminalApp/AppLogic.idl @@ -11,6 +11,7 @@ namespace TerminalApp { DefaultMode, MaximizedMode, + FullscreenMode, }; [default_interface] runtimeclass AppLogic : IF7Listener diff --git a/src/cascadia/TerminalApp/GlobalAppSettings.cpp b/src/cascadia/TerminalApp/GlobalAppSettings.cpp index 52d7368330f..cdb67c1b81d 100644 --- a/src/cascadia/TerminalApp/GlobalAppSettings.cpp +++ b/src/cascadia/TerminalApp/GlobalAppSettings.cpp @@ -38,6 +38,7 @@ static constexpr std::string_view ConfirmCloseAllKey{ "confirmCloseAllTabs" }; static constexpr std::string_view SnapToGridOnResizeKey{ "snapToGridOnResize" }; static constexpr std::wstring_view DefaultLaunchModeValue{ L"default" }; static constexpr std::wstring_view MaximizedLaunchModeValue{ L"maximized" }; +static constexpr std::wstring_view FullscreenLaunchModeValue{ L"fullscreen" }; static constexpr std::wstring_view LightThemeValue{ L"light" }; static constexpr std::wstring_view DarkThemeValue{ L"dark" }; static constexpr std::wstring_view SystemThemeValue{ L"system" }; @@ -473,6 +474,10 @@ LaunchMode GlobalAppSettings::_ParseLaunchMode(const std::wstring& launchModeStr { return LaunchMode::MaximizedMode; } + else if (launchModeString == FullscreenLaunchModeValue) + { + return LaunchMode::FullscreenMode; + } return LaunchMode::DefaultMode; } @@ -490,6 +495,8 @@ std::wstring_view GlobalAppSettings::_SerializeLaunchMode(const LaunchMode launc { case LaunchMode::MaximizedMode: return MaximizedLaunchModeValue; + case LaunchMode::FullscreenMode: + return FullscreenLaunchModeValue; default: return DefaultLaunchModeValue; } diff --git a/src/cascadia/TerminalApp/TerminalPage.cpp b/src/cascadia/TerminalApp/TerminalPage.cpp index 88829ba9247..2d074ba9a0f 100644 --- a/src/cascadia/TerminalApp/TerminalPage.cpp +++ b/src/cascadia/TerminalApp/TerminalPage.cpp @@ -188,8 +188,8 @@ namespace winrt::TerminalApp::implementation if (_appArgs.GetStartupActions().empty()) { _OpenNewTab(nullptr); - _startupState = StartupState::Initialized; - _InitializedHandlers(*this, nullptr); + + _CompleteInitialization(); } else { @@ -222,9 +222,31 @@ namespace winrt::TerminalApp::implementation { _actionDispatch->DoAction(action); } - _startupState = StartupState::Initialized; - _InitializedHandlers(*this, nullptr); + + _CompleteInitialization(); + } + } + + // Method Description: + // - Perform and steps that need to be done once our initial state is all + // set up. This includes entering fullscreen mode and firing our + // Initialized event. + // Arguments: + // - + // Return Value: + // - + void TerminalPage::_CompleteInitialization() + { + // GH#288 - When we finish initialization, if the user wanted us + // launched _fullscreen_, toggle fullscreen mode. This will make sure + // that the window size is _first_ set up as something sensible, so + // leaving fullscreen returns to a reasonable size. + if (_settings->GlobalSettings().GetLaunchMode() == winrt::TerminalApp::LaunchMode::FullscreenMode) + { + _ToggleFullscreen(); } + _startupState = StartupState::Initialized; + _InitializedHandlers(*this, nullptr); } // Method Description: diff --git a/src/cascadia/TerminalApp/TerminalPage.h b/src/cascadia/TerminalApp/TerminalPage.h index 2f6523a6672..f03a5d639c2 100644 --- a/src/cascadia/TerminalApp/TerminalPage.h +++ b/src/cascadia/TerminalApp/TerminalPage.h @@ -173,6 +173,8 @@ namespace winrt::TerminalApp::implementation void _SetNewTabButtonColor(const Windows::UI::Color& color, const Windows::UI::Color& accentColor); void _ClearNewTabButtonColor(); + void _CompleteInitialization(); + #pragma region ActionHandlers // These are all defined in AppActionHandlers.cpp void _HandleOpenNewTabDropdown(const IInspectable& sender, const TerminalApp::ActionEventArgs& args); diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index c27bfae1ad1..4ed62bf66ba 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -239,61 +239,59 @@ void AppHost::_HandleCreateWindow(const HWND hwnd, RECT proposedRect, winrt::Ter long adjustedHeight = 0; long adjustedWidth = 0; - if (launchMode == winrt::TerminalApp::LaunchMode::DefaultMode) + + // Find nearest monitor. + HMONITOR hmon = MonitorFromRect(&proposedRect, MONITOR_DEFAULTTONEAREST); + + // Get nearest monitor information + MONITORINFO monitorInfo; + monitorInfo.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(hmon, &monitorInfo); + + // This API guarantees that dpix and dpiy will be equal, but neither is an + // optional parameter so give two UINTs. + UINT dpix = USER_DEFAULT_SCREEN_DPI; + UINT dpiy = USER_DEFAULT_SCREEN_DPI; + // If this fails, we'll use the default of 96. + GetDpiForMonitor(hmon, MDT_EFFECTIVE_DPI, &dpix, &dpiy); + + // We need to check if the top left point of the titlebar of the window is within any screen + RECT offScreenTestRect; + offScreenTestRect.left = proposedRect.left; + offScreenTestRect.top = proposedRect.top; + offScreenTestRect.right = offScreenTestRect.left + 1; + offScreenTestRect.bottom = offScreenTestRect.top + 1; + + bool isTitlebarIntersectWithMonitors = false; + EnumDisplayMonitors( + nullptr, &offScreenTestRect, [](HMONITOR, HDC, LPRECT, LPARAM lParam) -> BOOL { + auto intersectWithMonitor = reinterpret_cast(lParam); + *intersectWithMonitor = true; + // Continue the enumeration + return FALSE; + }, + reinterpret_cast(&isTitlebarIntersectWithMonitors)); + + if (!isTitlebarIntersectWithMonitors) { - // Find nearest monitor. - HMONITOR hmon = MonitorFromRect(&proposedRect, MONITOR_DEFAULTTONEAREST); - - // Get nearest monitor information - MONITORINFO monitorInfo; - monitorInfo.cbSize = sizeof(MONITORINFO); - GetMonitorInfo(hmon, &monitorInfo); - - // This API guarantees that dpix and dpiy will be equal, but neither is an - // optional parameter so give two UINTs. - UINT dpix = USER_DEFAULT_SCREEN_DPI; - UINT dpiy = USER_DEFAULT_SCREEN_DPI; - // If this fails, we'll use the default of 96. - GetDpiForMonitor(hmon, MDT_EFFECTIVE_DPI, &dpix, &dpiy); - - // We need to check if the top left point of the titlebar of the window is within any screen - RECT offScreenTestRect; - offScreenTestRect.left = proposedRect.left; - offScreenTestRect.top = proposedRect.top; - offScreenTestRect.right = offScreenTestRect.left + 1; - offScreenTestRect.bottom = offScreenTestRect.top + 1; - - bool isTitlebarIntersectWithMonitors = false; - EnumDisplayMonitors( - nullptr, &offScreenTestRect, [](HMONITOR, HDC, LPRECT, LPARAM lParam) -> BOOL { - auto intersectWithMonitor = reinterpret_cast(lParam); - *intersectWithMonitor = true; - // Continue the enumeration - return FALSE; - }, - reinterpret_cast(&isTitlebarIntersectWithMonitors)); - - if (!isTitlebarIntersectWithMonitors) - { - // If the title bar is out-of-screen, we set the initial position to - // the top left corner of the nearest monitor - proposedRect.left = monitorInfo.rcWork.left; - proposedRect.top = monitorInfo.rcWork.top; - } + // If the title bar is out-of-screen, we set the initial position to + // the top left corner of the nearest monitor + proposedRect.left = monitorInfo.rcWork.left; + proposedRect.top = monitorInfo.rcWork.top; + } - auto initialSize = _logic.GetLaunchDimensions(dpix); + auto initialSize = _logic.GetLaunchDimensions(dpix); - const short islandWidth = Utils::ClampToShortMax( - static_cast(ceil(initialSize.X)), 1); - const short islandHeight = Utils::ClampToShortMax( - static_cast(ceil(initialSize.Y)), 1); + const short islandWidth = Utils::ClampToShortMax( + static_cast(ceil(initialSize.X)), 1); + const short islandHeight = Utils::ClampToShortMax( + static_cast(ceil(initialSize.Y)), 1); - // Get the size of a window we'd need to host that client rect. This will - // add the titlebar space. - const auto nonClientSize = _window->GetTotalNonClientExclusiveSize(dpix); - adjustedWidth = islandWidth + nonClientSize.cx; - adjustedHeight = islandHeight + nonClientSize.cy; - } + // Get the size of a window we'd need to host that client rect. This will + // add the titlebar space. + const auto nonClientSize = _window->GetTotalNonClientExclusiveSize(dpix); + adjustedWidth = islandWidth + nonClientSize.cx; + adjustedHeight = islandHeight + nonClientSize.cy; const COORD origin{ gsl::narrow(proposedRect.left), gsl::narrow(proposedRect.top) }; diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 73cb2d7a3c5..add8ac56898 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -143,6 +143,7 @@ void IslandWindow::_HandleCreateWindow(const WPARAM, const LPARAM lParam) noexce } ShowWindow(_window.get(), nCmdShow); + UpdateWindow(_window.get()); } diff --git a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp index 2dfa8bdf75a..cea3d07d387 100644 --- a/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp @@ -838,7 +838,10 @@ void NonClientIslandWindow::OnApplicationThemeChanged(const ElementTheme& reques void NonClientIslandWindow::_SetIsFullscreen(const bool fullscreenEnabled) { IslandWindow::_SetIsFullscreen(fullscreenEnabled); - _titlebar.Visibility(!fullscreenEnabled ? Visibility::Visible : Visibility::Collapsed); + if (_titlebar) + { + _titlebar.Visibility(!fullscreenEnabled ? 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