1
0
Fork 0
mirror of https://github.com/juce-framework/JUCE.git synced 2026-02-03 03:30:06 +00:00

Windowing: Fix issue where components dragged between monitors with different scalings could detach from the mouse

This bug could be observed by running the WidgetsDemo Drag+Drop pane on
Windows 10, and dragging an item between two displays at different scale
factors.

This is issue is a regression introduced in
9817a2bb66. The regression was caused by
the change in mouse position calculation. The incorrect version switched
to using ClientToScreen, but the correct version used
getPointFromLocalLParam.

The function getPointFromLocalLParam was replaced by clientLParamToPoint
in 24ab3cb6a3, and is restored by this
commit.
This commit is contained in:
reuk 2024-11-27 20:10:35 +00:00
parent c24d1a17a7
commit 2fcf9ebf38
No known key found for this signature in database

View file

@ -2683,22 +2683,15 @@ private:
client,
};
std::optional<LRESULT> doMouseMove (LPARAM lParam, bool isMouseDownEvent, WindowArea area)
std::optional<LRESULT> doMouseMove (const LPARAM lParam, bool isMouseDownEvent, WindowArea area)
{
auto point = getPOINTFromLParam (lParam);
if (area == WindowArea::client)
ClientToScreen (hwnd, &point);
const auto adjustedLParam = MAKELPARAM (point.x, point.y);
// Check if the mouse has moved since being pressed in the caption area.
// If it has, then we defer to DefWindowProc to handle the mouse movement.
// Allowing DefWindowProc to handle WM_NCLBUTTONDOWN directly will pause message
// processing (and therefore painting) when the mouse is clicked in the caption area,
// which is why we wait until the mouse is *moved* before asking the system to take over.
// Letting the system handle the move is important for things like Aero Snap to work.
if (captionMouseDown.has_value() && *captionMouseDown != adjustedLParam)
if (area == WindowArea::nonclient && captionMouseDown.has_value() && *captionMouseDown != lParam)
{
captionMouseDown.reset();
@ -2710,20 +2703,21 @@ private:
// ModifierKeys::currentModifiers gets left in the wrong state. As a workaround, we
// manually update the modifier keys after DefWindowProc exits, and update the
// capture state if necessary.
const auto result = DefWindowProc (hwnd, WM_NCLBUTTONDOWN, HTCAPTION, adjustedLParam);
const auto result = DefWindowProc (hwnd, WM_NCLBUTTONDOWN, HTCAPTION, lParam);
getMouseModifiers();
releaseCaptureIfNecessary();
return result;
}
const auto position = getLocalPointFromScreenLParam (adjustedLParam);
ModifierKeys modsToSend (ModifierKeys::currentModifiers);
// this will be handled by WM_TOUCH
if (isTouchEvent() || areOtherTouchSourcesActive())
return {};
const auto position = area == WindowArea::client ? getPointFromLocalLParam (lParam)
: getLocalPointFromScreenLParam (lParam);
if (! isMouseOver)
{
isMouseOver = true;
@ -2808,7 +2802,7 @@ private:
isDragging = true;
doMouseEvent (clientLparamToPoint (lParam), MouseInputSource::defaultPressure);
doMouseEvent (getPointFromLocalLParam (lParam), MouseInputSource::defaultPressure);
}
}
@ -3726,11 +3720,21 @@ private:
return globalToLocal (convertPhysicalScreenPointToLogical (globalPos, hwnd).toFloat());
}
Point<float> clientLparamToPoint (LPARAM lParam)
Point<float> getPointFromLocalLParam (LPARAM lParam) noexcept
{
auto point = getPOINTFromLParam (lParam);
ClientToScreen (hwnd, &point);
return getLocalPointFromScreenLParam (MAKELPARAM (point.x, point.y));
const auto p = D2DUtilities::toPoint (getPOINTFromLParam (lParam));
if (! isPerMonitorDPIAwareWindow (hwnd))
return p.toFloat();
// LPARAM is relative to this window's top-left but may be on a different monitor so we need to calculate the
// physical screen position and then convert this to local logical coordinates
auto r = getWindowScreenRect (hwnd);
const auto windowBorder = findPhysicalBorderSize().value_or (BorderSize<int>{});
const auto offset = p
+ Point { (int) r.left, (int) r.top }
+ Point { windowBorder.getLeft(), windowBorder.getTop() };
return globalToLocal (Desktop::getInstance().getDisplays().physicalToLogical (offset).toFloat());
}
Point<float> getCurrentMousePos() noexcept
@ -3978,7 +3982,7 @@ private:
case WM_LBUTTONUP:
case WM_MBUTTONUP:
case WM_RBUTTONUP:
doMouseUp (clientLparamToPoint (lParam), wParam);
doMouseUp (getPointFromLocalLParam (lParam), wParam);
return 0;
case WM_POINTERWHEEL: