Merge remote-tracking branch 'origin/5.13' into dev

Change-Id: I38389a69411f4549fed432f1181dbe23398b34a2
bb10
Friedemann Kleint 2019-03-26 08:24:59 +01:00
commit 7f635d9777
108 changed files with 1540 additions and 850 deletions

105
dist/changes-5.12.2 vendored Normal file
View 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".

View File

@ -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()) {

View File

@ -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

View File

@ -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

View File

@ -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"));

View File

@ -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

View File

@ -62,6 +62,7 @@ function(_qt5_$${CMAKE_MODULE_NAME}_process_prl_file prl_file_location Configura
set(_search_paths)
string(REPLACE \"\\$\\$[QT_INSTALL_LIBS]\" \"${_qt5_install_libs}\" _static_depends \"${_static_depends}\")
foreach(_flag ${_static_depends})
string(REPLACE \"\\\"\" \"\" _flag ${_flag})
if(_flag MATCHES \"^-l(.*)$\")
# Handle normal libraries passed as -lfoo
set(_lib \"${CMAKE_MATCH_1}\")

View File

@ -13,7 +13,14 @@ equals(TEMPLATE, app): TEMPLATE = aux
isEmpty(TARGETPATH): error("Must set TARGETPATH (QML import name)")
qmldir_file = $$_PRO_FILE_PWD_/qmldir
!isEmpty(DYNAMIC_QMLDIR) {
qmldir_path = $$OUT_PWD
write_file($${qmldir_path}/qmldir, DYNAMIC_QMLDIR)|error("Aborting.")
} else {
qmldir_path = $$_PRO_FILE_PWD_
}
qmldir_file = $${qmldir_path}/qmldir
fq_qml_files =
for(qmlf, QML_FILES): fq_qml_files += $$absolute_path($$qmlf, $$_PRO_FILE_PWD_)
@ -42,13 +49,20 @@ builtin_resources {
}
# Install rules
qmldir.base = $$_PRO_FILE_PWD_
qmldir.base = $$qmldir_path
# Tools need qmldir and plugins.qmltypes always installed on the file system
qmldir.files = $$qmldir_file $$fq_aux_qml_files
qmldir.files = $$qmldir_file
install_qml_files: qmldir.files += $$fq_qml_files
qmldir.path = $$[QT_INSTALL_QML]/$$TARGETPATH
INSTALLS += qmldir
qmlfiles.base = $$_PRO_FILE_PWD_
qmlfiles.files = $$fq_aux_qml_files
install_qml_files: qmlfiles.files += $$fq_qml_files
qmlfiles.path = $${qmldir.path}
INSTALLS += qmlfiles
!debug_and_release|!build_all|CONFIG(release, debug|release) {
!prefix_build {
COPIES += qmldir

View File

@ -544,7 +544,15 @@ defineTest(qtConfResolveLibs) {
} else: contains(l, "^-l.*") {
lib = $$replace(l, "^-l", )
lcan =
unix {
integrity:contains(lib, "^.*\\.a") {
# INTEGRITY compiler searches for exact filename
# if -l argument has .a suffix
lcan += $${lib}
} else: contains(lib, "^:.*") {
# Use exact filename when -l:filename syntax is used.
lib ~= s/^://
lcan += $${lib}
} else: unix {
# Under UNIX, we look for actual shared libraries, in addition
# to static ones.
shexts = $$QMAKE_EXTENSION_SHLIB $$QMAKE_EXTENSIONS_AUX_SHLIB

View File

@ -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

View File

@ -32,15 +32,6 @@ EMCC_COMMON_LFLAGS = \
--bind \
-s \"BINARYEN_TRAP_MODE=\'clamp\'\"
EMCC_USE_PORTS_FLAGS = \
-s USE_FREETYPE=1 \
-s USE_ZLIB=1
# libpng does not build for WASM_OBJECT_FILES=1, see
# https://github.com/emscripten-core/emscripten/issues/8143
equals(WASM_OBJECT_FILES, 0):\
EMCC_USE_PORTS_FLAGS += -s USE_LIBPNG=1
# The -s arguments can also be used with release builds,
# but are here in debug for clarity.
EMCC_COMMON_LFLAGS_DEBUG = \
@ -87,9 +78,6 @@ QMAKE_COMPILER += emscripten
QMAKE_CC = emcc
QMAKE_CXX = em++
QMAKE_CFLAGS += $$EMCC_USE_PORTS_FLAGS
QMAKE_CXXFLAGS += $$EMCC_USE_PORTS_FLAGS
QMAKE_LINK = $$QMAKE_CXX
QMAKE_LINK_SHLIB = $$QMAKE_CXX
QMAKE_LINK_C = $$QMAKE_CC

View File

@ -13,19 +13,19 @@ QMAKE_CFLAGS_SSE4_1 = -msse4.1
QMAKE_CFLAGS_SSE4_2 = -msse4.2
QMAKE_CFLAGS_AVX = -mavx
QMAKE_CFLAGS_AVX2 = -mavx2
QMAKE_CFLAGS_F16C = -mf16c
QMAKE_CFLAGS_RDRND = -mrdrnd
QMAKE_CFLAGS_AVX512F = -mavx512f
QMAKE_CFLAGS_AVX512ER = -mavx512er
QMAKE_CFLAGS_AVX512CD = -mavx512cd
QMAKE_CFLAGS_AVX512PF = -mavx512pf
QMAKE_CFLAGS_AVX512DQ = -mavx512dq
QMAKE_CFLAGS_AVX512BW = -mavx512bw
QMAKE_CFLAGS_AVX512VL = -mavx512vl
QMAKE_CFLAGS_F16C = -mf16c
QMAKE_CFLAGS_RDRND = -mrdrnd
QMAKE_CFLAGS_AVX512F = -mavx512f
QMAKE_CFLAGS_AVX512ER = -mavx512er
QMAKE_CFLAGS_AVX512CD = -mavx512cd
QMAKE_CFLAGS_AVX512PF = -mavx512pf
QMAKE_CFLAGS_AVX512DQ = -mavx512dq
QMAKE_CFLAGS_AVX512BW = -mavx512bw
QMAKE_CFLAGS_AVX512VL = -mavx512vl
QMAKE_CFLAGS_AVX512IFMA = -mavx512ifma
QMAKE_CFLAGS_AVX512VBMI = -mavx512vbmi
QMAKE_CFLAGS_AESNI = -maes
QMAKE_CFLAGS_SHANI = -msha
QMAKE_CFLAGS_AESNI = -maes
QMAKE_CFLAGS_SHANI = -msha
QMAKE_COMPILER += clang_cl llvm

View File

@ -765,11 +765,19 @@ public class QtActivityDelegate
}
m_layout = new QtLayout(m_activity, startApplication);
int orientation = m_activity.getResources().getConfiguration().orientation;
try {
ActivityInfo info = m_activity.getPackageManager().getActivityInfo(m_activity.getComponentName(), PackageManager.GET_META_DATA);
if (info.metaData.containsKey("android.app.splash_screen_drawable")) {
String splashScreenKey = "android.app.splash_screen_drawable_"
+ (orientation == Configuration.ORIENTATION_LANDSCAPE ? "landscape" : "portrait");
if (!info.metaData.containsKey(splashScreenKey))
splashScreenKey = "android.app.splash_screen_drawable";
if (info.metaData.containsKey(splashScreenKey)) {
m_splashScreenSticky = info.metaData.containsKey("android.app.splash_screen_sticky") && info.metaData.getBoolean("android.app.splash_screen_sticky");
int id = info.metaData.getInt("android.app.splash_screen_drawable");
int id = info.metaData.getInt(splashScreenKey);
m_splashScreen = new ImageView(m_activity);
m_splashScreen.setImageDrawable(m_activity.getResources().getDrawable(id));
m_splashScreen.setScaleType(ImageView.ScaleType.FIT_XY);
@ -789,7 +797,6 @@ public class QtActivityDelegate
new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
int orientation = m_activity.getResources().getConfiguration().orientation;
int rotation = m_activity.getWindowManager().getDefaultDisplay().getRotation();
boolean rot90 = (rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270);
boolean currentlyLandscape = (orientation == Configuration.ORIENTATION_LANDSCAPE);

View File

@ -52,6 +52,12 @@
<!-- Messages maps -->
<!-- Splash screen -->
<!-- Orientation-specific (portrait/landscape) data is checked first. If not available for current orientation,
then android.app.splash_screen_drawable. For best results, use together with splash_screen_sticky and
use hideSplashScreen() with a fade-out animation from Qt Android Extras to hide the splash screen when you
are done populating your window with content. -->
<!-- meta-data android:name="android.app.splash_screen_drawable_portrait" android:resource="@drawable/logo_portrait" / -->
<!-- meta-data android:name="android.app.splash_screen_drawable_landscape" android:resource="@drawable/logo_landscape" / -->
<!-- meta-data android:name="android.app.splash_screen_drawable" android:resource="@drawable/logo"/ -->
<!-- meta-data android:name="android.app.splash_screen_sticky" android:value="true"/ -->
<!-- Splash screen -->

View File

@ -28,357 +28,71 @@
/*!
\page datastreamformat.html
\title Serializing Qt Data Types
\brief Representations of data types that can be serialized by QDataStream.
\brief List of data types that can be serialized by QDataStream.
The \l QDataStream allows you to serialize some of the Qt data types.
The table below lists the data types that QDataStream can serialize
and how they are represented. The format described below is
\l{QDataStream::setVersion()}{version 13}.
The \l QDataStream class allows you to serialize the Qt data types
listed in this section as of \l{QDataStream::setVersion()}{version 18}.
It is always best to cast integers to a Qt integer type, such as
qint16 or quint32, when reading and writing. This ensures that
\l{qint16} or \l{quint32}, when reading and writing. This ensures that
you always know exactly what size integers you are reading and
writing, no matter what the underlying platform and architecture
the application happens to be running on.
\table
\row \li bool
\li \list
\li boolean
\endlist
\row \li qint8
\li \list
\li signed byte
\endlist
\row \li qint16
\li \list
\li signed 16-bit integer
\endlist
\row \li qint32
\li \list
\li signed 32-bit integer
\endlist
\row \li qint64
\li \list
\li signed 64-bit integer
\endlist
\row \li quint8
\li \list
\li unsigned byte
\endlist
\row \li quint16
\li \list
\li unsigned 16-bit integer
\endlist
\row \li quint32
\li \list
\li unsigned 32-bit integer
\endlist
\row \li quint64
\li \list
\li unsigned 64-bit integer
\endlist
\row \li \c float
\li \list
\li 32-bit floating point number using the standard IEEE 754 format
\endlist
\row \li \c double
\li \list
\li 64-bit floating point number using the standard IEEE 754 format
\endlist
\row \li \c {const char *}
\li \list
\li The string length (quint32)
\li The string bytes, excluding the terminating 0
\endlist
\row \li QBitArray
\li \list
\li The array size (quint32)
\li The array bits, i.e. (size + 7)/8 bytes
\endlist
\row \li QBrush
\li \list
\li The brush style (quint8)
\li The brush color (QColor)
\li If style is CustomPattern, the brush pixmap (QPixmap)
\endlist
\row \li QByteArray
\li \list
\li If the byte array is null: 0xFFFFFFFF (quint32)
\li Otherwise: the array size (quint32) followed by the array bytes, i.e. size bytes
\endlist
\row \li \l QColor
\li \list
\li Color spec (qint8)
\li Alpha value (quint16)
\li Red value (quint16)
\li Green value (quint16)
\li Blue value (quint16)
\li Pad value (quint16)
\endlist
\row \li QCursor
\li \list
\li Shape ID (qint16)
\li If shape is BitmapCursor: The bitmap (QPixmap), mask (QPixmap), and hot spot (QPoint)
\endlist
\row \li QDate
\li \list
\li Julian day (quint32)
\endlist
\row \li QDateTime
\li \list
\li Date (QDate)
\li Time (QTime)
\li The \l{Qt::TimeSpec}{time spec}
offsetFromUtc (qint32) if Qt::TimeSpec is offsetFromUtc
TimeZone(QTimeZone) if Qt::TimeSpec is TimeZone
\endlist
\row \li QEasingCurve
\li \list
\li type (quint8)
\li func (quint64)
\li hasConfig (bool)
\li If hasConfig is true then these fields follow:
\li list
\li period (double)
\li amplitude (double)
\li overshoot (double)
\endlist
\row \li QFont
\li \list
\li The family (QString)
\li The style name (QString)
\li The point size (double)
\li The pixel size (qint32)
\li The style hint (quint8)
\li The style strategy (quint16)
\li The char set (quint8)
\li The weight (quint8)
\li The font bits (quint8)
\li The font stretch (quint16)
\li The extended font bits (quint8)
\li The letter spacing (double)
\li The word spacing (double)
\li The hinting preference (quint8)
\endlist
\row \li QHash<Key, T>
\li \list
\li The number of items (quint32)
\li For all items, the key (Key) and value (T)
\endlist
\row \li QIcon
\li \list
\li The number of pixmap entries (quint32)
\li For all pixmap entries:
\list
\li The pixmap (QPixmap)
\li The file name (QString)
\li The pixmap size (QSize)
\li The \l{QIcon::Mode}{mode} (quint32)
\li The \l{QIcon::State}{state} (quint32)
\endlist
\endlist
\row \li QImage
\li \list
\li If the image is null a "null image" marker is saved;
otherwise the image is saved in PNG or BMP format (depending
on the stream version). If you want control of the format,
stream the image into a QBuffer (using QImageIOHandler/QImageIOPlugin) and stream
that.
\endlist
\row \li QKeySequence
\li \list
\li A QList<int>, where each integer is a key in the key sequence
\endlist
\row \li QLinkedList<T>
\li \list
\li The number of items (quint32)
\li The items (T)
\endlist
\row \li QList<T>
\li \list
\li The number of items (quint32)
\li The items (T)
\endlist
\row \li QMap<Key, T>
\li \list
\li The number of items (quint32)
\li For all items, the key (Key) and value (T)
\endlist
\row \li QMargins
\li \list
\li left (int)
\li top (int)
\li right (int)
\li bottom (int)
\endlist
\row \li QMatrix
\li \list
\li m11 (double)
\li m12 (double)
\li m21 (double)
\li m22 (double)
\li dx (double)
\li dy (double)
\endlist
\row \li QMatrix4x4
\li \list
\li m11 (float)
\li m12 (float)
\li m13 (float)
\li m14 (float)
\li m21 (float)
\li m22 (float)
\li m23 (float)
\li m24 (float)
\li m31 (float)
\li m32 (float)
\li m33 (float)
\li m34 (float)
\li m41 (float)
\li m42 (float)
\li m43 (float)
\li m44 (float)
\endlist
\row \li QPair<T1, T2>
\li \list
\li first (T1)
\li second (T2)
\endlist
\row \li QPalette
\li The disabled, active, and inactive color groups, each of which consists
of the following:
\list
\li foreground (QBrush)
\li button (QBrush)
\li light (QBrush)
\li midlight (QBrush)
\li dark (QBrush)
\li mid (QBrush)
\li text (QBrush)
\li brightText (QBrush)
\li buttonText (QBrush)
\li base (QBrush)
\li background (QBrush)
\li shadow (QBrush)
\li highlight (QBrush)
\li highlightedText (QBrush)
\li link (QBrush)
\li linkVisited (QBrush)
\endlist
\row \li QPen
\li \list
\li The pen styles (quint8)
\li The pen width (quint16)
\li The pen color (QColor)
\endlist
\row \li QPicture
\li \list
\li The size of the picture data (quint32)
\li The raw bytes of picture data (char)
\endlist
\row \li QPixmap
\li \list
\li Save it as a PNG image.
\endlist
\row \li QPoint
\li \list
\li The x coordinate (qint32)
\li The y coordinate (qint32)
\endlist
\row \li QQuaternion
\li \list
\li The scalar component (float)
\li The x coordinate (float)
\li The y coordinate (float)
\li The z coordinate (float)
\endlist
\row \li QRect
\li \list
\li left (qint32)
\li top (qint32)
\li right (qint32)
\li bottom (qint32)
\endlist
\row \li QRegExp
\li \list
\li The regexp pattern (QString)
\li Case sensitivity (quint8)
\li Regular expression syntax (quint8)
\li Minimal matching (quint8)
\endlist
\row \li QRegularExpression
\li \list
\li The regular expression pattern (QString)
\li The pattern options (quint32)
\endlist
\row \li QRegion
\li \list
\li The size of the data, i.e. 8 + 16 * (number of rectangles) (quint32)
\li 10 (qint32)
\li The number of rectangles (quint32)
\li The rectangles in sequential order (QRect)
\endlist
\row \li QSize
\li \list
\li width (qint32)
\li height (qint32)
\endlist
\row \li QString
\li \list
\li If the string is null: 0xFFFFFFFF (quint32)
\li Otherwise: The string length in bytes (quint32) followed by the data in UTF-16
\endlist
\row \li QTime
\li \list
\li Milliseconds since midnight (quint32)
\endlist
\row \li QTransform
\li \list
\li m11 (double)
\li m12 (double)
\li m13 (double)
\li m21 (double)
\li m22 (double)
\li m23 (double)
\li m31 (double)
\li m32 (double)
\li m33 (double)
\endlist
\row \li QUrl
\li \list
\li Holds an URL (QString)
\endlist
\row \li QVariant
\li \list
\li The type of the data (quint32)
\li The null flag (qint8)
\li The data of the specified type
\endlist
\row \li QVector2D
\li \list
\li the x coordinate (float)
\li the y coordinate (float)
\endlist
\row \li QVector3D
\li \list
\li the x coordinate (float)
\li the y coordinate (float)
\li the z coordinate (float)
\endlist
\row \li QVector4D
\li \list
\li the x coordinate (float)
\li the y coordinate (float)
\li the z coordinate (float)
\li the w coordinate (float)
\endlist
\row \li QVector<T>
\li \list
\li The number of items (quint32)
\li The items (T)
\endlist
\endtable
\list
\li bool
\li \l{qint8}
\li \l{qint16}
\li \l{qint32}
\li \l{qint64}
\li \l{quint8}
\li \l{quint16}
\li \l{quint32}
\li \l{quint64}
\li \c float
\li \c double
\li \c {const char *}
\li QBitArray
\li QBrush
\li QByteArray
\li QColor
\li QCursor
\li QDate
\li QDateTime
\li QEasingCurve
\li QFont
\li QGenericMatrix
\li QHash<Key, T>
\li QIcon
\li QImage
\li QKeySequence
\li QLinkedList<T>
\li QList<T>
\li QMap<Key, T>
\li QMargins
\li QMatrix4x4
\li QPair<T1, T2>
\li QPalette
\li QPen
\li QPicture
\li QPixmap
\li QPoint
\li QQuaternion
\li QRect
\li QRegExp
\li QRegularExpression
\li QRegion
\li QSize
\li QString
\li QTime
\li QTransform
\li QUrl
\li QVariant
\li QVector2D
\li QVector3D
\li QVector4D
\li QVector<T>
\endlist
\sa {JSON Support in Qt}
*/

View File

@ -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()) {

View File

@ -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);

View File

@ -629,7 +629,10 @@ void QIconLoaderEngine::ensureLoaded()
void QIconLoaderEngine::paint(QPainter *painter, const QRect &rect,
QIcon::Mode mode, QIcon::State state)
{
QSize pixmapSize = rect.size();
const qreal dpr = !qApp->testAttribute(Qt::AA_UseHighDpiPixmaps) ?
qreal(1.0) : painter->device()->devicePixelRatioF();
QSize pixmapSize = rect.size() * dpr;
painter->drawPixmap(rect, pixmap(pixmapSize, mode, state));
}

View File

@ -127,7 +127,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);
@ -786,7 +786,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) {
@ -1492,10 +1492,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
/*!

View File

@ -228,7 +228,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;

View File

@ -113,6 +113,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);
};
@ -139,6 +140,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 };
}

View File

@ -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();

View File

@ -462,87 +462,6 @@ QList<int> QPlatformIntegration::possibleKeys(const QKeyEvent *) const
return QList<int>();
}
/*!
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().
*/
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);
}
/*!
Just removes the screen, call destroyScreen instead.
\sa destroyScreen()
*/
void QPlatformIntegration::removeScreen(QScreen *screen)
{
const bool wasPrimary = (!QGuiApplicationPrivate::screen_list.isEmpty() && QGuiApplicationPrivate::screen_list.at(0) == screen);
QGuiApplicationPrivate::screen_list.removeOne(screen);
QGuiApplicationPrivate::resetCachedDevicePixelRatio();
if (wasPrimary && qGuiApp && !QGuiApplicationPrivate::screen_list.isEmpty())
emit qGuiApp->primaryScreenChanged(QGuiApplicationPrivate::screen_list.at(0));
}
/*!
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 QPlatformIntegration::destroyScreen(QPlatformScreen *screen)
{
QScreen *qScreen = screen->screen();
removeScreen(qScreen);
delete qScreen;
delete screen;
}
/*!
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 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);
}
QStringList QPlatformIntegration::themeNames() const
{
return QStringList();

View File

@ -192,8 +192,6 @@ public:
#endif
virtual void setApplicationIcon(const QIcon &icon) const;
void removeScreen(QScreen *screen);
virtual void beep() const;
#if QT_CONFIG(vulkan) || defined(Q_CLANG_QDOC)
@ -202,10 +200,6 @@ public:
protected:
QPlatformIntegration() = default;
void screenAdded(QPlatformScreen *screen, bool isPrimary = false);
void destroyScreen(QPlatformScreen *screen);
void setPrimaryScreen(QPlatformScreen *newPrimary);
};
QT_END_NAMESPACE

View File

@ -61,8 +61,7 @@ QPlatformScreen::~QPlatformScreen()
{
Q_D(QPlatformScreen);
if (d->screen) {
qWarning("Manually deleting a QPlatformScreen. Call QPlatformIntegration::destroyScreen instead.");
QGuiApplicationPrivate::platformIntegration()->removeScreen(d->screen);
qWarning("Manually deleting a QPlatformScreen. Call QWindowSystemInterface::handleScreenRemoved instead.");
delete d->screen;
}
}

View File

@ -106,9 +106,18 @@ void QScreenPrivate::setPlatformScreen(QPlatformScreen *screen)
*/
QScreen::~QScreen()
{
if (!qApp)
// Remove screen
const bool wasPrimary = QGuiApplication::primaryScreen() == this;
QGuiApplicationPrivate::screen_list.removeOne(this);
QGuiApplicationPrivate::resetCachedDevicePixelRatio();
if (!qGuiApp)
return;
QScreen *newPrimaryScreen = QGuiApplication::primaryScreen();
if (wasPrimary && newPrimaryScreen)
emit qGuiApp->primaryScreenChanged(newPrimaryScreen);
// Allow clients to manage windows that are affected by the screen going
// away, before we fall back to moving them to the primary screen.
emit qApp->screenRemoved(this);
@ -116,11 +125,8 @@ QScreen::~QScreen()
if (QGuiApplication::closingDown())
return;
QScreen *primaryScreen = QGuiApplication::primaryScreen();
if (this == primaryScreen)
return;
bool movingFromVirtualSibling = primaryScreen && primaryScreen->handle()->virtualSiblings().contains(handle());
bool movingFromVirtualSibling = newPrimaryScreen
&& newPrimaryScreen->handle()->virtualSiblings().contains(handle());
// Move any leftover windows to the primary screen
const auto allWindows = QGuiApplication::allWindows();
@ -129,7 +135,7 @@ QScreen::~QScreen()
continue;
const bool wasVisible = window->isVisible();
window->setScreen(primaryScreen);
window->setScreen(newPrimaryScreen);
// Re-show window if moved from a virtual sibling screen. Otherwise
// leave it up to the application developer to show the window.

View File

@ -169,6 +169,7 @@ private:
friend class QPlatformIntegration;
friend class QPlatformScreen;
friend class QHighDpiScaling;
friend class QWindowSystemInterface;
};
#ifndef QT_NO_DEBUG_STREAM

View File

@ -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:

View File

@ -780,6 +780,67 @@ 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)
{
// 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 =

View File

@ -237,6 +237,10 @@ public:
#endif
// 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);

View File

@ -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);

View File

@ -1390,7 +1390,8 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
QString scheme = req.url().scheme();
#ifdef Q_OS_WASM
if (scheme == QLatin1String("http") || scheme == QLatin1String("https")) {
// Support http, https, and relateive urls
if (scheme == QLatin1String("http") || scheme == QLatin1String("https") || scheme.isEmpty()) {
QNetworkReplyWasmImpl *reply = new QNetworkReplyWasmImpl(this);
QNetworkReplyWasmImplPrivate *priv = reply->d_func();
priv->manager = this;

View File

@ -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"
},
{

View File

@ -908,7 +908,7 @@ QFont QFontconfigDatabase::defaultFont() const
void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef &fontDef) const
{
bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
bool forcedAntialiasSetting = !antialias;
bool forcedAntialiasSetting = !antialias || QHighDpiScaling::isActive();
const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services();
bool useXftConf = false;

View File

@ -223,6 +223,7 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format
continue;
}
QXlibPointer<XVisualInfo> visual(glXGetVisualFromFBConfig(display, candidate));
int actualRed;
int actualGreen;
int actualBlue;
@ -231,7 +232,8 @@ GLXFBConfig qglx_findConfig(Display *display, int screen , QSurfaceFormat format
glXGetFBConfigAttrib(display, candidate, GLX_GREEN_SIZE, &actualGreen);
glXGetFBConfigAttrib(display, candidate, GLX_BLUE_SIZE, &actualBlue);
glXGetFBConfigAttrib(display, candidate, GLX_ALPHA_SIZE, &actualAlpha);
// Sometimes the visuals don't have a depth that includes the alpha channel.
actualAlpha = qMin(actualAlpha, visual->depth - actualRed - actualGreen - actualBlue);
if (requestedRed && actualRed < requestedRed)
continue;

View File

@ -7,7 +7,7 @@ CONFIG += static internal_module
DEFINES += QT_NO_CAST_FROM_ASCII
PRECOMPILED_HEADER = ../../../corelib/global/qt_pch.h
QMAKE_USE_PRIVATE += xkbcommon
QMAKE_USE += xkbcommon
HEADERS += \
qxkbcommon_p.h

View File

@ -1,6 +1,6 @@
TARGET = ibusplatforminputcontextplugin
QT += dbus gui-private
QT += dbus gui-private xkbcommon_support-private
SOURCES += $$PWD/qibusplatforminputcontext.cpp \
$$PWD/qibusproxy.cpp \
$$PWD/qibusproxyportal.cpp \

View File

@ -51,6 +51,8 @@
#include <QtGui/private/qguiapplication_p.h>
#include <QtXkbCommonSupport/private/qxkbcommon_p.h>
#include "qibusproxy.h"
#include "qibusproxyportal.h"
#include "qibusinputcontextproxy.h"
@ -335,14 +337,12 @@ void QIBusPlatformInputContext::forwardKeyEvent(uint keyval, uint keycode, uint
if (!input)
return;
if (debug)
qDebug() << "forwardKeyEvent" << keyval << keycode << state;
QEvent::Type type = QEvent::KeyPress;
if (state & IBUS_RELEASE_MASK)
type = QEvent::KeyRelease;
state &= ~IBUS_RELEASE_MASK;
keycode += 8;
Qt::KeyboardModifiers modifiers = Qt::NoModifier;
if (state & IBUS_SHIFT_MASK)
@ -354,7 +354,13 @@ void QIBusPlatformInputContext::forwardKeyEvent(uint keyval, uint keycode, uint
if (state & IBUS_META_MASK)
modifiers |= Qt::MetaModifier;
QKeyEvent event(type, keyval, modifiers, QString(keyval));
int qtcode = QXkbCommon::keysymToQtKey(keyval, modifiers);
QString text = QXkbCommon::lookupStringNoKeysymTransformations(keyval);
if (debug)
qDebug() << "forwardKeyEvent" << keyval << keycode << state << modifiers << qtcode << text;
QKeyEvent event(type, qtcode, modifiers, keycode, keyval, state, text);
QCoreApplication::sendEvent(input, &event);
}

View File

@ -1,10 +1,11 @@
TEMPLATE = subdirs
QT_FOR_CONFIG += gui-private
qtHaveModule(dbus) {
!mac:!win32:SUBDIRS += ibus
qtConfig(xkbcommon) {
SUBDIRS += compose
qtHaveModule(dbus) {
!macos:!win32:SUBDIRS += ibus
}
}
qtConfig(xkbcommon): SUBDIRS += compose

View File

@ -173,7 +173,7 @@ QAndroidPlatformIntegration::QAndroidPlatformIntegration(const QStringList &para
qFatal("Could not bind GL_ES API");
m_primaryScreen = new QAndroidPlatformScreen();
screenAdded(m_primaryScreen);
QWindowSystemInterface::handleScreenAdded(m_primaryScreen);
m_primaryScreen->setPhysicalSize(QSize(m_defaultPhysicalSizeWidth, m_defaultPhysicalSizeHeight));
m_primaryScreen->setSize(QSize(m_defaultScreenWidth, m_defaultScreenHeight));
m_primaryScreen->setAvailableGeometry(QRect(0, 0, m_defaultGeometryWidth, m_defaultGeometryHeight));

View File

@ -53,6 +53,7 @@
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatforminputcontext.h>
#include <qpa/qplatforminputcontextfactory_p.h>
#include <qpa/qwindowsysteminterface.h>
#if QT_CONFIG(tslib)
#include <QtInputSupport/private/qtslib_p.h>
@ -69,13 +70,13 @@ QBsdFbIntegration::QBsdFbIntegration(const QStringList &paramList)
QBsdFbIntegration::~QBsdFbIntegration()
{
destroyScreen(m_primaryScreen.take());
QWindowSystemInterface::handleScreenRemoved(m_primaryScreen.take());
}
void QBsdFbIntegration::initialize()
{
if (m_primaryScreen->initialize())
screenAdded(m_primaryScreen.data());
QWindowSystemInterface::handleScreenAdded(m_primaryScreen.data());
else
qWarning("bsdfb: Failed to initialize screen");

View File

@ -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 \

View File

@ -44,13 +44,16 @@
#include <private/qcore_mac_p.h>
#include <QScopedPointer>
#include "qiosurfacegraphicsbuffer.h"
QT_BEGIN_NAMESPACE
class QCocoaBackingStore : public QRasterBackingStore
class QNSWindowBackingStore : public QRasterBackingStore
{
public:
QCocoaBackingStore(QWindow *window);
~QCocoaBackingStore();
QNSWindowBackingStore(QWindow *window);
~QNSWindowBackingStore();
void flush(QWindow *, const QRegion &, const QPoint &) override;
@ -60,6 +63,49 @@ private:
void redrawRoundedBottomCorners(CGRect) const;
};
class QCALayerBackingStore : public QPlatformBackingStore
{
public:
QCALayerBackingStore(QWindow *window);
~QCALayerBackingStore();
void resize(const QSize &size, const QRegion &staticContents) override;
void beginPaint(const QRegion &region) override;
QPaintDevice *paintDevice() override;
void endPaint() override;
void flush(QWindow *, const QRegion &, const QPoint &) override;
void composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
QPlatformTextureList *textures, bool translucentBackground) override;
QPlatformGraphicsBuffer *graphicsBuffer() const override;
private:
QSize m_requestedSize;
QRegion m_paintedRegion;
class GraphicsBuffer : public QIOSurfaceGraphicsBuffer
{
public:
GraphicsBuffer(const QSize &size, qreal devicePixelRatio,
const QPixelFormat &format, QCFType<CGColorSpaceRef> colorSpace);
QRegion dirtyRegion; // In unscaled coordinates
QImage *asImage();
private:
qreal m_devicePixelRatio;
QImage m_image;
};
void ensureBackBuffer();
bool recreateBackBufferIfNeeded();
bool prepareForFlush();
std::list<std::unique_ptr<GraphicsBuffer>> m_buffers;
};
QT_END_NAMESPACE
#endif

View File

@ -42,24 +42,28 @@
#include "qcocoawindow.h"
#include "qcocoahelpers.h"
#include <QtCore/qmath.h>
#include <QuartzCore/CATransaction.h>
QT_BEGIN_NAMESPACE
QCocoaBackingStore::QCocoaBackingStore(QWindow *window)
QNSWindowBackingStore::QNSWindowBackingStore(QWindow *window)
: QRasterBackingStore(window)
{
}
QCocoaBackingStore::~QCocoaBackingStore()
QNSWindowBackingStore::~QNSWindowBackingStore()
{
}
bool QCocoaBackingStore::windowHasUnifiedToolbar() const
bool QNSWindowBackingStore::windowHasUnifiedToolbar() const
{
Q_ASSERT(window()->handle());
return static_cast<QCocoaWindow *>(window()->handle())->m_drawContentBorderGradient;
}
QImage::Format QCocoaBackingStore::format() const
QImage::Format QNSWindowBackingStore::format() const
{
if (windowHasUnifiedToolbar())
return QImage::Format_ARGB32_Premultiplied;
@ -78,7 +82,7 @@ QImage::Format QCocoaBackingStore::format() const
coordinates, and the \a offset will be the child window's offset in relation
to the backingstore's top level window.
*/
void QCocoaBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
void QNSWindowBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{
if (m_image.isNull())
return;
@ -103,131 +107,113 @@ void QCocoaBackingStore::flush(QWindow *window, const QRegion &region, const QPo
qCDebug(lcQpaBackingStore) << "Flushing" << region << "of" << view << qPrintable(targetViewDescription);
}
// 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 &region, const QPo
https://trac.webkit.org/changeset/85376/webkit
*/
void QCocoaBackingStore::redrawRoundedBottomCorners(CGRect windowRect) const
void QNSWindowBackingStore::redrawRoundedBottomCorners(CGRect windowRect) const
{
#if !defined(QT_APPLE_NO_PRIVATE_APIS)
Q_ASSERT(this->window()->handle());
@ -285,4 +271,345 @@ void QCocoaBackingStore::redrawRoundedBottomCorners(CGRect windowRect) const
#endif
}
// ----------------------------------------------------------------------------
// https://stackoverflow.com/a/52722575/2761869
template<class R>
struct backwards_t {
R r;
constexpr auto begin() const { using std::rbegin; return rbegin(r); }
constexpr auto begin() { using std::rbegin; return rbegin(r); }
constexpr auto end() const { using std::rend; return rend(r); }
constexpr auto end() { using std::rend; return rend(r); }
};
template<class R>
constexpr backwards_t<R> backwards(R&& r) { return {std::forward<R>(r)}; }
QCALayerBackingStore::QCALayerBackingStore(QWindow *window)
: QPlatformBackingStore(window)
{
qCDebug(lcQpaBackingStore) << "Creating QCALayerBackingStore for" << window;
m_buffers.resize(1);
}
QCALayerBackingStore::~QCALayerBackingStore()
{
}
void QCALayerBackingStore::resize(const QSize &size, const QRegion &staticContents)
{
qCDebug(lcQpaBackingStore) << "Resize requested to" << size;
if (!staticContents.isNull())
qCWarning(lcQpaBackingStore) << "QCALayerBackingStore does not support static contents";
m_requestedSize = size;
}
void QCALayerBackingStore::beginPaint(const QRegion &region)
{
Q_UNUSED(region);
QMacAutoReleasePool pool;
qCInfo(lcQpaBackingStore) << "Beginning paint of" << region << "into backingstore of" << m_requestedSize;
ensureBackBuffer(); // Find an unused back buffer, or reserve space for a new one
const bool bufferWasRecreated = recreateBackBufferIfNeeded();
m_buffers.back()->lock(QPlatformGraphicsBuffer::SWWriteAccess);
// Although undocumented, QBackingStore::beginPaint expects the painted region
// to be cleared before use if the window has a surface format with an alpha.
// Fresh IOSurfaces are already cleared, so we don't need to clear those.
if (!bufferWasRecreated && window()->format().hasAlpha()) {
qCDebug(lcQpaBackingStore) << "Clearing" << region << "before use";
QPainter painter(m_buffers.back()->asImage());
painter.setCompositionMode(QPainter::CompositionMode_Source);
for (const QRect &rect : region)
painter.fillRect(rect, Qt::transparent);
}
m_paintedRegion += region;
}
void QCALayerBackingStore::ensureBackBuffer()
{
if (window()->format().swapBehavior() == QSurfaceFormat::SingleBuffer)
return;
// The current back buffer may have been assigned to a layer in a previous flush,
// but we deferred the swap. Do it now if the surface has been picked up by CA.
if (m_buffers.back() && m_buffers.back()->isInUse() && m_buffers.back() != m_buffers.front()) {
qCInfo(lcQpaBackingStore) << "Back buffer has been picked up by CA, swapping to front";
std::swap(m_buffers.back(), m_buffers.front());
}
if (Q_UNLIKELY(lcQpaBackingStore().isDebugEnabled())) {
// ┌───────┬───────┬───────┬─────┬──────┐
// │ front ┊ spare ┊ spare ┊ ... ┊ back │
// └───────┴───────┴───────┴─────┴──────┘
for (const auto &buffer : m_buffers) {
qCDebug(lcQpaBackingStore).nospace() << " "
<< (buffer == m_buffers.front() ? "front" :
buffer == m_buffers.back() ? " back" :
"spare"
) << ": " << buffer.get();
}
}
// Ensure our back buffer is ready to draw into. If not, find a buffer that
// is not in use, or reserve space for a new buffer if none can be found.
for (auto &buffer : backwards(m_buffers)) {
if (!buffer || !buffer->isInUse()) {
// Buffer is okey to use, swap if necessary
if (buffer != m_buffers.back())
std::swap(buffer, m_buffers.back());
qCDebug(lcQpaBackingStore) << "Using back buffer" << m_buffers.back().get();
static const int kMaxSwapChainDepth = 3;
if (m_buffers.size() > kMaxSwapChainDepth) {
qCDebug(lcQpaBackingStore) << "Reducing swap chain depth to" << kMaxSwapChainDepth;
m_buffers.erase(std::next(m_buffers.begin(), 1), std::prev(m_buffers.end(), 2));
}
break;
} else if (buffer == m_buffers.front()) {
// We've exhausted the available buffers, make room for a new one
const int swapChainDepth = m_buffers.size() + 1;
qCDebug(lcQpaBackingStore) << "Available buffers exhausted, increasing swap chain depth to" << swapChainDepth;
m_buffers.resize(swapChainDepth);
break;
}
}
Q_ASSERT(!m_buffers.back() || !m_buffers.back()->isInUse());
}
// Disabled until performance issue on 5K iMac Pro has been investigated further,
// as rounding up during resize will typically result in full screen buffer sizes
// and low frame rate also for smaller window sizes.
#define USE_LAZY_BUFFER_ALLOCATION_DURING_LIVE_WINDOW_RESIZE 0
bool QCALayerBackingStore::recreateBackBufferIfNeeded()
{
const qreal devicePixelRatio = window()->devicePixelRatio();
QSize requestedBufferSize = m_requestedSize * devicePixelRatio;
const NSView *backingStoreView = static_cast<QCocoaWindow *>(window()->handle())->view();
Q_UNUSED(backingStoreView);
auto bufferSizeMismatch = [&](const QSize requested, const QSize actual) {
#if USE_LAZY_BUFFER_ALLOCATION_DURING_LIVE_WINDOW_RESIZE
if (backingStoreView.inLiveResize) {
// Prevent over-eager buffer allocation during window resize by reusing larger buffers
return requested.width() > actual.width() || requested.height() > actual.height();
}
#endif
return requested != actual;
};
if (!m_buffers.back() || bufferSizeMismatch(requestedBufferSize, m_buffers.back()->size())) {
#if USE_LAZY_BUFFER_ALLOCATION_DURING_LIVE_WINDOW_RESIZE
if (backingStoreView.inLiveResize) {
// Prevent over-eager buffer allocation during window resize by rounding up
QSize nativeScreenSize = window()->screen()->geometry().size() * devicePixelRatio;
requestedBufferSize = QSize(qNextPowerOfTwo(requestedBufferSize.width()),
qNextPowerOfTwo(requestedBufferSize.height())).boundedTo(nativeScreenSize);
}
#endif
qCInfo(lcQpaBackingStore) << "Creating surface of" << requestedBufferSize
<< "based on requested" << m_requestedSize << "and dpr =" << devicePixelRatio;
static auto pixelFormat = QImage::toPixelFormat(QImage::Format_ARGB32_Premultiplied);
NSView *view = static_cast<QCocoaWindow *>(window()->handle())->view();
auto colorSpace = QCFType<CGColorSpaceRef>::constructFromGet(view.window.screen.colorSpace.CGColorSpace);
m_buffers.back().reset(new GraphicsBuffer(requestedBufferSize, devicePixelRatio, pixelFormat, colorSpace));
return true;
}
return false;
}
QPaintDevice *QCALayerBackingStore::paintDevice()
{
Q_ASSERT(m_buffers.back());
return m_buffers.back()->asImage();
}
void QCALayerBackingStore::endPaint()
{
qCInfo(lcQpaBackingStore) << "Paint ended with painted region" << m_paintedRegion;
m_buffers.back()->unlock();
}
void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion &region, const QPoint &offset)
{
Q_UNUSED(region);
Q_UNUSED(offset);
if (!prepareForFlush())
return;
QMacAutoReleasePool pool;
NSView *backingStoreView = static_cast<QCocoaWindow *>(window()->handle())->view();
NSView *flushedView = static_cast<QCocoaWindow *>(flushedWindow->handle())->view();
id backBufferSurface = (__bridge id)m_buffers.back()->surface();
if (flushedView.layer.contents == backBufferSurface) {
// We've managed to paint to the back buffer again before Core Animation had time
// to flush the transaction and persist the layer changes to the window server.
// The layer already knows about the back buffer, and we don't need to re-apply
// it to pick up the surface changes, so bail out early.
qCInfo(lcQpaBackingStore).nospace() << "Skipping flush of " << flushedView
<< ", layer already reflects back buffer";
return;
}
// Trigger a new display cycle if there isn't one. This ensures that our layer updates
// are committed as part of a display-cycle instead of on the next runloop pass. This
// means CA won't try to throttle us if we flush too fast, and we'll coalesce our flush
// with other pending view and layer updates.
backingStoreView.window.viewsNeedDisplay = YES;
if (window()->format().swapBehavior() == QSurfaceFormat::SingleBuffer) {
// The private API [CALayer reloadValueForKeyPath:@"contents"] would be preferable,
// but barring any side effects or performance issues we opt for the hammer for now.
flushedView.layer.contents = nil;
}
qCInfo(lcQpaBackingStore) << "Flushing" << backBufferSurface
<< "to" << flushedView.layer << "of" << flushedView;
flushedView.layer.contents = backBufferSurface;
if (flushedView != backingStoreView) {
const CGSize backingStoreSize = backingStoreView.bounds.size;
flushedView.layer.contentsRect = CGRectApplyAffineTransform(
[flushedView convertRect:flushedView.bounds toView:backingStoreView],
// The contentsRect is in unit coordinate system
CGAffineTransformMakeScale(1.0 / backingStoreSize.width, 1.0 / backingStoreSize.height));
}
// Since we may receive multiple flushes before a new frame is started, we do not
// swap any buffers just yet. Instead we check in the next beginPaint if the layer's
// surface is in use, and if so swap to an unused surface as the new back buffer.
// Note: Ideally CoreAnimation would mark a surface as in use the moment we assign
// it to a layer, but as that's not the case we may end up painting to the same back
// buffer once more if we are painting faster than CA can ship the surfaces over to
// the window server.
}
void QCALayerBackingStore::composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
QPlatformTextureList *textures, bool translucentBackground)
{
if (!prepareForFlush())
return;
QPlatformBackingStore::composeAndFlush(window, region, offset, textures, translucentBackground);
}
QPlatformGraphicsBuffer *QCALayerBackingStore::graphicsBuffer() const
{
return m_buffers.back().get();
}
bool QCALayerBackingStore::prepareForFlush()
{
if (!m_buffers.back()) {
qCWarning(lcQpaBackingStore) << "Tried to flush backingstore without painting to it first";
return false;
}
// Update dirty state of buffers based on what was painted. The back buffer will be
// less dirty, since we painted to it, while other buffers will become more dirty.
// This allows us to minimize copies between front and back buffers on swap in the
// cases where the painted region overlaps with the previous frame (front buffer).
for (const auto &buffer : m_buffers) {
if (buffer == m_buffers.back())
buffer->dirtyRegion -= m_paintedRegion;
else
buffer->dirtyRegion += m_paintedRegion;
}
// After painting, the back buffer is only guaranteed to have content for the painted
// region, and may still have dirty areas that need to be synced up with the front buffer,
// if we have one. We know that the front buffer is always up to date.
if (!m_buffers.back()->dirtyRegion.isEmpty() && m_buffers.front() != m_buffers.back()) {
QRegion preserveRegion = m_buffers.back()->dirtyRegion;
qCDebug(lcQpaBackingStore) << "Preserving" << preserveRegion << "from front to back buffer";
m_buffers.front()->lock(QPlatformGraphicsBuffer::SWReadAccess);
const QImage *frontBuffer = m_buffers.front()->asImage();
const QRect frontSurfaceBounds(QPoint(0, 0), m_buffers.front()->size());
const qreal sourceDevicePixelRatio = frontBuffer->devicePixelRatio();
m_buffers.back()->lock(QPlatformGraphicsBuffer::SWWriteAccess);
QPainter painter(m_buffers.back()->asImage());
painter.setCompositionMode(QPainter::CompositionMode_Source);
// Let painter operate in device pixels, to make it easier to compare coordinates
const qreal targetDevicePixelRatio = painter.device()->devicePixelRatio();
painter.scale(1.0 / targetDevicePixelRatio, 1.0 / targetDevicePixelRatio);
for (const QRect &rect : preserveRegion) {
QRect sourceRect(rect.topLeft() * sourceDevicePixelRatio, rect.size() * sourceDevicePixelRatio);
QRect targetRect(rect.topLeft() * targetDevicePixelRatio, rect.size() * targetDevicePixelRatio);
#ifdef QT_DEBUG
if (Q_UNLIKELY(!frontSurfaceBounds.contains(sourceRect.bottomRight()))) {
qCWarning(lcQpaBackingStore) << "Front buffer too small to preserve"
<< QRegion(sourceRect).subtracted(frontSurfaceBounds);
}
#endif
painter.drawImage(targetRect, *frontBuffer, sourceRect);
}
m_buffers.back()->unlock();
m_buffers.front()->unlock();
// The back buffer is now completely in sync, ready to be presented
m_buffers.back()->dirtyRegion = QRegion();
}
// Prepare for another round of painting
m_paintedRegion = QRegion();
return true;
}
// ----------------------------------------------------------------------------
QCALayerBackingStore::GraphicsBuffer::GraphicsBuffer(const QSize &size, qreal devicePixelRatio,
const QPixelFormat &format, QCFType<CGColorSpaceRef> colorSpace)
: QIOSurfaceGraphicsBuffer(size, format, colorSpace)
, dirtyRegion(0, 0, size.width() / devicePixelRatio, size.height() / devicePixelRatio)
, m_devicePixelRatio(devicePixelRatio)
{
}
QImage *QCALayerBackingStore::GraphicsBuffer::asImage()
{
if (m_image.isNull()) {
qCDebug(lcQpaBackingStore) << "Setting up paint device for" << this;
CFRetain(surface());
m_image = QImage(data(), size().width(), size().height(),
bytesPerLine(), QImage::toImageFormat(format()),
QImageCleanupFunction(CFRelease), surface());
m_image.setDevicePixelRatio(m_devicePixelRatio);
}
Q_ASSERT_X(m_image.constBits() == data(), "QCALayerBackingStore",
"IOSurfaces should have have a fixed location in memory once created");
return &m_image;
}
QT_END_NAMESPACE

View File

@ -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

View 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

View 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

View File

@ -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;

View File

@ -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

View File

@ -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()

View File

@ -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

View File

@ -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();

View File

@ -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();

View File

@ -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 {

View File

@ -310,7 +310,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()

View File

@ -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

View File

@ -49,6 +49,7 @@
#include <QCoreApplication>
#include <QFileInfo>
#include <qpa/qplatformwindow.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtEventDispatcherSupport/private/qgenericunixeventdispatcher_p.h>
#include <Application.h>
@ -81,12 +82,12 @@ QHaikuIntegration::QHaikuIntegration(const QStringList &parameters)
m_services = new QHaikuServices;
// notify system about available screen
screenAdded(m_screen);
QWindowSystemInterface::handleScreenAdded(m_screen);
}
QHaikuIntegration::~QHaikuIntegration()
{
destroyScreen(m_screen);
QWindowSystemInterface::handleScreenRemoved(m_screen);
m_screen = nullptr;
delete m_services;

View File

@ -51,7 +51,7 @@
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatforminputcontextfactory_p.h>
#include <qpa/qwindowsysteminterface.h>
QT_BEGIN_NAMESPACE
@ -64,13 +64,13 @@ QIntegrityFbIntegration::QIntegrityFbIntegration(const QStringList &paramList)
QIntegrityFbIntegration::~QIntegrityFbIntegration()
{
destroyScreen(m_primaryScreen);
QWindowSystemInterface::handleScreenRemoved(m_primaryScreen);
}
void QIntegrityFbIntegration::initialize()
{
if (m_primaryScreen->initialize())
screenAdded(m_primaryScreen);
QWindowSystemInterface::handleScreenAdded(m_primaryScreen);
else
qWarning("integrityfb: Failed to initialize screen");

View File

@ -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();

View File

@ -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;

View File

@ -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

View File

@ -54,6 +54,7 @@
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatforminputcontextfactory_p.h>
#include <qpa/qwindowsysteminterface.h>
#if QT_CONFIG(libinput)
#include <QtInputSupport/private/qlibinputhandler_p.h>
@ -89,13 +90,13 @@ QLinuxFbIntegration::QLinuxFbIntegration(const QStringList &paramList)
QLinuxFbIntegration::~QLinuxFbIntegration()
{
destroyScreen(m_primaryScreen);
QWindowSystemInterface::handleScreenRemoved(m_primaryScreen);
}
void QLinuxFbIntegration::initialize()
{
if (m_primaryScreen->initialize())
screenAdded(m_primaryScreen);
QWindowSystemInterface::handleScreenAdded(m_primaryScreen);
else
qWarning("linuxfb: Failed to initialize screen");

View File

@ -43,6 +43,7 @@
#include <QtGui/private/qpixmap_raster_p.h>
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformwindow.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtFontDatabaseSupport/private/qfreetypefontdatabase_p.h>
#if defined(Q_OS_WINRT)
@ -108,7 +109,7 @@ QMinimalIntegration::QMinimalIntegration(const QStringList &parameters)
mPrimaryScreen->mDepth = 32;
mPrimaryScreen->mFormat = QImage::Format_ARGB32_Premultiplied;
screenAdded(mPrimaryScreen);
QWindowSystemInterface::handleScreenAdded(mPrimaryScreen);
}
QMinimalIntegration::~QMinimalIntegration()

View File

@ -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;
}

View File

@ -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()

View File

@ -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);
}

View File

@ -68,8 +68,6 @@ public:
QPlatformPrinterSupport *printerSupport() const;
void addScreen(QOpenWFDScreen *screen);
void destroyScreen(QOpenWFDScreen *screen);
private:
QList<QPlatformScreen *> mScreens;
QList<QOpenWFDDevice *>mDevices;

View File

@ -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;

View File

@ -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();
}

View File

@ -52,6 +52,7 @@
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatforminputcontextfactory_p.h>
#include <private/qinputdevicemanager_p_p.h>
#include <qpa/qwindowsysteminterface.h>
#include <QtCore/QRegularExpression>
@ -77,13 +78,13 @@ QVncIntegration::QVncIntegration(const QStringList &paramList)
QVncIntegration::~QVncIntegration()
{
delete m_server;
destroyScreen(m_primaryScreen);
QWindowSystemInterface::handleScreenRemoved(m_primaryScreen);
}
void QVncIntegration::initialize()
{
if (m_primaryScreen->initialize())
screenAdded(m_primaryScreen);
QWindowSystemInterface::handleScreenAdded(m_primaryScreen);
else
qWarning("vnc: Failed to initialize screen");

View File

@ -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;
}
@ -113,7 +116,7 @@ bool QWasmIntegration::hasCapability(QPlatformIntegration::Capability cap) const
switch (cap) {
case ThreadedPixmaps: return true;
case OpenGL: return true;
case ThreadedOpenGL: return true;
case ThreadedOpenGL: return false;
case RasterGLSurface: return false; // to enable this you need to fix qopenglwidget and quickwidget for wasm
case MultipleWindows: return true;
case WindowManagement: return true;
@ -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

View File

@ -27,9 +27,9 @@
<script type='text/javascript'>
function init() {
var spinner = document.getElementById('qtspinner');
var canvas = document.getElementById('qtcanvas');
var status = document.getElementById('qtstatus')
var spinner = document.querySelector('#qtspinner');
var canvas = document.querySelector('#qtcanvas');
var status = document.querySelector('#qtstatus')
var qtLoader = QtLoader({
canvasElements : [canvas],

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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();
}

View File

@ -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),

View File

@ -192,6 +192,10 @@ bool QXcbNativeBackingStore::scroll(const QRegion &area, int dx, int dy)
void QXcbNativeBackingStore::beginPaint(const QRegion &region)
{
QX11PlatformPixmap *x11pm = qt_x11Pixmap(m_pixmap);
if (x11pm)
x11pm->setIsBackingStore(true);
#if QT_CONFIG(xrender)
if (m_translucentBackground) {
const QVector<XRectangle> xrects = qt_region_to_xrectangles(region);

View File

@ -200,6 +200,7 @@ public:
uint has_pattern : 1;
uint has_alpha_pen : 1;
uint has_alpha_brush : 1;
uint use_sysclip : 1;
uint render_hints;
const QXcbX11Info *xinfo;
@ -701,6 +702,9 @@ bool QX11PaintEngine::begin(QPaintDevice *pdev)
d->xlibMaxLinePoints = 32762; // a safe number used to avoid, call to XMaxRequestSize(d->dpy) - 3;
d->opacity = 1;
QX11PlatformPixmap *x11pm = paintDevice()->devType() == QInternal::Pixmap ? qt_x11Pixmap(*static_cast<QPixmap *>(paintDevice())) : nullptr;
d->use_sysclip = paintDevice()->devType() == QInternal::Widget || (x11pm ? x11pm->isBackingStore() : false);
// Set up the polygon clipper. Note: This will only work in
// polyline mode as long as we have a buffer zone, since a
// polyline may be clipped into several non-connected polylines.
@ -1472,7 +1476,7 @@ void QX11PaintEngine::updatePen(const QPen &pen)
}
if (!d->has_clipping) { // if clipping is set the paintevent clip region is merged with the clip region
QRegion sysClip = systemClip();
QRegion sysClip = d->use_sysclip ? systemClip() : QRegion();
if (!sysClip.isEmpty())
x11SetClipRegion(d->dpy, d->gc, 0, d->picture, sysClip);
else
@ -1603,7 +1607,7 @@ void QX11PaintEngine::updateBrush(const QBrush &brush, const QPointF &origin)
vals.fill_style = s;
XChangeGC(d->dpy, d->gc_brush, mask, &vals);
if (!d->has_clipping) {
QRegion sysClip = systemClip();
QRegion sysClip = d->use_sysclip ? systemClip() : QRegion();
if (!sysClip.isEmpty())
x11SetClipRegion(d->dpy, d->gc_brush, 0, d->picture, sysClip);
else
@ -2223,7 +2227,7 @@ void QX11PaintEngine::updateMatrix(const QTransform &mtx)
void QX11PaintEngine::updateClipRegion_dev(const QRegion &clipRegion, Qt::ClipOperation op)
{
Q_D(QX11PaintEngine);
QRegion sysClip = systemClip();
QRegion sysClip = d->use_sysclip ? systemClip() : QRegion();
if (op == Qt::NoClip) {
d->has_clipping = false;
d->crgn = sysClip;

View File

@ -1772,6 +1772,20 @@ XID QX11PlatformPixmap::createBitmapFromImage(const QImage &image)
return hd;
}
bool QX11PlatformPixmap::isBackingStore() const
{
return (flags & IsBackingStore);
}
void QX11PlatformPixmap::setIsBackingStore(bool on)
{
if (on)
flags |= IsBackingStore;
else {
flags &= ~IsBackingStore;
}
}
#if QT_CONFIG(xrender)
void QX11PlatformPixmap::convertToARGB32(bool preserveContents)
{

View File

@ -90,6 +90,8 @@ public:
void convertToARGB32(bool preserveContents = true);
#endif
bool isBackingStore() const;
void setIsBackingStore(bool on);
private:
friend class QX11PaintEngine;
friend const QXcbX11Info &qt_x11Info(const QPixmap &pixmap);
@ -110,7 +112,8 @@ private:
Uninitialized = 0x1,
Readonly = 0x2,
InvertedWhenBoundToTexture = 0x4,
GlSurfaceCreatedWithAlpha = 0x8
GlSurfaceCreatedWithAlpha = 0x8,
IsBackingStore = 0x10
};
uint flags;

View File

@ -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();

View File

@ -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:

View File

@ -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();

View File

@ -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;

View File

@ -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)

View File

@ -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");

View File

@ -70,10 +70,10 @@ public:
void setVisible(bool visible) override;
#if QT_DEPRECATED_SINCE(5, 13)
QT_DEPRECATED void setOrientation(Qt::Orientation orientation);
QT_DEPRECATED Qt::Orientation orientation() const;
QT_DEPRECATED void setExtension(QWidget* extension);
QT_DEPRECATED QWidget* extension() const;
QT_DEPRECATED_X("Use show/hide on the affected widget instead") void setOrientation(Qt::Orientation orientation);
QT_DEPRECATED_X("Use show/hide on the affected widget instead") Qt::Orientation orientation() const;
QT_DEPRECATED_X("Use show/hide on the affected widget instead") void setExtension(QWidget* extension);
QT_DEPRECATED_X("Use show/hide on the affected widget instead") QWidget* extension() const;
#endif
QSize sizeHint() const override;
@ -98,7 +98,7 @@ public Q_SLOTS:
virtual void reject();
#if QT_DEPRECATED_SINCE(5, 13)
QT_DEPRECATED void showExtension(bool);
QT_DEPRECATED_X("Use show/hide on the affected widget instead") void showExtension(bool);
#endif
protected:

View File

@ -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)) {

View File

@ -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);
}

View File

@ -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

View File

@ -67,18 +67,21 @@ extern QString qt_setWindowTitle_helperHelper(const QString&, const QWidget*); /
// qmainwindow.cpp
extern QMainWindowLayout *qt_mainwindow_layout(const QMainWindow *window);
static inline QMainWindowLayout *qt_mainwindow_layout_from_dock(const QDockWidget *dock)
static const QMainWindow *mainwindow_from_dock(const QDockWidget *dock)
{
const QWidget *p = dock->parentWidget();
while (p) {
const QMainWindow *window = qobject_cast<const QMainWindow*>(p);
if (window)
return qt_mainwindow_layout(window);
p = p->parentWidget();
for (const QWidget *p = dock->parentWidget(); p; p = p->parentWidget()) {
if (const QMainWindow *window = qobject_cast<const QMainWindow*>(p))
return window;
}
return nullptr;
}
static inline QMainWindowLayout *qt_mainwindow_layout_from_dock(const QDockWidget *dock)
{
auto mainWindow = mainwindow_from_dock(dock);
return mainWindow ? qt_mainwindow_layout(mainWindow) : nullptr;
}
static inline bool hasFeature(const QDockWidgetPrivate *priv, QDockWidget::DockWidgetFeature feature)
{ return (priv->features & feature) == feature; }
@ -839,8 +842,9 @@ void QDockWidgetPrivate::endDrag(bool abort)
q->releaseMouse();
if (state->dragging) {
QMainWindowLayout *mwLayout = qt_mainwindow_layout_from_dock(q);
Q_ASSERT(mwLayout != 0);
const QMainWindow *mainWindow = mainwindow_from_dock(q);
Q_ASSERT(mainWindow != nullptr);
QMainWindowLayout *mwLayout = qt_mainwindow_layout(mainWindow);
if (abort || !mwLayout->plug(state->widgetItem)) {
if (hasFeature(this, QDockWidget::DockWidgetFloatable)) {
@ -861,8 +865,12 @@ void QDockWidgetPrivate::endDrag(bool abort)
} else {
setResizerActive(false);
}
if (q->isFloating()) // Might not be floating when dragging a QDockWidgetGroupWindow
if (q->isFloating()) { // Might not be floating when dragging a QDockWidgetGroupWindow
undockedGeometry = q->geometry();
#if QT_CONFIG(tabwidget)
tabPosition = mwLayout->tabPosition(mainWindow->dockWidgetArea(q));
#endif
}
q->activateWindow();
} else {
// The tab was not plugged back in the QMainWindow but the QDockWidget cannot

View File

@ -57,6 +57,10 @@
#include "QtWidgets/qboxlayout.h"
#include "QtWidgets/qdockwidget.h"
#if QT_CONFIG(tabwidget)
# include "QtWidgets/qtabwidget.h"
#endif
QT_REQUIRE_CONFIG(dockwidget);
QT_BEGIN_NAMESPACE
@ -81,28 +85,26 @@ class QDockWidgetPrivate : public QWidgetPrivate
};
public:
inline QDockWidgetPrivate()
: QWidgetPrivate(), state(nullptr),
features(QDockWidget::DockWidgetClosable
| QDockWidget::DockWidgetMovable
| QDockWidget::DockWidgetFloatable),
allowedAreas(Qt::AllDockWidgetAreas), resizer(nullptr)
{ }
void init();
void _q_toggleView(bool); // private slot
void _q_toggleTopLevel(); // private slot
void updateButtons();
DragState *state;
QDockWidget::DockWidgetFeatures features;
Qt::DockWidgetAreas allowedAreas;
#if QT_CONFIG(tabwidget)
QTabWidget::TabPosition tabPosition = QTabWidget::North;
#endif
DragState *state = nullptr;
QDockWidget::DockWidgetFeatures features = QDockWidget::DockWidgetClosable
| QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable;
Qt::DockWidgetAreas allowedAreas = Qt::AllDockWidgetAreas;
QFont font;
#ifndef QT_NO_ACTION
QAction *toggleViewAction;
QAction *toggleViewAction = nullptr;
#endif
// QMainWindow *findMainWindow(QWidget *widget) const;
@ -129,7 +131,7 @@ public:
bool isAnimating() const;
private:
QWidgetResizeHandler *resizer;
QWidgetResizeHandler *resizer = nullptr;
};
class Q_WIDGETS_EXPORT QDockWidgetLayout : public QLayout

View File

@ -2525,6 +2525,30 @@ void QMainWindowLayout::updateGapIndicator()
#endif // QT_CONFIG(rubberband)
}
static QTabBar::Shape tabwidgetPositionToTabBarShape(QWidget *w)
{
QTabBar::Shape result = QTabBar::RoundedSouth;
#if QT_CONFIG(tabwidget)
if (qobject_cast<QDockWidget *>(w)) {
switch (static_cast<QDockWidgetPrivate *>(qt_widget_private(w))->tabPosition) {
case QTabWidget::North:
result = QTabBar::RoundedNorth;
break;
case QTabWidget::South:
result = QTabBar::RoundedSouth;
break;
case QTabWidget::West:
result = QTabBar::RoundedWest;
break;
case QTabWidget::East:
result = QTabBar::RoundedEast;
break;
}
}
#endif // tabwidget
return result;
}
void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
{
if (!parentWidget()->isVisible() || parentWidget()->isMinimized()
@ -2573,8 +2597,9 @@ void QMainWindowLayout::hover(QLayoutItem *widgetItem, const QPoint &mousePos)
QDockWidgetGroupWindow *floatingTabs = createTabbedDockWindow(); // FIXME
floatingTabs->setGeometry(dropTo->geometry());
QDockAreaLayoutInfo *info = floatingTabs->layoutInfo();
const QTabBar::Shape shape = tabwidgetPositionToTabBarShape(dropTo);
*info = QDockAreaLayoutInfo(&layoutState.dockAreaLayout.sep, QInternal::LeftDock,
Qt::Horizontal, QTabBar::RoundedSouth,
Qt::Horizontal, shape,
static_cast<QMainWindow *>(parentWidget()));
info->tabbed = true;
QLayout *parentLayout = dropTo->parentWidget()->layout();

View File

@ -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)

View File

@ -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

View File

@ -0,0 +1,5 @@
[remainingTime]
windows
osx
[basic_chrono]
osx

View File

@ -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);

View File

@ -1,5 +1,6 @@
[]
rhel-7.4
rhel-7.6
ubuntu-18.04
[customGesture]
# QTBUG-67254

View File

@ -67,7 +67,9 @@ static QString targetName( BuildType buildMode, const QString& target, const QSt
break;
case Dll: // dll
targetName.prepend("lib");
targetName.append("." + version + ".dylib");
if (!version.isEmpty())
targetName.append('.' + version);
targetName.append(".dylib");
break;
case Lib: // lib
targetName.prepend("lib");

Some files were not shown because too many files have changed in this diff Show More