Change the candidate window to a stable transparent host window occupying about 1/4 of the screen (updating with the cursor monitor/DPI), with content wrapping according to the host width and scrolling according to the host height, and fix the issues of high-DPI edge cropping and inconsistency between measurement and CSS limits.

This commit is contained in:
fanlusky committed 2026-08-08 21:37:09 +08:00
1 parent 73fd24b53d
commit ac8d47ef09
7 files changed
+580 -75

No files matched your search

+66
View File
@@ -3,6 +3,7 @@
#include "defines/globals.h"
#include "ipc/ipc.h"
#include "webview_utils.h"
#include <algorithm>
#include <cmath>
#include <utility>
#include <winuser.h>
@@ -83,6 +84,68 @@ FLOAT GetScaleForPoint(POINT pt)
return ScaleFromMonitor(MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST));
}
HalfScreenDipLimits QueryHalfScreenDipLimitsForPoint(POINT pt)
{
HalfScreenDipLimits limits{};
limits.scale = GetScaleForPoint(pt);
if (limits.scale <= 0.0f)
{
limits.scale = 1.0f;
}
limits.monitor = GetMonitorCoordinatesFromPoint(pt);
const double monitorWidthPx =
static_cast<double>((std::max)(1, limits.monitor.right - limits.monitor.left));
const double monitorHeightPx =
static_cast<double>((std::max)(1, limits.monitor.bottom - limits.monitor.top));
limits.maxWidthDip = (monitorWidthPx * 0.5) / static_cast<double>(limits.scale);
limits.maxHeightDip = (monitorHeightPx * 0.5) / static_cast<double>(limits.scale);
return limits;
}
HalfScreenDipLimits QueryHalfScreenDipLimitsForHwnd(HWND hwnd)
{
RECT windowRect{};
if (hwnd && GetWindowRect(hwnd, &windowRect))
{
POINT anchor{windowRect.left + (windowRect.right - windowRect.left) / 2,
windowRect.top + (windowRect.bottom - windowRect.top) / 2};
HalfScreenDipLimits limits = QueryHalfScreenDipLimitsForPoint(anchor);
// Prefer the HWND's own DPI once it has landed on a monitor.
const FLOAT hwndScale = GetWindowScale(hwnd);
if (hwndScale > 0.0f)
{
const double monitorWidthPx =
static_cast<double>((std::max)(1, limits.monitor.right - limits.monitor.left));
const double monitorHeightPx =
static_cast<double>((std::max)(1, limits.monitor.bottom - limits.monitor.top));
limits.scale = hwndScale;
limits.maxWidthDip = (monitorWidthPx * 0.5) / static_cast<double>(limits.scale);
limits.maxHeightDip = (monitorHeightPx * 0.5) / static_cast<double>(limits.scale);
}
return limits;
}
POINT origin{0, 0};
return QueryHalfScreenDipLimitsForPoint(origin);
}
double ClampWidthDipToHalfScreen(double widthDip, const HalfScreenDipLimits &limits)
{
if (limits.maxWidthDip > 0.0)
{
return (std::min)(widthDip, limits.maxWidthDip);
}
return widthDip;
}
double ClampHeightDipToHalfScreen(double heightDip, const HalfScreenDipLimits &limits)
{
if (limits.maxHeightDip > 0.0)
{
return (std::min)(heightDip, limits.maxHeightDip);
}
return heightDip;
}
MonitorCoordinates GetMonitorCoordinatesFromPoint(POINT pt)
{
return MonitorCoordinatesFromHandle(MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST));
@@ -189,6 +252,9 @@ int AdjustCandidateWindowPosition( //
properPos->first = point->x;
properPos->second = point->y + caretGapPx;
// Clamp to the card itself so a right-edge push leaves the opaque card flush
// with the monitor (shadow may clip). Reserving SHADOW here opened a large
// visible gap at high DPI.
int width = static_cast<int>(std::ceil(containerSize.first * scale));
const double boundary_height_dip = is_vertical ? max_vertical_container_height : containerSize.second;
const int boundary_height = static_cast<int>(std::ceil(boundary_height_dip * scale));