Here’s some more patches to update Quarter to handle recent changes in Qt. This time, to deal with the devicePixelRatio issues — each “logical” pixel can correspond to 2 physical pixels for high DPI displays (e.g., Mac retina displays). The viewport and event coordinates need to take this conversion factor into account.
These diffs are against a previous less robust way of dealing with this issue, so they are not going to work directly against a pure Quarter source but the relevant new code is all there..
I have pushed these into our svn repository:
https://grey.colorado.edu/emergent/index.php/Coin3d
Cheers,
- Randy
Index: include/Quarter/QuarterWidget.h
===================================================================
--- include/Quarter/QuarterWidget.h (revision 32)
+++ include/Quarter/QuarterWidget.h (working copy)
@@ -74,6 +74,7 @@
Q_PROPERTY(TransparencyType transparencyType READ transparencyType WRITE setTransparencyType)
Q_PROPERTY(RenderMode renderMode READ renderMode WRITE setRenderMode)
Q_PROPERTY(StereoMode stereoMode READ stereoMode WRITE setStereoMode)
+ Q_PROPERTY(qreal devicePixelRatio READ devicePixelRatio NOTIFY devicePixelRatioChanged)
Q_ENUMS(TransparencyType)
Q_ENUMS(RenderMode)
@@ -127,6 +128,8 @@
void setBackgroundColor(const QColor & color);
QColor backgroundColor(void) const;
+ qreal devicePixelRatio(void) const;
+
void resetNavigationModeFile(void);
void setNavigationModeFile(const QUrl & url = QUrl(DEFAULT_NAVIGATIONFILE));
const QUrl & navigationModeFile(void) const;
@@ -187,11 +190,15 @@
void setStereoMode(StereoMode mode);
void setTransparencyType(TransparencyType type);
+signals:
+ void devicePixelRatioChanged(qreal dev_pixel_ratio);
+
protected:
virtual void resizeGL(int width, int height);
virtual void initializeGL(void);
virtual void paintGL(void);
virtual void actualRedraw(void);
+ virtual bool updateDevicePixelRatio(void);
private:
void constructor(const QT_GL_WIDGET * sharewidget);
Index: include/Quarter/devices/InputDevice.h
===================================================================
--- include/Quarter/devices/InputDevice.h (revision 32)
+++ include/Quarter/devices/InputDevice.h (working copy)
@@ -32,9 +32,11 @@
namespace SIM { namespace Coin3D { namespace Quarter {
+class QuarterWidget;
+
class QUARTER_DLL_API InputDevice {
public:
- InputDevice(void);
+ InputDevice(QuarterWidget* quarter);
virtual ~InputDevice() {}
/*!
@@ -50,6 +52,7 @@
protected:
SbVec2s mousepos;
SbVec2s windowsize;
+ QuarterWidget* quarter;
};
}}} // namespace
Index: include/Quarter/devices/Keyboard.h
===================================================================
--- include/Quarter/devices/Keyboard.h (revision 32)
+++ include/Quarter/devices/Keyboard.h (working copy)
@@ -33,7 +33,7 @@
class QUARTER_DLL_API Keyboard : public InputDevice {
public:
- Keyboard(void);
+ Keyboard(QuarterWidget* quarter);
virtual ~Keyboard();
virtual const SoEvent * translateEvent(QEvent * event);
Index: include/Quarter/devices/Mouse.h
===================================================================
--- include/Quarter/devices/Mouse.h (revision 32)
+++ include/Quarter/devices/Mouse.h (working copy)
@@ -28,12 +28,13 @@
class QEvent;
class SoEvent;
+class QuarterWidget;
namespace SIM { namespace Coin3D { namespace Quarter {
class QUARTER_DLL_API Mouse : public InputDevice {
public:
- Mouse(void);
+ Mouse(QuarterWidget* quarter);
virtual ~Mouse();
virtual const SoEvent * translateEvent(QEvent * event);
Index: include/Quarter/devices/SpaceNavigatorDevice.h
===================================================================
--- include/Quarter/devices/SpaceNavigatorDevice.h (revision 32)
+++ include/Quarter/devices/SpaceNavigatorDevice.h (working copy)
@@ -33,7 +33,7 @@
class QUARTER_DLL_API SpaceNavigatorDevice : public InputDevice {
public:
- SpaceNavigatorDevice(void);
+ SpaceNavigatorDevice(QuarterWidget* quarter);
virtual ~SpaceNavigatorDevice();
virtual const SoEvent * translateEvent(QEvent * event);
Index: src/Quarter/EventFilter.cpp
===================================================================
--- src/Quarter/EventFilter.cpp (revision 32)
+++ src/Quarter/EventFilter.cpp (working copy)
@@ -67,9 +67,7 @@
SbVec2s mousepos(event->pos().x(), this->windowsize[1] - event->pos().y() - 1);
// the following corrects for high-dpi displays (e.g., mac retina)
-#if (QT_VERSION >= 0x050000)
- mousepos *= ((QGuiApplication*)QGuiApplication::instance())->devicePixelRatio();
-#endif
+ mousepos *= quarterwidget->devicePixelRatio();
foreach(InputDevice * device, this->devices) {
device->setMousePosition(mousepos);
}
@@ -88,17 +86,19 @@
{
PRIVATE(this) = new EventFilterP;
- PRIVATE(this)->quarterwidget = dynamic_cast<QuarterWidget *>(parent);
+ QuarterWidget* quarter = dynamic_cast<QuarterWidget *>(parent);
+
+ PRIVATE(this)->quarterwidget = quarter;
assert(PRIVATE(this)->quarterwidget);
PRIVATE(this)->windowsize = SbVec2s(PRIVATE(this)->quarterwidget->width(),
PRIVATE(this)->quarterwidget->height());
- PRIVATE(this)->devices += new Mouse;
- PRIVATE(this)->devices += new Keyboard;
+ PRIVATE(this)->devices += new Mouse(quarter);
+ PRIVATE(this)->devices += new Keyboard(quarter);
#ifdef HAVE_SPACENAV_LIB
- PRIVATE(this)->devices += new SpaceNavigatorDevice;
+ PRIVATE(this)->devices += new SpaceNavigatorDevice(quarter);
#endif // HAVE_SPACENAV_LIB
}
Index: src/Quarter/InputDevice.cpp
===================================================================
--- src/Quarter/InputDevice.cpp (revision 32)
+++ src/Quarter/InputDevice.cpp (working copy)
@@ -23,6 +23,7 @@
#include <Quarter/devices/InputDevice.h>
#include <QInputEvent>
#include <Inventor/events/SoEvents.h>
+#include <Quarter/QuarterWidget.h>
using namespace SIM::Coin3D::Quarter;
@@ -34,7 +35,8 @@
devices.
*/
-InputDevice::InputDevice(void)
+InputDevice::InputDevice(QuarterWidget* quart) :
+ quarter(quart)
{
this->mousepos = SbVec2s(0, 0);
}
Index: src/Quarter/Keyboard.cpp
===================================================================
--- src/Quarter/Keyboard.cpp (revision 32)
+++ src/Quarter/Keyboard.cpp (working copy)
@@ -41,7 +41,8 @@
#define PRIVATE(obj) obj->pimpl
-Keyboard::Keyboard(void)
+Keyboard::Keyboard(QuarterWidget* quart) :
+ InputDevice(quart)
{
PRIVATE(this) = new KeyboardP(this);
}
Index: src/Quarter/Mouse.cpp
===================================================================
--- src/Quarter/Mouse.cpp (revision 32)
+++ src/Quarter/Mouse.cpp (working copy)
@@ -32,6 +32,8 @@
#include <QEvent>
#include <QSize>
#include <QWheelEvent>
+#include <Quarter/QuarterWidget.h>
+
#if (QT_VERSION >= 0x050000)
#include <QGuiApplication>
#endif
@@ -74,7 +76,8 @@
#define PRIVATE(obj) obj->pimpl
#define PUBLIC(obj) obj->publ
-Mouse::Mouse(void)
+Mouse::Mouse(QuarterWidget* quart) :
+ InputDevice(quart)
{
PRIVATE(this) = new MouseP(this);
}
@@ -125,9 +128,7 @@
assert(this->windowsize[1] != -1);
SbVec2s pos(event->pos().x(), this->windowsize[1] - event->pos().y() - 1);
// the following corrects for high-dpi displays (e.g., mac retina)
-#if (QT_VERSION >= 0x050000)
- pos *= ((QGuiApplication*)QGuiApplication::instance())->devicePixelRatio();
-#endif
+ pos *= publ->quarter->devicePixelRatio();
this->location2->setPosition(pos);
this->mousebutton->setPosition(pos);
return this->location2;
@@ -139,9 +140,7 @@
PUBLIC(this)->setModifiers(this->mousebutton, event);
SbVec2s pos(event->pos().x(), PUBLIC(this)->windowsize[1] - event->pos().y() - 1);
// the following corrects for high-dpi displays (e.g., mac retina)
-#if (QT_VERSION >= 0x050000)
- pos *= ((QGuiApplication*)QGuiApplication::instance())->devicePixelRatio();
-#endif
+ pos *= publ->quarter->devicePixelRatio();
this->location2->setPosition(pos);
this->mousebutton->setPosition(pos);
@@ -164,9 +163,7 @@
PUBLIC(this)->setModifiers(this->mousebutton, event);
SbVec2s pos(event->pos().x(), PUBLIC(this)->windowsize[1] - event->pos().y() - 1);
// the following corrects for high-dpi displays (e.g., mac retina)
-#if (QT_VERSION >= 0x050000)
- pos *= ((QGuiApplication*)QGuiApplication::instance())->devicePixelRatio();
-#endif
+ pos *= publ->quarter->devicePixelRatio();
this->location2->setPosition(pos);
this->mousebutton->setPosition(pos);
Index: src/Quarter/QuarterWidget.cpp
===================================================================
--- src/Quarter/QuarterWidget.cpp (revision 32)
+++ src/Quarter/QuarterWidget.cpp (working copy)
@@ -456,6 +456,23 @@
}
/*!
+ \property QuarterWidget::devicePixelRatio
+
+ \copydetails QuarterWidget::devicePixelRatio
+*/
+
+/*!
+ The ratio between logical and physical pixel sizes -- obtained from the window that
+the widget is located within, and updated whenver any change occurs, emitting a devicePixelRatioChanged signal. Only available for version Qt 5.6 and above (will be 1.0 for all previous versions)
+ */
+
+qreal
+QuarterWidget::devicePixelRatio(void) const
+{
+ return PRIVATE(this)->device_pixel_ratio;
+}
+
+/*!
Sets the Inventor scenegraph to be rendered
*/
void
@@ -657,6 +674,31 @@
this->getSoRenderManager()->reinitialize();
}
+
+bool
+QuarterWidget::updateDevicePixelRatio(void) {
+#ifdef QT_OPEN_GL_WIDGET
+ qreal dev_pix_ratio = 1.0;
+ QWidget* winwidg = window();
+ QWindow* win = NULL;
+ if(winwidg) {
+ win = winwidg->windowHandle();
+ }
+ if(win) {
+ dev_pix_ratio = win->devicePixelRatio();
+ }
+ else {
+ dev_pix_ratio = ((QGuiApplication*)QGuiApplication::instance())->devicePixelRatio();
+ }
+ if(PRIVATE(this)->device_pixel_ratio != dev_pix_ratio) {
+ PRIVATE(this)->device_pixel_ratio = dev_pix_ratio;
+ emit devicePixelRatioChanged(dev_pix_ratio);
+ return true;
+ }
+#endif
+ return false;
+}
+
/*!
Overridden from QGLWidget to resize the Coin scenegraph
*/
@@ -664,17 +706,12 @@
QuarterWidget::resizeGL(int width, int height)
{
#ifdef QT_OPEN_GL_WIDGET
- float dev_pix_ratio = 1.0f;
- QWindow* win = windowHandle();
- if(win) {
- dev_pix_ratio = win->devicePixelRatio();
- }
- else {
- dev_pix_ratio = ((QGuiApplication*)QGuiApplication::instance())->devicePixelRatio();
- }
+ updateDevicePixelRatio();
+ qreal dev_pix_ratio = devicePixelRatio();
width = (int)(dev_pix_ratio * width);
height = (int)(dev_pix_ratio * height);
#endif
+
SbViewportRegion vp(width, height);
PRIVATE(this)->sorendermanager->setViewportRegion(vp);
PRIVATE(this)->soeventmanager->setViewportRegion(vp);
@@ -686,6 +723,17 @@
void
QuarterWidget::paintGL(void)
{
+#ifdef QT_OPEN_GL_WIDGET
+ if(updateDevicePixelRatio()) {
+ qreal dev_pix_ratio = devicePixelRatio();
+ int width = (int)(dev_pix_ratio * this->width());
+ int height = (int)(dev_pix_ratio * this->height());
+ SbViewportRegion vp(width, height);
+ PRIVATE(this)->sorendermanager->setViewportRegion(vp);
+ PRIVATE(this)->soeventmanager->setViewportRegion(vp);
+ }
+#endif
+
assert(this->isValid() && "No valid GL context found!");
// We might have to process the delay queue here since we don't know
// if paintGL() is called from Qt, and we might have some sensors
Index: src/Quarter/QuarterWidgetP.cpp
===================================================================
--- src/Quarter/QuarterWidgetP.cpp (revision 32)
+++ src/Quarter/QuarterWidgetP.cpp (working copy)
@@ -72,6 +72,7 @@
interactionmodeenabled(false),
clearzbuffer(true),
clearwindow(true),
+ device_pixel_ratio(1.0),
addactions(true)
{
this->cachecontext = findCacheContext(masterptr, sharewidget);
Index: src/Quarter/QuarterWidgetP.h
===================================================================
--- src/Quarter/QuarterWidgetP.h (revision 32)
+++ src/Quarter/QuarterWidgetP.h (working copy)
@@ -90,6 +90,7 @@
bool processdelayqueue;
QUrl navigationModeFile;
SoScXMLStateMachine * currentStateMachine;
+ qreal device_pixel_ratio;
static void rendercb(void * userdata, SoRenderManager *);
static void prerendercb(void * userdata, SoRenderManager * manager);
Index: src/Quarter/SpaceNavigatorDevice.cpp
===================================================================
--- src/Quarter/SpaceNavigatorDevice.cpp (revision 32)
+++ src/Quarter/SpaceNavigatorDevice.cpp (working copy)
@@ -72,7 +72,8 @@
#define PRIVATE(obj) obj->pimpl
using namespace SIM::Coin3D::Quarter;
-SpaceNavigatorDevice::SpaceNavigatorDevice()
+SpaceNavigatorDevice::SpaceNavigatorDevice(QuarterWidget* quart) :
+ InputDevice(quart)
{
PRIVATE(this) = new SpaceNavigatorDeviceP(this);