Fix multiple regressions since #18215 (#18345)

Fixes
* Cursor vanishing, because
  ```cpp
  CoreWindow::GetForCurrentThread().PointerCursor()
  ```
  returned a non-null, but still invisible cursor.
* Alt/F7 not dispatching to newly created windows, because the
  `WM_ACTIVATE` message now arrives before the `AppHost` is initialized.
  This caused the messages to be delivered to old windows.
* Windows Terminal blocking expedited shutdown,
  because we return `FALSE` on non-`ENDSESSION_CLOSEAPP` messages.

Closes #18331
Closes #18335

## Validation Steps Performed
* Cursor still doesn't really vanish for me in the first place 
* Alt/F7 work in new windows without triggering old ones 
This commit is contained in:
Leonard Hecker 2025-01-06 13:41:19 -08:00 committed by GitHub
parent c6e7f3244b
commit 7cd46c0397
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 49 additions and 29 deletions

View File

@ -57,7 +57,7 @@ DEFINE_ENUM_FLAG_OPERATORS(winrt::Microsoft::Terminal::Control::MouseButtonState
// the current foreground window, but still on top of another Terminal window in the background.
static void hideCursorUntilMoved()
{
static CoreCursor previousCursor{ nullptr };
static bool cursorIsHidden;
static const auto shouldVanish = []() {
BOOL shouldVanish = TRUE;
SystemParametersInfoW(SPI_GETMOUSEVANISH, 0, &shouldVanish, 0);
@ -68,16 +68,16 @@ static void hideCursorUntilMoved()
const auto window = CoreWindow::GetForCurrentThread();
static constexpr auto releaseCapture = [](CoreWindow window, PointerEventArgs) {
if (previousCursor)
if (cursorIsHidden)
{
window.ReleasePointerCapture();
}
};
static constexpr auto restoreCursor = [](CoreWindow window, PointerEventArgs) {
if (previousCursor)
if (cursorIsHidden)
{
window.PointerCursor(previousCursor);
previousCursor = nullptr;
cursorIsHidden = false;
window.PointerCursor(CoreCursor{ CoreCursorType::Arrow, 0 });
}
};
@ -90,20 +90,14 @@ static void hideCursorUntilMoved()
return true;
}();
if (shouldVanish && !previousCursor)
if (shouldVanish && !cursorIsHidden)
{
try
{
const auto window = CoreWindow::GetForCurrentThread();
previousCursor = window.PointerCursor();
if (!previousCursor)
{
return;
}
window.PointerCursor(nullptr);
window.SetPointerCapture();
cursorIsHidden = true;
}
catch (...)
{

View File

@ -815,7 +815,7 @@ void AppHost::_WindowActivated(bool activated)
{
_windowLogic.WindowActivated(activated);
if (activated && _isWindowInitialized != WindowInitializedState::NotInitialized)
if (activated)
{
QueryPerformanceCounter(&_lastActivatedTime);
_virtualDesktopId = {};

View File

@ -413,13 +413,8 @@ void WindowEmperor::HandleCommandlineArgs(int nCmdShow)
// It almost seems like there's a pattern here...
(msg.wParam == VK_SPACE && msg.message == WM_SYSKEYDOWN))
{
if (const auto w = _mostRecentWindow())
{
const auto vkey = gsl::narrow_cast<uint32_t>(msg.wParam);
const auto scanCode = gsl::narrow_cast<uint8_t>(msg.lParam >> 16);
w->OnDirectKeyEvent(vkey, scanCode, keyDown);
continue;
}
_dispatchSpecialKey(msg);
continue;
}
}
@ -442,6 +437,40 @@ void WindowEmperor::HandleCommandlineArgs(int nCmdShow)
__assume(false);
}
void WindowEmperor::_dispatchSpecialKey(MSG& msg) const
{
const auto hwnd = msg.hwnd;
AppHost* window = nullptr;
// Just in case someone has targed a specific HWND,
// we'll try to dispatch it to the corresponding class.
// Usually this will not find anything because under WinUI the hidden CoreInput
// window is responsible for all input handling (for whatever reason).
for (const auto& h : _windows)
{
const auto w = h->GetWindow();
if (w && w->GetHandle() == hwnd)
{
window = h.get();
break;
}
}
if (!window)
{
window = _mostRecentWindow();
if (!window)
{
return;
}
}
const auto vkey = gsl::narrow_cast<uint32_t>(msg.wParam);
const auto scanCode = gsl::narrow_cast<uint8_t>(msg.lParam >> 16);
const bool keyDown = msg.message & 1;
window->OnDirectKeyEvent(vkey, scanCode, keyDown);
}
void WindowEmperor::_dispatchCommandline(winrt::TerminalApp::CommandlineArgs args)
{
const auto exitCode = args.ExitCode();
@ -826,14 +855,10 @@ LRESULT WindowEmperor::_messageHandler(HWND window, UINT const message, WPARAM c
case WM_QUERYENDSESSION:
// For WM_QUERYENDSESSION and WM_ENDSESSION, refer to:
// https://docs.microsoft.com/en-us/windows/win32/rstmgr/guidelines-for-applications
if (lParam == ENDSESSION_CLOSEAPP)
{
// ENDSESSION_CLOSEAPP: The application is using a file that must be replaced,
// the system is being serviced, or system resources are exhausted.
RegisterApplicationRestart(nullptr, RESTART_NO_CRASH | RESTART_NO_HANG);
return TRUE;
}
return FALSE;
// ENDSESSION_CLOSEAPP: The application is using a file that must be replaced,
// the system is being serviced, or system resources are exhausted.
RegisterApplicationRestart(nullptr, RESTART_NO_CRASH | RESTART_NO_HANG);
return TRUE;
case WM_ENDSESSION:
_forcePersistence = true;
PostQuitMessage(0);

View File

@ -50,6 +50,7 @@ private:
AppHost* _mostRecentWindow() const noexcept;
bool _summonWindow(const SummonWindowSelectionArgs& args) const;
void _summonAllWindows() const;
void _dispatchSpecialKey(MSG& msg) const;
void _dispatchCommandline(winrt::TerminalApp::CommandlineArgs args);
safe_void_coroutine _dispatchCommandlineCurrentDesktop(winrt::TerminalApp::CommandlineArgs args);
LRESULT _messageHandler(HWND window, UINT message, WPARAM wParam, LPARAM lParam) noexcept;