diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 3b54950ec00..f2a6f8bd040 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -834,10 +834,20 @@ void IslandWindow::SetAlwaysOnTop(const bool alwaysOnTop) // - void IslandWindow::ShowWindowChanged(const bool showOrHide) { - const auto hwnd = GetHandle(); - if (hwnd) + if (const auto hwnd = GetHandle()) { - PostMessage(hwnd, WM_SYSCOMMAND, showOrHide ? SC_RESTORE : SC_MINIMIZE, 0); + // IMPORTANT! + // + // ONLY "restore" if already minimized. If the window is maximized or + // snapped, a restore will restore-down the window instead. + if (showOrHide == true && ::IsIconic(hwnd)) + { + ::PostMessage(hwnd, WM_SYSCOMMAND, SC_RESTORE, 0); + } + else if (showOrHide == false) + { + ::PostMessage(hwnd, WM_SYSCOMMAND, SC_MINIMIZE, 0); + } } } diff --git a/src/interactivity/base/InteractivityFactory.cpp b/src/interactivity/base/InteractivityFactory.cpp index 737057bda87..baa3ab861a0 100644 --- a/src/interactivity/base/InteractivityFactory.cpp +++ b/src/interactivity/base/InteractivityFactory.cpp @@ -436,6 +436,15 @@ void InteractivityFactory::SetPseudoWindowCallback(std::function fun // It can be fun to toggle WM_QUERYOPEN but DefWindowProc returns TRUE. case WM_SIZE: { + // Curiously, at least on Windows 10 (and rarely on Windows 11), if you + // minimize the Terminal by clicking on the taskbar, then alt-tab to try + // and restore the window, the Taskbar will decide to call + // SwitchToWindow on us, the invisible, owned window of the main window. + // When that happens, we'll get a WM_SIZE(SIZE_RESTORED, lParam=0). The + // main window will NOT get a SwitchToWindow called. If we don't + // actually inform the hosting process about this, then the main HWND + // might stay hidden. Refer to GH#13589 + if (wParam == SIZE_RESTORED) { _WritePseudoWindowCallback(true); @@ -447,23 +456,23 @@ void InteractivityFactory::SetPseudoWindowCallback(std::function fun } break; } - // case WM_WINDOWPOSCHANGING: - // As long as user32 didn't eat the `ShowWindow` call because the window state requested - // matches the existing WS_VISIBLE state of the HWND... we should hear from it in WM_WINDOWPOSCHANGING. - // WM_WINDOWPOSCHANGING can tell us a bunch through the flags fields. - // We can also check IsIconic/IsZoomed on the HWND during the message - // and we could suppress the change to prevent things from happening. + // case WM_WINDOWPOSCHANGING: + // As long as user32 didn't eat the `ShowWindow` call because the window state requested + // matches the existing WS_VISIBLE state of the HWND... we should hear from it in WM_WINDOWPOSCHANGING. + // WM_WINDOWPOSCHANGING can tell us a bunch through the flags fields. + // We can also check IsIconic/IsZoomed on the HWND during the message + // and we could suppress the change to prevent things from happening. // case WM_SYSCOMMAND: - // WM_SYSCOMMAND will not come through. Don't try. + // WM_SYSCOMMAND will not come through. Don't try. + // WM_SHOWWINDOW does come through on some of the messages. case WM_SHOWWINDOW: - // WM_SHOWWINDOW comes through on some of the messages. + { + if (0 == lParam) // Someone explicitly called ShowWindow on us. { - if (0 == lParam) // Someone explicitly called ShowWindow on us. - { - _WritePseudoWindowCallback((bool)wParam); - } + _WritePseudoWindowCallback((bool)wParam); } } + } // If we get this far, call the default window proc return DefWindowProcW(hWnd, Message, wParam, lParam); } @@ -478,18 +487,12 @@ void InteractivityFactory::SetPseudoWindowCallback(std::function fun // - void InteractivityFactory::_WritePseudoWindowCallback(bool showOrHide) { - // BODGY - // - // GH#13158 - At least temporarily, only allow the PTY to HIDE the terminal - // window. There seem to be many issues with this so far, and the quickest - // route to mitigate them seems to be limiting the interaction here to - // allowing ConPTY to minimize the terminal only. This will still allow - // applications to hide the Terminal via GetConsoleWindow(), but should - // broadly prevent any other impact of this feature. + // IMPORTANT! // - // Should we need to restore this functionality in the future, we should - // only do so with great caution. - if (_pseudoWindowMessageCallback && showOrHide == false) + // A hosting terminal window should only "restore" itself in response to + // this message, if it's already minimized. If the window is maximized a + // restore will restore-down the window instead. + if (_pseudoWindowMessageCallback) { _pseudoWindowMessageCallback(showOrHide); }