summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorQt Forward Merge Bot <qt_forward_merge_bot@qt-project.org>2019-03-20 01:00:08 +0100
committerTor Arne Vestbø <tor.arne.vestbo@qt.io>2019-03-20 14:09:30 +0100
commit6893919b0c4cddfbd82ebf963cc7bebde816b1b3 (patch)
tree9bfa1b57707fe609f9401c5b3bd5cd85ec1ae777 /src
parent3ca05b2a2e80863202bdb6a225f72debbb28b8fe (diff)
parent2bafd997ee515d3b6a6a8fb030e1265a4713713e (diff)
Merge remote-tracking branch 'origin/5.12' into 5.13
Conflicts: src/gui/kernel/qplatformintegration.cpp src/gui/kernel/qplatformintegration.h src/plugins/platforms/wasm/qwasmintegration.cpp src/plugins/platforms/xcb/qxcbconnection_screens.cpp Change-Id: I15063d42e9a1e226d9d2d2d372f75141b84c5c1b
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/angle/src/libANGLE/Context.cpp3
-rw-r--r--src/3rdparty/angle/src/libANGLE/Stream.cpp8
-rw-r--r--src/3rdparty/angle/src/libANGLE/Texture.cpp3
-rw-r--r--src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp3
-rw-r--r--src/angle/patches/0013-Fix-compilation-with-icc-converting-between-egl-s-an.patch93
-rw-r--r--src/corelib/io/qtemporaryfile.cpp4
-rw-r--r--src/corelib/kernel/qtranslator.cpp3
-rw-r--r--src/gui/image/qimage.cpp11
-rw-r--r--src/gui/image/qimage.h4
-rw-r--r--src/gui/image/qimage_p.h6
-rw-r--r--src/gui/kernel/qplatformgraphicsbuffer.h2
-rw-r--r--src/gui/kernel/qplatformintegration.cpp61
-rw-r--r--src/gui/kernel/qplatformintegration.h12
-rw-r--r--src/gui/kernel/qplatformscreen.cpp5
-rw-r--r--src/gui/kernel/qscreen.h1
-rw-r--r--src/gui/kernel/qwindow.cpp14
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp66
-rw-r--r--src/gui/kernel/qwindowsysteminterface.h4
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp81
-rw-r--r--src/network/configure.json4
-rw-r--r--src/plugins/platforms/android/qandroidplatformintegration.cpp2
-rw-r--r--src/plugins/platforms/bsdfb/qbsdfbintegration.cpp5
-rw-r--r--src/plugins/platforms/cocoa/cocoa.pro4
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h52
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm543
-rw-r--r--src/plugins/platforms/cocoa/qcocoaintegration.mm17
-rw-r--r--src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h77
-rw-r--r--src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.mm188
-rw-r--r--src/plugins/platforms/cocoa/qnsview_drawing.mm7
-rw-r--r--src/plugins/platforms/directfb/qdirectfb_egl.cpp3
-rw-r--r--src/plugins/platforms/directfb/qdirectfbintegration.cpp3
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp4
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsintegration.cpp12
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsintegration_p.h3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp6
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp2
-rw-r--r--src/plugins/platforms/haiku/qhaikuintegration.cpp5
-rw-r--r--src/plugins/platforms/integrity/qintegrityfbintegration.cpp6
-rw-r--r--src/plugins/platforms/ios/qiosintegration.h4
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm4
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm10
-rw-r--r--src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp5
-rw-r--r--src/plugins/platforms/minimal/qminimalintegration.cpp3
-rw-r--r--src/plugins/platforms/minimalegl/qminimaleglintegration.cpp5
-rw-r--r--src/plugins/platforms/mirclient/qmirclientintegration.cpp7
-rw-r--r--src/plugins/platforms/offscreen/qoffscreenintegration.cpp3
-rw-r--r--src/plugins/platforms/openwfd/qopenwfdintegration.cpp11
-rw-r--r--src/plugins/platforms/openwfd/qopenwfdintegration.h2
-rw-r--r--src/plugins/platforms/openwfd/qopenwfdport.cpp4
-rw-r--r--src/plugins/platforms/qnx/qqnxintegration.cpp6
-rw-r--r--src/plugins/platforms/vnc/qvncintegration.cpp5
-rw-r--r--src/plugins/platforms/wasm/qwasmintegration.cpp7
-rw-r--r--src/plugins/platforms/windows/qwindowsintegration.h3
-rw-r--r--src/plugins/platforms/windows/qwindowsscreen.cpp8
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp10
-rw-r--r--src/plugins/platforms/winrt/qwinrtintegration.cpp4
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp18
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp3
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_basic.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_screens.cpp12
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h2
-rw-r--r--src/plugins/platforms/xcb/qxcbnativeinterface.cpp7
-rw-r--r--src/tools/androiddeployqt/main.cpp2
-rw-r--r--src/widgets/kernel/qgesturemanager.cpp5
-rw-r--r--src/widgets/kernel/qgesturerecognizer.cpp6
-rw-r--r--src/widgets/styles/qstyle.cpp4
-rw-r--r--src/widgets/widgets/qsplashscreen.cpp13
-rw-r--r--src/widgets/widgets/qsplitter.cpp8
69 files changed, 1164 insertions, 349 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/Context.cpp b/src/3rdparty/angle/src/libANGLE/Context.cpp
index f638beda58..84f7936feb 100644
--- a/src/3rdparty/angle/src/libANGLE/Context.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Context.cpp
@@ -451,7 +451,8 @@ egl::Error Context::onDestroy(const egl::Display *display)
for (auto &zeroTexture : mZeroTextures)
{
- ANGLE_TRY(zeroTexture.second->onDestroy(this));
+ auto result = zeroTexture.second->onDestroy(this);
+ ANGLE_TRY(egl::Error(result));
zeroTexture.second.set(this, nullptr);
}
mZeroTextures.clear();
diff --git a/src/3rdparty/angle/src/libANGLE/Stream.cpp b/src/3rdparty/angle/src/libANGLE/Stream.cpp
index 68279976b7..e384c7d486 100644
--- a/src/3rdparty/angle/src/libANGLE/Stream.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Stream.cpp
@@ -192,8 +192,9 @@ Error Stream::consumerAcquire(const gl::Context *context)
{
if (mPlanes[i].texture != nullptr)
{
- ANGLE_TRY(mPlanes[i].texture->acquireImageFromStream(
- context, mProducerImplementation->getGLFrameDescription(i)));
+ auto result = mPlanes[i].texture->acquireImageFromStream(
+ context, mProducerImplementation->getGLFrameDescription(i));
+ ANGLE_TRY(Error(result));
}
}
@@ -213,7 +214,8 @@ Error Stream::consumerRelease(const gl::Context *context)
{
if (mPlanes[i].texture != nullptr)
{
- ANGLE_TRY(mPlanes[i].texture->releaseImageFromStream(context));
+ auto result = mPlanes[i].texture->releaseImageFromStream(context);
+ ANGLE_TRY(Error(result));
}
}
diff --git a/src/3rdparty/angle/src/libANGLE/Texture.cpp b/src/3rdparty/angle/src/libANGLE/Texture.cpp
index da92e65916..7447604fe6 100644
--- a/src/3rdparty/angle/src/libANGLE/Texture.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Texture.cpp
@@ -550,7 +550,8 @@ Error Texture::onDestroy(const Context *context)
{
if (mBoundSurface)
{
- ANGLE_TRY(mBoundSurface->releaseTexImage(context, EGL_BACK_BUFFER));
+ auto result = mBoundSurface->releaseTexImage(context, EGL_BACK_BUFFER);
+ ANGLE_TRY(Error(result));
mBoundSurface = nullptr;
}
if (mBoundStream)
diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
index 75c6298868..b583273641 100644
--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
+++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
@@ -376,7 +376,8 @@ egl::Error Renderer9::initializeDevice()
ASSERT(!mBlit);
mBlit = new Blit9(this);
- ANGLE_TRY(mBlit->initialize());
+ auto result = mBlit->initialize();
+ ANGLE_TRY(egl::Error(result));
ASSERT(!mVertexDataManager && !mIndexDataManager);
mVertexDataManager = new VertexDataManager(this);
diff --git a/src/angle/patches/0013-Fix-compilation-with-icc-converting-between-egl-s-an.patch b/src/angle/patches/0013-Fix-compilation-with-icc-converting-between-egl-s-an.patch
new file mode 100644
index 0000000000..6d3b1cac08
--- /dev/null
+++ b/src/angle/patches/0013-Fix-compilation-with-icc-converting-between-egl-s-an.patch
@@ -0,0 +1,93 @@
+From 2d8118620d4871f74a3ddca233529ff540384477 Mon Sep 17 00:00:00 2001
+From: Yuhang Zhao <2546789017@qq.com>
+Date: Wed, 13 Feb 2019 23:26:55 +0800
+Subject: [PATCH] Fix compilation with icc, converting between egl's and gl's
+ Error types
+
+Each has two constructors from the other, one copying the other
+moving; and this leads to an ambiguous overload when converting
+Texture::onDestroy()'s gl::error to the egl::Error that
+gl::Context::onDestroy() returns. Passing the value through a
+temporary prevents the move-constructor from being attempted and saves
+the day. Thanks to Ville Voutilainen for suggesting the fix.
+
+Fixes: QTBUG-73698
+Change-Id: I628173399a73cee2e253201bc3e8d3e6477a2fbf
+---
+ src/3rdparty/angle/src/libANGLE/Context.cpp | 3 ++-
+ src/3rdparty/angle/src/libANGLE/Stream.cpp | 8 +++++---
+ src/3rdparty/angle/src/libANGLE/Texture.cpp | 3 ++-
+ .../angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp | 3 ++-
+ 4 files changed, 11 insertions(+), 6 deletions(-)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/Context.cpp b/src/3rdparty/angle/src/libANGLE/Context.cpp
+index f638beda58..84f7936feb 100644
+--- a/src/3rdparty/angle/src/libANGLE/Context.cpp
++++ b/src/3rdparty/angle/src/libANGLE/Context.cpp
+@@ -451,7 +451,8 @@ egl::Error Context::onDestroy(const egl::Display *display)
+
+ for (auto &zeroTexture : mZeroTextures)
+ {
+- ANGLE_TRY(zeroTexture.second->onDestroy(this));
++ auto result = zeroTexture.second->onDestroy(this);
++ ANGLE_TRY(egl::Error(result));
+ zeroTexture.second.set(this, nullptr);
+ }
+ mZeroTextures.clear();
+diff --git a/src/3rdparty/angle/src/libANGLE/Stream.cpp b/src/3rdparty/angle/src/libANGLE/Stream.cpp
+index 68279976b7..e384c7d486 100644
+--- a/src/3rdparty/angle/src/libANGLE/Stream.cpp
++++ b/src/3rdparty/angle/src/libANGLE/Stream.cpp
+@@ -192,8 +192,9 @@ Error Stream::consumerAcquire(const gl::Context *context)
+ {
+ if (mPlanes[i].texture != nullptr)
+ {
+- ANGLE_TRY(mPlanes[i].texture->acquireImageFromStream(
+- context, mProducerImplementation->getGLFrameDescription(i)));
++ auto result = mPlanes[i].texture->acquireImageFromStream(
++ context, mProducerImplementation->getGLFrameDescription(i));
++ ANGLE_TRY(Error(result));
+ }
+ }
+
+@@ -213,7 +214,8 @@ Error Stream::consumerRelease(const gl::Context *context)
+ {
+ if (mPlanes[i].texture != nullptr)
+ {
+- ANGLE_TRY(mPlanes[i].texture->releaseImageFromStream(context));
++ auto result = mPlanes[i].texture->releaseImageFromStream(context);
++ ANGLE_TRY(Error(result));
+ }
+ }
+
+diff --git a/src/3rdparty/angle/src/libANGLE/Texture.cpp b/src/3rdparty/angle/src/libANGLE/Texture.cpp
+index da92e65916..7447604fe6 100644
+--- a/src/3rdparty/angle/src/libANGLE/Texture.cpp
++++ b/src/3rdparty/angle/src/libANGLE/Texture.cpp
+@@ -550,7 +550,8 @@ Error Texture::onDestroy(const Context *context)
+ {
+ if (mBoundSurface)
+ {
+- ANGLE_TRY(mBoundSurface->releaseTexImage(context, EGL_BACK_BUFFER));
++ auto result = mBoundSurface->releaseTexImage(context, EGL_BACK_BUFFER);
++ ANGLE_TRY(Error(result));
+ mBoundSurface = nullptr;
+ }
+ if (mBoundStream)
+diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
+index 75c6298868..b583273641 100644
+--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d9/Renderer9.cpp
+@@ -376,7 +376,8 @@ egl::Error Renderer9::initializeDevice()
+
+ ASSERT(!mBlit);
+ mBlit = new Blit9(this);
+- ANGLE_TRY(mBlit->initialize());
++ auto result = mBlit->initialize();
++ ANGLE_TRY(egl::Error(result));
+
+ ASSERT(!mVertexDataManager && !mIndexDataManager);
+ mVertexDataManager = new VertexDataManager(this);
+--
+2.20.1.windows.1
+
diff --git a/src/corelib/io/qtemporaryfile.cpp b/src/corelib/io/qtemporaryfile.cpp
index 35bb465a04..ced08a9a87 100644
--- a/src/corelib/io/qtemporaryfile.cpp
+++ b/src/corelib/io/qtemporaryfile.cpp
@@ -908,8 +908,8 @@ QTemporaryFile *QTemporaryFile::createNativeFile(QFile &file)
qint64 old_off = 0;
if(wasOpen)
old_off = file.pos();
- else
- file.open(QIODevice::ReadOnly);
+ else if (!file.open(QIODevice::ReadOnly))
+ return nullptr;
//dump data
QTemporaryFile *ret = new QTemporaryFile;
if (ret->open()) {
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index dc39490ab0..a2111a084f 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -66,6 +66,7 @@
#endif
#include <stdlib.h>
+#include <new>
#include "qobject_p.h"
@@ -585,7 +586,7 @@ bool QTranslatorPrivate::do_load(const QString &realname, const QString &directo
#endif // QT_USE_MMAP
if (!ok) {
- d->unmapPointer = new char[d->unmapLength];
+ d->unmapPointer = new (std::nothrow) char[d->unmapLength];
if (d->unmapPointer) {
file.seek(0);
qint64 readResult = file.read(d->unmapPointer, d->unmapLength);
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 18e94cf256..0463ef6a42 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -124,7 +124,7 @@ QImageData * QImageData::create(const QSize &size, QImage::Format format)
int height = size.height();
int depth = qt_depthForFormat(format);
auto params = calculateImageParameters(width, height, depth);
- if (params.bytesPerLine < 0)
+ if (!params.isValid())
return nullptr;
QScopedPointer<QImageData> d(new QImageData);
@@ -783,7 +783,7 @@ QImageData *QImageData::create(uchar *data, int width, int height, int bpl, QIm
const int depth = qt_depthForFormat(format);
auto params = calculateImageParameters(width, height, depth);
- if (params.totalSize < 0)
+ if (!params.isValid())
return nullptr;
if (bpl > 0) {
@@ -1488,10 +1488,17 @@ qsizetype QImage::sizeInBytes() const
\sa scanLine()
*/
+#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
+qsizetype QImage::bytesPerLine() const
+{
+ return d ? d->bytes_per_line : 0;
+}
+#else
int QImage::bytesPerLine() const
{
return d ? d->bytes_per_line : 0;
}
+#endif
/*!
diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h
index 45f571807c..8335e117f2 100644
--- a/src/gui/image/qimage.h
+++ b/src/gui/image/qimage.h
@@ -226,7 +226,11 @@ public:
uchar *scanLine(int);
const uchar *scanLine(int) const;
const uchar *constScanLine(int) const;
+#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
+ qsizetype bytesPerLine() const;
+#else
int bytesPerLine() const;
+#endif
bool valid(int x, int y) const;
bool valid(const QPoint &pt) const;
diff --git a/src/gui/image/qimage_p.h b/src/gui/image/qimage_p.h
index de12a313e8..d88ad2d1d2 100644
--- a/src/gui/image/qimage_p.h
+++ b/src/gui/image/qimage_p.h
@@ -109,6 +109,7 @@ struct Q_GUI_EXPORT QImageData { // internal image data
struct ImageSizeParameters {
qsizetype bytesPerLine;
qsizetype totalSize;
+ bool isValid() const { return bytesPerLine > 0 && totalSize > 0; }
};
static ImageSizeParameters calculateImageParameters(qsizetype width, qsizetype height, qsizetype depth);
};
@@ -135,6 +136,11 @@ QImageData::calculateImageParameters(qsizetype width, qsizetype height, qsizetyp
qsizetype dummy;
if (mul_overflow(height, qsizetype(sizeof(uchar *)), &dummy))
return invalid; // why is this here?
+#if QT_VERSION < QT_VERSION_CHECK(6,0,0)
+ // Disallow images where width * depth calculations might overflow
+ if (width > (INT_MAX - 31) / depth)
+ return invalid;
+#endif
return { bytes_per_line, total_size };
}
diff --git a/src/gui/kernel/qplatformgraphicsbuffer.h b/src/gui/kernel/qplatformgraphicsbuffer.h
index 65c24bebc9..9004116ea4 100644
--- a/src/gui/kernel/qplatformgraphicsbuffer.h
+++ b/src/gui/kernel/qplatformgraphicsbuffer.h
@@ -71,12 +71,14 @@ public:
TextureAccess = 0x04,
HWCompositor = 0x08
};
+ Q_ENUM(AccessType);
Q_DECLARE_FLAGS(AccessTypes, AccessType);
enum Origin {
OriginBottomLeft,
OriginTopLeft
};
+ Q_ENUM(Origin);
~QPlatformGraphicsBuffer();
diff --git a/src/gui/kernel/qplatformintegration.cpp b/src/gui/kernel/qplatformintegration.cpp
index 199ef0de07..6ae6e4a528 100644
--- a/src/gui/kernel/qplatformintegration.cpp
+++ b/src/gui/kernel/qplatformintegration.cpp
@@ -463,40 +463,16 @@ QList<int> QPlatformIntegration::possibleKeys(const QKeyEvent *) const
}
/*!
- Should be called by the implementation whenever a new screen is added.
-
- The first screen added will be the primary screen, used for default-created
- windows, GL contexts, and other resources unless otherwise specified.
-
- This adds the screen to QGuiApplication::screens(), and emits the
- QGuiApplication::screenAdded() signal.
-
- The screen should be deleted by calling QPlatformIntegration::destroyScreen().
+ \deprecated Use QWindowSystemInterface::handleScreenAdded instead.
*/
void QPlatformIntegration::screenAdded(QPlatformScreen *ps, bool isPrimary)
{
- QScreen *screen = new QScreen(ps);
-
- if (isPrimary) {
- QGuiApplicationPrivate::screen_list.prepend(screen);
- } else {
- QGuiApplicationPrivate::screen_list.append(screen);
- }
-
- QGuiApplicationPrivate::resetCachedDevicePixelRatio();
-
- emit qGuiApp->screenAdded(screen);
-
- if (isPrimary)
- emit qGuiApp->primaryScreenChanged(screen);
+ QWindowSystemInterface::handleScreenAdded(ps, isPrimary);
}
/*!
- Just removes the screen, call destroyScreen instead.
-
- \sa destroyScreen()
+ \deprecated Use QWindowSystemInterface::handleScreenRemoved instead.
*/
-
void QPlatformIntegration::removeScreen(QScreen *screen)
{
const bool wasPrimary = (!QGuiApplicationPrivate::screen_list.isEmpty() && QGuiApplicationPrivate::screen_list.at(0) == screen);
@@ -509,38 +485,19 @@ void QPlatformIntegration::removeScreen(QScreen *screen)
}
/*!
- Should be called by the implementation whenever a screen is removed.
-
- This removes the screen from QGuiApplication::screens(), and deletes it.
-
- Failing to call this and manually deleting the QPlatformScreen instead may
- lead to a crash due to a pure virtual call.
+ \deprecated Use QWindowSystemInterface::handleScreenRemoved instead.
*/
-void QPlatformIntegration::destroyScreen(QPlatformScreen *screen)
+void QPlatformIntegration::destroyScreen(QPlatformScreen *platformScreen)
{
- QScreen *qScreen = screen->screen();
- removeScreen(qScreen);
- delete qScreen;
- delete screen;
+ QWindowSystemInterface::handleScreenRemoved(platformScreen);
}
/*!
- Should be called whenever the primary screen changes.
-
- When the screen specified as primary changes, this method will notify
- QGuiApplication and emit the QGuiApplication::primaryScreenChanged signal.
- */
-
+ \deprecated Use QWindowSystemInterface::handlePrimaryScreenChanged instead.
+*/
void QPlatformIntegration::setPrimaryScreen(QPlatformScreen *newPrimary)
{
- QScreen* newPrimaryScreen = newPrimary->screen();
- int idx = QGuiApplicationPrivate::screen_list.indexOf(newPrimaryScreen);
- Q_ASSERT(idx >= 0);
- if (idx == 0)
- return;
-
- QGuiApplicationPrivate::screen_list.swapItemsAt(0, idx);
- emit qGuiApp->primaryScreenChanged(newPrimaryScreen);
+ QWindowSystemInterface::handlePrimaryScreenChanged(newPrimary);
}
QStringList QPlatformIntegration::themeNames() const
diff --git a/src/gui/kernel/qplatformintegration.h b/src/gui/kernel/qplatformintegration.h
index de5f9c1c9a..6950bbaf72 100644
--- a/src/gui/kernel/qplatformintegration.h
+++ b/src/gui/kernel/qplatformintegration.h
@@ -192,7 +192,9 @@ public:
#endif
virtual void setApplicationIcon(const QIcon &icon) const;
- void removeScreen(QScreen *screen);
+#if QT_DEPRECATED_SINCE(5, 12)
+ QT_DEPRECATED_X("Use QWindowSystemInterface::handleScreenRemoved") void removeScreen(QScreen *screen);
+#endif
virtual void beep() const;
@@ -203,9 +205,11 @@ public:
protected:
QPlatformIntegration() = default;
- void screenAdded(QPlatformScreen *screen, bool isPrimary = false);
- void destroyScreen(QPlatformScreen *screen);
- void setPrimaryScreen(QPlatformScreen *newPrimary);
+#if QT_DEPRECATED_SINCE(5, 12)
+ QT_DEPRECATED_X("Use QWindowSystemInterface::handleScreenAdded") void screenAdded(QPlatformScreen *screen, bool isPrimary = false);
+ QT_DEPRECATED_X("Use QWindowSystemInterface::handleScreenRemoved") void destroyScreen(QPlatformScreen *screen);
+ QT_DEPRECATED_X("Use QWindowSystemInterface::handlePrimaryScreenChanged") void setPrimaryScreen(QPlatformScreen *newPrimary);
+#endif
};
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp
index b7b312e89e..21ae75ba8f 100644
--- a/src/gui/kernel/qplatformscreen.cpp
+++ b/src/gui/kernel/qplatformscreen.cpp
@@ -61,8 +61,11 @@ QPlatformScreen::~QPlatformScreen()
{
Q_D(QPlatformScreen);
if (d->screen) {
- qWarning("Manually deleting a QPlatformScreen. Call QPlatformIntegration::destroyScreen instead.");
+ qWarning("Manually deleting a QPlatformScreen. Call QWindowSystemInterface::handleScreenRemoved instead.");
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
QGuiApplicationPrivate::platformIntegration()->removeScreen(d->screen);
+QT_WARNING_POP
delete d->screen;
}
}
diff --git a/src/gui/kernel/qscreen.h b/src/gui/kernel/qscreen.h
index 8c9b16e08e..14392d3036 100644
--- a/src/gui/kernel/qscreen.h
+++ b/src/gui/kernel/qscreen.h
@@ -169,6 +169,7 @@ private:
friend class QPlatformIntegration;
friend class QPlatformScreen;
friend class QHighDpiScaling;
+ friend class QWindowSystemInterface;
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 1cc2435239..590e2a85bb 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -1922,9 +1922,6 @@ void QWindowPrivate::destroy()
resizeEventPending = true;
receivedExpose = false;
exposed = false;
-
- if (wasVisible)
- maybeQuitOnLastWindowClosed();
}
/*!
@@ -2313,8 +2310,17 @@ bool QWindow::event(QEvent *ev)
#endif
case QEvent::Close:
- if (ev->isAccepted())
+ if (ev->isAccepted()) {
+ Q_D(QWindow);
+ bool wasVisible = isVisible();
destroy();
+ if (wasVisible) {
+ // FIXME: This check for visibility is a workaround for both QWidgetWindow
+ // and QWindow having logic to emit lastWindowClosed, and possibly quit the
+ // application. We should find a better way to handle this.
+ d->maybeQuitOnLastWindowClosed();
+ }
+ }
break;
case QEvent::Expose:
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index 7067ece1d8..ec6911b334 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -780,6 +780,72 @@ QT_DEFINE_QPA_EVENT_HANDLER(void, handleTouchCancelEvent, QWindow *window, ulong
QWindowSystemInterfacePrivate::handleWindowSystemEvent<Delivery>(e);
}
+/*!
+ Should be called by the implementation whenever a new screen is added.
+
+ The first screen added will be the primary screen, used for default-created
+ windows, GL contexts, and other resources unless otherwise specified.
+
+ This adds the screen to QGuiApplication::screens(), and emits the
+ QGuiApplication::screenAdded() signal.
+
+ The screen should be deleted by calling QWindowSystemInterface::handleScreenRemoved().
+*/
+void QWindowSystemInterface::handleScreenAdded(QPlatformScreen *ps, bool isPrimary)
+{
+ QScreen *screen = new QScreen(ps);
+
+ if (isPrimary)
+ QGuiApplicationPrivate::screen_list.prepend(screen);
+ else
+ QGuiApplicationPrivate::screen_list.append(screen);
+
+ QGuiApplicationPrivate::resetCachedDevicePixelRatio();
+
+ emit qGuiApp->screenAdded(screen);
+
+ if (isPrimary)
+ emit qGuiApp->primaryScreenChanged(screen);
+}
+
+/*!
+ Should be called by the implementation whenever a screen is removed.
+
+ This removes the screen from QGuiApplication::screens(), and deletes it.
+
+ Failing to call this and manually deleting the QPlatformScreen instead may
+ lead to a crash due to a pure virtual call.
+*/
+void QWindowSystemInterface::handleScreenRemoved(QPlatformScreen *platformScreen)
+{
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
+ QGuiApplicationPrivate::platformIntegration()->removeScreen(platformScreen->screen());
+QT_WARNING_POP
+
+ // Important to keep this order since the QSceen doesn't own the platform screen
+ delete platformScreen->screen();
+ delete platformScreen;
+}
+
+/*!
+ Should be called whenever the primary screen changes.
+
+ When the screen specified as primary changes, this method will notify
+ QGuiApplication and emit the QGuiApplication::primaryScreenChanged signal.
+ */
+void QWindowSystemInterface::handlePrimaryScreenChanged(QPlatformScreen *newPrimary)
+{
+ QScreen *newPrimaryScreen = newPrimary->screen();
+ int indexOfScreen = QGuiApplicationPrivate::screen_list.indexOf(newPrimaryScreen);
+ Q_ASSERT(indexOfScreen >= 0);
+ if (indexOfScreen == 0)
+ return;
+
+ QGuiApplicationPrivate::screen_list.swapItemsAt(0, indexOfScreen);
+ emit qGuiApp->primaryScreenChanged(newPrimaryScreen);
+}
+
void QWindowSystemInterface::handleScreenOrientationChange(QScreen *screen, Qt::ScreenOrientation orientation)
{
QWindowSystemInterfacePrivate::ScreenOrientationEvent *e =
diff --git a/src/gui/kernel/qwindowsysteminterface.h b/src/gui/kernel/qwindowsysteminterface.h
index 1dde9130ac..bf98c33a1a 100644
--- a/src/gui/kernel/qwindowsysteminterface.h
+++ b/src/gui/kernel/qwindowsysteminterface.h
@@ -233,6 +233,10 @@ public:
static bool handleNativeEvent(QWindow *window, const QByteArray &eventType, void *message, long *result);
// Changes to the screen
+ static void handleScreenAdded(QPlatformScreen *screen, bool isPrimary = false);
+ static void handleScreenRemoved(QPlatformScreen *screen);
+ static void handlePrimaryScreenChanged(QPlatformScreen *newPrimary);
+
static void handleScreenOrientationChange(QScreen *screen, Qt::ScreenOrientation newOrientation);
static void handleScreenGeometryChange(QScreen *screen, const QRect &newGeometry, const QRect &newAvailableGeometry);
static void handleScreenLogicalDotsPerInchChange(QScreen *screen, qreal newDpiX, qreal newDpiY);
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index 323253c70d..2e1a2b5bff 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -58,23 +58,17 @@
#include <limits.h>
#include <qbasictimer.h>
#include "private/qfunctions_p.h"
+#include <qloggingcategory.h>
#include <algorithm>
-// #define LAYOUT_DEBUG
-
-#ifdef LAYOUT_DEBUG
-#define LDEBUG qDebug()
-#define INC_INDENT debug_indent += " "
-#define DEC_INDENT debug_indent = debug_indent.left(debug_indent.length()-2)
-#else
-#define LDEBUG if(0) qDebug()
-#define INC_INDENT do {} while(0)
-#define DEC_INDENT do {} while(0)
-#endif
-
QT_BEGIN_NAMESPACE
+Q_LOGGING_CATEGORY(lcDraw, "qt.text.drawing")
+Q_LOGGING_CATEGORY(lcHit, "qt.text.hittest")
+Q_LOGGING_CATEGORY(lcLayout, "qt.text.layout")
+Q_LOGGING_CATEGORY(lcTable, "qt.text.layout.table")
+
// ################ should probably add frameFormatChange notification!
struct QTextLayoutStruct;
@@ -583,16 +577,16 @@ QTextDocumentLayoutPrivate::hitTest(QTextFrame *frame, const QFixedPoint &point,
QTextFrame *rootFrame = docPrivate->rootFrame();
-// LDEBUG << "checking frame" << frame->firstPosition() << "point=" << point
-// << "position" << fd->position << "size" << fd->size;
+ qCDebug(lcHit) << "checking frame" << frame->firstPosition() << "point=" << point.toPointF()
+ << "position" << fd->position.toPointF() << "size" << fd->size.toSizeF();
if (frame != rootFrame) {
if (relativePoint.y < 0 || relativePoint.x < 0) {
*position = frame->firstPosition() - 1;
-// LDEBUG << "before pos=" << *position;
+ qCDebug(lcHit) << "before pos=" << *position;
return PointBefore;
} else if (relativePoint.y > fd->size.height || relativePoint.x > fd->size.width) {
*position = frame->lastPosition() + 1;
-// LDEBUG << "after pos=" << *position;
+ qCDebug(lcHit) << "after pos=" << *position;
return PointAfter;
}
}
@@ -666,8 +660,6 @@ QTextDocumentLayoutPrivate::HitPoint
QTextDocumentLayoutPrivate::hitTest(QTextFrame::Iterator it, HitPoint hit, const QFixedPoint &p,
int *position, QTextLayout **l, Qt::HitTestAccuracy accuracy) const
{
- INC_INDENT;
-
for (; !it.atEnd(); ++it) {
QTextFrame *c = it.currentFrame();
HitPoint hp;
@@ -693,8 +685,7 @@ QTextDocumentLayoutPrivate::hitTest(QTextFrame::Iterator it, HitPoint hit, const
}
}
- DEC_INDENT;
-// LDEBUG << "inside=" << hit << " pos=" << *position;
+ qCDebug(lcHit) << "inside=" << hit << " pos=" << *position;
return hit;
}
@@ -741,15 +732,14 @@ QTextDocumentLayoutPrivate::hitTest(const QTextBlock &bl, const QFixedPoint &poi
QTextLayout *tl = bl.layout();
QRectF textrect = tl->boundingRect();
textrect.translate(tl->position());
-// LDEBUG << " checking block" << bl.position() << "point=" << point
-// << " tlrect" << textrect;
+ qCDebug(lcHit) << " checking block" << bl.position() << "point=" << point.toPointF() << " tlrect" << textrect;
*position = bl.position();
if (point.y.toReal() < textrect.top()) {
-// LDEBUG << " before pos=" << *position;
+ qCDebug(lcHit) << " before pos=" << *position;
return PointBefore;
} else if (point.y.toReal() > textrect.bottom()) {
*position += bl.length();
-// LDEBUG << " after pos=" << *position;
+ qCDebug(lcHit) << " after pos=" << *position;
return PointAfter;
}
@@ -781,7 +771,7 @@ QTextDocumentLayoutPrivate::hitTest(const QTextBlock &bl, const QFixedPoint &poi
}
*position += off;
-// LDEBUG << " inside=" << hit << " pos=" << *position;
+ qCDebug(lcHit) << " inside=" << hit << " pos=" << *position;
return hit;
}
@@ -944,8 +934,7 @@ void QTextDocumentLayoutPrivate::drawFrame(const QPointF &offset, QPainter *pain
|| off.x() > context.clip.right() || off.x() + fd->size.width.toReal() < context.clip.left()))
return;
-// LDEBUG << debug_indent << "drawFrame" << frame->firstPosition() << "--" << frame->lastPosition() << "at" << offset;
-// INC_INDENT;
+ qCDebug(lcDraw) << "drawFrame" << frame->firstPosition() << "--" << frame->lastPosition() << "at" << offset;
// if the cursor is /on/ a table border we may need to repaint it
// afterwards, as we usually draw the decoration first
@@ -1076,8 +1065,6 @@ void QTextDocumentLayoutPrivate::drawFrame(const QPointF &offset, QPainter *pain
painter->setPen(oldPen);
}
-// DEC_INDENT;
-
return;
}
@@ -1280,7 +1267,7 @@ void QTextDocumentLayoutPrivate::drawBlock(const QPointF &offset, QPainter *pain
r.translate(offset + tl->position());
if (!bl.isVisible() || (context.clip.isValid() && (r.bottom() < context.clip.y() || r.top() > context.clip.bottom())))
return;
-// LDEBUG << debug_indent << "drawBlock" << bl.position() << "at" << offset << "br" << tl->boundingRect();
+ qCDebug(lcDraw) << "drawBlock" << bl.position() << "at" << offset << "br" << tl->boundingRect();
QTextBlockFormat blockFormat = bl.blockFormat();
@@ -1512,7 +1499,7 @@ QTextLayoutStruct QTextDocumentLayoutPrivate::layoutCell(QTextTable *t, const QT
int layoutFrom, int layoutTo, QTextTableData *td,
QFixed absoluteTableY, bool withPageBreaks)
{
- LDEBUG << "layoutCell";
+ qCDebug(lcTable) << "layoutCell";
QTextLayoutStruct layoutStruct;
layoutStruct.frame = t;
layoutStruct.minimumWidth = 0;
@@ -1587,7 +1574,7 @@ QTextLayoutStruct QTextDocumentLayoutPrivate::layoutCell(QTextTable *t, const QT
QRectF QTextDocumentLayoutPrivate::layoutTable(QTextTable *table, int layoutFrom, int layoutTo, QFixed parentY)
{
- LDEBUG << "layoutTable";
+ qCDebug(lcTable) << "layoutTable from" << layoutFrom << "to" << layoutTo << "parentY" << parentY;
QTextTableData *td = static_cast<QTextTableData *>(data(table));
Q_ASSERT(td->sizeDirty);
const int rows = table->rows();
@@ -1709,6 +1696,7 @@ recalc_minmax_widths:
if (length.type() == QTextLength::FixedLength) {
td->minWidths[i] = td->widths[i] = qMax(scaleToDevice(QFixed::fromReal(length.rawValue())), td->minWidths.at(i));
remainingWidth -= td->widths.at(i);
+ qCDebug(lcTable) << "column" << i << "has width constraint" << td->minWidths.at(i) << "px, remaining width now" << remainingWidth;
} else if (length.type() == QTextLength::PercentageLength) {
totalPercentage += QFixed::fromReal(length.rawValue());
} else if (length.type() == QTextLength::VariableLength) {
@@ -1716,6 +1704,7 @@ recalc_minmax_widths:
td->widths[i] = td->minWidths.at(i);
remainingWidth -= td->minWidths.at(i);
+ qCDebug(lcTable) << "column" << i << "has variable width, min" << td->minWidths.at(i) << "remaining width now" << remainingWidth;
}
totalMinWidth += td->minWidths.at(i);
}
@@ -1735,6 +1724,8 @@ recalc_minmax_widths:
} else {
td->widths[i] = td->minWidths.at(i);
}
+ qCDebug(lcTable) << "column" << i << "has width constraint" << columnWidthConstraints.at(i).rawValue()
+ << "%, allocated width" << td->widths[i] << "remaining width now" << remainingWidth;
remainingWidth -= td->widths.at(i);
}
}
@@ -1978,9 +1969,12 @@ relayout:
td->minimumWidth += rightMargin - td->border;
td->maximumWidth = td->columnPositions.at(0);
- for (int i = 0; i < columns; ++i)
+ for (int i = 0; i < columns; ++i) {
if (td->maxWidths.at(i) != QFIXED_MAX)
td->maximumWidth += td->maxWidths.at(i) + 2 * td->border + cellSpacing;
+ qCDebug(lcTable) << "column" << i << "has final width" << td->widths.at(i).toReal()
+ << "min" << td->minWidths.at(i).toReal() << "max" << td->maxWidths.at(i).toReal();
+ }
td->maximumWidth += rightMargin - td->border;
td->updateTableSize();
@@ -2052,9 +2046,8 @@ void QTextDocumentLayoutPrivate::positionFloat(QTextFrame *frame, QTextLine *cur
QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, int layoutTo, QFixed parentY)
{
- LDEBUG << "layoutFrame (pre)";
+ qCDebug(lcLayout, "layoutFrame (%d--%d), parent=%p", f->firstPosition(), f->lastPosition(), f->parentFrame());
Q_ASSERT(data(f)->sizeDirty);
-// qDebug("layouting frame (%d--%d), parent=%p", f->firstPosition(), f->lastPosition(), f->parentFrame());
QTextFrameFormat fformat = f->frameFormat();
@@ -2076,9 +2069,8 @@ QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, in
QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, int layoutTo, QFixed frameWidth, QFixed frameHeight, QFixed parentY)
{
- LDEBUG << "layoutFrame from=" << layoutFrom << "to=" << layoutTo;
+ qCDebug(lcLayout, "layoutFrame (%d--%d), parent=%p", f->firstPosition(), f->lastPosition(), f->parentFrame());
Q_ASSERT(data(f)->sizeDirty);
-// qDebug("layouting frame (%d--%d), parent=%p", f->firstPosition(), f->lastPosition(), f->parentFrame());
QTextFrameData *fd = data(f);
QFixed newContentsWidth;
@@ -2165,8 +2157,8 @@ QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, in
layoutStruct.maximumWidth = QFIXED_MAX;
layoutStruct.fullLayout = fullLayout || (fd->oldContentsWidth != newContentsWidth);
layoutStruct.updateRect = QRectF(QPointF(0, 0), QSizeF(qreal(INT_MAX), qreal(INT_MAX)));
- LDEBUG << "layoutStruct: x_left" << layoutStruct.x_left << "x_right" << layoutStruct.x_right
- << "fullLayout" << layoutStruct.fullLayout;
+ qCDebug(lcLayout) << "layoutStruct: x_left" << layoutStruct.x_left << "x_right" << layoutStruct.x_right
+ << "fullLayout" << layoutStruct.fullLayout;
fd->oldContentsWidth = newContentsWidth;
layoutStruct.pageHeight = QFixed::fromReal(document->pageSize().height());
@@ -2220,7 +2212,7 @@ QRectF QTextDocumentLayoutPrivate::layoutFrame(QTextFrame *f, int layoutFrom, in
void QTextDocumentLayoutPrivate::layoutFlow(QTextFrame::Iterator it, QTextLayoutStruct *layoutStruct,
int layoutFrom, int layoutTo, QFixed width)
{
- LDEBUG << "layoutFlow from=" << layoutFrom << "to=" << layoutTo;
+ qCDebug(lcLayout) << "layoutFlow from=" << layoutFrom << "to=" << layoutTo;
QTextFrameData *fd = data(layoutStruct->frame);
fd->currentLayoutStruct = layoutStruct;
@@ -2578,9 +2570,8 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
QTextLayout *tl = bl.layout();
const int blockLength = bl.length();
- LDEBUG << "layoutBlock from=" << layoutFrom << "to=" << layoutTo;
-
-// qDebug() << "layoutBlock; width" << layoutStruct->x_right - layoutStruct->x_left << "(maxWidth is btw" << tl->maximumWidth() << ')';
+ qCDebug(lcLayout) << "layoutBlock from=" << layoutFrom << "to=" << layoutTo
+ << "; width" << layoutStruct->x_right - layoutStruct->x_left << "(maxWidth is btw" << tl->maximumWidth() << ')';
if (previousBlockFormat) {
qreal margin = qMax(blockFormat.topMargin(), previousBlockFormat->bottomMargin());
@@ -2612,7 +2603,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
// force relayout if we cross a page boundary
|| (layoutStruct->pageHeight != QFIXED_MAX && layoutStruct->absoluteY() + QFixed::fromReal(tl->boundingRect().height()) > layoutStruct->pageBottom)) {
- LDEBUG << " do layout";
+ qCDebug(lcLayout) << "do layout";
QTextOption option = docPrivate->defaultTextOption;
option.setTextDirection(dir);
option.setTabs( blockFormat.tabPositions() );
@@ -2741,7 +2732,7 @@ void QTextDocumentLayoutPrivate::layoutBlock(const QTextBlock &bl, int blockPosi
const int cnt = tl->lineCount();
QFixed bottom;
for (int i = 0; i < cnt; ++i) {
- LDEBUG << "going to move text line" << i;
+ qCDebug(lcLayout) << "going to move text line" << i;
QTextLine line = tl->lineAt(i);
layoutStruct->contentsWidth
= qMax(layoutStruct->contentsWidth, QFixed::fromReal(line.x() + tl->lineAt(i).naturalTextWidth()) + totalRightMargin);
diff --git a/src/network/configure.json b/src/network/configure.json
index e6c87b550b..07d46b790e 100644
--- a/src/network/configure.json
+++ b/src/network/configure.json
@@ -86,11 +86,11 @@
"sources": [
{ "type": "openssl" },
{
- "libs": "-lssleay32 -llibeay32",
+ "libs": "-lssleay32 -llibeay32 -lUser32 -lWs2_32 -lAdvapi32 -lGdi32",
"condition": "config.win32"
},
{
- "libs": "-llibssl -llibcrypto",
+ "libs": "-llibssl -llibcrypto -lUser32 -lWs2_32 -lAdvapi32 -lCrypt32",
"condition": "config.msvc"
},
{
diff --git a/src/plugins/platforms/android/qandroidplatformintegration.cpp b/src/plugins/platforms/android/qandroidplatformintegration.cpp
index 763b294660..e0c437be27 100644
--- a/src/plugins/platforms/android/qandroidplatformintegration.cpp
+++ b/src/plugins/platforms/android/qandroidplatformintegration.cpp
@@ -173,7 +173,7 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList &para
qFatal("Could not bind GL_ES API");
m_primaryScreen = new QAndroidPlatformScreen();
- screenAdded(m_primaryScreen);
+ QWindowSystemInterface::handleScreenAdded(m_primaryScreen);
m_primaryScreen->setPhysicalSize(QSize(m_defaultPhysicalSizeWidth, m_defaultPhysicalSizeHeight));
m_primaryScreen->setSize(QSize(m_defaultScreenWidth, m_defaultScreenHeight));
m_primaryScreen->setAvailableGeometry(QRect(0, 0, m_defaultGeometryWidth, m_defaultGeometryHeight));
diff --git a/src/plugins/platforms/bsdfb/qbsdfbintegration.cpp b/src/plugins/platforms/bsdfb/qbsdfbintegration.cpp
index 6a7d445e69..e4c90d26af 100644
--- a/src/plugins/platforms/bsdfb/qbsdfbintegration.cpp
+++ b/src/plugins/platforms/bsdfb/qbsdfbintegration.cpp
@@ -53,6 +53,7 @@
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatforminputcontext.h>
#include <qpa/qplatforminputcontextfactory_p.h>
+#include <qpa/qwindowsysteminterface.h>
#if QT_CONFIG(tslib)
#include <QtInputSupport/private/qtslib_p.h>
@@ -69,13 +70,13 @@ QBsdFbIntegration::QBsdFbIntegration(const QStringList &paramList)
QBsdFbIntegration::~QBsdFbIntegration()
{
- destroyScreen(m_primaryScreen.take());
+ QWindowSystemInterface::handleScreenRemoved(m_primaryScreen.take());
}
void QBsdFbIntegration::initialize()
{
if (m_primaryScreen->initialize())
- screenAdded(m_primaryScreen.data());
+ QWindowSystemInterface::handleScreenAdded(m_primaryScreen.data());
else
qWarning("bsdfb: Failed to initialize screen");
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro
index 8d65cf328f..083b7c1655 100644
--- a/src/plugins/platforms/cocoa/cocoa.pro
+++ b/src/plugins/platforms/cocoa/cocoa.pro
@@ -33,6 +33,7 @@ SOURCES += main.mm \
qcocoaintrospection.mm \
qcocoakeymapper.mm \
qcocoamimetypes.mm \
+ qiosurfacegraphicsbuffer.mm \
messages.cpp
HEADERS += qcocoaintegration.h \
@@ -67,6 +68,7 @@ HEADERS += qcocoaintegration.h \
qcocoaintrospection.h \
qcocoakeymapper.h \
messages.h \
+ qiosurfacegraphicsbuffer.h \
qcocoamimetypes.h
qtConfig(opengl.*) {
@@ -81,7 +83,7 @@ qtConfig(vulkan) {
RESOURCES += qcocoaresources.qrc
-LIBS += -framework AppKit -framework CoreServices -framework Carbon -framework IOKit -framework QuartzCore -framework CoreVideo -framework Metal -lcups
+LIBS += -framework AppKit -framework CoreServices -framework Carbon -framework IOKit -framework QuartzCore -framework CoreVideo -framework Metal -framework IOSurface -lcups
QT += \
core-private gui-private \
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index b4cd506513..508f24d578 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -44,13 +44,16 @@
#include <private/qcore_mac_p.h>
+#include <QScopedPointer>
+#include "qiosurfacegraphicsbuffer.h"
+
QT_BEGIN_NAMESPACE
-class QCocoaBackingStore : public QRasterBackingStore
+class QNSWindowBackingStore : public QRasterBackingStore
{
public:
- QCocoaBackingStore(QWindow *window);
- ~QCocoaBackingStore();
+ QNSWindowBackingStore(QWindow *window);
+ ~QNSWindowBackingStore();
void flush(QWindow *, const QRegion &, const QPoint &) override;
@@ -60,6 +63,49 @@ private:
void redrawRoundedBottomCorners(CGRect) const;
};
+class QCALayerBackingStore : public QPlatformBackingStore
+{
+public:
+ QCALayerBackingStore(QWindow *window);
+ ~QCALayerBackingStore();
+
+ void resize(const QSize &size, const QRegion &staticContents) override;
+
+ void beginPaint(const QRegion &region) override;
+ QPaintDevice *paintDevice() override;
+ void endPaint() override;
+
+ void flush(QWindow *, const QRegion &, const QPoint &) override;
+ void composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
+ QPlatformTextureList *textures, bool translucentBackground) override;
+
+ QPlatformGraphicsBuffer *graphicsBuffer() const override;
+
+private:
+ QSize m_requestedSize;
+ QRegion m_paintedRegion;
+
+ class GraphicsBuffer : public QIOSurfaceGraphicsBuffer
+ {
+ public:
+ GraphicsBuffer(const QSize &size, qreal devicePixelRatio,
+ const QPixelFormat &format, QCFType<CGColorSpaceRef> colorSpace);
+
+ QRegion dirtyRegion; // In unscaled coordinates
+ QImage *asImage();
+
+ private:
+ qreal m_devicePixelRatio;
+ QImage m_image;
+ };
+
+ void ensureBackBuffer();
+ bool recreateBackBufferIfNeeded();
+ bool prepareForFlush();
+
+ std::list<std::unique_ptr<GraphicsBuffer>> m_buffers;
+};
+
QT_END_NAMESPACE
#endif
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 81a0a7d040..8e4e928bc5 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -42,24 +42,28 @@
#include "qcocoawindow.h"
#include "qcocoahelpers.h"
+#include <QtCore/qmath.h>
+
+#include <QuartzCore/CATransaction.h>
+
QT_BEGIN_NAMESPACE
-QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
+QNSWindowBackingStore::QNSWindowBackingStore(QWindow *window)
: QRasterBackingStore(window)
{
}
-QCocoaBackingStore::~QCocoaBackingStore()
+QNSWindowBackingStore::~QNSWindowBackingStore()
{
}
-bool QCocoaBackingStore::windowHasUnifiedToolbar() const
+bool QNSWindowBackingStore::windowHasUnifiedToolbar() const
{
Q_ASSERT(window()->handle());
return static_cast<QCocoaWindow *>(window()->handle())->m_drawContentBorderGradient;
}
-QImage::Format QCocoaBackingStore::format() const
+QImage::Format QNSWindowBackingStore::format() const
{
if (windowHasUnifiedToolbar())
return QImage::Format_ARGB32_Premultiplied;
@@ -78,7 +82,7 @@ QImage::Format QCocoaBackingStore::format() const
coordinates, and the \a offset will be the child window's offset in relation
to the backingstore's top level window.
*/
-void QCocoaBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+void QNSWindowBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
if (m_image.isNull())
return;
@@ -103,131 +107,113 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion &region, const QPo
qCDebug(lcQpaBackingStore) << "Flushing" << region << "of" << view << qPrintable(targetViewDescription);
}
- // Prevent potentially costly color conversion by assigning the display color space
- // to the backingstore image. This does not copy the underlying image data.
- CGColorSpaceRef displayColorSpace = view.window.screen.colorSpace.CGColorSpace;
- QCFType<CGImageRef> cgImage = CGImageCreateCopyWithColorSpace(
- QCFType<CGImageRef>(m_image.toCGImage()), displayColorSpace);
-
- if (view.layer) {
- // In layer-backed mode, locking focus on a view does not give the right
- // view transformation, and doesn't give us a graphics context to render
- // via when drawing outside of the display cycle. Instead we tell AppKit
- // that we want to update the layer's content, via [NSView wantsUpdateLayer],
- // which result in AppKit not creating a backingstore for each layer, and
- // we then directly set the layer's backingstore (content) to our backingstore,
- // masked to the part of the subview that is relevant.
- // FIXME: Figure out if there's a way to do partial updates
- view.layer.contents = (__bridge id)static_cast<CGImageRef>(cgImage);
- if (view != topLevelView) {
- const CGSize topLevelSize = topLevelView.bounds.size;
- view.layer.contentsRect = CGRectApplyAffineTransform(
- [view convertRect:view.bounds toView:topLevelView],
- // The contentsRect is in unit coordinate system
- CGAffineTransformMakeScale(1.0 / topLevelSize.width, 1.0 / topLevelSize.height));
- }
- } else {
- // Normally a NSView is drawn via drawRect, as part of the display cycle in the
- // main runloop, via setNeedsDisplay and friends. AppKit will lock focus on each
- // individual view, starting with the top level and then traversing any subviews,
- // calling drawRect for each of them. This pull model results in expose events
- // sent to Qt, which result in drawing to the backingstore and flushing it.
- // Qt may also decide to paint and flush the backingstore via e.g. timers,
- // or other events such as mouse events, in which case we're in a push model.
- // If there is no focused view, it means we're in the latter case, and need
- // to manually flush the NSWindow after drawing to its graphic context.
- const bool drawingOutsideOfDisplayCycle = ![NSView focusView];
-
- // We also need to ensure the flushed view has focus, so that the graphics
- // context is set up correctly (coordinate system, clipping, etc). Outside
- // of the normal display cycle there is no focused view, as explained above,
- // so we have to handle it manually. There's also a corner case inside the
- // normal display cycle due to way QWidgetBackingStore composits native child
- // widgets, where we'll get a flush of a native child during the drawRect of
- // its parent/ancestor, and the parent/ancestor being the one locked by AppKit.
- // In this case we also need to lock and unlock focus manually.
- const bool shouldHandleViewLockManually = [NSView focusView] != view;
- if (shouldHandleViewLockManually && ![view lockFocusIfCanDraw]) {
- qWarning() << "failed to lock focus of" << view;
- return;
- }
+ // Normally a NSView is drawn via drawRect, as part of the display cycle in the
+ // main runloop, via setNeedsDisplay and friends. AppKit will lock focus on each
+ // individual view, starting with the top level and then traversing any subviews,
+ // calling drawRect for each of them. This pull model results in expose events
+ // sent to Qt, which result in drawing to the backingstore and flushing it.
+ // Qt may also decide to paint and flush the backingstore via e.g. timers,
+ // or other events such as mouse events, in which case we're in a push model.
+ // If there is no focused view, it means we're in the latter case, and need
+ // to manually flush the NSWindow after drawing to its graphic context.
+ const bool drawingOutsideOfDisplayCycle = ![NSView focusView];
+
+ // We also need to ensure the flushed view has focus, so that the graphics
+ // context is set up correctly (coordinate system, clipping, etc). Outside
+ // of the normal display cycle there is no focused view, as explained above,
+ // so we have to handle it manually. There's also a corner case inside the
+ // normal display cycle due to way QWidgetBackingStore composits native child
+ // widgets, where we'll get a flush of a native child during the drawRect of
+ // its parent/ancestor, and the parent/ancestor being the one locked by AppKit.
+ // In this case we also need to lock and unlock focus manually.
+ const bool shouldHandleViewLockManually = [NSView focusView] != view;
+ if (shouldHandleViewLockManually && ![view lockFocusIfCanDraw]) {
+ qWarning() << "failed to lock focus of" << view;
+ return;
+ }
- const qreal devicePixelRatio = m_image.devicePixelRatio();
+ const qreal devicePixelRatio = m_image.devicePixelRatio();
- // If the flushed window is a content view, and we're filling the drawn area
- // completely, or it doesn't have a window background we need to preserve,
- // we can get away with copying instead of blending the backing store.
- QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
- const NSCompositingOperation compositingOperation = cocoaWindow->isContentView()
- && (cocoaWindow->isOpaque() || view.window.backgroundColor == NSColor.clearColor)
- ? NSCompositingOperationCopy : NSCompositingOperationSourceOver;
+ // If the flushed window is a content view, and we're filling the drawn area
+ // completely, or it doesn't have a window background we need to preserve,
+ // we can get away with copying instead of blending the backing store.
+ QCocoaWindow *cocoaWindow = static_cast<QCocoaWindow *>(window->handle());
+ const NSCompositingOperation compositingOperation = cocoaWindow->isContentView()
+ && (cocoaWindow->isOpaque() || view.window.backgroundColor == NSColor.clearColor)
+ ? NSCompositingOperationCopy : NSCompositingOperationSourceOver;
#ifdef QT_DEBUG
- static bool debugBackingStoreFlush = [[NSUserDefaults standardUserDefaults]
- boolForKey:@"QtCocoaDebugBackingStoreFlush"];
+ static bool debugBackingStoreFlush = [[NSUserDefaults standardUserDefaults]
+ boolForKey:@"QtCocoaDebugBackingStoreFlush"];
#endif
- // -------------------------------------------------------------------------
+ // -------------------------------------------------------------------------
- // The current contexts is typically a NSWindowGraphicsContext, but can be
- // NSBitmapGraphicsContext e.g. when debugging the view hierarchy in Xcode.
- // If we need to distinguish things here in the future, we can use e.g.
- // [NSGraphicsContext drawingToScreen], or the attributes of the context.
- NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext];
- Q_ASSERT_X(graphicsContext, "QCocoaBackingStore",
- "Focusing the view should give us a current graphics context");
+ // The current contexts is typically a NSWindowGraphicsContext, but can be
+ // NSBitmapGraphicsContext e.g. when debugging the view hierarchy in Xcode.
+ // If we need to distinguish things here in the future, we can use e.g.
+ // [NSGraphicsContext drawingToScreen], or the attributes of the context.
+ NSGraphicsContext *graphicsContext = [NSGraphicsContext currentContext];
+ Q_ASSERT_X(graphicsContext, "QCocoaBackingStore",
+ "Focusing the view should give us a current graphics context");
- // Create temporary image to use for blitting, without copying image data
- NSImage *backingStoreImage = [[[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize] autorelease];
+ // Prevent potentially costly color conversion by assigning the display color space
+ // to the backingstore image. This does not copy the underlying image data.
+ CGColorSpaceRef displayColorSpace = view.window.screen.colorSpace.CGColorSpace;
+ QCFType<CGImageRef> cgImage = CGImageCreateCopyWithColorSpace(
+ QCFType<CGImageRef>(m_image.toCGImage()), displayColorSpace);
- QRegion clippedRegion = region;
- for (QWindow *w = window; w; w = w->parent()) {
- if (!w->mask().isEmpty()) {
- clippedRegion &= w == window ? w->mask()
- : w->mask().translated(window->mapFromGlobal(w->mapToGlobal(QPoint(0, 0))));
- }
+ // Create temporary image to use for blitting, without copying image data
+ NSImage *backingStoreImage = [[[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize] autorelease];
+
+ QRegion clippedRegion = region;
+ for (QWindow *w = window; w; w = w->parent()) {
+ if (!w->mask().isEmpty()) {
+ clippedRegion &= w == window ? w->mask()
+ : w->mask().translated(window->mapFromGlobal(w->mapToGlobal(QPoint(0, 0))));
}
+ }
- for (const QRect &viewLocalRect : clippedRegion) {
- QPoint backingStoreOffset = viewLocalRect.topLeft() + offset;
- QRect backingStoreRect(backingStoreOffset * devicePixelRatio, viewLocalRect.size() * devicePixelRatio);
- if (graphicsContext.flipped) // Flip backingStoreRect to match graphics context
- backingStoreRect.moveTop(m_image.height() - (backingStoreRect.y() + backingStoreRect.height()));
+ for (const QRect &viewLocalRect : clippedRegion) {
+ QPoint backingStoreOffset = viewLocalRect.topLeft() + offset;
+ QRect backingStoreRect(backingStoreOffset * devicePixelRatio, viewLocalRect.size() * devicePixelRatio);
+ if (graphicsContext.flipped) // Flip backingStoreRect to match graphics context
+ backingStoreRect.moveTop(m_image.height() - (backingStoreRect.y() + backingStoreRect.height()));
- CGRect viewRect = viewLocalRect.toCGRect();
+ CGRect viewRect = viewLocalRect.toCGRect();
- if (windowHasUnifiedToolbar())
- NSDrawWindowBackground(viewRect);
+ if (windowHasUnifiedToolbar())
+ NSDrawWindowBackground(viewRect);
- [backingStoreImage drawInRect:viewRect fromRect:backingStoreRect.toCGRect()
- operation:compositingOperation fraction:1.0 respectFlipped:YES hints:nil];
+ [backingStoreImage drawInRect:viewRect fromRect:backingStoreRect.toCGRect()
+ operation:compositingOperation fraction:1.0 respectFlipped:YES hints:nil];
#ifdef QT_DEBUG
- if (Q_UNLIKELY(debugBackingStoreFlush)) {
- [[NSColor colorWithCalibratedRed:drand48() green:drand48() blue:drand48() alpha:0.3] set];
- [NSBezierPath fillRect:viewRect];
-
- if (drawingOutsideOfDisplayCycle) {
- [[[NSColor magentaColor] colorWithAlphaComponent:0.5] set];
- [NSBezierPath strokeLineFromPoint:viewLocalRect.topLeft().toCGPoint()
- toPoint:viewLocalRect.bottomRight().toCGPoint()];
- }
+ if (Q_UNLIKELY(debugBackingStoreFlush)) {
+ [[NSColor colorWithCalibratedRed:drand48() green:drand48() blue:drand48() alpha:0.3] set];
+ [NSBezierPath fillRect:viewRect];
+
+ if (drawingOutsideOfDisplayCycle) {
+ [[[NSColor magentaColor] colorWithAlphaComponent:0.5] set];
+ [NSBezierPath strokeLineFromPoint:viewLocalRect.topLeft().toCGPoint()
+ toPoint:viewLocalRect.bottomRight().toCGPoint()];
}
-#endif
}
+#endif
+ }
- // -------------------------------------------------------------------------
+ // -------------------------------------------------------------------------
- if (shouldHandleViewLockManually)
- [view unlockFocus];
+ if (shouldHandleViewLockManually)
+ [view unlockFocus];
- if (drawingOutsideOfDisplayCycle) {
- redrawRoundedBottomCorners([view convertRect:region.boundingRect().toCGRect() toView:nil]);
- [view.window flushWindow];
- }
+ if (drawingOutsideOfDisplayCycle) {
+ redrawRoundedBottomCorners([view convertRect:region.boundingRect().toCGRect() toView:nil]);
+ [view.window flushWindow];
}
- // Done flushing to either CALayer or NSWindow backingstore
+
+ // Done flushing to NSWindow backingstore
QCocoaWindow *topLevelCocoaWindow = static_cast<QCocoaWindow *>(topLevelWindow->handle());
if (Q_UNLIKELY(topLevelCocoaWindow->m_needsInvalidateShadow)) {
@@ -251,7 +237,7 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion &region, const QPo
https://trac.webkit.org/changeset/85376/webkit
*/
-void QCocoaBackingStore::redrawRoundedBottomCorners(CGRect windowRect) const
+void QNSWindowBackingStore::redrawRoundedBottomCorners(CGRect windowRect) const
{
#if !defined(QT_APPLE_NO_PRIVATE_APIS)
Q_ASSERT(this->window()->handle());
@@ -285,4 +271,345 @@ void QCocoaBackingStore::redrawRoundedBottomCorners(CGRect windowRect) const
#endif
}
+// ----------------------------------------------------------------------------
+
+// https://stackoverflow.com/a/52722575/2761869
+template<class R>
+struct backwards_t {
+ R r;
+ constexpr auto begin() const { using std::rbegin; return rbegin(r); }
+ constexpr auto begin() { using std::rbegin; return rbegin(r); }
+ constexpr auto end() const { using std::rend; return rend(r); }
+ constexpr auto end() { using std::rend; return rend(r); }
+};
+template<class R>
+constexpr backwards_t<R> backwards(R&& r) { return {std::forward<R>(r)}; }
+
+QCALayerBackingStore::QCALayerBackingStore(QWindow *window)
+ : QPlatformBackingStore(window)
+{
+ qCDebug(lcQpaBackingStore) << "Creating QCALayerBackingStore for" << window;
+ m_buffers.resize(1);
+}
+
+QCALayerBackingStore::~QCALayerBackingStore()
+{
+}
+
+void QCALayerBackingStore::resize(const QSize &size, const QRegion &staticContents)
+{
+ qCDebug(lcQpaBackingStore) << "Resize requested to" << size;
+
+ if (!staticContents.isNull())
+ qCWarning(lcQpaBackingStore) << "QCALayerBackingStore does not support static contents";
+
+ m_requestedSize = size;
+}
+
+void QCALayerBackingStore::beginPaint(const QRegion &region)
+{
+ Q_UNUSED(region);
+
+ QMacAutoReleasePool pool;
+
+ qCInfo(lcQpaBackingStore) << "Beginning paint of" << region << "into backingstore of" << m_requestedSize;
+
+ ensureBackBuffer(); // Find an unused back buffer, or reserve space for a new one
+
+ const bool bufferWasRecreated = recreateBackBufferIfNeeded();
+
+ m_buffers.back()->lock(QPlatformGraphicsBuffer::SWWriteAccess);
+
+ // Although undocumented, QBackingStore::beginPaint expects the painted region
+ // to be cleared before use if the window has a surface format with an alpha.
+ // Fresh IOSurfaces are already cleared, so we don't need to clear those.
+ if (!bufferWasRecreated && window()->format().hasAlpha()) {
+ qCDebug(lcQpaBackingStore) << "Clearing" << region << "before use";
+ QPainter painter(m_buffers.back()->asImage());
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+ for (const QRect &rect : region)
+ painter.fillRect(rect, Qt::transparent);
+ }
+
+ m_paintedRegion += region;
+}
+
+void QCALayerBackingStore::ensureBackBuffer()
+{
+ if (window()->format().swapBehavior() == QSurfaceFormat::SingleBuffer)
+ return;
+
+ // The current back buffer may have been assigned to a layer in a previous flush,
+ // but we deferred the swap. Do it now if the surface has been picked up by CA.
+ if (m_buffers.back() && m_buffers.back()->isInUse() && m_buffers.back() != m_buffers.front()) {
+ qCInfo(lcQpaBackingStore) << "Back buffer has been picked up by CA, swapping to front";
+ std::swap(m_buffers.back(), m_buffers.front());
+ }
+
+ if (Q_UNLIKELY(lcQpaBackingStore().isDebugEnabled())) {
+ // ┌───────┬───────┬───────┬─────┬──────┐
+ // │ front ┊ spare ┊ spare ┊ ... ┊ back │
+ // └───────┴───────┴───────┴─────┴──────┘
+ for (const auto &buffer : m_buffers) {
+ qCDebug(lcQpaBackingStore).nospace() << " "
+ << (buffer == m_buffers.front() ? "front" :
+ buffer == m_buffers.back() ? " back" :
+ "spare"
+ ) << ": " << buffer.get();
+ }
+ }
+
+ // Ensure our back buffer is ready to draw into. If not, find a buffer that
+ // is not in use, or reserve space for a new buffer if none can be found.
+ for (auto &buffer : backwards(m_buffers)) {
+ if (!buffer || !buffer->isInUse()) {
+ // Buffer is okey to use, swap if necessary
+ if (buffer != m_buffers.back())
+ std::swap(buffer, m_buffers.back());
+ qCDebug(lcQpaBackingStore) << "Using back buffer" << m_buffers.back().get();
+
+ static const int kMaxSwapChainDepth = 3;
+ if (m_buffers.size() > kMaxSwapChainDepth) {
+ qCDebug(lcQpaBackingStore) << "Reducing swap chain depth to" << kMaxSwapChainDepth;
+ m_buffers.erase(std::next(m_buffers.begin(), 1), std::prev(m_buffers.end(), 2));
+ }
+
+ break;
+ } else if (buffer == m_buffers.front()) {
+ // We've exhausted the available buffers, make room for a new one
+ const int swapChainDepth = m_buffers.size() + 1;
+ qCDebug(lcQpaBackingStore) << "Available buffers exhausted, increasing swap chain depth to" << swapChainDepth;
+ m_buffers.resize(swapChainDepth);
+ break;
+ }
+ }
+
+ Q_ASSERT(!m_buffers.back() || !m_buffers.back()->isInUse());
+}
+
+// Disabled until performance issue on 5K iMac Pro has been investigated further,
+// as rounding up during resize will typically result in full screen buffer sizes
+// and low frame rate also for smaller window sizes.
+#define USE_LAZY_BUFFER_ALLOCATION_DURING_LIVE_WINDOW_RESIZE 0
+
+bool QCALayerBackingStore::recreateBackBufferIfNeeded()
+{
+ const qreal devicePixelRatio = window()->devicePixelRatio();
+ QSize requestedBufferSize = m_requestedSize * devicePixelRatio;
+
+ const NSView *backingStoreView = static_cast<QCocoaWindow *>(window()->handle())->view();
+ Q_UNUSED(backingStoreView);
+
+ auto bufferSizeMismatch = [&](const QSize requested, const QSize actual) {
+#if USE_LAZY_BUFFER_ALLOCATION_DURING_LIVE_WINDOW_RESIZE
+ if (backingStoreView.inLiveResize) {
+ // Prevent over-eager buffer allocation during window resize by reusing larger buffers
+ return requested.width() > actual.width() || requested.height() > actual.height();
+ }
+#endif
+ return requested != actual;
+ };
+
+ if (!m_buffers.back() || bufferSizeMismatch(requestedBufferSize, m_buffers.back()->size())) {
+#if USE_LAZY_BUFFER_ALLOCATION_DURING_LIVE_WINDOW_RESIZE
+ if (backingStoreView.inLiveResize) {
+ // Prevent over-eager buffer allocation during window resize by rounding up
+ QSize nativeScreenSize = window()->screen()->geometry().size() * devicePixelRatio;
+ requestedBufferSize = QSize(qNextPowerOfTwo(requestedBufferSize.width()),
+ qNextPowerOfTwo(requestedBufferSize.height())).boundedTo(nativeScreenSize);
+ }
+#endif
+
+ qCInfo(lcQpaBackingStore) << "Creating surface of" << requestedBufferSize
+ << "based on requested" << m_requestedSize << "and dpr =" << devicePixelRatio;
+
+ static auto pixelFormat = QImage::toPixelFormat(QImage::Format_ARGB32_Premultiplied);
+
+ NSView *view = static_cast<QCocoaWindow *>(window()->handle())->view();
+ auto colorSpace = QCFType<CGColorSpaceRef>::constructFromGet(view.window.screen.colorSpace.CGColorSpace);
+
+ m_buffers.back().reset(new GraphicsBuffer(requestedBufferSize, devicePixelRatio, pixelFormat, colorSpace));
+ return true;
+ }
+
+ return false;
+}
+
+QPaintDevice *QCALayerBackingStore::paintDevice()
+{
+ Q_ASSERT(m_buffers.back());
+ return m_buffers.back()->asImage();
+}
+
+void QCALayerBackingStore::endPaint()
+{
+ qCInfo(lcQpaBackingStore) << "Paint ended with painted region" << m_paintedRegion;
+ m_buffers.back()->unlock();
+}
+
+void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion &region, const QPoint &offset)
+{
+ Q_UNUSED(region);
+ Q_UNUSED(offset);
+
+ if (!prepareForFlush())
+ return;
+
+ QMacAutoReleasePool pool;
+
+ NSView *backingStoreView = static_cast<QCocoaWindow *>(window()->handle())->view();
+ NSView *flushedView = static_cast<QCocoaWindow *>(flushedWindow->handle())->view();
+
+ id backBufferSurface = (__bridge id)m_buffers.back()->surface();
+ if (flushedView.layer.contents == backBufferSurface) {
+ // We've managed to paint to the back buffer again before Core Animation had time
+ // to flush the transaction and persist the layer changes to the window server.
+ // The layer already knows about the back buffer, and we don't need to re-apply
+ // it to pick up the surface changes, so bail out early.
+ qCInfo(lcQpaBackingStore).nospace() << "Skipping flush of " << flushedView
+ << ", layer already reflects back buffer";
+ return;
+ }
+
+ // Trigger a new display cycle if there isn't one. This ensures that our layer updates
+ // are committed as part of a display-cycle instead of on the next runloop pass. This
+ // means CA won't try to throttle us if we flush too fast, and we'll coalesce our flush
+ // with other pending view and layer updates.
+ backingStoreView.window.viewsNeedDisplay = YES;
+
+ if (window()->format().swapBehavior() == QSurfaceFormat::SingleBuffer) {
+ // The private API [CALayer reloadValueForKeyPath:@"contents"] would be preferable,
+ // but barring any side effects or performance issues we opt for the hammer for now.
+ flushedView.layer.contents = nil;
+ }
+
+ qCInfo(lcQpaBackingStore) << "Flushing" << backBufferSurface
+ << "to" << flushedView.layer << "of" << flushedView;
+
+ flushedView.layer.contents = backBufferSurface;
+
+ if (flushedView != backingStoreView) {
+ const CGSize backingStoreSize = backingStoreView.bounds.size;
+ flushedView.layer.contentsRect = CGRectApplyAffineTransform(
+ [flushedView convertRect:flushedView.bounds toView:backingStoreView],
+ // The contentsRect is in unit coordinate system
+ CGAffineTransformMakeScale(1.0 / backingStoreSize.width, 1.0 / backingStoreSize.height));
+ }
+
+ // Since we may receive multiple flushes before a new frame is started, we do not
+ // swap any buffers just yet. Instead we check in the next beginPaint if the layer's
+ // surface is in use, and if so swap to an unused surface as the new back buffer.
+
+ // Note: Ideally CoreAnimation would mark a surface as in use the moment we assign
+ // it to a layer, but as that's not the case we may end up painting to the same back
+ // buffer once more if we are painting faster than CA can ship the surfaces over to
+ // the window server.
+}
+
+void QCALayerBackingStore::composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
+ QPlatformTextureList *textures, bool translucentBackground)
+{
+ if (!prepareForFlush())
+ return;
+
+ QPlatformBackingStore::composeAndFlush(window, region, offset, textures, translucentBackground);
+}
+
+QPlatformGraphicsBuffer *QCALayerBackingStore::graphicsBuffer() const
+{
+ return m_buffers.back().get();
+}
+
+bool QCALayerBackingStore::prepareForFlush()
+{
+ if (!m_buffers.back()) {
+ qCWarning(lcQpaBackingStore) << "Tried to flush backingstore without painting to it first";
+ return false;
+ }
+
+ // Update dirty state of buffers based on what was painted. The back buffer will be
+ // less dirty, since we painted to it, while other buffers will become more dirty.
+ // This allows us to minimize copies between front and back buffers on swap in the
+ // cases where the painted region overlaps with the previous frame (front buffer).
+ for (const auto &buffer : m_buffers) {
+ if (buffer == m_buffers.back())
+ buffer->dirtyRegion -= m_paintedRegion;
+ else
+ buffer->dirtyRegion += m_paintedRegion;
+ }
+
+ // After painting, the back buffer is only guaranteed to have content for the painted
+ // region, and may still have dirty areas that need to be synced up with the front buffer,
+ // if we have one. We know that the front buffer is always up to date.
+ if (!m_buffers.back()->dirtyRegion.isEmpty() && m_buffers.front() != m_buffers.back()) {
+ QRegion preserveRegion = m_buffers.back()->dirtyRegion;
+ qCDebug(lcQpaBackingStore) << "Preserving" << preserveRegion << "from front to back buffer";
+
+ m_buffers.front()->lock(QPlatformGraphicsBuffer::SWReadAccess);
+ const QImage *frontBuffer = m_buffers.front()->asImage();
+
+ const QRect frontSurfaceBounds(QPoint(0, 0), m_buffers.front()->size());
+ const qreal sourceDevicePixelRatio = frontBuffer->devicePixelRatio();
+
+ m_buffers.back()->lock(QPlatformGraphicsBuffer::SWWriteAccess);
+ QPainter painter(m_buffers.back()->asImage());
+ painter.setCompositionMode(QPainter::CompositionMode_Source);
+
+ // Let painter operate in device pixels, to make it easier to compare coordinates
+ const qreal targetDevicePixelRatio = painter.device()->devicePixelRatio();
+ painter.scale(1.0 / targetDevicePixelRatio, 1.0 / targetDevicePixelRatio);
+
+ for (const QRect &rect : preserveRegion) {
+ QRect sourceRect(rect.topLeft() * sourceDevicePixelRatio, rect.size() * sourceDevicePixelRatio);
+ QRect targetRect(rect.topLeft() * targetDevicePixelRatio, rect.size() * targetDevicePixelRatio);
+
+#ifdef QT_DEBUG
+ if (Q_UNLIKELY(!frontSurfaceBounds.contains(sourceRect.bottomRight()))) {
+ qCWarning(lcQpaBackingStore) << "Front buffer too small to preserve"
+ << QRegion(sourceRect).subtracted(frontSurfaceBounds);
+ }
+#endif
+ painter.drawImage(targetRect, *frontBuffer, sourceRect);
+ }
+
+ m_buffers.back()->unlock();
+ m_buffers.front()->unlock();
+
+ // The back buffer is now completely in sync, ready to be presented
+ m_buffers.back()->dirtyRegion = QRegion();
+ }
+
+ // Prepare for another round of painting
+ m_paintedRegion = QRegion();
+
+ return true;
+}
+
+// ----------------------------------------------------------------------------
+
+QCALayerBackingStore::GraphicsBuffer::GraphicsBuffer(const QSize &size, qreal devicePixelRatio,
+ const QPixelFormat &format, QCFType<CGColorSpaceRef> colorSpace)
+ : QIOSurfaceGraphicsBuffer(size, format, colorSpace)
+ , dirtyRegion(0, 0, size.width() / devicePixelRatio, size.height() / devicePixelRatio)
+ , m_devicePixelRatio(devicePixelRatio)
+{
+}
+
+QImage *QCALayerBackingStore::GraphicsBuffer::asImage()
+{
+ if (m_image.isNull()) {
+ qCDebug(lcQpaBackingStore) << "Setting up paint device for" << this;
+ CFRetain(surface());
+ m_image = QImage(data(), size().width(), size().height(),
+ bytesPerLine(), QImage::toImageFormat(format()),
+ QImageCleanupFunction(CFRelease), surface());
+ m_image.setDevicePixelRatio(m_devicePixelRatio);
+ }
+
+ Q_ASSERT_X(m_image.constBits() == data(), "QCALayerBackingStore",
+ "IOSurfaces should have have a fixed location in memory once created");
+
+ return &m_image;
+}
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm
index affbee35b7..fb3d05d3e4 100644
--- a/src/plugins/platforms/cocoa/qcocoaintegration.mm
+++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm
@@ -244,7 +244,7 @@ QCocoaIntegration::~QCocoaIntegration()
// Delete screens in reverse order to avoid crash in case of multiple screens
while (!mScreens.isEmpty()) {
- destroyScreen(mScreens.takeLast());
+ QWindowSystemInterface::handleScreenRemoved(mScreens.takeLast());
}
clearToolbars();
@@ -304,7 +304,7 @@ void QCocoaIntegration::updateScreens()
screen = new QCocoaScreen(i);
mScreens.append(screen);
qCDebug(lcQpaScreen) << "Adding" << screen;
- screenAdded(screen);
+ QWindowSystemInterface::handleScreenAdded(screen);
}
siblings << screen;
}
@@ -321,7 +321,7 @@ void QCocoaIntegration::updateScreens()
// Prevent stale references to NSScreen during destroy
screen->m_screenIndex = -1;
qCDebug(lcQpaScreen) << "Removing" << screen;
- destroyScreen(screen);
+ QWindowSystemInterface::handleScreenRemoved(screen);
}
}
@@ -407,7 +407,16 @@ QPlatformOpenGLContext *QCocoaIntegration::createPlatformOpenGLContext(QOpenGLCo
QPlatformBackingStore *QCocoaIntegration::createPlatformBackingStore(QWindow *window) const
{
- return new QCocoaBackingStore(window);
+ QCocoaWindow *platformWindow = static_cast<QCocoaWindow*>(window->handle());
+ if (!platformWindow) {
+ qWarning() << window << "must be created before being used with a backingstore";
+ return nullptr;
+ }
+
+ if (platformWindow->view().layer)
+ return new QCALayerBackingStore(window);
+ else
+ return new QNSWindowBackingStore(window);
}
QAbstractEventDispatcher *QCocoaIntegration::createEventDispatcher() const
diff --git a/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h b/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h
new file mode 100644
index 0000000000..872773cb7a
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QIOSURFACEGRAPHICSBUFFER_H
+#define QIOSURFACEGRAPHICSBUFFER_H
+
+#include <qpa/qplatformgraphicsbuffer.h>
+#include <private/qcore_mac_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIOSurfaceGraphicsBuffer : public QPlatformGraphicsBuffer
+{
+public:
+ QIOSurfaceGraphicsBuffer(const QSize &size, const QPixelFormat &format, QCFType<CGColorSpaceRef> colorSpace);
+ ~QIOSurfaceGraphicsBuffer();
+
+ const uchar *data() const override;
+ uchar *data() override;
+ int bytesPerLine() const override;
+
+ IOSurfaceRef surface();
+ bool isInUse() const;
+
+protected:
+ bool doLock(AccessTypes access, const QRect &rect) override;
+ void doUnlock() override;
+
+private:
+ QCFType<IOSurfaceRef> m_surface;
+
+ friend QDebug operator<<(QDebug, const QIOSurfaceGraphicsBuffer *);
+};
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug, const QIOSurfaceGraphicsBuffer *);
+#endif
+
+QT_END_NAMESPACE
+
+#endif // QIOSURFACEGRAPHICSBUFFER_H
diff --git a/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.mm b/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.mm
new file mode 100644
index 0000000000..a367487e85
--- /dev/null
+++ b/src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.mm
@@ -0,0 +1,188 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qiosurfacegraphicsbuffer.h"
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qloggingcategory.h>
+
+#include <CoreGraphics/CoreGraphics.h>
+#include <IOSurface/IOSurface.h>
+
+// CGColorSpaceCopyPropertyList is available on 10.12 and above,
+// but was only added in the 10.14 SDK, so declare it just in case.
+extern "C" CFPropertyListRef CGColorSpaceCopyPropertyList(CGColorSpaceRef space);
+
+QT_BEGIN_NAMESPACE
+
+Q_LOGGING_CATEGORY(lcQpaIOSurface, "qt.qpa.backingstore.iosurface");
+
+QIOSurfaceGraphicsBuffer::QIOSurfaceGraphicsBuffer(const QSize &size, const QPixelFormat &format, QCFType<CGColorSpaceRef> colorSpace)
+ : QPlatformGraphicsBuffer(size, format)
+{
+ const size_t width = size.width();
+ const size_t height = size.height();
+
+ Q_ASSERT(width <= IOSurfaceGetPropertyMaximum(kIOSurfaceWidth));
+ Q_ASSERT(height <= IOSurfaceGetPropertyMaximum(kIOSurfaceHeight));
+
+ static const char bytesPerElement = 4;
+
+ const size_t bytesPerRow = IOSurfaceAlignProperty(kIOSurfaceBytesPerRow, width * bytesPerElement);
+ const size_t totalBytes = IOSurfaceAlignProperty(kIOSurfaceAllocSize, height * bytesPerRow);
+
+ NSDictionary *options = @{
+ (id)kIOSurfaceWidth: @(width),
+ (id)kIOSurfaceHeight: @(height),
+ (id)kIOSurfacePixelFormat: @(unsigned('BGRA')),
+ (id)kIOSurfaceBytesPerElement: @(bytesPerElement),
+ (id)kIOSurfaceBytesPerRow: @(bytesPerRow),
+ (id)kIOSurfaceAllocSize: @(totalBytes),
+ };
+
+ m_surface = IOSurfaceCreate((CFDictionaryRef)options);
+ Q_ASSERT(m_surface);
+
+ Q_ASSERT(size_t(bytesPerLine()) == bytesPerRow);
+ Q_ASSERT(size_t(byteCount()) == totalBytes);
+
+ if (colorSpace) {
+ IOSurfaceSetValue(m_surface, CFSTR("IOSurfaceColorSpace"),
+ QCFType<CFPropertyListRef>(CGColorSpaceCopyPropertyList(colorSpace)));
+ }
+}
+
+QIOSurfaceGraphicsBuffer::~QIOSurfaceGraphicsBuffer()
+{
+}
+
+const uchar *QIOSurfaceGraphicsBuffer::data() const
+{
+ return (const uchar *)IOSurfaceGetBaseAddress(m_surface);
+}
+
+uchar *QIOSurfaceGraphicsBuffer::data()
+{
+ return (uchar *)IOSurfaceGetBaseAddress(m_surface);
+}
+
+int QIOSurfaceGraphicsBuffer::bytesPerLine() const
+{
+ return IOSurfaceGetBytesPerRow(m_surface);
+}
+
+IOSurfaceRef QIOSurfaceGraphicsBuffer::surface()
+{
+ return m_surface;
+}
+
+bool QIOSurfaceGraphicsBuffer::isInUse() const
+{
+ return IOSurfaceIsInUse(m_surface);
+}
+
+IOSurfaceLockOptions lockOptionsForAccess(QPlatformGraphicsBuffer::AccessTypes access)
+{
+ IOSurfaceLockOptions lockOptions = 0;
+ if (!(access & QPlatformGraphicsBuffer::SWWriteAccess))
+ lockOptions |= kIOSurfaceLockReadOnly;
+ return lockOptions;
+}
+
+bool QIOSurfaceGraphicsBuffer::doLock(AccessTypes access, const QRect &rect)
+{
+ Q_UNUSED(rect);
+ Q_ASSERT(!isLocked());
+
+ qCDebug(lcQpaIOSurface) << "Locking" << this << "for" << access;
+
+ // FIXME: Teach QPlatformBackingStore::composeAndFlush about non-2D texture
+ // targets, so that we can use CGLTexImageIOSurface2D to support TextureAccess.
+ if (access & (TextureAccess | HWCompositor))
+ return false;
+
+ auto lockOptions = lockOptionsForAccess(access);
+
+ // Try without read-back first
+ lockOptions |= kIOSurfaceLockAvoidSync;
+ kern_return_t ret = IOSurfaceLock(m_surface, lockOptions, nullptr);
+ if (ret == kIOSurfaceSuccess)
+ return true;
+
+ if (ret == kIOReturnCannotLock) {
+ qCWarning(lcQpaIOSurface) << "Locking of" << this << "requires read-back";
+ lockOptions ^= kIOSurfaceLockAvoidSync;
+ ret = IOSurfaceLock(m_surface, lockOptions, nullptr);
+ }
+
+ if (ret != kIOSurfaceSuccess) {
+ qCWarning(lcQpaIOSurface) << "Failed to lock" << this << ret;
+ return false;
+ }
+
+ return true;
+}
+
+void QIOSurfaceGraphicsBuffer::doUnlock()
+{
+ qCDebug(lcQpaIOSurface) << "Unlocking" << this << "from" << isLocked();
+
+ auto lockOptions = lockOptionsForAccess(isLocked());
+ bool success = IOSurfaceUnlock(m_surface, lockOptions, nullptr) == kIOSurfaceSuccess;
+ Q_ASSERT_X(success, "QIOSurfaceGraphicsBuffer", "Unlocking surface should succeed");
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+QDebug operator<<(QDebug debug, const QIOSurfaceGraphicsBuffer *graphicsBuffer)
+{
+ QDebugStateSaver saver(debug);
+ debug.nospace();
+ debug << "QIOSurfaceGraphicsBuffer(" << (const void *)graphicsBuffer;
+ if (graphicsBuffer) {
+ debug << ", surface=" << graphicsBuffer->m_surface;
+ debug << ", size=" << graphicsBuffer->size();
+ debug << ", isLocked=" << bool(graphicsBuffer->isLocked());
+ debug << ", isInUse=" << graphicsBuffer->isInUse();
+ }
+ debug << ')';
+ return debug;
+}
+#endif // !QT_NO_DEBUG_STREAM
+
+QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qnsview_drawing.mm b/src/plugins/platforms/cocoa/qnsview_drawing.mm
index 6db5ed8bad..f7e14b7883 100644
--- a/src/plugins/platforms/cocoa/qnsview_drawing.mm
+++ b/src/plugins/platforms/cocoa/qnsview_drawing.mm
@@ -163,6 +163,13 @@
return NSViewLayerContentsRedrawDuringViewResize;
}
+- (NSViewLayerContentsPlacement)layerContentsPlacement
+{
+ // Always place the layer at top left without any automatic scaling,
+ // so that we can re-use larger layers when resizing a window down.
+ return NSViewLayerContentsPlacementTopLeft;
+}
+
- (void)updateMetalLayerDrawableSize:(CAMetalLayer *)layer
{
CGSize drawableSize = layer.bounds.size;
diff --git a/src/plugins/platforms/directfb/qdirectfb_egl.cpp b/src/plugins/platforms/directfb/qdirectfb_egl.cpp
index dad553c890..d3c95f0b65 100644
--- a/src/plugins/platforms/directfb/qdirectfb_egl.cpp
+++ b/src/plugins/platforms/directfb/qdirectfb_egl.cpp
@@ -44,6 +44,7 @@
#include <QtGui/QOpenGLContext>
#include <qpa/qplatformopenglcontext.h>
+#include <qpa/qwindowsysteminterface.h>
#include <QtGui/QScreen>
#include <QtEglSupport/private/qeglplatformcontext_p.h>
@@ -248,7 +249,7 @@ QPlatformOpenGLContext *QDirectFbIntegrationEGL::createPlatformOpenGLContext(QOp
void QDirectFbIntegrationEGL::initializeScreen()
{
m_primaryScreen.reset(new QDirectFbScreenEGL(0));
- screenAdded(m_primaryScreen.data());
+ QWindowSystemInterface::handleScreenAdded(m_primaryScreen.data());
}
bool QDirectFbIntegrationEGL::hasCapability(QPlatformIntegration::Capability cap) const
diff --git a/src/plugins/platforms/directfb/qdirectfbintegration.cpp b/src/plugins/platforms/directfb/qdirectfbintegration.cpp
index cdf340da7a..73e308da53 100644
--- a/src/plugins/platforms/directfb/qdirectfbintegration.cpp
+++ b/src/plugins/platforms/directfb/qdirectfbintegration.cpp
@@ -56,6 +56,7 @@
#include <QtCore/QThread>
#include <QtCore/QAbstractEventDispatcher>
#include <qpa/qplatforminputcontextfactory_p.h>
+#include <qpa/qwindowsysteminterface.h>
QT_BEGIN_NAMESPACE
@@ -113,7 +114,7 @@ void QDirectFbIntegration::initializeDirectFB()
void QDirectFbIntegration::initializeScreen()
{
m_primaryScreen.reset(new QDirectFbScreen(0));
- screenAdded(m_primaryScreen.data());
+ QWindowSystemInterface::handleScreenAdded(m_primaryScreen.data());
}
void QDirectFbIntegration::initializeInput()
diff --git a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp
index 0a3a37863a..81bad45cd2 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsdeviceintegration.cpp
@@ -200,10 +200,8 @@ void QEglFSDeviceIntegration::screenInit()
void QEglFSDeviceIntegration::screenDestroy()
{
QGuiApplication *app = qGuiApp;
- QEglFSIntegration *platformIntegration = static_cast<QEglFSIntegration *>(
- QGuiApplicationPrivate::platformIntegration());
while (!app->screens().isEmpty())
- platformIntegration->removeScreen(app->screens().constLast()->handle());
+ QWindowSystemInterface::handleScreenRemoved(app->screens().constLast()->handle());
}
QSizeF QEglFSDeviceIntegration::physicalScreenSize() const
diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
index 8ccb0ef2cd..48469b0f8c 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
@@ -120,16 +120,6 @@ QEglFSIntegration::QEglFSIntegration()
initResources();
}
-void QEglFSIntegration::addScreen(QPlatformScreen *screen, bool isPrimary)
-{
- screenAdded(screen, isPrimary);
-}
-
-void QEglFSIntegration::removeScreen(QPlatformScreen *screen)
-{
- destroyScreen(screen);
-}
-
void QEglFSIntegration::initialize()
{
qt_egl_device_integration()->platformInit();
@@ -147,7 +137,7 @@ void QEglFSIntegration::initialize()
m_vtHandler.reset(new QFbVtHandler);
if (qt_egl_device_integration()->usesDefaultScreen())
- addScreen(new QEglFSScreen(display()));
+ QWindowSystemInterface::handleScreenAdded(new QEglFSScreen(display()));
else
qt_egl_device_integration()->screenInit();
diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h
index 4b4585d33c..898b322834 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h
+++ b/src/plugins/platforms/eglfs/api/qeglfsintegration_p.h
@@ -103,9 +103,6 @@ public:
QFbVtHandler *vtHandler() { return m_vtHandler.data(); }
- void addScreen(QPlatformScreen *screen, bool isPrimary = false);
- void removeScreen(QPlatformScreen *screen);
-
private:
EGLNativeDisplayType nativeDisplay() const;
void createInputHandlers();
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp
index 5e2708e958..cb7844aff0 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_emu/qeglfsemulatorintegration.cpp
@@ -45,6 +45,8 @@
#include <QtEglSupport/private/qeglconvenience_p.h>
#include <QtEglSupport/private/qeglplatformcontext_p.h>
+#include <qpa/qwindowsysteminterface.h>
+
#include <QtCore/QJsonDocument>
#include <QtCore/QJsonArray>
#include <QtCore/QJsonParseError>
@@ -80,8 +82,6 @@ bool QEglFSEmulatorIntegration::usesDefaultScreen()
void QEglFSEmulatorIntegration::screenInit()
{
- QEglFSIntegration *integration = static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration());
-
// Use qgsGetDisplays() call to retrieve the available screens from the Emulator
if (getDisplays) {
QByteArray displaysInfo = getDisplays();
@@ -93,7 +93,7 @@ void QEglFSEmulatorIntegration::screenInit()
QJsonArray screenArray = displaysDocument.array();
for (auto screenValue : screenArray) {
if (screenValue.isObject())
- integration->addScreen(new QEglFSEmulatorScreen(screenValue.toObject()));
+ QWindowSystemInterface::handleScreenAdded(new QEglFSEmulatorScreen(screenValue.toObject()));
}
}
} else {
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
index ab39af6b80..ecdfb352ab 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
@@ -260,7 +260,7 @@ QKmsDevice *QEglFSKmsEglDeviceIntegration::createDevice()
if (Q_UNLIKELY(!deviceName))
qFatal("Failed to query device name from EGLDevice");
- return new QEglFSKmsEglDevice(this, screenConfig(), deviceName);
+ return new QEglFSKmsEglDevice(this, screenConfig(), QLatin1String(deviceName));
}
bool QEglFSKmsEglDeviceIntegration::query_egl_device()
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp
index b073577797..4f0b0d7725 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_support/qeglfskmsdevice.cpp
@@ -58,7 +58,7 @@ void QEglFSKmsDevice::registerScreen(QPlatformScreen *screen,
QEglFSKmsScreen *s = static_cast<QEglFSKmsScreen *>(screen);
s->setVirtualPosition(virtualPos);
s->setVirtualSiblings(virtualSiblings);
- static_cast<QEglFSIntegration *>(QGuiApplicationPrivate::platformIntegration())->addScreen(s, isPrimary);
+ QWindowSystemInterface::handleScreenAdded(s, isPrimary);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/haiku/qhaikuintegration.cpp b/src/plugins/platforms/haiku/qhaikuintegration.cpp
index 8bd2171794..44df6ae8f5 100644
--- a/src/plugins/platforms/haiku/qhaikuintegration.cpp
+++ b/src/plugins/platforms/haiku/qhaikuintegration.cpp
@@ -49,6 +49,7 @@
#include <QCoreApplication>
#include <QFileInfo>
#include <qpa/qplatformwindow.h>
+#include <qpa/qwindowsysteminterface.h>
#include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h>
#include <Application.h>
@@ -81,12 +82,12 @@ QHaikuIntegration::QHaikuIntegration(const QStringList &parameters)
m_services = new QHaikuServices;
// notify system about available screen
- screenAdded(m_screen);
+ QWindowSystemInterface::handleScreenAdded(m_screen);
}
QHaikuIntegration::~QHaikuIntegration()
{
- destroyScreen(m_screen);
+ QWindowSystemInterface::handleScreenRemoved(m_screen);
m_screen = nullptr;
delete m_services;
diff --git a/src/plugins/platforms/integrity/qintegrityfbintegration.cpp b/src/plugins/platforms/integrity/qintegrityfbintegration.cpp
index ae802bb1fa..3ad31dc562 100644
--- a/src/plugins/platforms/integrity/qintegrityfbintegration.cpp
+++ b/src/plugins/platforms/integrity/qintegrityfbintegration.cpp
@@ -51,7 +51,7 @@
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatforminputcontextfactory_p.h>
-
+#include <qpa/qwindowsysteminterface.h>
QT_BEGIN_NAMESPACE
@@ -64,13 +64,13 @@ QIntegrityFbIntegration::QIntegrityFbIntegration(const QStringList &paramList)
QIntegrityFbIntegration::~QIntegrityFbIntegration()
{
- destroyScreen(m_primaryScreen);
+ QWindowSystemInterface::handleScreenRemoved(m_primaryScreen);
}
void QIntegrityFbIntegration::initialize()
{
if (m_primaryScreen->initialize())
- screenAdded(m_primaryScreen);
+ QWindowSystemInterface::handleScreenAdded(m_primaryScreen);
else
qWarning("integrityfb: Failed to initialize screen");
diff --git a/src/plugins/platforms/ios/qiosintegration.h b/src/plugins/platforms/ios/qiosintegration.h
index 818250fcee..eeb44b54d3 100644
--- a/src/plugins/platforms/ios/qiosintegration.h
+++ b/src/plugins/platforms/ios/qiosintegration.h
@@ -92,10 +92,6 @@ public:
QPlatformAccessibility *accessibility() const override;
#endif
- // Called from Objective-C class QIOSScreenTracker, which can't be friended
- void addScreen(QPlatformScreen *screen) { screenAdded(screen); }
- void destroyScreen(QPlatformScreen *screen) { QPlatformIntegration::destroyScreen(screen); }
-
void beep() const override;
static QIOSIntegration *instance();
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index bec8354fcc..9eca0eaad3 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -107,7 +107,7 @@ void QIOSIntegration::initialize()
}
for (UIScreen *screen in screens)
- addScreen(new QIOSScreen(screen));
+ QWindowSystemInterface::handleScreenAdded(new QIOSScreen(screen));
// Depends on a primary screen being present
m_inputContext = new QIOSInputContext;
@@ -143,7 +143,7 @@ QIOSIntegration::~QIOSIntegration()
m_inputContext = 0;
foreach (QScreen *screen, QGuiApplication::screens())
- destroyScreen(screen->handle());
+ QWindowSystemInterface::handleScreenRemoved(screen->handle());
delete m_platformServices;
m_platformServices = 0;
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index 4f753be21a..9aba658479 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -50,6 +50,7 @@
#include <QtGui/private/qwindow_p.h>
#include <private/qcoregraphics_p.h>
+#include <qpa/qwindowsysteminterface.h>
#include <sys/sysctl.h>
@@ -105,10 +106,10 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
+ (void)screenConnected:(NSNotification*)notification
{
- QIOSIntegration *integration = QIOSIntegration::instance();
- Q_ASSERT_X(integration, Q_FUNC_INFO, "Screen connected before QIOSIntegration creation");
+ Q_ASSERT_X(QIOSIntegration::instance(), Q_FUNC_INFO,
+ "Screen connected before QIOSIntegration creation");
- integration->addScreen(new QIOSScreen([notification object]));
+ QWindowSystemInterface::handleScreenAdded(new QIOSScreen([notification object]));
}
+ (void)screenDisconnected:(NSNotification*)notification
@@ -116,8 +117,7 @@ static QIOSScreen* qtPlatformScreenFor(UIScreen *uiScreen)
QIOSScreen *screen = qtPlatformScreenFor([notification object]);
Q_ASSERT_X(screen, Q_FUNC_INFO, "Screen disconnected that we didn't know about");
- QIOSIntegration *integration = QIOSIntegration::instance();
- integration->destroyScreen(screen);
+ QWindowSystemInterface::handleScreenRemoved(screen);
}
+ (void)screenModeChanged:(NSNotification*)notification
diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
index 9e38900bcd..68843aa4c5 100644
--- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
+++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp
@@ -54,6 +54,7 @@
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatforminputcontextfactory_p.h>
+#include <qpa/qwindowsysteminterface.h>
#if QT_CONFIG(libinput)
#include <QtInputSupport/private/qlibinputhandler_p.h>
@@ -89,13 +90,13 @@ QLinuxFbIntegration::QLinuxFbIntegration(const QStringList &paramList)
QLinuxFbIntegration::~QLinuxFbIntegration()
{
- destroyScreen(m_primaryScreen);
+ QWindowSystemInterface::handleScreenRemoved(m_primaryScreen);
}
void QLinuxFbIntegration::initialize()
{
if (m_primaryScreen->initialize())
- screenAdded(m_primaryScreen);
+ QWindowSystemInterface::handleScreenAdded(m_primaryScreen);
else
qWarning("linuxfb: Failed to initialize screen");
diff --git a/src/plugins/platforms/minimal/qminimalintegration.cpp b/src/plugins/platforms/minimal/qminimalintegration.cpp
index 0c04608fca..f457f69f11 100644
--- a/src/plugins/platforms/minimal/qminimalintegration.cpp
+++ b/src/plugins/platforms/minimal/qminimalintegration.cpp
@@ -43,6 +43,7 @@
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformwindow.h>
+#include <qpa/qwindowsysteminterface.h>
#include <QtFontDatabaseSupport/private/qfreetypefontdatabase_p.h>
#if defined(Q_OS_WINRT)
@@ -108,7 +109,7 @@ QMinimalIntegration::QMinimalIntegration(const QStringList &parameters)
mPrimaryScreen->mDepth = 32;
mPrimaryScreen->mFormat = QImage::Format_ARGB32_Premultiplied;
- screenAdded(mPrimaryScreen);
+ QWindowSystemInterface::handleScreenAdded(mPrimaryScreen);
}
QMinimalIntegration::~QMinimalIntegration()
diff --git a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
index da58441d67..a0d35a80cd 100644
--- a/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
+++ b/src/plugins/platforms/minimalegl/qminimaleglintegration.cpp
@@ -58,6 +58,7 @@
#include <QtGui/QSurfaceFormat>
#include <QtGui/QOpenGLContext>
#include <QtGui/QScreen>
+#include <qpa/qwindowsysteminterface.h>
// this is where EGL headers are pulled in, make sure it is last
#include "qminimaleglscreen.h"
@@ -90,7 +91,7 @@ protected:
QMinimalEglIntegration::QMinimalEglIntegration()
: mFontDb(new QGenericUnixFontDatabase()), mScreen(new QMinimalEglScreen(EGL_DEFAULT_DISPLAY))
{
- screenAdded(mScreen);
+ QWindowSystemInterface::handleScreenAdded(mScreen);
#ifdef QEGL_EXTRA_DEBUG
qWarning("QMinimalEglIntegration\n");
@@ -99,7 +100,7 @@ QMinimalEglIntegration::QMinimalEglIntegration()
QMinimalEglIntegration::~QMinimalEglIntegration()
{
- destroyScreen(mScreen);
+ QWindowSystemInterface::handleScreenRemoved(mScreen);
delete mFontDb;
}
diff --git a/src/plugins/platforms/mirclient/qmirclientintegration.cpp b/src/plugins/platforms/mirclient/qmirclientintegration.cpp
index eef96ee3de..d2b1dbee0d 100644
--- a/src/plugins/platforms/mirclient/qmirclientintegration.cpp
+++ b/src/plugins/platforms/mirclient/qmirclientintegration.cpp
@@ -58,6 +58,7 @@
#include <qpa/qplatformnativeinterface.h>
#include <qpa/qplatforminputcontextfactory_p.h>
#include <qpa/qplatforminputcontext.h>
+#include <qpa/qwindowsysteminterface.h>
#include <QtEglSupport/private/qeglconvenience_p.h>
#include <QtEglSupport/private/qeglpbuffer_p.h>
#include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h>
@@ -149,12 +150,12 @@ void QMirClientClientIntegration::initialize()
// Init the ScreenObserver
mScreenObserver.reset(new QMirClientScreenObserver(mMirConnection));
connect(mScreenObserver.data(), &QMirClientScreenObserver::screenAdded,
- [this](QMirClientScreen *screen) { this->screenAdded(screen); });
+ [this](QMirClientScreen *screen) { QWindowSystemInterface::handleScreenAdded(screen); });
connect(mScreenObserver.data(), &QMirClientScreenObserver::screenRemoved,
this, &QMirClientClientIntegration::destroyScreen);
Q_FOREACH (auto screen, mScreenObserver->screens()) {
- screenAdded(screen);
+ QWindowSystemInterface::handleScreenAdded(screen);
}
// Initialize input.
@@ -392,7 +393,7 @@ void QMirClientClientIntegration::destroyScreen(QMirClientScreen *screen)
#if QT_VERSION < QT_VERSION_CHECK(5, 5, 0)
delete screen;
#else
- QPlatformIntegration::destroyScreen(screen);
+ QWindowSystemInterface::handleScreenRemoved(screen);
#endif
}
diff --git a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
index f2933b7179..869e9228cd 100644
--- a/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
+++ b/src/plugins/platforms/offscreen/qoffscreenintegration.cpp
@@ -63,6 +63,7 @@
#include <qpa/qplatforminputcontextfactory_p.h>
#include <qpa/qplatforminputcontext.h>
#include <qpa/qplatformtheme.h>
+#include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatformservices.h>
@@ -121,7 +122,7 @@ QOffscreenIntegration::QOffscreenIntegration()
#endif
m_services.reset(new QPlatformServices);
- screenAdded(new QOffscreenScreen);
+ QWindowSystemInterface::handleScreenAdded(new QOffscreenScreen);
}
QOffscreenIntegration::~QOffscreenIntegration()
diff --git a/src/plugins/platforms/openwfd/qopenwfdintegration.cpp b/src/plugins/platforms/openwfd/qopenwfdintegration.cpp
index 4850ca2e45..c5dc40a206 100644
--- a/src/plugins/platforms/openwfd/qopenwfdintegration.cpp
+++ b/src/plugins/platforms/openwfd/qopenwfdintegration.cpp
@@ -50,6 +50,7 @@
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/QOpenGLContext>
#include <QtGui/QScreen>
+#include <qpa/qwindowsysteminterface.h>
#include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h>
#include <QtFontDatabaseSupport/private/qgenericunixfontdatabase_p.h>
@@ -135,13 +136,3 @@ QPlatformPrinterSupport * QOpenWFDIntegration::printerSupport() const
{
return mPrinterSupport;
}
-
-void QOpenWFDIntegration::addScreen(QOpenWFDScreen *screen)
-{
- screenAdded(screen);
-}
-
-void QOpenWFDIntegration::destroyScreen(QOpenWFDScreen *screen)
-{
- QPlatformIntegration::destroyScreen(screen);
-}
diff --git a/src/plugins/platforms/openwfd/qopenwfdintegration.h b/src/plugins/platforms/openwfd/qopenwfdintegration.h
index 1ce1001bed..444aaccaaf 100644
--- a/src/plugins/platforms/openwfd/qopenwfdintegration.h
+++ b/src/plugins/platforms/openwfd/qopenwfdintegration.h
@@ -68,8 +68,6 @@ public:
QPlatformPrinterSupport *printerSupport() const;
- void addScreen(QOpenWFDScreen *screen);
- void destroyScreen(QOpenWFDScreen *screen);
private:
QList<QPlatformScreen *> mScreens;
QList<QOpenWFDDevice *>mDevices;
diff --git a/src/plugins/platforms/openwfd/qopenwfdport.cpp b/src/plugins/platforms/openwfd/qopenwfdport.cpp
index 33254fe83c..34b4439958 100644
--- a/src/plugins/platforms/openwfd/qopenwfdport.cpp
+++ b/src/plugins/platforms/openwfd/qopenwfdport.cpp
@@ -133,7 +133,7 @@ void QOpenWFDPort::attach()
wfdBindPipelineToPort(mDevice->handle(),mPort,mPipeline);
mScreen = new QOpenWFDScreen(this);
- mDevice->integration()->addScreen(mScreen);
+ QWindowSystemInterface::handleScreenAdded(mScreen);
mAttached = true;
}
@@ -145,7 +145,7 @@ void QOpenWFDPort::detach()
mAttached = false;
mOn = false;
- mDevice->integration()->destroyScreen(mScreen);
+ QWindowSystemInterface::handleScreenRemoved(mScreen);
wfdDestroyPipeline(mDevice->handle(),mPipeline);
mPipelineId = WFD_INVALID_PIPELINE_ID;
diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp
index a996e765c4..a45dcabeb7 100644
--- a/src/plugins/platforms/qnx/qqnxintegration.cpp
+++ b/src/plugins/platforms/qnx/qqnxintegration.cpp
@@ -649,7 +649,7 @@ void QQnxIntegration::createDisplay(screen_display_t display, bool isPrimary)
{
QQnxScreen *screen = new QQnxScreen(m_screenContext, display, isPrimary);
m_screens.append(screen);
- screenAdded(screen);
+ QWindowSystemInterface::handleScreenAdded(screen);
screen->adjustOrientation();
QObject::connect(m_screenEventHandler, SIGNAL(newWindowCreated(void*)),
@@ -669,14 +669,14 @@ void QQnxIntegration::removeDisplay(QQnxScreen *screen)
Q_CHECK_PTR(screen);
Q_ASSERT(m_screens.contains(screen));
m_screens.removeAll(screen);
- destroyScreen(screen);
+ QWindowSystemInterface::handleScreenRemoved(screen);
}
void QQnxIntegration::destroyDisplays()
{
qIntegrationDebug();
Q_FOREACH (QQnxScreen *screen, m_screens) {
- QPlatformIntegration::destroyScreen(screen);
+ QWindowSystemInterface::handleScreenRemoved(screen);
}
m_screens.clear();
}
diff --git a/src/plugins/platforms/vnc/qvncintegration.cpp b/src/plugins/platforms/vnc/qvncintegration.cpp
index 1e2cf6292c..c7a796464a 100644
--- a/src/plugins/platforms/vnc/qvncintegration.cpp
+++ b/src/plugins/platforms/vnc/qvncintegration.cpp
@@ -52,6 +52,7 @@
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatforminputcontextfactory_p.h>
#include <private/qinputdevicemanager_p_p.h>
+#include <qpa/qwindowsysteminterface.h>
#include <QtCore/QRegularExpression>
@@ -77,13 +78,13 @@ QVncIntegration::QVncIntegration(const QStringList &paramList)
QVncIntegration::~QVncIntegration()
{
delete m_server;
- destroyScreen(m_primaryScreen);
+ QWindowSystemInterface::handleScreenRemoved(m_primaryScreen);
}
void QVncIntegration::initialize()
{
if (m_primaryScreen->initialize())
- screenAdded(m_primaryScreen);
+ QWindowSystemInterface::handleScreenAdded(m_primaryScreen);
else
qWarning("vnc: Failed to initialize screen");
diff --git a/src/plugins/platforms/wasm/qwasmintegration.cpp b/src/plugins/platforms/wasm/qwasmintegration.cpp
index 1964cefdad..499a82adbd 100644
--- a/src/plugins/platforms/wasm/qwasmintegration.cpp
+++ b/src/plugins/platforms/wasm/qwasmintegration.cpp
@@ -98,7 +98,10 @@ QWasmIntegration::QWasmIntegration()
QWasmIntegration::~QWasmIntegration()
{
delete m_fontDb;
- qDeleteAll(m_screens);
+
+ while (!m_screens.isEmpty())
+ QWindowSystemInterface::handleScreenRemoved(m_screens.takeLast());
+
s_instance = nullptr;
}
@@ -191,7 +194,7 @@ void QWasmIntegration::addScreen(const QString &canvasId)
QWasmScreen *screen = new QWasmScreen(canvasId);
m_clipboard->installEventHandlers(canvasId);
m_screens.append(screen);
- screenAdded(screen);
+ QWindowSystemInterface::handleScreenAdded(screen);
}
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h
index da86852766..e28b2c2fb3 100644
--- a/src/plugins/platforms/windows/qwindowsintegration.h
+++ b/src/plugins/platforms/windows/qwindowsintegration.h
@@ -107,9 +107,6 @@ public:
static QWindowsIntegration *instance() { return m_instance; }
- inline void emitScreenAdded(QPlatformScreen *s, bool isPrimary = false) { screenAdded(s, isPrimary); }
- inline void emitDestroyScreen(QPlatformScreen *s) { destroyScreen(s); }
-
unsigned options() const;
void beep() const override;
diff --git a/src/plugins/platforms/windows/qwindowsscreen.cpp b/src/plugins/platforms/windows/qwindowsscreen.cpp
index a161dc46e9..0520f88935 100644
--- a/src/plugins/platforms/windows/qwindowsscreen.cpp
+++ b/src/plugins/platforms/windows/qwindowsscreen.cpp
@@ -121,7 +121,7 @@ BOOL QT_WIN_CALLBACK monitorEnumCallback(HMONITOR hMonitor, HDC, LPRECT, LPARAM
QWindowsScreenData data;
if (monitorData(hMonitor, &data)) {
WindowsScreenDataList *result = reinterpret_cast<WindowsScreenDataList *>(p);
- // QPlatformIntegration::screenAdded() documentation specifies that first
+ // QWindowSystemInterface::handleScreenAdded() documentation specifies that first
// added screen will be the primary screen, so order accordingly.
// Note that the side effect of this policy is that there is no way to change primary
// screen reported by Qt, unless we want to delete all existing screens and add them
@@ -521,7 +521,7 @@ void QWindowsScreenManager::removeScreen(int index)
if (movedWindowCount)
QWindowSystemInterface::flushWindowSystemEvents();
}
- QWindowsIntegration::instance()->emitDestroyScreen(m_screens.takeAt(index));
+ QWindowSystemInterface::handleScreenRemoved(m_screens.takeAt(index));
}
/*!
@@ -541,7 +541,7 @@ bool QWindowsScreenManager::handleScreenChanges()
} else {
QWindowsScreen *newScreen = new QWindowsScreen(newData);
m_screens.push_back(newScreen);
- QWindowsIntegration::instance()->emitScreenAdded(newScreen,
+ QWindowSystemInterface::handleScreenAdded(newScreen,
newData.flags & QWindowsScreenData::PrimaryScreen);
qCDebug(lcQpaWindows) << "New Monitor: " << newData;
} // exists
@@ -561,7 +561,7 @@ void QWindowsScreenManager::clearScreens()
{
// Delete screens in reverse order to avoid crash in case of multiple screens
while (!m_screens.isEmpty())
- QWindowsIntegration::instance()->emitDestroyScreen(m_screens.takeLast());
+ QWindowSystemInterface::handleScreenRemoved(m_screens.takeLast());
}
const QWindowsScreen *QWindowsScreenManager::screenAtDp(const QPoint &p) const
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 8bf090bf03..07fd2916c2 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -1759,15 +1759,12 @@ void QWindowsWindow::checkForScreenChanged()
QPlatformScreen *currentScreen = screen();
const auto &screenManager = QWindowsContext::instance()->screenManager();
- // QTBUG-62971: When dragging a window by its border, detect by mouse position
- // to prevent it from oscillating between screens when it resizes
- const QWindowsScreen *newScreen = testFlag(ResizeMoveActive)
- ? screenManager.screenAtDp(QWindowsCursor::mousePosition())
- : screenManager.screenForHwnd(m_data.hwnd);
+ const QWindowsScreen *newScreen = screenManager.screenForHwnd(m_data.hwnd);
if (newScreen != nullptr && newScreen != currentScreen) {
qCDebug(lcQpaWindows).noquote().nospace() << __FUNCTION__
<< ' ' << window() << " \"" << currentScreen->name()
<< "\"->\"" << newScreen->name() << '"';
+ setFlag(SynchronousGeometryChangeEvent);
QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen());
}
}
@@ -1786,11 +1783,14 @@ void QWindowsWindow::handleGeometryChange()
fireExpose(QRect(QPoint(0, 0), m_data.geometry.size()), true);
}
+ const bool wasSync = testFlag(SynchronousGeometryChangeEvent);
checkForScreenChanged();
if (testFlag(SynchronousGeometryChangeEvent))
QWindowSystemInterface::flushWindowSystemEvents(QEventLoop::ExcludeUserInputEvents);
+ if (!wasSync)
+ clearFlag(SynchronousGeometryChangeEvent);
qCDebug(lcQpaEvents) << __FUNCTION__ << this << window() << m_data.geometry;
}
diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp
index 78cbc3aec3..27d3746933 100644
--- a/src/plugins/platforms/winrt/qwinrtintegration.cpp
+++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp
@@ -133,7 +133,7 @@ QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate)
});
d->inputContext.reset(new QWinRTInputContext(d->mainScreen));
- screenAdded(d->mainScreen);
+ QWindowSystemInterface::handleScreenAdded(d->mainScreen);
d->platformServices = new QWinRTServices;
d->clipboard = new QWinRTClipboard;
#if QT_CONFIG(accessibility)
@@ -154,7 +154,7 @@ QWinRTIntegration::~QWinRTIntegration()
Q_ASSERT_SUCCEEDED(hr);
}
- destroyScreen(d->mainScreen);
+ QWindowSystemInterface::handleScreenRemoved(d->mainScreen);
Windows::Foundation::Uninitialize();
}
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
index d42a33c22b..476de6d1e5 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
@@ -652,6 +652,12 @@ static const char *qglx_threadedgl_blacklist_renderer[] = {
0
};
+static const char *qglx_threadedgl_blacklist_vendor[] = {
+ "llvmpipe", // QTCREATORBUG-10666
+ "nouveau", // https://bugs.freedesktop.org/show_bug.cgi?id=91632
+ nullptr
+};
+
void QGLXContext::queryDummyContext()
{
if (m_queriedDummyContext)
@@ -710,6 +716,18 @@ void QGLXContext::queryDummyContext()
}
}
}
+ if (const char *vendor = (const char *) glGetString(GL_VENDOR)) {
+ for (int i = 0; qglx_threadedgl_blacklist_vendor[i]; ++i) {
+ if (strstr(vendor, qglx_threadedgl_blacklist_vendor[i]) != 0) {
+ qCDebug(lcQpaGl).nospace() << "Multithreaded OpenGL disabled: "
+ "blacklisted vendor \""
+ << qglx_threadedgl_blacklist_vendor[i]
+ << "\"";
+ m_supportsThreading = false;
+ break;
+ }
+ }
+ }
if (glxvendor && m_supportsThreading) {
// Blacklist Mesa drivers due to QTCREATORBUG-10875 (crash in creator),
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 1ff06dd39e..06d1000993 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -152,10 +152,9 @@ QXcbConnection::~QXcbConnection()
if (m_eventQueue)
delete m_eventQueue;
- QXcbIntegration *integration = QXcbIntegration::instance();
// Delete screens in reverse order to avoid crash in case of multiple screens
while (!m_screens.isEmpty())
- integration->destroyScreen(m_screens.takeLast());
+ QWindowSystemInterface::handleScreenRemoved(m_screens.takeLast());
while (!m_virtualDesktops.isEmpty())
delete m_virtualDesktops.takeLast();
diff --git a/src/plugins/platforms/xcb/qxcbconnection_basic.h b/src/plugins/platforms/xcb/qxcbconnection_basic.h
index 3691763398..b979129cba 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_basic.h
+++ b/src/plugins/platforms/xcb/qxcbconnection_basic.h
@@ -40,6 +40,7 @@
#define QXCBBASICCONNECTION_H
#include "qxcbatom.h"
+#include "qxcbexport.h"
#include <QtCore/QPair>
#include <QtCore/QObject>
@@ -55,7 +56,7 @@ QT_BEGIN_NAMESPACE
Q_DECLARE_LOGGING_CATEGORY(lcQpaXcb)
-class QXcbBasicConnection : public QObject
+class Q_XCB_EXPORT QXcbBasicConnection : public QObject
{
Q_OBJECT
public:
diff --git a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
index 4bafe83156..9ba71ada37 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_screens.cpp
@@ -44,6 +44,8 @@
#include <QtCore/QString>
#include <QtCore/QList>
+#include <qpa/qwindowsysteminterface.h>
+
#include <xcb/xinerama.h>
void QXcbConnection::xrandrSelectEvents()
@@ -211,7 +213,7 @@ void QXcbConnection::updateScreen(QXcbScreen *screen, const xcb_randr_output_cha
m_screens.swapItemsAt(0, idx);
}
screen->virtualDesktop()->setPrimaryScreen(screen);
- QXcbIntegration::instance()->setPrimaryScreen(screen);
+ QWindowSystemInterface::handlePrimaryScreenChanged(screen);
}
}
}
@@ -234,7 +236,7 @@ QXcbScreen *QXcbConnection::createScreen(QXcbVirtualDesktop *virtualDesktop,
m_screens.append(screen);
}
virtualDesktop->addScreen(screen);
- QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
+ QWindowSystemInterface::handleScreenAdded(screen, screen->isPrimary());
return screen;
}
@@ -261,10 +263,10 @@ void QXcbConnection::destroyScreen(QXcbScreen *screen)
const int idx = m_screens.indexOf(newPrimary);
if (idx > 0)
m_screens.swapItemsAt(0, idx);
- QXcbIntegration::instance()->setPrimaryScreen(newPrimary);
+ QWindowSystemInterface::handlePrimaryScreenChanged(newPrimary);
}
- QXcbIntegration::instance()->destroyScreen(screen);
+ QWindowSystemInterface::handleScreenRemoved(screen);
}
}
@@ -406,7 +408,7 @@ void QXcbConnection::initializeScreens()
// Push the screens to QGuiApplication
for (QXcbScreen *screen : qAsConst(m_screens)) {
qCDebug(lcQpaScreen) << "adding" << screen << "(Primary:" << screen->isPrimary() << ")";
- QXcbIntegration::instance()->screenAdded(screen, screen->isPrimary());
+ QWindowSystemInterface::handleScreenAdded(screen, screen->isPrimary());
}
qCDebug(lcQpaScreen) << "primary output is" << qAsConst(m_screens).first()->name();
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index f13e232291..571726c354 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -137,8 +137,6 @@ private:
QScopedPointer<QPlatformServices> m_services;
- friend class QXcbConnection; // access QPlatformIntegration::screenAdded()
-
mutable QByteArray m_wmClass;
const char *m_instanceName;
bool m_canGrab;
diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
index 4d526a6bda..899081e752 100644
--- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
+++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp
@@ -412,12 +412,15 @@ void *QXcbNativeInterface::atspiBus()
auto reply = Q_XCB_REPLY(xcb_get_property, defaultConnection->xcb_connection(),
false, defaultConnection->rootWindow(),
atspiBusAtom, XCB_ATOM_STRING, 0, 128);
- Q_ASSERT(!reply->bytes_after);
+ if (!reply)
+ return nullptr;
+
char *data = (char *)xcb_get_property_value(reply.get());
int length = xcb_get_property_value_length(reply.get());
return new QByteArray(data, length);
}
- return 0;
+
+ return nullptr;
}
void QXcbNativeInterface::setAppTime(QScreen* screen, xcb_timestamp_t time)
diff --git a/src/tools/androiddeployqt/main.cpp b/src/tools/androiddeployqt/main.cpp
index fd7f72eebf..3af5237f3d 100644
--- a/src/tools/androiddeployqt/main.cpp
+++ b/src/tools/androiddeployqt/main.cpp
@@ -900,7 +900,7 @@ bool readInputFile(Options *options)
options->extraPlugins = extraPlugins.toString().split(QLatin1Char(','));
}
- {
+ if (!options->auxMode) {
const QJsonValue stdcppPath = jsonObject.value(QStringLiteral("stdcpp-path"));
if (stdcppPath.isUndefined()) {
fprintf(stderr, "No stdcpp-path defined in json file.\n");
diff --git a/src/widgets/kernel/qgesturemanager.cpp b/src/widgets/kernel/qgesturemanager.cpp
index 57d6994c88..cd27c9c5be 100644
--- a/src/widgets/kernel/qgesturemanager.cpp
+++ b/src/widgets/kernel/qgesturemanager.cpp
@@ -143,11 +143,6 @@ Qt::GestureType QGestureManager::registerGestureRecognizer(QGestureRecognizer *r
void QGestureManager::unregisterGestureRecognizer(Qt::GestureType type)
{
QList<QGestureRecognizer *> list = m_recognizers.values(type);
- while (QGestureRecognizer *recognizer = m_recognizers.take(type)) {
- // ensuring an entry exists causes the recognizer to be deleted on destruction of the manager
- auto &gestures = m_obsoleteGestures[recognizer];
- Q_UNUSED(gestures);
- }
foreach (QGesture *g, m_gestureToRecognizer.keys()) {
QGestureRecognizer *recognizer = m_gestureToRecognizer.value(g);
if (list.contains(recognizer)) {
diff --git a/src/widgets/kernel/qgesturerecognizer.cpp b/src/widgets/kernel/qgesturerecognizer.cpp
index 65c46a5e56..75d091ce4e 100644
--- a/src/widgets/kernel/qgesturerecognizer.cpp
+++ b/src/widgets/kernel/qgesturerecognizer.cpp
@@ -41,6 +41,7 @@
#include "private/qgesture_p.h"
#include "private/qgesturemanager_p.h"
+#include "private/qapplication_p.h"
#ifndef QT_NO_GESTURES
@@ -231,6 +232,11 @@ Qt::GestureType QGestureRecognizer::registerRecognizer(QGestureRecognizer *recog
*/
void QGestureRecognizer::unregisterRecognizer(Qt::GestureType type)
{
+ auto qAppPriv = QApplicationPrivate::instance();
+ if (!qAppPriv)
+ return;
+ if (!qAppPriv->gestureManager)
+ return;
QGestureManager::instance()->unregisterGestureRecognizer(type);
}
diff --git a/src/widgets/styles/qstyle.cpp b/src/widgets/styles/qstyle.cpp
index ac4fb7fbd1..97ec1d3f19 100644
--- a/src/widgets/styles/qstyle.cpp
+++ b/src/widgets/styles/qstyle.cpp
@@ -1971,8 +1971,8 @@ void QStyle::drawItemPixmap(QPainter *painter, const QRect &rect, int alignment,
\value SH_Widget_Animate Deprecated. Use \l{SH_Widget_Animation_Duration} instead.
- \value SH_Splitter_OpaqueResize Determines if resizing is opaque
- This enum value has been introduced in Qt 5.2
+ \value SH_Splitter_OpaqueResize Determines if widgets are resized dynamically (opaquely) while
+ interactively moving the splitter. This enum value was introduced in Qt 5.2.
\value SH_TabBar_ChangeCurrentDelay Determines the delay before the current
tab is changed while dragging over the tabbar, in milliseconds. This
diff --git a/src/widgets/widgets/qsplashscreen.cpp b/src/widgets/widgets/qsplashscreen.cpp
index 4af4f90119..bf6bf1c7c9 100644
--- a/src/widgets/widgets/qsplashscreen.cpp
+++ b/src/widgets/widgets/qsplashscreen.cpp
@@ -289,8 +289,7 @@ void QSplashScreen::setPixmap(const QPixmap &pixmap)
// 1) If a QDesktopScreenWidget is found in the parent hierarchy, use that (see docs on
// QSplashScreen(QWidget *, QPixmap).
// 2) If a widget with associated QWindow is found, use that
-// 3) When nothing can be found, do not position the widget, allowing for
-// QPlatformWindow::initialGeometry() to center it over the cursor
+// 3) When nothing can be found, try to center it over the cursor
static inline int screenNumberOf(const QDesktopScreenWidget *dsw)
{
@@ -307,7 +306,15 @@ const QScreen *QSplashScreenPrivate::screenFor(const QWidget *w)
if (QWindow *window = p->windowHandle())
return window->screen();
}
- return nullptr;
+#if QT_CONFIG(cursor)
+ // Note: We could rely on QPlatformWindow::initialGeometry() to center it
+ // over the cursor, but not all platforms (namely Android) use that.
+ if (QGuiApplication::screens().size() > 1) {
+ if (auto screenAtCursor = QGuiApplication::screenAt(QCursor::pos()))
+ return screenAtCursor;
+ }
+#endif // cursor
+ return QGuiApplication::primaryScreen();
}
void QSplashScreenPrivate::setPixmap(const QPixmap &p, const QScreen *screen)
diff --git a/src/widgets/widgets/qsplitter.cpp b/src/widgets/widgets/qsplitter.cpp
index 98bb23caad..de838a8f93 100644
--- a/src/widgets/widgets/qsplitter.cpp
+++ b/src/widgets/widgets/qsplitter.cpp
@@ -161,11 +161,10 @@ Qt::Orientation QSplitterHandle::orientation() const
/*!
- Returns \c true if widgets are resized dynamically (opaquely), otherwise
- returns \c false. This value is controlled by the QSplitter.
+ Returns \c true if widgets are resized dynamically (opaquely) while interactively moving the
+ splitter. Otherwise returns \c false. This value is controlled by the QSplitter.
\sa QSplitter::opaqueResize()
-
*/
bool QSplitterHandle::opaqueResize() const
{
@@ -1483,7 +1482,8 @@ int QSplitter::closestLegalPosition(int pos, int index)
/*!
\property QSplitter::opaqueResize
- \brief whether resizing is opaque
+ Returns \c true if widgets are resized dynamically (opaquely) while interactively moving the
+ splitter. Otherwise returns \c false.
The default resize behavior is style dependent (determined by the
SH_Splitter_OpaqueResize style hint). However, you can override it