From ec462b245fa138a6b036f3db9c960015a36fd828 Mon Sep 17 00:00:00 2001
From: Paul Olav Tvete <paul.tvete@theqtcompany.com>
Date: Mon, 22 Jun 2015 12:25:33 +0200
Subject: [PATCH] X11 changes for highdpi

Adapt the xcb plugin to work with the new cross-platform
high-DPI scaling.

Fixes for drag and drop is done in a separate change.

Task-number: QTBUG-46615
Change-Id: I29002721169750b9de59edb0f3e9134adabc4855
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
---
 src/plugins/platforms/xcb/qxcbbackingstore.cpp |  3 ++-
 src/plugins/platforms/xcb/qxcbscreen.cpp       |  9 ++++++++
 src/plugins/platforms/xcb/qxcbscreen.h         |  2 ++
 src/plugins/platforms/xcb/qxcbwindow.cpp       | 31 +++++++++++++-------------
 4 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index 44e9a54..e62d515 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -49,6 +49,7 @@
 #include <qdebug.h>
 #include <qpainter.h>
 #include <qscreen.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
 #include <qpa/qplatformgraphicsbuffer.h>
 
 #include <algorithm>
@@ -365,7 +366,7 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
     QSize imageSize = m_image->size();
 
     QRegion clipped = region;
-    clipped &= QRect(QPoint(), window->size());
+    clipped &= QRect(QPoint(), QHighDpi::toNativePixels(window->size(), window));
     clipped &= QRect(0, 0, imageSize.width(), imageSize.height()).translated(-offset);
 
     QRect bounds = clipped.boundingRect();
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index 8a47535..29262b5 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -44,6 +44,7 @@
 
 #include <qpa/qwindowsysteminterface.h>
 #include <private/qmath_p.h>
+#include <QtGui/private/qhighdpiscaling_p.h>
 
 QT_BEGIN_NAMESPACE
 
@@ -86,6 +87,7 @@ QXcbScreen::QXcbScreen(QXcbConnection *connection, QXcbVirtualDesktop *virtualDe
     , m_orientation(Qt::PrimaryOrientation)
     , m_refreshRate(60)
     , m_forcedDpi(-1)
+    , m_pixelDensity(1)
     , m_hintStyle(QFontEngine::HintStyle(-1))
     , m_noFontHinting(false)
     , m_subpixelType(QFontEngine::SubpixelAntialiasingType(-1))
@@ -302,6 +304,11 @@ QDpi QXcbScreen::logicalDpi() const
     return virtualDpi();
 }
 
+qreal QXcbScreen::pixelDensity() const
+{
+    return m_pixelDensity;
+}
+
 QPlatformCursor *QXcbScreen::cursor() const
 {
     return m_cursor;
@@ -457,6 +464,8 @@ void QXcbScreen::updateGeometry(const QRect &geom, uint8_t rotation)
     }
     free(workArea);
 
+    qreal dpi = xGeometry.width() / physicalSize().width() * qreal(25.4);
+    m_pixelDensity = qRound(dpi/96);
     m_geometry = QRect(xGeometry.topLeft(), xGeometry.size());
     m_nativeGeometry = QRect(xGeometry.topLeft(), xGeometry.size());
     m_availableGeometry = QRect(xAvailableGeometry.topLeft(), xAvailableGeometry.size());
diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h
index f61f28e..cbb6307 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.h
+++ b/src/plugins/platforms/xcb/qxcbscreen.h
@@ -96,6 +96,7 @@ public:
     QSizeF physicalVirtualSize() const { return m_virtualSizeMillimeters; }
     QDpi virtualDpi() const;
     QDpi logicalDpi() const Q_DECL_OVERRIDE;
+    qreal pixelDensity() const Q_DECL_OVERRIDE;
     QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
     qreal refreshRate() const Q_DECL_OVERRIDE { return m_refreshRate; }
     Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE { return m_orientation; }
@@ -168,6 +169,7 @@ private:
     QXcbCursor *m_cursor;
     int m_refreshRate;
     int m_forcedDpi;
+    int m_pixelDensity;
     QFontEngine::HintStyle m_hintStyle;
     bool m_noFontHinting;
     QFontEngine::SubpixelAntialiasingType m_subpixelType;
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index 61e3dcf..f9a85cd 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -37,6 +37,7 @@
 #include <QScreen>
 #include <QtGui/QIcon>
 #include <QtGui/QRegion>
+#include <QtGui/private/qhighdpiscaling_p.h>
 
 #include "qxcbintegration.h"
 #include "qxcbconnection.h"
@@ -320,7 +321,7 @@ void QXcbWindow::create()
     Qt::WindowType type = window()->type();
 
     QXcbScreen *currentScreen = xcbScreen();
-    QRect rect = window()->geometry();
+    QRect rect = windowGeometry();
     QXcbScreen *platformScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
 
     m_xcbScreen = platformScreen;
@@ -363,15 +364,15 @@ void QXcbWindow::create()
     if (platformScreen != currentScreen)
         QWindowSystemInterface::handleWindowScreenChanged(window(), platformScreen->QPlatformScreen::screen());
 
-    QSize minimumSize = window()->minimumSize();
+    const QSize minimumSize = windowMinimumSize();
     if (rect.width() > 0 || rect.height() > 0) {
         rect.setWidth(qBound(1, rect.width(), XCOORD_MAX));
         rect.setHeight(qBound(1, rect.height(), XCOORD_MAX));
     } else if (minimumSize.width() > 0 || minimumSize.height() > 0) {
         rect.setSize(minimumSize);
     } else {
-        rect.setWidth(defaultWindowWidth);
-        rect.setHeight(defaultWindowHeight);
+        rect.setWidth(QHighDpi::toNativePixels(int(defaultWindowWidth), platformScreen->QPlatformScreen::screen()));
+        rect.setHeight(QHighDpi::toNativePixels(int(defaultWindowHeight), platformScreen->QPlatformScreen::screen()));
     }
 
     xcb_window_t xcb_parent_id = platformScreen->root();
@@ -641,11 +642,11 @@ void QXcbWindow::setGeometry(const QRect &rect)
 
     propagateSizeHints();
 
-    QXcbScreen *currentScreen = xcbScreen();
+    QXcbScreen *currentScreen = m_xcbScreen;
     QXcbScreen *newScreen = parent() ? parentScreen() : static_cast<QXcbScreen*>(screenForGeometry(rect));
 
     if (!newScreen)
-        newScreen = currentScreen;
+        newScreen = xcbScreen();
 
     m_xcbScreen = newScreen;
     const QRect wmGeometry = windowToWmGeometry(rect);
@@ -1260,7 +1261,7 @@ void QXcbWindow::updateMotifWmHintsBeforeMap()
         mwmhints.flags &= ~MWM_HINTS_INPUT_MODE;
     }
 
-    if (window()->minimumSize() == window()->maximumSize()) {
+    if (windowMinimumSize() == windowMaximumSize()) {
         // fixed size, remove the resize handle (since mwm/dtwm
         // isn't smart enough to do it itself)
         mwmhints.flags |= MWM_HINTS_FUNCTIONS;
@@ -1556,10 +1557,10 @@ void QXcbWindow::propagateSizeHints()
         xcb_size_hints_set_size(&hints, true, xRect.width(), xRect.height());
     xcb_size_hints_set_win_gravity(&hints, m_gravity);
 
-    QSize minimumSize = window()->minimumSize();
-    QSize maximumSize = window()->maximumSize();
-    QSize baseSize = window()->baseSize();
-    QSize sizeIncrement = window()->sizeIncrement();
+    QSize minimumSize = windowMinimumSize();
+    QSize maximumSize = windowMaximumSize();
+    QSize baseSize = windowBaseSize();
+    QSize sizeIncrement = windowSizeIncrement();
 
     if (minimumSize.width() > 0 || minimumSize.height() > 0)
         xcb_size_hints_set_min_size(&hints,
@@ -1951,13 +1952,13 @@ void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *even
         }
 #ifndef QT_NO_DRAGANDDROP
     } else if (event->type == atom(QXcbAtom::XdndEnter)) {
-        connection()->drag()->handleEnter(window(), event);
+        connection()->drag()->handleEnter(this, event);
     } else if (event->type == atom(QXcbAtom::XdndPosition)) {
-        connection()->drag()->handlePosition(window(), event);
+        connection()->drag()->handlePosition(this, event);
     } else if (event->type == atom(QXcbAtom::XdndLeave)) {
-        connection()->drag()->handleLeave(window(), event);
+        connection()->drag()->handleLeave(this, event);
     } else if (event->type == atom(QXcbAtom::XdndDrop)) {
-        connection()->drag()->handleDrop(window(), event);
+        connection()->drag()->handleDrop(this, event);
 #endif
     } else if (event->type == atom(QXcbAtom::_XEMBED)) {
         handleXEmbedMessage(event);
-- 
2.6.2

