Skip to content

Commit 4c1c2cc

Browse files
committed
fix(tabbookmark): DPI scaling for drag detection
The previous implementation relied on static, unscaled system metrics, causing micro-movements to be seen as drag events on high-resolution screens. This patch introduces `GetDpiForWindow` and scales the drag threshold manually (since `GetSystemMetricsForDpi` does not work as expected) on Windows 10 1607 or later, based on Chromium's. Fix .
1 parent fcd535f commit 4c1c2cc

1 file changed

Lines changed: 32 additions & 7 deletions

File tree

src/tabbookmark.cc

Lines changed: 32 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99

1010
namespace {
1111

12+
// https://source.chromium.org/chromium/chromium/src/+/main:ui/views/view.cc;l=127;drc=f67ec84a19893049f899352c79fa990872da2ff7
13+
constexpr int kDragThreshold = 8;
14+
constexpr UINT kDefaultDpi = 96;
1215
POINT lbutton_down_point = {-1, -1};
1316

1417
// This implements tick fault tolerance to prevent users from directly closing
@@ -219,17 +222,39 @@ bool HandleCloseButton(const MOUSEHOOKSTRUCT* pmouse) {
219222
return true;
220223
}
221224

225+
// https://github.com/Bush2021/chrome_plus/issues/226
226+
UINT GetWindowDpiSafe(HWND hwnd) {
227+
// `GetDpiForWindow` requires Windows 10, version 1607 or later.
228+
const HMODULE user32 = GetModuleHandleW(L"user32.dll");
229+
if (!user32) {
230+
return kDefaultDpi;
231+
}
232+
using GetDpiForWindowFn = UINT(WINAPI*)(HWND);
233+
const auto fn = reinterpret_cast<GetDpiForWindowFn>(
234+
GetProcAddress(user32, "GetDpiForWindow"));
235+
if (!fn) {
236+
return kDefaultDpi;
237+
}
238+
const UINT dpi = fn(hwnd);
239+
return dpi ? dpi : kDefaultDpi;
240+
}
241+
222242
// Check if mouse movement is a drag operation.
223243
// Since `MouseProc` hook doesn't handle any drag-related events,
224244
// this detection can return early to avoid interference.
225245
bool HandleDrag(const MOUSEHOOKSTRUCT* pmouse) {
226-
// Add drag detection logic for
227-
// https://github.com/Bush2021/chrome_plus/issues/152
228-
static const int kDragThresholdX = GetSystemMetrics(SM_CXDRAG);
229-
static const int kDragThresholdY = GetSystemMetrics(SM_CYDRAG);
230-
const int dx = pmouse->pt.x - lbutton_down_point.x;
231-
const int dy = pmouse->pt.y - lbutton_down_point.y;
232-
return (abs(dx) > kDragThresholdX || abs(dy) > kDragThresholdY);
246+
const int dx = std::abs(pmouse->pt.x - lbutton_down_point.x);
247+
const int dy = std::abs(pmouse->pt.y - lbutton_down_point.y);
248+
if (dx <= kDragThreshold && dy <= kDragThreshold) {
249+
return false;
250+
}
251+
252+
const UINT dpi = GetWindowDpiSafe(WindowFromPoint(pmouse->pt));
253+
// We scale it manually since `GetSystemMetricsForDpi` does not work for some
254+
// reason, see https://github.com/AvaloniaUI/Avalonia/issues/12112
255+
const int threshold = MulDiv(kDragThreshold, dpi, kDefaultDpi);
256+
const bool is_drag = (dx > threshold || dy > threshold);
257+
return is_drag;
233258
}
234259

235260
// Open bookmarks in a new tab.

0 commit comments

Comments
 (0)