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
This commit is contained in:
commit
6893919b0c
105
dist/changes-5.12.2
vendored
Normal file
105
dist/changes-5.12.2
vendored
Normal file
@ -0,0 +1,105 @@
|
||||
Qt 5.12.2 is a bug-fix release. It maintains both forward and backward
|
||||
compatibility (source and binary) with Qt 5.12.0 through 5.12.1.
|
||||
|
||||
For more details, refer to the online documentation included in this
|
||||
distribution. The documentation is also available online:
|
||||
|
||||
https://doc.qt.io/qt-5/index.html
|
||||
|
||||
The Qt version 5.12 series is binary compatible with the 5.11.x series.
|
||||
Applications compiled for 5.11 will continue to run with 5.12.
|
||||
|
||||
Some of the changes listed in this file include issue tracking numbers
|
||||
corresponding to tasks in the Qt Bug Tracker:
|
||||
|
||||
https://bugreports.qt.io/
|
||||
|
||||
Each of these identifiers can be entered in the bug tracker to obtain more
|
||||
information about a particular change.
|
||||
|
||||
****************************************************************************
|
||||
* Important Behavior Changes *
|
||||
****************************************************************************
|
||||
|
||||
- QtTestLib:
|
||||
* [QTBUG-72928] Blacklisting of tests will be taken into account for
|
||||
XPASS and XFAIL. A blacklisted test that causes an XPASS will no
|
||||
longer be a fail.
|
||||
|
||||
****************************************************************************
|
||||
* QtCore *
|
||||
****************************************************************************
|
||||
|
||||
- [QTBUG-72885] Fixed a number of warnings with Clang or Clang-Tidy in
|
||||
Qt headers related to alignment of Qt private classes.
|
||||
|
||||
- QDate, QTime and QDateTime;
|
||||
* [QTBUG-51208] Corrected documentation of how non-placeholder
|
||||
characters are handled in format patterns passed to toString().
|
||||
|
||||
- QCoreApplication:
|
||||
* [QTBUG-57171] Fixed an out-of-bounds access if the translatable
|
||||
string passed to tr() ended in '%'.
|
||||
|
||||
- QFileInfo:
|
||||
* [QTBUG-72644] Fixed a bug that would cause QFileInfo to report an
|
||||
link incorrectly as a non-link.
|
||||
|
||||
- QLocale:
|
||||
* Fixed a crash if qDebug() is used after main() has exited.
|
||||
* [QTBUG-73403] Fixed a race condition in getting the system locale
|
||||
(possible regression from Qt 5.11.x)
|
||||
|
||||
- QSysInfo:
|
||||
* Fixed a bug on BSD systems in getting the machineUniqueId().
|
||||
* Fixed a bug on Windows in 32-bit applications getting the
|
||||
machineUniqueId() when the OS is 64-bit.
|
||||
|
||||
- QWaitCondition:
|
||||
* Fixed handling of wait(QDeadlineTimer::Forever) on 32-bit platforms.
|
||||
|
||||
****************************************************************************
|
||||
* QtWidgets *
|
||||
****************************************************************************
|
||||
|
||||
- ItemViews:
|
||||
* Fixed a regression with wrongly drawn centered/right aligned item
|
||||
texts
|
||||
|
||||
****************************************************************************
|
||||
* Third-Party Code *
|
||||
****************************************************************************
|
||||
|
||||
- libpng was updated to version 1.6.36
|
||||
|
||||
****************************************************************************
|
||||
* Freetype *
|
||||
****************************************************************************
|
||||
|
||||
- Upgraded bundled Freetype version to 2.9.1. This also adds support for
|
||||
the latest emoji font in use on Android 9.
|
||||
|
||||
****************************************************************************
|
||||
* Android *
|
||||
****************************************************************************
|
||||
|
||||
- Added the --no-strip command line option to androiddeployqt.
|
||||
|
||||
- qmake:
|
||||
* Can now set the version name and code for Android using
|
||||
ANDROID_VERSION_NAME and ANDROID_VERSION_CODE respectively in the pro
|
||||
file.
|
||||
|
||||
****************************************************************************
|
||||
* Windows *
|
||||
****************************************************************************
|
||||
|
||||
- Fixed an issue where loading fonts from files or data would sometimes
|
||||
mistakenly classify them as oblique.
|
||||
|
||||
****************************************************************************
|
||||
* qmake *
|
||||
****************************************************************************
|
||||
|
||||
- [QTBUG-27079] A new feature "cmdline" was added that implies "CONFIG +=
|
||||
console" and "CONFIG -= app_bundle".
|
@ -59,6 +59,8 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
Q_INIT_RESOURCE(systray);
|
||||
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
|
||||
QApplication app(argc, argv);
|
||||
|
||||
if (!QSystemTrayIcon::isSystemTrayAvailable()) {
|
||||
|
@ -59,6 +59,8 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
Q_INIT_RESOURCE(classwizard);
|
||||
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
|
||||
QApplication app(argc, argv);
|
||||
|
||||
#ifndef QT_NO_TRANSLATION
|
||||
|
@ -59,6 +59,8 @@ int main(int argc, char *argv[])
|
||||
{
|
||||
Q_INIT_RESOURCE(licensewizard);
|
||||
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
|
||||
QApplication app(argc, argv);
|
||||
|
||||
#ifndef QT_NO_TRANSLATION
|
||||
|
@ -59,6 +59,7 @@
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
QApplication app(argc, argv);
|
||||
QGuiApplication::setApplicationDisplayName(Dialog::tr("Standard Dialogs"));
|
||||
|
||||
|
@ -123,6 +123,8 @@ QWizardPage *createConclusionPage()
|
||||
int main(int argc, char *argv[])
|
||||
//! [9] //! [11]
|
||||
{
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
|
||||
QApplication app(argc, argv);
|
||||
|
||||
#ifndef QT_NO_TRANSLATION
|
||||
|
@ -28,6 +28,7 @@ for(resource, RESOURCES) {
|
||||
!exists($$absolute_path($$resource, $$_PRO_FILE_PWD_)): \
|
||||
warning("Failure to find: $$resource")
|
||||
qmake_immediate.files += $$resource
|
||||
OTHER_FILES *= $$resource
|
||||
}
|
||||
RESOURCES -= $$resource
|
||||
next()
|
||||
@ -57,6 +58,7 @@ for(resource, RESOURCES) {
|
||||
alias = $$relative_path($$file, $$abs_base)
|
||||
resource_file_content += \
|
||||
"<file alias=\"$$xml_escape($$alias)\">$$xml_escape($$file)</file>"
|
||||
OTHER_FILES *= $$file
|
||||
}
|
||||
}
|
||||
|
||||
@ -73,9 +75,11 @@ for(resource, RESOURCES) {
|
||||
}
|
||||
|
||||
!isEmpty(RESOURCES):contains(TEMPLATE, .*lib):plugin:static {
|
||||
resource_init_function = $$lower($$basename(TARGET))_plugin_resource_init
|
||||
pluginBaseName = $$basename(TARGET)
|
||||
pluginName = $$lower($$replace(pluginBaseName, [-], _))
|
||||
resource_init_function = $${pluginName}_plugin_resource_init
|
||||
DEFINES += "QT_PLUGIN_RESOURCE_INIT_FUNCTION=$$resource_init_function"
|
||||
RESOURCE_INIT_CPP = $$OUT_PWD/$$lower($$basename(TARGET))_plugin_resources.cpp
|
||||
RESOURCE_INIT_CPP = $$OUT_PWD/$${pluginName}_plugin_resources.cpp
|
||||
|
||||
GENERATED_SOURCES += $$RESOURCE_INIT_CPP
|
||||
QMAKE_DISTCLEAN += $$RESOURCE_INIT_CPP
|
||||
|
3
src/3rdparty/angle/src/libANGLE/Context.cpp
vendored
3
src/3rdparty/angle/src/libANGLE/Context.cpp
vendored
@ -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();
|
||||
|
8
src/3rdparty/angle/src/libANGLE/Stream.cpp
vendored
8
src/3rdparty/angle/src/libANGLE/Stream.cpp
vendored
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
3
src/3rdparty/angle/src/libANGLE/Texture.cpp
vendored
3
src/3rdparty/angle/src/libANGLE/Texture.cpp
vendored
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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()) {
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
||||
|
||||
/*!
|
||||
|
@ -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;
|
||||
|
@ -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 };
|
||||
}
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -169,6 +169,7 @@ private:
|
||||
friend class QPlatformIntegration;
|
||||
friend class QPlatformScreen;
|
||||
friend class QHighDpiScaling;
|
||||
friend class QWindowSystemInterface;
|
||||
};
|
||||
|
||||
#ifndef QT_NO_DEBUG_STREAM
|
||||
|
@ -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:
|
||||
|
@ -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 =
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
@ -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"
|
||||
},
|
||||
{
|
||||
|
@ -173,7 +173,7 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList ¶
|
||||
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));
|
||||
|
@ -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 ¶mList)
|
||||
|
||||
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");
|
||||
|
||||
|
@ -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 \
|
||||
|
@ -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 ®ion) override;
|
||||
QPaintDevice *paintDevice() override;
|
||||
void endPaint() override;
|
||||
|
||||
void flush(QWindow *, const QRegion &, const QPoint &) override;
|
||||
void composeAndFlush(QWindow *window, const QRegion ®ion, 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
|
||||
|
@ -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 ®ion, const QPoint &offset)
|
||||
void QNSWindowBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
||||
{
|
||||
if (m_image.isNull())
|
||||
return;
|
||||
@ -103,131 +107,113 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo
|
||||
qCDebug(lcQpaBackingStore) << "Flushing" << region << "of" << view << qPrintable(targetViewDescription);
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
||||
// 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"];
|
||||
#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");
|
||||
|
||||
// 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];
|
||||
// Create temporary image to use for blitting, without copying image data
|
||||
NSImage *backingStoreImage = [[[NSImage alloc] initWithCGImage:cgImage size:NSZeroSize] autorelease];
|
||||
|
||||
// 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();
|
||||
|
||||
// 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"];
|
||||
#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");
|
||||
|
||||
// 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()));
|
||||
|
||||
CGRect viewRect = viewLocalRect.toCGRect();
|
||||
|
||||
if (windowHasUnifiedToolbar())
|
||||
NSDrawWindowBackground(viewRect);
|
||||
|
||||
[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()];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
if (shouldHandleViewLockManually)
|
||||
[view unlockFocus];
|
||||
|
||||
if (drawingOutsideOfDisplayCycle) {
|
||||
redrawRoundedBottomCorners([view convertRect:region.boundingRect().toCGRect() toView:nil]);
|
||||
[view.window flushWindow];
|
||||
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))));
|
||||
}
|
||||
}
|
||||
|
||||
// Done flushing to either CALayer or NSWindow backingstore
|
||||
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();
|
||||
|
||||
if (windowHasUnifiedToolbar())
|
||||
NSDrawWindowBackground(viewRect);
|
||||
|
||||
[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()];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
if (shouldHandleViewLockManually)
|
||||
[view unlockFocus];
|
||||
|
||||
if (drawingOutsideOfDisplayCycle) {
|
||||
redrawRoundedBottomCorners([view convertRect:region.boundingRect().toCGRect() toView:nil]);
|
||||
[view.window flushWindow];
|
||||
}
|
||||
|
||||
|
||||
// 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 ®ion, 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 ®ion)
|
||||
{
|
||||
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 ®ion, 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 ®ion, 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
|
||||
|
@ -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
|
||||
|
77
src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h
Normal file
77
src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.h
Normal file
@ -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
|
188
src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.mm
Normal file
188
src/plugins/platforms/cocoa/qiosurfacegraphicsbuffer.mm
Normal file
@ -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
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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 {
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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 ¶meters)
|
||||
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;
|
||||
|
@ -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 ¶mList)
|
||||
|
||||
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");
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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 ¶mList)
|
||||
|
||||
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");
|
||||
|
||||
|
@ -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 ¶meters)
|
||||
mPrimaryScreen->mDepth = 32;
|
||||
mPrimaryScreen->mFormat = QImage::Format_ARGB32_Premultiplied;
|
||||
|
||||
screenAdded(mPrimaryScreen);
|
||||
QWindowSystemInterface::handleScreenAdded(mPrimaryScreen);
|
||||
}
|
||||
|
||||
QMinimalIntegration::~QMinimalIntegration()
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -68,8 +68,6 @@ public:
|
||||
|
||||
QPlatformPrinterSupport *printerSupport() const;
|
||||
|
||||
void addScreen(QOpenWFDScreen *screen);
|
||||
void destroyScreen(QOpenWFDScreen *screen);
|
||||
private:
|
||||
QList<QPlatformScreen *> mScreens;
|
||||
QList<QOpenWFDDevice *>mDevices;
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
}
|
||||
|
@ -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 ¶mList)
|
||||
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");
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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();
|
||||
|
@ -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:
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
@ -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");
|
||||
|
@ -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)) {
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
5
tests/auto/corelib/kernel/qtimer/BLACKLIST
Normal file
5
tests/auto/corelib/kernel/qtimer/BLACKLIST
Normal file
@ -0,0 +1,5 @@
|
||||
[remainingTime]
|
||||
windows
|
||||
osx
|
||||
[basic_chrono]
|
||||
osx
|
@ -230,6 +230,8 @@ private slots:
|
||||
|
||||
void convertColorTable();
|
||||
|
||||
void wideImage();
|
||||
|
||||
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
||||
void toWinHBITMAP_data();
|
||||
void toWinHBITMAP();
|
||||
@ -3559,6 +3561,24 @@ void tst_QImage::convertColorTable()
|
||||
QCOMPARE(rgb32.pixel(0,0), 0xffffffff);
|
||||
}
|
||||
|
||||
void tst_QImage::wideImage()
|
||||
{
|
||||
// QTBUG-73731 and QTBUG-73732
|
||||
QImage i(538994187, 2, QImage::Format_ARGB32);
|
||||
QImage i2(32, 32, QImage::Format_ARGB32);
|
||||
i2.fill(Qt::white);
|
||||
|
||||
// Test that it doesn't crash:
|
||||
QPainter painter(&i);
|
||||
// With the composition mode is SourceOver out it's an invalid write
|
||||
// With the composition mode is Source it's an invalid read
|
||||
painter.drawImage(0, 0, i2);
|
||||
painter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
painter.drawImage(0, 0, i2);
|
||||
|
||||
// Qt6: Test that it actually works on 64bit architectures.
|
||||
}
|
||||
|
||||
#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT)
|
||||
QT_BEGIN_NAMESPACE
|
||||
Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &p, int hbitmapFormat = 0);
|
||||
|
@ -4075,6 +4075,8 @@ void tst_QGraphicsView::update()
|
||||
QTRY_COMPARE(view.lastUpdateRegions.at(0), QRegion(updateRect) & viewportRect);
|
||||
}
|
||||
QTRY_VERIFY(!viewPrivate->fullUpdatePending);
|
||||
#else
|
||||
Q_UNUSED(updateRect);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@ -126,6 +126,10 @@ void MainWindow::aboutDialog()
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#if QT_VERSION >= 0x050600
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
#endif
|
||||
|
||||
for (int a = 1; a < argc; ++a) {
|
||||
if (!qstrcmp(argv[a], "-n")) {
|
||||
qDebug("AA_DontUseNativeDialogs");
|
||||
|
@ -798,6 +798,9 @@ static const char *property_string =
|
||||
" signed short mirrorDiff : 16;\n"
|
||||
" ushort lowerCaseSpecial : 1;\n"
|
||||
" signed short lowerCaseDiff : 15;\n"
|
||||
"#ifdef Q_OS_WASM\n"
|
||||
" unsigned char : 0; //wasm 64 packing trick\n"
|
||||
"#endif\n"
|
||||
" ushort upperCaseSpecial : 1;\n"
|
||||
" signed short upperCaseDiff : 15;\n"
|
||||
" ushort titleCaseSpecial : 1;\n"
|
||||
@ -806,6 +809,9 @@ static const char *property_string =
|
||||
" signed short caseFoldDiff : 15;\n"
|
||||
" ushort unicodeVersion : 8; /* 5 used */\n"
|
||||
" ushort nfQuickCheck : 8;\n" // could be narrowed
|
||||
"#ifdef Q_OS_WASM\n"
|
||||
" unsigned char : 0; //wasm 64 packing trick\n"
|
||||
"#endif\n"
|
||||
" ushort graphemeBreakClass : 5; /* 5 used */\n"
|
||||
" ushort wordBreakClass : 5; /* 5 used */\n"
|
||||
" ushort sentenceBreakClass : 8; /* 4 used */\n"
|
||||
@ -2470,10 +2476,6 @@ static QByteArray createPropertyInfo()
|
||||
out += ", ";
|
||||
out += QByteArray::number( p.lowerCaseDiff );
|
||||
out += ", ";
|
||||
out += "#ifdef Q_OS_WASM \n";
|
||||
// " unsigned char : 0; //wasm 64 packing trick QTBUG-65259\n"
|
||||
out += "#endif \n";
|
||||
out += ", ";
|
||||
// " ushort upperCaseSpecial : 1;\n"
|
||||
// " signed short upperCaseDiff : 15;\n"
|
||||
out += QByteArray::number( p.upperCaseSpecial );
|
||||
@ -2498,10 +2500,6 @@ static QByteArray createPropertyInfo()
|
||||
// " ushort nfQuickCheck : 8;\n"
|
||||
out += QByteArray::number( p.nfQuickCheck );
|
||||
out += ", ";
|
||||
out += "#ifdef Q_OS_WASM \n";
|
||||
// " unsigned char : 0; //wasm 64 packing trick QTBUG-65259\n"
|
||||
out += "#endif \n";
|
||||
out += ", ";
|
||||
// " ushort graphemeBreakClass : 5; /* 5 used */\n"
|
||||
// " ushort wordBreakClass : 5; /* 5 used */\n"
|
||||
// " ushort sentenceBreakClass : 8; /* 4 used */\n"
|
||||
|
Loading…
Reference in New Issue
Block a user