Support fractional device pixel ratio in native Qt widget
When fractional DPI scaling is used, the VTK render window / interactor has the wrong size because it's calculated from devicePixelRatio()
which is an integer API returning a rounded value.
Starting with Qt 5.6, there's a devicePixelRatioF()
API that can return a non-integer device pixel ratio. This makes sure the new API is used in QVTKOpenGLNativeWidget
, when available.
The problem was first reported by me on the VTK developers mailing list:
https://www.vtk.org/pipermail/vtk-developers/2018-February/035826.html
Test Program (Sphere.cxx
)
#include <vtkSphereSource.h>
#include <vtkPolyData.h>
#include <vtkSmartPointer.h>
#include <vtkPolyDataMapper.h>
#include <vtkActor.h>
#include <vtkRenderWindow.h>
#include <vtkRenderer.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkGenericOpenGLRenderWindow.h>
#include <QApplication>
#include <QPointer>
#include <QSurfaceFormat>
#include <QVTKOpenGLNativeWidget.h>
int main(int argc, char *argv[])
{
QSurfaceFormat::setDefaultFormat(QVTKOpenGLNativeWidget::defaultFormat());
QApplication app(argc, argv);
vtkNew<vtkGenericOpenGLRenderWindow> window;
QPointer<QVTKOpenGLNativeWidget> widget = new QVTKOpenGLNativeWidget();
widget->SetRenderWindow(window.Get());
// Create a sphere
vtkSmartPointer<vtkSphereSource> sphereSource =
vtkSmartPointer<vtkSphereSource>::New();
sphereSource->SetCenter(0.0, 0.0, 0.0);
sphereSource->SetRadius(5.0);
vtkSmartPointer<vtkPolyDataMapper> mapper =
vtkSmartPointer<vtkPolyDataMapper>::New();
mapper->SetInputConnection(sphereSource->GetOutputPort());
vtkSmartPointer<vtkActor> actor =
vtkSmartPointer<vtkActor>::New();
actor->SetMapper(mapper);
vtkSmartPointer<vtkRenderer> renderer =
vtkSmartPointer<vtkRenderer>::New();
window->AddRenderer(renderer);
renderer->AddActor(actor);
widget->resize(300, 300);
widget->show();
return app.exec();
}
CMakeLists.txt
cmake_minimum_required(VERSION 2.8)
PROJECT(dpibug)
find_package(VTK REQUIRED)
include(${VTK_USE_FILE})
add_executable(Sphere MACOSX_BUNDLE Sphere.cxx)
if(VTK_LIBRARIES)
target_link_libraries(Sphere ${VTK_LIBRARIES})
else()
target_link_libraries(Sphere vtkHybrid vtkWidgets)
endif()
Output Before (Qt 5.9.5, run with QT_SCREEN_SCALE_FACTORS=1.4 ./Sphere
)
Notice how the render window has the wrong size.
Output After (Qt 5.9.5, run with QT_SCREEN_SCALE_FACTORS=1.4 ./Sphere
)
The render window is now the correct size.
Edited by Elvis Stansvik