diff --git a/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp b/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp index 88fe008996..3ec2a0b18d 100644 --- a/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp +++ b/modules/juce_gui_basics/mouse/juce_DragAndDropContainer.cpp @@ -324,12 +324,35 @@ private: void setNewScreenPos (Point screenPos) { - auto newPos = screenPos - imageOffset; + setTopLeftPosition (std::invoke ([&] + { + if (auto* p = getParentComponent()) + return p->getLocalPoint (nullptr, screenPos - imageOffset); - if (auto* p = getParentComponent()) - newPos = p->getLocalPoint (nullptr, newPos); + #if JUCE_WINDOWS + // On Windows, the mouse position is continuous in physical pixels across screen boundaries. + // i.e. if two screens are set to different scale factors, when the mouse moves horizontally + // between those screens, the mouse's physical y coordinate will be preserved, and if + // the mouse moves vertically between screens its physical x coordinate will be preserved. - setTopLeftPosition (newPos); + // To avoid the dragged image detaching from the mouse, compute the new top left position + // in physical coords and then convert back to logical. + // If we were to stay in logical coordinates the whole time, the image may detach from the + // mouse because the mouse does not move continuously in logical coordinate space. + + const auto& displays = Desktop::getInstance().getDisplays(); + const auto physicalPos = displays.logicalToPhysical (screenPos); + + float scale = 1.0f; + + if (auto* p = getPeer()) + scale = (float) p->getPlatformScaleFactor(); + + return displays.physicalToLogical (physicalPos - (imageOffset * scale)); + #else + return screenPos - imageOffset; + #endif + })); } void sendDragMove (DragAndDropTarget::SourceDetails& details) const