Skip to content

Commit

Permalink
Restore the ability for alt+tab to restore the Terminal after minimiz…
Browse files Browse the repository at this point in the history
…ing with taskbar

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 the invisible, owned ConPTY window instead of the main window. When that happens, ConPTY'll get a `WM_SIZE(SIZE_RESTORED, lParam=0)`. The main window will NOT get a `SwitchToWindow` called. If ConPTY doesn't actually inform the hosting process about this, then the main HWND might stay hidden.

* Refer to #13158 where we disabled this.
* Closes #13589
* **TODO** Does this also address #13248
* Tested manually on a Windows 10 VM.
* Confirmed that opening tabs while maximized/snapped doesn't restore down.
* `[Native]::ShowWindow([Native]::GetConsoleWindow(), 6)` still works
  • Loading branch information
zadjii-msft committed Jul 28, 2022
1 parent 17db409 commit 9c53724
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 26 deletions.
16 changes: 13 additions & 3 deletions src/cascadia/WindowsTerminal/IslandWindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -844,10 +844,20 @@ void IslandWindow::SetAlwaysOnTop(const bool alwaysOnTop)
// - <none>
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);
}
}
}

Expand Down
49 changes: 26 additions & 23 deletions src/interactivity/base/InteractivityFactory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,15 @@ void InteractivityFactory::SetPseudoWindowCallback(std::function<void(bool)> 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);
Expand All @@ -447,23 +456,23 @@ void InteractivityFactory::SetPseudoWindowCallback(std::function<void(bool)> 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);
}
Expand All @@ -478,18 +487,12 @@ void InteractivityFactory::SetPseudoWindowCallback(std::function<void(bool)> fun
// - <none>
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);
}
Expand Down

0 comments on commit 9c53724

Please sign in to comment.