mirror of
https://github.com/microsoft/terminal.git
synced 2025-12-10 18:43:54 -06:00
wpf: use the new TSF implementation (#18861)
This fixes two issues in the WPF terminal control: - The emoji picker and other IME candidate windows didn't show up in the right place - Submitting an emoji via the emoji picker would result in two win32 input mode events with a VK of 65535 and the surrogate pair halves. I am not sure I did the right thing with the thread TSF handle... (cherry picked from commit 06f736bebe84eda0c34b935a875eebe031a899b7) Service-Card-Id: PVTI_lADOAF3p4s4AxadtzgZ-Sw0 Service-Version: 1.23
This commit is contained in:
parent
5ddbb9897b
commit
c2f9191fc3
@ -19,6 +19,79 @@ using namespace ::Microsoft::Terminal::Core;
|
||||
|
||||
static LPCWSTR term_window_class = L"HwndTerminalClass";
|
||||
|
||||
STDMETHODIMP HwndTerminal::TsfDataProvider::QueryInterface(REFIID, void**) noexcept
|
||||
{
|
||||
return E_NOTIMPL;
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE HwndTerminal::TsfDataProvider::AddRef() noexcept
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
ULONG STDMETHODCALLTYPE HwndTerminal::TsfDataProvider::Release() noexcept
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
HWND HwndTerminal::TsfDataProvider::GetHwnd()
|
||||
{
|
||||
return _terminal->GetHwnd();
|
||||
}
|
||||
|
||||
RECT HwndTerminal::TsfDataProvider::GetViewport()
|
||||
{
|
||||
const auto hwnd = GetHwnd();
|
||||
|
||||
RECT rc;
|
||||
GetClientRect(hwnd, &rc);
|
||||
|
||||
// https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-getclientrect
|
||||
// > The left and top members are zero. The right and bottom members contain the width and height of the window.
|
||||
// --> We can turn the client rect into a screen-relative rect by adding the left/top position.
|
||||
ClientToScreen(hwnd, reinterpret_cast<POINT*>(&rc));
|
||||
rc.right += rc.left;
|
||||
rc.bottom += rc.top;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
RECT HwndTerminal::TsfDataProvider::GetCursorPosition()
|
||||
{
|
||||
// Convert from columns/rows to pixels.
|
||||
til::point cursorPos;
|
||||
til::size fontSize;
|
||||
{
|
||||
const auto lock = _terminal->_terminal->LockForReading();
|
||||
cursorPos = _terminal->_terminal->GetCursorPosition(); // measured in terminal cells
|
||||
fontSize = _terminal->_actualFont.GetSize(); // measured in pixels, not DIP
|
||||
}
|
||||
POINT ptSuggestion = {
|
||||
.x = cursorPos.x * fontSize.width,
|
||||
.y = cursorPos.y * fontSize.height,
|
||||
};
|
||||
|
||||
ClientToScreen(GetHwnd(), &ptSuggestion);
|
||||
|
||||
// Final measurement should be in pixels
|
||||
return {
|
||||
.left = ptSuggestion.x,
|
||||
.top = ptSuggestion.y,
|
||||
.right = ptSuggestion.x + fontSize.width,
|
||||
.bottom = ptSuggestion.y + fontSize.height,
|
||||
};
|
||||
}
|
||||
|
||||
void HwndTerminal::TsfDataProvider::HandleOutput(std::wstring_view text)
|
||||
{
|
||||
_terminal->_WriteTextToConnection(text);
|
||||
}
|
||||
|
||||
Microsoft::Console::Render::Renderer* HwndTerminal::TsfDataProvider::GetRenderer()
|
||||
{
|
||||
return _terminal->_renderer.get();
|
||||
}
|
||||
|
||||
// This magic flag is "documented" at https://msdn.microsoft.com/en-us/library/windows/desktop/ms646301(v=vs.85).aspx
|
||||
// "If the high-order bit is 1, the key is down; otherwise, it is up."
|
||||
static constexpr short KeyPressed{ gsl::narrow_cast<short>(0x8000) };
|
||||
@ -242,6 +315,7 @@ try
|
||||
{
|
||||
// As a rule, detach resources from the Terminal before shutting them down.
|
||||
// This ensures that teardown is reentrant.
|
||||
_tsfHandle = {};
|
||||
|
||||
// Shut down the renderer (and therefore the thread) before we implode
|
||||
_renderer.reset();
|
||||
@ -941,6 +1015,16 @@ void __stdcall TerminalSetFocus(void* terminal)
|
||||
{
|
||||
LOG_IF_FAILED(uiaEngine->Enable());
|
||||
}
|
||||
publicTerminal->_FocusTSF();
|
||||
}
|
||||
|
||||
void HwndTerminal::_FocusTSF() noexcept
|
||||
{
|
||||
if (!_tsfHandle)
|
||||
{
|
||||
_tsfHandle = Microsoft::Console::TSF::Handle::Create();
|
||||
_tsfHandle.AssociateFocus(&_tsfDataProvider);
|
||||
}
|
||||
}
|
||||
|
||||
void __stdcall TerminalKillFocus(void* terminal)
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include "../../buffer/out/textBuffer.hpp"
|
||||
#include "../../renderer/inc/FontInfoDesired.hpp"
|
||||
#include "../../types/IControlAccessibilityInfo.h"
|
||||
#include "../../tsf/Handle.h"
|
||||
|
||||
namespace Microsoft::Console::Render::Atlas
|
||||
{
|
||||
@ -85,6 +86,21 @@ public:
|
||||
static LRESULT CALLBACK HwndTerminalWndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) noexcept;
|
||||
|
||||
private:
|
||||
struct TsfDataProvider : public Microsoft::Console::TSF::IDataProvider
|
||||
{
|
||||
TsfDataProvider(HwndTerminal* t) :
|
||||
_terminal(t) {}
|
||||
virtual ~TsfDataProvider() = default;
|
||||
STDMETHODIMP TsfDataProvider::QueryInterface(REFIID, void**) noexcept override;
|
||||
ULONG STDMETHODCALLTYPE TsfDataProvider::AddRef() noexcept override;
|
||||
ULONG STDMETHODCALLTYPE TsfDataProvider::Release() noexcept override;
|
||||
HWND GetHwnd() override;
|
||||
RECT GetViewport() override;
|
||||
RECT GetCursorPosition() override;
|
||||
void HandleOutput(std::wstring_view text) override;
|
||||
Microsoft::Console::Render::Renderer* GetRenderer() override;
|
||||
HwndTerminal* _terminal;
|
||||
};
|
||||
wil::unique_hwnd _hwnd;
|
||||
FontInfoDesired _desiredFont;
|
||||
FontInfo _actualFont;
|
||||
@ -106,6 +122,10 @@ private:
|
||||
std::optional<til::point> _lastMouseClickPos;
|
||||
std::optional<til::point> _singleClickTouchdownPos;
|
||||
|
||||
// _tsfHandle uses _tsfDataProvider. Destructors run from bottom to top; this maintains correct destruction order.
|
||||
TsfDataProvider _tsfDataProvider{ this };
|
||||
Microsoft::Console::TSF::Handle _tsfHandle;
|
||||
|
||||
friend HRESULT _stdcall CreateTerminal(HWND parentHwnd, _Out_ void** hwnd, _Out_ void** terminal);
|
||||
friend HRESULT _stdcall TerminalTriggerResize(_In_ void* terminal, _In_ til::CoordType width, _In_ til::CoordType height, _Out_ til::size* dimensions);
|
||||
friend HRESULT _stdcall TerminalTriggerResizeWithDimension(_In_ void* terminal, _In_ til::size dimensions, _Out_ til::size* dimensionsInPixels);
|
||||
@ -129,6 +149,8 @@ private:
|
||||
HRESULT _CopyToSystemClipboard(const std::string& stringToCopy, LPCWSTR lpszFormat) const;
|
||||
void _PasteTextFromClipboard() noexcept;
|
||||
|
||||
void _FocusTSF() noexcept;
|
||||
|
||||
const unsigned int _NumberOfClicks(til::point clickPos, std::chrono::steady_clock::time_point clickTime) noexcept;
|
||||
HRESULT _StartSelection(LPARAM lParam) noexcept;
|
||||
HRESULT _MoveSelection(LPARAM lParam) noexcept;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user