fix(tsf): convert candidate anchors to physical coordinates

This commit is contained in:
Ouchihao committed 2026-09-04 18:11:48 +08:00
1 parent 68c203cd5b
commit 089e47b60c
6 files changed
+37 -43

No files matched your search

+3 -2
View File
@@ -54,8 +54,9 @@ STDAPI CGetTextExtentEditSession::DoEditSession(TfEditCookie ec)
return S_OK;
}
Global::Point[0] = rc.left * Global::DpiScale;
Global::Point[1] = rc.bottom * Global::DpiScale;
const POINT anchor = GetPhysicalTextAnchor(_pContextView, rc);
Global::Point[0] = anchor.x;
Global::Point[1] = anchor.y;
if (Global::current_process_name == Global::ZEN_BROWSER)
{
Global::firefox_like_cnt++;
-1
View File
@@ -10,7 +10,6 @@ inline std::wstring ZEN_BROWSER = L"zen.exe";
// inline std::unordered_set<std::wstring> VSCodeSeries = {L"Code.exe", L"Code - Insiders.exe", L"VSCodium.exe"};
// inline bool IsVSCodeLike = false;
inline LONG INVALID_Y = -100000;
inline thread_local float DpiScale = 1.0f;
} // namespace Global
namespace GlobalSettings
-32
View File
@@ -11,7 +11,6 @@
#include <winuser.h>
#include <Windows.h>
#include <shellapi.h>
#include <shellscalingapi.h>
#include <algorithm>
#include <atomic>
#include <string>
@@ -23,7 +22,6 @@
#include "Utils/FanyUtils.h"
#include "../Utils/PerfTimer.h"
#pragma comment(lib, "Shcore.lib")
#pragma comment(lib, "Shell32.lib")
#pragma comment(lib, "Ole32.lib")
@@ -1439,36 +1437,6 @@ STDAPI CMetasequoiaIME::ActivateEx(ITfThreadMgr *pThreadMgr, TfClientId tfClient
// uses terminal activation/deactivation to reconcile floating-toolbar
// visibility and status snapshots to update its displayed mode.
{
HWND hwndTarget = GetFocus();
if (!hwndTarget)
{
hwndTarget = GetForegroundWindow();
}
// Always refresh: a prior UNAWARE host can leave a stale DpiScale on this
// thread, which then mis-multiplies GetTextExt screen coords for DPI-aware
// apps (Word/Excel) — especially damaging on extended displays with
// negative virtual-desktop X.
Global::DpiScale = 1.0f;
if (hwndTarget)
{
DPI_AWARENESS awareness = GetAwarenessFromDpiAwarenessContext(GetWindowDpiAwarenessContext(hwndTarget));
if (awareness == DPI_AWARENESS_UNAWARE)
{
/* 宿主是非感知程序,需要反向缩放 */
DPI_AWARENESS_CONTEXT oldCtx = SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);
HMONITOR hMon = MonitorFromWindow(hwndTarget, MONITOR_DEFAULTTONEAREST);
UINT dpiX = 96, dpiY = 96;
GetDpiForMonitor(hMon, MDT_EFFECTIVE_DPI, &dpiX, &dpiY);
SetThreadDpiAwarenessContext(oldCtx);
Global::DpiScale = dpiX / 96.0f;
}
}
}
return S_OK;
ExitError:
+23 -1
View File
@@ -7,6 +7,22 @@
#include <fmt/xchar.h>
#include "../Utils/PerfTimer.h"
POINT GetPhysicalTextAnchor(_In_ ITfContextView *pContextView, _In_ const RECT &textExtent)
{
POINT anchor = {textExtent.left, textExtent.bottom};
HWND hostWindow = nullptr;
if (SUCCEEDED(pContextView->GetWnd(&hostWindow)) && hostWindow)
{
hostWindow = GetAncestor(hostWindow, GA_ROOT);
POINT physicalAnchor = anchor;
if (hostWindow && LogicalToPhysicalPointForPerMonitorDPI(hostWindow, &physicalAnchor))
{
anchor = physicalAnchor;
}
}
return anchor;
}
CTfTextLayoutSink::CTfTextLayoutSink(_In_ CMetasequoiaIME *pTextService)
{
_pTextService = pTextService;
@@ -223,7 +239,7 @@ HRESULT CTfTextLayoutSink::_UnadviseTextLayoutSink()
* @param lpRect
* @return HRESULT
*/
HRESULT CTfTextLayoutSink::_GetTextExt(_Out_ RECT *lpRect)
HRESULT CTfTextLayoutSink::_GetTextExt(_Out_ RECT *lpRect, _Out_ POINT *lpAnchor)
{
PerfTimer timer;
HRESULT hr = S_OK;
@@ -241,6 +257,7 @@ HRESULT CTfTextLayoutSink::_GetTextExt(_Out_ RECT *lpRect)
// Set default value to make sure the window is hidden by moving it out of the screen
lpRect->left = 0;
lpRect->bottom = Global::INVALID_Y;
*lpAnchor = {0, Global::INVALID_Y};
}
else if (isClipped && lpRect && (lpRect->right <= lpRect->left || lpRect->bottom <= lpRect->top))
{
@@ -248,6 +265,11 @@ HRESULT CTfTextLayoutSink::_GetTextExt(_Out_ RECT *lpRect)
// degenerate clipped extents that would anchor the candidate off-screen.
lpRect->left = 0;
lpRect->bottom = Global::INVALID_Y;
*lpAnchor = {0, Global::INVALID_Y};
}
else
{
*lpAnchor = GetPhysicalTextAnchor(pContextView, *lpRect);
}
pContextView->Release();
+3 -1
View File
@@ -4,6 +4,8 @@
class CMetasequoiaIME;
POINT GetPhysicalTextAnchor(_In_ ITfContextView *pContextView, _In_ const RECT &textExtent);
class CTfTextLayoutSink : public ITfTextLayoutSink
{
public:
@@ -21,7 +23,7 @@ class CTfTextLayoutSink : public ITfTextLayoutSink
HRESULT _StartLayout(_In_ ITfContext *pContextDocument, TfEditCookie ec, _In_ ITfRange *pRangeComposition);
VOID _EndLayout();
HRESULT _GetTextExt(_Out_ RECT *lpRect);
HRESULT _GetTextExt(_Out_ RECT *lpRect, _Out_ POINT *lpAnchor);
ITfContext *_GetContextDocument()
{
return _pContextDocument;
+8 -6
View File
@@ -819,10 +819,11 @@ HRESULT CCandidateListUIPresenter::_StartCandidateList(TfClientId tfClientId, _I
_candidateWindowVisible = FALSE;
RECT rcTextExt;
if (SUCCEEDED(_GetTextExt(&rcTextExt)))
POINT anchor;
if (SUCCEEDED(_GetTextExt(&rcTextExt, &anchor)))
{
Global::Point[0] = rcTextExt.left * Global::DpiScale;
Global::Point[1] = rcTextExt.bottom * Global::DpiScale;
Global::Point[0] = anchor.x;
Global::Point[1] = anchor.y;
_LayoutChangeNotification(&rcTextExt);
}
@@ -1083,14 +1084,15 @@ BOOL CCandidateListUIPresenter::_MovePage(_In_ int offSet)
void CCandidateListUIPresenter::_MoveWindowToTextExt()
{
RECT rc;
POINT anchor;
if (FAILED(_GetTextExt(&rc)))
if (FAILED(_GetTextExt(&rc, &anchor)))
{
return;
}
Global::Point[0] = rc.left * Global::DpiScale;
Global::Point[1] = rc.bottom * Global::DpiScale;
Global::Point[0] = anchor.x;
Global::Point[1] = anchor.y;
}
//+---------------------------------------------------------------------------
//