MouseCursor with scaleFactor on Windows


#1

I’m noticing that the Windows version of MouseCursor does not seem to obey a passed in scaleFactor parameter.

Looking at the CustomMouseCursorInfo::create() method in juce_win32_Windowing.cpp, I see that it looks at the system metrics for restricting the size, but scaleFactor does not seem to be used at all.

void* CustomMouseCursorInfo::create() const
{
    const int maxW = GetSystemMetrics (SM_CXCURSOR);
    const int maxH = GetSystemMetrics (SM_CYCURSOR);

#if SCALE_FACTOR_TEST
    int w = (float)image.getWidth() / scaleFactor + 0.5;
    int h = (float)image.getHeight() / scaleFactor + 0.5;
    Image im = image.rescaled(w, h);

    int hotspotX = hotspot.x;
    int hotspotY = hotspot.y;
#else
    Image im(image);

    int hotspotX = hotspot.x;
    int hotspotY = hotspot.y;
#endif
   ....

I tried switching to the above SCALE_FACTOR_TEST code and that seems to do the trick. But I’m just wondering if I’m missing some reason that the scaleFactor is intentionally ignored.


MouseCursor hotspot and scaleFactor question
#2

Actually, this appears to go a bit deeper. This is orthogonal to the missing scaleFactor code, but custom cursors in general are incorrectly sized on high DPI.

Simple test: juce Hello World example. Add the following method:

void MainComponent::mouseMove(const MouseEvent & inMouseEvent)
{
    setMouseCursor(juce::MouseCursor::DraggingHandCursor);
}

If you run this on a high-DPI monitor the resulting dragging hand icon appears tiny.


#3

Not sure if anyone else cares about this one, but just in case…

My workaround for this is to patch the juce code as mentioned in my first comment, and then create a MouseCursor per DPI scale.

To get the current DPI (regardless of app-DPI-awareness) I use the PhysicalToLogicalPointForPerMonitorDPI() function.

It feels pretty hacky to me, but then so does Windows’ DPI awareness in general.