diff --git a/src/cascadia/TerminalControl/TermControl.cpp b/src/cascadia/TerminalControl/TermControl.cpp index 9f17c8692dd..3724edd542c 100644 --- a/src/cascadia/TerminalControl/TermControl.cpp +++ b/src/cascadia/TerminalControl/TermControl.cpp @@ -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 (...) { diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index c7db8e38e1a..ac255aa95b2 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -815,7 +815,7 @@ void AppHost::_WindowActivated(bool activated) { _windowLogic.WindowActivated(activated); - if (activated && _isWindowInitialized != WindowInitializedState::NotInitialized) + if (activated) { QueryPerformanceCounter(&_lastActivatedTime); _virtualDesktopId = {}; diff --git a/src/cascadia/WindowsTerminal/WindowEmperor.cpp b/src/cascadia/WindowsTerminal/WindowEmperor.cpp index 6c25d4c8ade..dd9499d00ec 100644 --- a/src/cascadia/WindowsTerminal/WindowEmperor.cpp +++ b/src/cascadia/WindowsTerminal/WindowEmperor.cpp @@ -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(msg.wParam); - const auto scanCode = gsl::narrow_cast(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(msg.wParam); + const auto scanCode = gsl::narrow_cast(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); diff --git a/src/cascadia/WindowsTerminal/WindowEmperor.h b/src/cascadia/WindowsTerminal/WindowEmperor.h index db3034bc6db..6b9b101507f 100644 --- a/src/cascadia/WindowsTerminal/WindowEmperor.h +++ b/src/cascadia/WindowsTerminal/WindowEmperor.h @@ -50,6 +50,7 @@ class WindowEmperor 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;