Repository: matplotlib/matplotlib
File: lib/matplotlib/tests/test_backend_qt.py (Python)

Code before:
    assert result == answer


@pytest.mark.backend('QtAgg', skip_on_importerror=True)
def test_device_pixel_ratio_change():
    """
    Make sure that if the pixel ratio changes, the figure dpi changes but the
    widget remains the same logical size.
    """

    prop = 'matplotlib.backends.backend_qt.FigureCanvasQT.devicePixelRatioF'
    with mock.patch(prop) as p:
        p.return_value = 3

        fig = plt.figure(figsize=(5, 2), dpi=120)
        qt_canvas = fig.canvas
        qt_canvas.show()

        def set_device_pixel_ratio(ratio):
            p.return_value = ratio

            current_version = tuple(int(x) for x in QtCore.qVersion().split('.', 2)[:2])
            if current_version >= (6, 6):
                # Emitting this event is simply to trigger the DPI change handler
                # in Matplotlib in the same manner that it would occur normally.
                qt_canvas.eventFilter(
                    None,
                    QtCore.QEvent(QtCore.QEvent.Type.DevicePixelRatioChange))
            else:
                # The value here doesn't matter, as we can't mock the C++ QScreen
                # object, but can override the functional wrapper around it.
                # Emitting this event is simply to trigger the DPI change handler
                # in Matplotlib in the same manner that it would occur normally.
                screen.logicalDotsPerInchChanged.emit(96)

            qt_canvas.draw()
            qt_canvas.flush_events()

            # Make sure the mocking worked
            assert qt_canvas.device_pixel_ratio == ratio

        qt_canvas.manager.show()
        size = qt_canvas.size()
        screen = qt_canvas.window().windowHandle().screen()
        set_device_pixel_ratio(3)

        # The DPI and the renderer width/height change
        assert fig.dpi == 360
        assert qt_canvas.renderer.width == 1800
        assert qt_canvas.renderer.height == 720


Review comment (suggestion):
Is calling eventFilter() the standard way to emit a self-created event? This feels a bit hacky, which may be ok. But I'd rathe comment like this
```suggestion
                # Create an event to explicitly trigger the DPI change handler.
                # We push the event into Qt's event handling system by injecting it into
                # the eventFilter
                qt_canvas.eventFilter(
```


Code after:


@pytest.mark.backend('QtAgg', skip_on_importerror=True)
def test_device_pixel_ratio_change(qt_core):
    """
    Make sure that if the pixel ratio changes, the figure dpi changes but the
    widget remains the same logical size.
    """

    prop = 'matplotlib.backends.backend_qt.FigureCanvasQT.devicePixelRatioF'
    with mock.patch(prop) as p:
        p.return_value = 3

        fig = plt.figure(figsize=(5, 2), dpi=120)
        qt_canvas = fig.canvas
        qt_canvas.show()

        def set_device_pixel_ratio(ratio):
            p.return_value = ratio

            window = qt_canvas.window().windowHandle()
            current_version = tuple(
                int(x) for x in qt_core.qVersion().split('.', 2)[:2])
            if current_version >= (6, 6):
                qt_core.QCoreApplication.sendEvent(
                    window,
                    qt_core.QEvent(qt_core.QEvent.Type.DevicePixelRatioChange))
            else:
                # The value here doesn't matter, as we can't mock the C++ QScreen
                # object, but can override the functional wrapper around it.
                # Emitting this event is simply to trigger the DPI change handler
                # in Matplotlib in the same manner that it would occur normally.
                window.screen().logicalDotsPerInchChanged.emit(96)

            qt_canvas.draw()
            qt_canvas.flush_events()

            # Make sure the mocking worked
            assert qt_canvas.device_pixel_ratio == ratio

        qt_canvas.manager.show()
        size = qt_canvas.size()
        set_device_pixel_ratio(3)

        # The DPI and the renderer width/height change
        assert fig.dpi == 360
        assert qt_canvas.renderer.width == 1800
        assert qt_canvas.renderer.height == 720

        # The actual widget size and figure logical size don't change.
        assert size.width() == 600