summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiang Qi <liang.qi@qt.io>2019-04-24 09:52:30 +0200
committerLiang Qi <liang.qi@qt.io>2019-04-24 09:52:30 +0200
commitdc373186841802f2dd17fcd243efdeca7d5433e9 (patch)
tree4fff0a3366b63db97ca5a8b04a220bb0b8c56450 /src
parent7d646508c8219408f90103ed13613db8d01a4065 (diff)
parentcb10ec56f733c34d23c9e5511b19c1e508d0f13f (diff)
Merge remote-tracking branch 'origin/5.13' into dev
Conflicts: src/gui/util/qshaderformat.cpp src/gui/util/qshaderformat_p.h src/widgets/graphicsview/qgraphicsitem_p.h Change-Id: Idafd88eb9a0a15b4af29f6143d009c1ec8ceecca
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/angle/src/libANGLE/Display.cpp17
-rw-r--r--src/3rdparty/angle/src/libANGLE/Display.h1
-rw-r--r--src/3rdparty/angle/src/libGLESv2/global_state.cpp2
-rw-r--r--src/angle/patches/0013-ANGLE-clean-up-displays-on-dll-unload.patch78
-rw-r--r--src/corelib/global/qglobal_p.h3
-rw-r--r--src/corelib/io/qfilesystemengine_win.cpp13
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp2
-rw-r--r--src/corelib/kernel/qobjectdefs.h4
-rw-r--r--src/corelib/tools/qdatetime.cpp3
-rw-r--r--src/corelib/tools/qdatetime.h2
-rw-r--r--src/corelib/tools/qlocale.cpp11
-rw-r--r--src/corelib/tools/qlocale.qdoc2
-rw-r--r--src/gui/kernel/qoffscreensurface.cpp8
-rw-r--r--src/gui/painting/qcoregraphics.mm158
-rw-r--r--src/gui/painting/qcoregraphics_p.h36
-rw-r--r--src/gui/util/qshaderformat.cpp17
-rw-r--r--src/gui/util/qshaderformat_p.h13
-rw-r--r--src/gui/util/qshadergenerator.cpp67
-rw-r--r--src/gui/util/qshadernodesloader.cpp11
-rw-r--r--src/network/kernel/qhostaddress.cpp4
-rw-r--r--src/platformsupport/eglconvenience/qeglconvenience.cpp2
-rw-r--r--src/platformsupport/eglconvenience/qeglplatformcontext.cpp8
-rw-r--r--src/platformsupport/glxconvenience/glxconvenience.pro2
-rw-r--r--src/platformsupport/input/tslib/qtslib.cpp4
-rw-r--r--src/platformsupport/kmsconvenience/qkmsdevice.cpp8
-rw-r--r--src/platformsupport/platformcompositor/qopenglcompositor.cpp13
-rw-r--r--src/plugins/bearer/generic/qgenericengine.cpp2
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.h1
-rw-r--r--src/plugins/platforms/cocoa/qcocoabackingstore.mm23
-rw-r--r--src/plugins/platforms/cocoa/qnsview_drawing.mm1
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfsintegration.cpp4
-rw-r--r--src/plugins/platforms/eglfs/api/qeglfswindow.cpp3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h3
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp2
-rw-r--r--src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp3
-rw-r--r--src/plugins/platforms/windows/qwindowsdropdataobject.cpp22
-rw-r--r--src/plugins/platforms/windows/qwindowskeymapper.cpp20
-rw-r--r--src/plugins/platforms/windows/qwindowsmime.cpp5
-rw-r--r--src/plugins/platforms/windows/qwindowspointerhandler.cpp35
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp3
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp37
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h1
-rw-r--r--src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp4
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm71
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp11
-rw-r--r--src/widgets/graphicsview/qgraphicsitem_p.h2
-rw-r--r--src/widgets/graphicsview/qgraphicsscene.cpp2
-rw-r--r--src/widgets/itemviews/qheaderview.cpp16
-rw-r--r--src/widgets/itemviews/qlistwidget.cpp8
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp3
-rw-r--r--src/widgets/styles/qstylesheetstyle.cpp5
-rw-r--r--src/widgets/util/qsystemtrayicon_p.h4
-rw-r--r--src/widgets/util/qsystemtrayicon_x11.cpp75
-rw-r--r--src/widgets/widgets/qplaintextedit.cpp16
-rw-r--r--src/widgets/widgets/qtextedit.cpp23
55 files changed, 619 insertions, 275 deletions
diff --git a/src/3rdparty/angle/src/libANGLE/Display.cpp b/src/3rdparty/angle/src/libANGLE/Display.cpp
index 735b472787..0bb0bb05b1 100644
--- a/src/3rdparty/angle/src/libANGLE/Display.cpp
+++ b/src/3rdparty/angle/src/libANGLE/Display.cpp
@@ -364,6 +364,23 @@ Display *Display::GetDisplayFromDevice(Device *device, const AttributeMap &attri
return display;
}
+//static
+void Display::CleanupDisplays()
+{
+ // ~Display takes care of removing the entry from the according map
+ {
+ ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
+ while (!displays->empty())
+ delete displays->begin()->second;
+ }
+
+ {
+ DevicePlatformDisplayMap *displays = GetDevicePlatformDisplayMap();
+ while (!displays->empty())
+ delete displays->begin()->second;
+ }
+}
+
Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
: mImplementation(nullptr),
mDisplayId(displayId),
diff --git a/src/3rdparty/angle/src/libANGLE/Display.h b/src/3rdparty/angle/src/libANGLE/Display.h
index aa1d1c3b37..2a1c386d75 100644
--- a/src/3rdparty/angle/src/libANGLE/Display.h
+++ b/src/3rdparty/angle/src/libANGLE/Display.h
@@ -65,6 +65,7 @@ class Display final : angle::NonCopyable
static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap);
static Display *GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
const AttributeMap &attribMap);
+ static void CleanupDisplays();
static const ClientExtensions &GetClientExtensions();
static const std::string &GetClientExtensionString();
diff --git a/src/3rdparty/angle/src/libGLESv2/global_state.cpp b/src/3rdparty/angle/src/libGLESv2/global_state.cpp
index c5f3dfe4e1..26045bf5b2 100644
--- a/src/3rdparty/angle/src/libGLESv2/global_state.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/global_state.cpp
@@ -13,6 +13,7 @@
#include "common/tls.h"
#include "libANGLE/Thread.h"
+#include "libANGLE/Display.h"
namespace gl
{
@@ -140,6 +141,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID)
return static_cast<BOOL>(egl::DeallocateCurrentThread());
case DLL_PROCESS_DETACH:
+ egl::Display::CleanupDisplays();
return static_cast<BOOL>(egl::TerminateProcess());
}
diff --git a/src/angle/patches/0013-ANGLE-clean-up-displays-on-dll-unload.patch b/src/angle/patches/0013-ANGLE-clean-up-displays-on-dll-unload.patch
new file mode 100644
index 0000000000..fce3fd76b2
--- /dev/null
+++ b/src/angle/patches/0013-ANGLE-clean-up-displays-on-dll-unload.patch
@@ -0,0 +1,78 @@
+From d8ca4f6d0d8fffd8319f340685e03751049678ae Mon Sep 17 00:00:00 2001
+From: Oliver Wolff <oliver.wolff@qt.io>
+Date: Tue, 16 Apr 2019 10:19:27 +0200
+Subject: [PATCH] ANGLE: clean up displays on dll unload
+
+If the displays are not cleaned up on dll unloading, profilers might
+report memory leaks.
+
+Change-Id: I04cbc3c2448bfb450f7d840e216827f86856e963
+---
+ src/3rdparty/angle/src/libANGLE/Display.cpp | 17 +++++++++++++++++
+ src/3rdparty/angle/src/libANGLE/Display.h | 1 +
+ .../angle/src/libGLESv2/global_state.cpp | 2 ++
+ 3 files changed, 20 insertions(+)
+
+diff --git a/src/3rdparty/angle/src/libANGLE/Display.cpp b/src/3rdparty/angle/src/libANGLE/Display.cpp
+index 735b472787..0bb0bb05b1 100644
+--- a/src/3rdparty/angle/src/libANGLE/Display.cpp
++++ b/src/3rdparty/angle/src/libANGLE/Display.cpp
+@@ -364,6 +364,23 @@ Display *Display::GetDisplayFromDevice(Device *device, const AttributeMap &attri
+ return display;
+ }
+
++//static
++void Display::CleanupDisplays()
++{
++ // ~Display takes care of removing the entry from the according map
++ {
++ ANGLEPlatformDisplayMap *displays = GetANGLEPlatformDisplayMap();
++ while (!displays->empty())
++ delete displays->begin()->second;
++ }
++
++ {
++ DevicePlatformDisplayMap *displays = GetDevicePlatformDisplayMap();
++ while (!displays->empty())
++ delete displays->begin()->second;
++ }
++}
++
+ Display::Display(EGLenum platform, EGLNativeDisplayType displayId, Device *eglDevice)
+ : mImplementation(nullptr),
+ mDisplayId(displayId),
+diff --git a/src/3rdparty/angle/src/libANGLE/Display.h b/src/3rdparty/angle/src/libANGLE/Display.h
+index aa1d1c3b37..2a1c386d75 100644
+--- a/src/3rdparty/angle/src/libANGLE/Display.h
++++ b/src/3rdparty/angle/src/libANGLE/Display.h
+@@ -65,6 +65,7 @@ class Display final : angle::NonCopyable
+ static Display *GetDisplayFromDevice(Device *device, const AttributeMap &attribMap);
+ static Display *GetDisplayFromNativeDisplay(EGLNativeDisplayType nativeDisplay,
+ const AttributeMap &attribMap);
++ static void CleanupDisplays();
+
+ static const ClientExtensions &GetClientExtensions();
+ static const std::string &GetClientExtensionString();
+diff --git a/src/3rdparty/angle/src/libGLESv2/global_state.cpp b/src/3rdparty/angle/src/libGLESv2/global_state.cpp
+index c5f3dfe4e1..26045bf5b2 100644
+--- a/src/3rdparty/angle/src/libGLESv2/global_state.cpp
++++ b/src/3rdparty/angle/src/libGLESv2/global_state.cpp
+@@ -13,6 +13,7 @@
+ #include "common/tls.h"
+
+ #include "libANGLE/Thread.h"
++#include "libANGLE/Display.h"
+
+ namespace gl
+ {
+@@ -140,6 +141,7 @@ extern "C" BOOL WINAPI DllMain(HINSTANCE, DWORD reason, LPVOID)
+ return static_cast<BOOL>(egl::DeallocateCurrentThread());
+
+ case DLL_PROCESS_DETACH:
++ egl::Display::CleanupDisplays();
+ return static_cast<BOOL>(egl::TerminateProcess());
+ }
+
+--
+2.20.1.windows.1
+
diff --git a/src/corelib/global/qglobal_p.h b/src/corelib/global/qglobal_p.h
index d52f6268e4..58bc8b7bf3 100644
--- a/src/corelib/global/qglobal_p.h
+++ b/src/corelib/global/qglobal_p.h
@@ -61,6 +61,9 @@
#endif
#if defined(__cplusplus)
+#ifdef Q_CC_MINGW
+# include <unistd.h> // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
+#endif
#include <time.h>
QT_BEGIN_NAMESPACE
diff --git a/src/corelib/io/qfilesystemengine_win.cpp b/src/corelib/io/qfilesystemengine_win.cpp
index 2020e34f93..279918b812 100644
--- a/src/corelib/io/qfilesystemengine_win.cpp
+++ b/src/corelib/io/qfilesystemengine_win.cpp
@@ -310,9 +310,18 @@ static QString readSymLink(const QFileSystemEntry &link)
const wchar_t* PathBuffer = &rdb->SymbolicLinkReparseBuffer.PathBuffer[offset];
result = QString::fromWCharArray(PathBuffer, length);
}
- // cut-off "//?/" and "/??/"
- if (result.size() > 4 && result.at(0) == QLatin1Char('\\') && result.at(2) == QLatin1Char('?') && result.at(3) == QLatin1Char('\\'))
+ // cut-off "\\?\" and "\??\"
+ if (result.size() > 4
+ && result.at(0) == QLatin1Char('\\')
+ && result.at(2) == QLatin1Char('?')
+ && result.at(3) == QLatin1Char('\\')) {
result = result.mid(4);
+ // cut off UNC in addition when the link points at a UNC share
+ // in which case we need to prepend another backslash to get \\server\share
+ if (result.leftRef(3) == QLatin1String("UNC")) {
+ result.replace(0, 3, QLatin1Char('\\'));
+ }
+ }
}
free(rdb);
CloseHandle(handle);
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index 664e16540b..d171b313e6 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -3619,7 +3619,7 @@ QModelIndex QAbstractTableModel::sibling(int row, int column, const QModelIndex
bool QAbstractTableModel::hasChildren(const QModelIndex &parent) const
{
- if (parent.model() == this || !parent.isValid())
+ if (!parent.isValid())
return rowCount(parent) > 0 && columnCount(parent) > 0;
return false;
}
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index 418b8cf1d2..0bceab6fb4 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -515,7 +515,7 @@ struct Q_CORE_EXPORT QMetaObject
Qt::ConnectionType type = Qt::AutoConnection, decltype(function()) *ret = nullptr)
{
return invokeMethodImpl(context,
- new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(function),
+ new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)),
type,
ret);
}
@@ -527,7 +527,7 @@ struct Q_CORE_EXPORT QMetaObject
invokeMethod(QObject *context, Func function, typename std::result_of<Func()>::type *ret)
{
return invokeMethodImpl(context,
- new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(function),
+ new QtPrivate::QFunctorSlotObjectWithNoArgs<Func, decltype(function())>(std::move(function)),
Qt::AutoConnection,
ret);
}
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 969065ffee..6fa735dab7 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -58,6 +58,9 @@
#endif
#include <cmath>
+#ifdef Q_CC_MINGW
+# include <unistd.h> // Define _POSIX_THREAD_SAFE_FUNCTIONS to obtain localtime_r()
+#endif
#include <time.h>
#ifdef Q_OS_WIN
# include <qt_windows.h>
diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h
index fc901234ec..51d5dd9759 100644
--- a/src/corelib/tools/qdatetime.h
+++ b/src/corelib/tools/qdatetime.h
@@ -335,7 +335,7 @@ public:
inline bool operator>(const QDateTime &other) const { return other < *this; }
inline bool operator>=(const QDateTime &other) const { return !(*this < other); }
-#if QT_DEPRECATED_SINCE(5, 2)
+#if QT_DEPRECATED_SINCE(5, 2) // ### Qt 6: remove
QT_DEPRECATED void setUtcOffset(int seconds);
QT_DEPRECATED int utcOffset() const;
#endif // QT_DEPRECATED_SINCE
diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp
index 9f414b1b72..8e47d350d1 100644
--- a/src/corelib/tools/qlocale.cpp
+++ b/src/corelib/tools/qlocale.cpp
@@ -2482,6 +2482,17 @@ QString QLocale::toString(double i, char f, int prec) const
Returns a QLocale object initialized to the "C" locale.
+ This locale is based on en_US but with various quirks of its own, such as
+ simplified number formatting and its own date formatting. It implements the
+ POSIX standards that describe the behavior of standard library functions of
+ the "C" programming language.
+
+ Among other things, this means its collation order is based on the ASCII
+ values of letters, so that (for case-sensitive sorting) all upper-case
+ letters sort before any lower-case one (rather than each letter's upper- and
+ lower-case forms sorting adjacent to one another, before the next letter's
+ two forms).
+
\sa system()
*/
diff --git a/src/corelib/tools/qlocale.qdoc b/src/corelib/tools/qlocale.qdoc
index 91b0ab6442..f36fd7d6fc 100644
--- a/src/corelib/tools/qlocale.qdoc
+++ b/src/corelib/tools/qlocale.qdoc
@@ -104,7 +104,7 @@
This enumerated type is used to specify a language.
\value AnyLanguage
- \value C The "C" locale is identical in behavior to English/UnitedStates.
+ \value C A simplified English locale; see QLocale::c()
\value Abkhazian
\value Afan Obsolete, please use Oromo
diff --git a/src/gui/kernel/qoffscreensurface.cpp b/src/gui/kernel/qoffscreensurface.cpp
index ae027af627..0cc11ca3bb 100644
--- a/src/gui/kernel/qoffscreensurface.cpp
+++ b/src/gui/kernel/qoffscreensurface.cpp
@@ -46,6 +46,8 @@
#include "qwindow.h"
#include "qplatformwindow.h"
+#include <private/qwindow_p.h>
+
QT_BEGIN_NAMESPACE
/*!
@@ -199,12 +201,18 @@ void QOffscreenSurface::create()
if (QThread::currentThread() != qGuiApp->thread())
qWarning("Attempting to create QWindow-based QOffscreenSurface outside the gui thread. Expect failures.");
d->offscreenWindow = new QWindow(d->screen);
+ // Make the window frameless to prevent Windows from enlarging it, should it
+ // violate the minimum title bar width on the platform.
+ d->offscreenWindow->setFlags(d->offscreenWindow->flags()
+ | Qt::CustomizeWindowHint | Qt::FramelessWindowHint);
d->offscreenWindow->setObjectName(QLatin1String("QOffscreenSurface"));
// Remove this window from the global list since we do not want it to be destroyed when closing the app.
// The QOffscreenSurface has to be usable even after exiting the event loop.
QGuiApplicationPrivate::window_list.removeOne(d->offscreenWindow);
d->offscreenWindow->setSurfaceType(QWindow::OpenGLSurface);
d->offscreenWindow->setFormat(d->requestedFormat);
+ // Prevent QPlatformWindow::initialGeometry() and platforms from setting a default geometry.
+ qt_window_private(d->offscreenWindow)->setAutomaticPositionAndResizeEnabled(false);
d->offscreenWindow->setGeometry(0, 0, d->size.width(), d->size.height());
d->offscreenWindow->create();
}
diff --git a/src/gui/painting/qcoregraphics.mm b/src/gui/painting/qcoregraphics.mm
index 53066687d3..e2497eaadb 100644
--- a/src/gui/painting/qcoregraphics.mm
+++ b/src/gui/painting/qcoregraphics.mm
@@ -366,40 +366,35 @@ void qt_mac_scale_region(QRegion *region, qreal scaleFactor)
// ---------------------- QMacCGContext ----------------------
-QMacCGContext::QMacCGContext(QPaintDevice *paintDevice) : context(0)
+QMacCGContext::QMacCGContext(QPaintDevice *paintDevice)
{
- // In Qt 5, QWidget and QPixmap (and QImage) paint devices are all QImages under the hood.
- QImage *image = 0;
- if (paintDevice->devType() == QInternal::Image) {
- image = static_cast<QImage *>(paintDevice);
- } else if (paintDevice->devType() == QInternal::Pixmap) {
-
- const QPixmap *pm = static_cast<const QPixmap*>(paintDevice);
- QPlatformPixmap *data = const_cast<QPixmap *>(pm)->data_ptr().data();
- if (data && data->classId() == QPlatformPixmap::RasterClass) {
- image = data->buffer();
- } else {
- qDebug("QMacCGContext: Unsupported pixmap class");
- }
- } else if (paintDevice->devType() == QInternal::Widget) {
- // TODO test: image = static_cast<QImage *>(static_cast<const QWidget *>(paintDevice)->backingStore()->paintDevice());
- qDebug("QMacCGContext: not implemented: Widget class");
- }
-
- if (!image)
- return; // Context type not supported.
-
- QCFType<CGColorSpaceRef> colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
- context = CGBitmapContextCreate(image->bits(), image->width(), image->height(), 8,
- image->bytesPerLine(), colorSpace, qt_mac_bitmapInfoForImage(*image));
+ initialize(paintDevice);
+}
- CGContextTranslateCTM(context, 0, image->height());
- const qreal devicePixelRatio = paintDevice->devicePixelRatioF();
- CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio);
- CGContextScaleCTM(context, 1, -1);
+void QMacCGContext::initialize(QPaintDevice *paintDevice)
+{
+ // Find the underlying QImage of the paint device
+ switch (int deviceType = paintDevice->devType()) {
+ case QInternal::Pixmap: {
+ auto *platformPixmap = static_cast<QPixmap*>(paintDevice)->handle();
+ if (platformPixmap && platformPixmap->classId() == QPlatformPixmap::RasterClass)
+ initialize(platformPixmap->buffer());
+ else
+ qWarning() << "QMacCGContext: Unsupported pixmap class" << platformPixmap->classId();
+ break;
+ }
+ case QInternal::Image:
+ initialize(static_cast<const QImage *>(paintDevice));
+ break;
+ case QInternal::Widget:
+ qWarning() << "QMacCGContext: not implemented: Widget class";
+ break;
+ default:
+ qWarning() << "QMacCGContext:: Unsupported paint device type" << deviceType;
+ }
}
-QMacCGContext::QMacCGContext(QPainter *painter) : context(0)
+QMacCGContext::QMacCGContext(QPainter *painter)
{
QPaintEngine *paintEngine = painter->paintEngine();
@@ -414,51 +409,68 @@ QMacCGContext::QMacCGContext(QPainter *painter) : context(0)
return;
}
- int devType = painter->device()->devType();
- if (paintEngine->type() == QPaintEngine::Raster
- && (devType == QInternal::Widget ||
- devType == QInternal::Pixmap ||
- devType == QInternal::Image)) {
-
- const QImage *image = static_cast<const QImage *>(paintEngine->paintDevice());
- QCFType<CGColorSpaceRef> colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
- context = CGBitmapContextCreate((void *)image->bits(), image->width(), image->height(), 8,
- image->bytesPerLine(), colorSpace, qt_mac_bitmapInfoForImage(*image));
-
- // Invert y axis
- CGContextTranslateCTM(context, 0, image->height());
- CGContextScaleCTM(context, 1, -1);
-
- const qreal devicePixelRatio = image->devicePixelRatio();
-
- if (devType == QInternal::Widget) {
- // Set the clip rect which is an intersection of the system clip
- // and the painter clip. To make matters more interesting these
- // are in device pixels and device-independent pixels, respectively.
- QRegion clip = painter->paintEngine()->systemClip(); // get system clip in device pixels
- QTransform native = painter->deviceTransform(); // get device transform. dx/dy is in device pixels
-
- if (painter->hasClipping()) {
- QRegion r = painter->clipRegion(); // get painter clip, which is in device-independent pixels
- qt_mac_scale_region(&r, devicePixelRatio); // scale painter clip to device pixels
- r.translate(native.dx(), native.dy());
- if (clip.isEmpty())
- clip = r;
- else
- clip &= r;
- }
- qt_mac_clip_cg(context, clip, 0); // clip in device pixels
-
- // Scale the context so that painting happens in device-independent pixels
- CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio);
- CGContextTranslateCTM(context, native.dx() / devicePixelRatio, native.dy() / devicePixelRatio);
- } else {
- // Scale to paint in device-independent pixels
- CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio);
+ if (paintEngine->type() != QPaintEngine::Raster) {
+ qWarning() << "QMacCGContext:: Unsupported paint engine type" << paintEngine->type();
+ return;
+ }
+
+ // The raster paint engine always operates on a QImage
+ Q_ASSERT(paintEngine->paintDevice()->devType() == QInternal::Image);
+
+ // On behalf of one of these supported painter devices
+ switch (int painterDeviceType = painter->device()->devType()) {
+ case QInternal::Pixmap:
+ case QInternal::Image:
+ case QInternal::Widget:
+ break;
+ default:
+ qWarning() << "QMacCGContext:: Unsupported paint device type" << painterDeviceType;
+ return;
+ }
+
+ // Applying the clip is so entangled with the rest of the context setup
+ // that for simplicity we just pass in the painter.
+ initialize(static_cast<const QImage *>(paintEngine->paintDevice()), painter);
+}
+
+void QMacCGContext::initialize(const QImage *image, QPainter *painter)
+{
+ QCFType<CGColorSpaceRef> colorSpace = CGColorSpaceCreateWithName(kCGColorSpaceSRGB);
+ context = CGBitmapContextCreate((void *)image->bits(), image->width(), image->height(), 8,
+ image->bytesPerLine(), colorSpace, qt_mac_bitmapInfoForImage(*image));
+
+ // Invert y axis
+ CGContextTranslateCTM(context, 0, image->height());
+ CGContextScaleCTM(context, 1, -1);
+
+ const qreal devicePixelRatio = image->devicePixelRatio();
+
+ if (painter && painter->device()->devType() == QInternal::Widget) {
+ // Set the clip rect which is an intersection of the system clip and the painter clip
+ QRegion clip = painter->paintEngine()->systemClip();
+ QTransform deviceTransform = painter->deviceTransform();
+
+ if (painter->hasClipping()) {
+ // To make matters more interesting the painter clip is in device-independent pixels,
+ // so we need to scale it to match the device-pixels of the system clip.
+ QRegion painterClip = painter->clipRegion();
+ qt_mac_scale_region(&painterClip, devicePixelRatio);
+
+ painterClip.translate(deviceTransform.dx(), deviceTransform.dy());
+
+ if (clip.isEmpty())
+ clip = painterClip;
+ else
+ clip &= painterClip;
}
- } else {
- qDebug() << "QMacCGContext:: Unsupported painter devtype type" << devType;
+
+ qt_mac_clip_cg(context, clip, 0);
+
+ CGContextTranslateCTM(context, deviceTransform.dx(), deviceTransform.dy());
}
+
+ // Scale the context so that painting happens in device-independent pixels
+ CGContextScaleCTM(context, devicePixelRatio, devicePixelRatio);
}
QT_END_NAMESPACE
diff --git a/src/gui/painting/qcoregraphics_p.h b/src/gui/painting/qcoregraphics_p.h
index 868c2b08b5..ba2cde8325 100644
--- a/src/gui/painting/qcoregraphics_p.h
+++ b/src/gui/painting/qcoregraphics_p.h
@@ -51,6 +51,8 @@
// We mean it.
//
+#include <QtCore/private/qcore_mac_p.h>
+
#include <QtGui/private/qtguiglobal_p.h>
#include <QtGui/qregion.h>
#include <QtGui/qpalette.h>
@@ -89,38 +91,16 @@ Q_GUI_EXPORT QBrush qt_mac_toQBrush(CGColorRef color);
class Q_GUI_EXPORT QMacCGContext
{
public:
- inline QMacCGContext() { context = 0; }
+ QMacCGContext() = default;
QMacCGContext(QPaintDevice *pdev);
QMacCGContext(QPainter *p);
- inline QMacCGContext(CGContextRef cg, bool takeOwnership = false) {
- context = cg;
- if (!takeOwnership)
- CGContextRetain(context);
- }
- inline QMacCGContext(const QMacCGContext &copy) : context(0) { *this = copy; }
- inline ~QMacCGContext() {
- if (context)
- CGContextRelease(context);
- }
- inline bool isNull() const { return context; }
- inline operator CGContextRef() { return context; }
- inline QMacCGContext &operator=(const QMacCGContext &copy) {
- if (context)
- CGContextRelease(context);
- context = copy.context;
- CGContextRetain(context);
- return *this;
- }
- inline QMacCGContext &operator=(CGContextRef cg) {
- if (context)
- CGContextRelease(context);
- context = cg;
- CGContextRetain(context); //we do not take ownership
- return *this;
- }
+
+ operator CGContextRef() { return context; }
private:
- CGContextRef context;
+ void initialize(QPaintDevice *paintDevice);
+ void initialize(const QImage *, QPainter *painter = nullptr);
+ QCFType<CGContextRef> context;
};
QT_END_NAMESPACE
diff --git a/src/gui/util/qshaderformat.cpp b/src/gui/util/qshaderformat.cpp
index 324d84ffe1..ea86dd6ca5 100644
--- a/src/gui/util/qshaderformat.cpp
+++ b/src/gui/util/qshaderformat.cpp
@@ -43,6 +43,7 @@ QT_BEGIN_NAMESPACE
QShaderFormat::QShaderFormat() noexcept
: m_api(NoApi)
+ , m_shaderType(Fragment)
{
}
@@ -106,6 +107,9 @@ bool QShaderFormat::supports(const QShaderFormat &other) const noexcept
if (m_version < other.m_version)
return false;
+ if (m_shaderType != other.m_shaderType)
+ return false;
+
const auto containsAllExtensionsFromOther = std::includes(m_extensions.constBegin(),
m_extensions.constEnd(),
other.m_extensions.constBegin(),
@@ -119,12 +123,23 @@ bool QShaderFormat::supports(const QShaderFormat &other) const noexcept
return true;
}
+QShaderFormat::ShaderType QShaderFormat::shaderType() const Q_DECL_NOTHROW
+{
+ return m_shaderType;
+}
+
+void QShaderFormat::setShaderType(QShaderFormat::ShaderType shaderType) Q_DECL_NOTHROW
+{
+ m_shaderType = shaderType;
+}
+
bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept
{
return lhs.api() == rhs.api()
&& lhs.version() == rhs.version()
&& lhs.extensions() == rhs.extensions()
- && lhs.vendor() == rhs.vendor();
+ && lhs.vendor() == rhs.vendor()
+ && lhs.shaderType() == rhs.shaderType();
}
QT_END_NAMESPACE
diff --git a/src/gui/util/qshaderformat_p.h b/src/gui/util/qshaderformat_p.h
index 84bf71fdb6..c50d7d5729 100644
--- a/src/gui/util/qshaderformat_p.h
+++ b/src/gui/util/qshaderformat_p.h
@@ -69,6 +69,15 @@ public:
OpenGLES
};
+ enum ShaderType : int {
+ Vertex = 0,
+ TessellationControl,
+ TessellationEvaluation,
+ Geometry,
+ Fragment,
+ Compute
+ };
+
Q_GUI_EXPORT QShaderFormat() noexcept;
Q_GUI_EXPORT Api api() const noexcept;
@@ -86,11 +95,15 @@ public:
Q_GUI_EXPORT bool isValid() const noexcept;
Q_GUI_EXPORT bool supports(const QShaderFormat &other) const noexcept;
+ Q_GUI_EXPORT ShaderType shaderType() const Q_DECL_NOTHROW;
+ Q_GUI_EXPORT void setShaderType(ShaderType shaderType) Q_DECL_NOTHROW;
+
private:
Api m_api;
QVersionNumber m_version;
QStringList m_extensions;
QString m_vendor;
+ ShaderType m_shaderType;
};
Q_GUI_EXPORT bool operator==(const QShaderFormat &lhs, const QShaderFormat &rhs) noexcept;
diff --git a/src/gui/util/qshadergenerator.cpp b/src/gui/util/qshadergenerator.cpp
index 60cf5a2fc5..205118f41c 100644
--- a/src/gui/util/qshadergenerator.cpp
+++ b/src/gui/util/qshadergenerator.cpp
@@ -40,6 +40,7 @@
#include "qshadergenerator_p.h"
#include "qshaderlanguage_p.h"
+#include <QRegularExpression>
QT_BEGIN_NAMESPACE
@@ -56,7 +57,10 @@ namespace
case QShaderLanguage::Const:
return "const";
case QShaderLanguage::Input:
- return "varying";
+ if (format.shaderType() == QShaderFormat::Vertex)
+ return "attribute";
+ else
+ return "varying";
case QShaderLanguage::Output:
return ""; // Although fragment shaders for <=2 only have fixed outputs
case QShaderLanguage::Uniform:
@@ -314,12 +318,22 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
[enabledLayers] (const QString &s) { return enabledLayers.contains(s); });
};
+ QVector<QString> globalInputVariables;
+ const QRegularExpression globalInputExtractRegExp(QStringLiteral("^.*\\s+(\\w+).*;$"));
+
const QVector<QShaderNode> nodes = graph.nodes();
for (const QShaderNode &node : nodes) {
if (intersectsEnabledLayers(node.layers())) {
const QByteArrayList headerSnippets = node.rule(format).headerSnippets;
for (const QByteArray &snippet : headerSnippets) {
code << replaceParameters(snippet, node, format);
+
+ // If node is an input, record the variable name into the globalInputVariables vector
+ if (node.type() == QShaderNode::Input) {
+ const QRegularExpressionMatch match = globalInputExtractRegExp.match(QString::fromUtf8(code.last()));
+ if (match.hasMatch())
+ globalInputVariables.push_back(match.captured(1));
+ }
}
}
}
@@ -328,6 +342,14 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
code << QByteArrayLiteral("void main()");
code << QByteArrayLiteral("{");
+ // Table to store temporary variables that should be replaced by global
+ // variables. This avoids having vec3 v56 = vertexPosition; when we could
+ // just use vertexPosition directly.
+ // The added benefit is when having arrays, we don't try to create
+ // mat4 v38 = skinningPalelette[100] which would be invalid
+ QHash<QString, QString> localReferencesToGlobalInputs;
+ const QRegularExpression localToGlobalRegExp(QStringLiteral("^.*\\s+(\\w+)\\s*=\\s*(\\w+).*;$"));
+
for (const QShaderGraph::Statement &statement : graph.createStatements(enabledLayers)) {
const QShaderNode node = statement.node;
QByteArray line = node.rule(format).substitution;
@@ -338,6 +360,9 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
const bool isInput = port.direction == QShaderNodePort::Input;
const int portIndex = statement.portIndex(portDirection, portName);
+
+ Q_ASSERT(portIndex >= 0);
+
const int variableIndex = isInput ? statement.inputs.at(portIndex)
: statement.outputs.at(portIndex);
if (variableIndex < 0)
@@ -345,15 +370,51 @@ QByteArray QShaderGenerator::createShaderCode(const QStringList &enabledLayers)
const auto placeholder = QByteArray(QByteArrayLiteral("$") + portName.toUtf8());
const auto variable = QByteArray(QByteArrayLiteral("v") + QByteArray::number(variableIndex));
+
line.replace(placeholder, variable);
}
- code << QByteArrayLiteral(" ") + replaceParameters(line, node, format);
+ const QByteArray substitutionedLine = replaceParameters(line, node, format);
+
+ // Record name of temporary variable that possibly references a global input
+ // We will replace the temporary variables by the matching global variables later
+ bool isAGlobalInputVariable = false;
+ if (node.type() == QShaderNode::Input) {
+ const QRegularExpressionMatch match = localToGlobalRegExp.match(QString::fromUtf8(substitutionedLine));
+ if (match.hasMatch()) {
+ const QString globalVariable = match.captured(2);
+ if (globalInputVariables.contains(globalVariable)) {
+ const QString localVariable = match.captured(1);
+ // TO DO: Clean globalVariable (remove brackets ...)
+ localReferencesToGlobalInputs.insert(localVariable, globalVariable);
+ isAGlobalInputVariable = true;
+ }
+ }
+ }
+
+ // Only insert content for lines aren't inputs or have not matching
+ // globalVariables for now
+ if (!isAGlobalInputVariable)
+ code << QByteArrayLiteral(" ") + substitutionedLine;
}
code << QByteArrayLiteral("}");
code << QByteArray();
- return code.join('\n');
+
+ // Replace occurrences of local variables which reference a global variable
+ // by the global variables directly
+ auto it = localReferencesToGlobalInputs.cbegin();
+ const auto end = localReferencesToGlobalInputs.cend();
+ QString codeString = QString::fromUtf8(code.join('\n'));
+
+ while (it != end) {
+ const QRegularExpression r(QStringLiteral("\\b(%1)([\\b|\\.|;|\\)|\\[|\\s|\\*|\\+|\\/|\\-|,])").arg(it.key()),
+ QRegularExpression::MultilineOption);
+ codeString.replace(r, QStringLiteral("%1\\2").arg(it.value()));
+ ++it;
+ }
+
+ return codeString.toUtf8();
}
QT_END_NAMESPACE
diff --git a/src/gui/util/qshadernodesloader.cpp b/src/gui/util/qshadernodesloader.cpp
index af565c906d..922479332c 100644
--- a/src/gui/util/qshadernodesloader.cpp
+++ b/src/gui/util/qshadernodesloader.cpp
@@ -251,6 +251,17 @@ void QShaderNodesLoader::load(const QJsonObject &prototypesObject)
break;
}
+ // We default out to a Fragment ShaderType if nothing is specified
+ // as that was the initial behavior we introduced
+ const QString shaderType = formatObject.value(QStringLiteral("shaderType")).toString();
+ format.setShaderType(shaderType == QStringLiteral("Fragment") ? QShaderFormat::Fragment
+ : shaderType == QStringLiteral("Vertex") ? QShaderFormat::Vertex
+ : shaderType == QStringLiteral("TessellationControl") ? QShaderFormat::TessellationControl
+ : shaderType == QStringLiteral("TessellationEvaluation") ? QShaderFormat::TessellationEvaluation
+ : shaderType == QStringLiteral("Geometry") ? QShaderFormat::Geometry
+ : shaderType == QStringLiteral("Compute") ? QShaderFormat::Compute
+ : QShaderFormat::Fragment);
+
const QByteArray substitution = substitutionValue.toString().toUtf8();
const QJsonValue snippetsValue = ruleObject.value(QStringLiteral("headerSnippets"));
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp
index 644f4336ca..b54fb349fb 100644
--- a/src/network/kernel/qhostaddress.cpp
+++ b/src/network/kernel/qhostaddress.cpp
@@ -385,8 +385,8 @@ QHostAddress QNetmask::address(QAbstractSocket::NetworkLayerProtocol protocol) c
\value LocalHost The IPv4 localhost address. Equivalent to QHostAddress("127.0.0.1").
\value LocalHostIPv6 The IPv6 localhost address. Equivalent to QHostAddress("::1").
\value Broadcast The IPv4 broadcast address. Equivalent to QHostAddress("255.255.255.255").
- \value AnyIPv4 The IPv4 any-address. Equivalent to QHostAddress("0.0.0.0"). A socket bound with this address will listen only on IPv4 interaces.
- \value AnyIPv6 The IPv6 any-address. Equivalent to QHostAddress("::"). A socket bound with this address will listen only on IPv6 interaces.
+ \value AnyIPv4 The IPv4 any-address. Equivalent to QHostAddress("0.0.0.0"). A socket bound with this address will listen only on IPv4 interfaces.
+ \value AnyIPv6 The IPv6 any-address. Equivalent to QHostAddress("::"). A socket bound with this address will listen only on IPv6 interfaces.
\value Any The dual stack any-address. A socket bound with this address will listen on both IPv4 and IPv6 interfaces.
*/
diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp
index 020d035bf7..5ee4773b70 100644
--- a/src/platformsupport/eglconvenience/qeglconvenience.cpp
+++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp
@@ -268,7 +268,7 @@ EGLConfig QEglConfigChooser::chooseConfig()
configureAttributes.append(EGL_OPENGL_ES_BIT);
break;
}
- // fall through
+ Q_FALLTHROUGH();
default:
needsES2Plus = true;
break;
diff --git a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
index c0e528f922..94def16748 100644
--- a/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
+++ b/src/platformsupport/eglconvenience/qeglplatformcontext.cpp
@@ -134,7 +134,7 @@ QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatform
void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLContext *share)
{
- m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig);
+ m_format = q_glFormatFromConfig(m_eglDisplay, m_eglConfig, format);
// m_format now has the renderableType() resolved (it cannot be Default anymore)
// but does not yet contain version, profile, options.
m_shareContext = share ? static_cast<QEGLPlatformContext *>(share)->m_eglContext : 0;
@@ -248,6 +248,12 @@ void QEGLPlatformContext::adopt(const QVariant &nativeHandle, QPlatformOpenGLCon
value = 0;
eglQueryContext(m_eglDisplay, context, EGL_CONTEXT_CLIENT_TYPE, &value);
if (value == EGL_OPENGL_API || value == EGL_OPENGL_ES_API) {
+ // if EGL config supports both OpenGL and OpenGL ES render type,
+ // q_glFormatFromConfig() with the default "referenceFormat" parameter
+ // will always figure it out as OpenGL render type.
+ // We can override it to match user's real render type.
+ if (value == EGL_OPENGL_ES_API)
+ m_format.setRenderableType(QSurfaceFormat::OpenGLES);
m_api = value;
eglBindAPI(m_api);
} else {
diff --git a/src/platformsupport/glxconvenience/glxconvenience.pro b/src/platformsupport/glxconvenience/glxconvenience.pro
index 8367dc5e31..1b9cf79080 100644
--- a/src/platformsupport/glxconvenience/glxconvenience.pro
+++ b/src/platformsupport/glxconvenience/glxconvenience.pro
@@ -6,7 +6,7 @@ CONFIG += static internal_module
DEFINES += QT_NO_CAST_FROM_ASCII
-QMAKE_USE_PRIVATE += xlib
+QMAKE_USE += xlib
HEADERS += qglxconvenience_p.h
SOURCES += qglxconvenience.cpp
diff --git a/src/platformsupport/input/tslib/qtslib.cpp b/src/platformsupport/input/tslib/qtslib.cpp
index c4caea5c80..df57147af6 100644
--- a/src/platformsupport/input/tslib/qtslib.cpp
+++ b/src/platformsupport/input/tslib/qtslib.cpp
@@ -96,8 +96,8 @@ void QTsLibMouseHandler::readMouseData()
int x = sample.x;
int y = sample.y;
- // work around missing coordinates on mouse release
- if (sample.pressure == 0 && sample.x == 0 && sample.y == 0) {
+ // coordinates on release events can contain arbitrary values, just ignore them
+ if (sample.pressure == 0) {
x = m_x;
y = m_y;
}
diff --git a/src/platformsupport/kmsconvenience/qkmsdevice.cpp b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
index 4b27522976..5838c43eca 100644
--- a/src/platformsupport/kmsconvenience/qkmsdevice.cpp
+++ b/src/platformsupport/kmsconvenience/qkmsdevice.cpp
@@ -59,6 +59,7 @@ enum OutputConfiguration {
OutputConfigOff,
OutputConfigPreferred,
OutputConfigCurrent,
+ OutputConfigSkip,
OutputConfigMode,
OutputConfigModeline
};
@@ -191,6 +192,8 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
configuration = OutputConfigPreferred;
} else if (mode == "current") {
configuration = OutputConfigCurrent;
+ } else if (mode == "skip") {
+ configuration = OutputConfigSkip;
} else if (sscanf(mode.constData(), "%dx%d@%d", &configurationSize.rwidth(), &configurationSize.rheight(),
&configurationRefresh) == 3)
{
@@ -229,6 +232,11 @@ QPlatformScreen *QKmsDevice::createScreenForConnector(drmModeResPtr resources,
return nullptr;
}
+ if (configuration == OutputConfigSkip) {
+ qCDebug(qLcKmsDebug) << "Skipping output" << connectorName;
+ return nullptr;
+ }
+
// Get the current mode on the current crtc
drmModeModeInfo crtc_mode;
memset(&crtc_mode, 0, sizeof crtc_mode);
diff --git a/src/platformsupport/platformcompositor/qopenglcompositor.cpp b/src/platformsupport/platformcompositor/qopenglcompositor.cpp
index 0f4946f81a..635bf0107f 100644
--- a/src/platformsupport/platformcompositor/qopenglcompositor.cpp
+++ b/src/platformsupport/platformcompositor/qopenglcompositor.cpp
@@ -188,14 +188,15 @@ static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight)
topLeftRect.width(), topLeftRect.height());
}
-static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRect &targetWindowRect,
+static void clippedBlit(const QPlatformTextureList *textures, int idx, const QRect &sourceWindowRect,
+ const QRect &targetWindowRect,
QOpenGLTextureBlitter *blitter, QMatrix4x4 *rotationMatrix)
{
const QRect clipRect = textures->clipRect(idx);
if (clipRect.isEmpty())
return;
- const QRect rectInWindow = textures->geometry(idx);
+ const QRect rectInWindow = textures->geometry(idx).translated(sourceWindowRect.topLeft());
const QRect clippedRectInWindow = rectInWindow & clipRect.translated(rectInWindow.topLeft());
const QRect srcRect = toBottomLeftRect(clipRect, rectInWindow.height());
@@ -218,7 +219,7 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
const QRect targetWindowRect(QPoint(0, 0), m_targetWindow->geometry().size());
float currentOpacity = 1.0f;
BlendStateBinder blend;
-
+ const QRect sourceWindowRect = window->sourceWindow()->geometry();
for (int i = 0; i < textures->count(); ++i) {
uint textureId = textures->textureId(i);
const float opacity = window->sourceWindow()->opacity();
@@ -243,16 +244,16 @@ void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
target = m_rotationMatrix * target;
m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
} else if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
- // Texture from an FBO belonging to a QOpenGLWidget
+ // Texture from an FBO belonging to a QOpenGLWidget or QQuickWidget
blend.set(false);
- clippedBlit(textures, i, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr);
+ clippedBlit(textures, i, sourceWindowRect, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr);
}
}
for (int i = 0; i < textures->count(); ++i) {
if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) {
blend.set(true);
- clippedBlit(textures, i, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr);
+ clippedBlit(textures, i, sourceWindowRect, targetWindowRect, &m_blitter, m_rotation ? &m_rotationMatrix : nullptr);
}
}
diff --git a/src/plugins/bearer/generic/qgenericengine.cpp b/src/plugins/bearer/generic/qgenericengine.cpp
index 7472758418..b1f28849a7 100644
--- a/src/plugins/bearer/generic/qgenericengine.cpp
+++ b/src/plugins/bearer/generic/qgenericengine.cpp
@@ -300,7 +300,7 @@ void QGenericEngine::doRequestUpdate()
if (interface.flags() & QNetworkInterface::IsLoopBack)
continue;
-#ifndef Q_OS_WINRT
+#ifndef Q_OS_WIN
// ignore WLAN interface handled in separate engine
if (qGetInterfaceType(interface.name()) == QNetworkConfiguration::BearerWLAN)
continue;
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.h b/src/plugins/platforms/cocoa/qcocoabackingstore.h
index 508f24d578..6f24598250 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.h
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.h
@@ -93,6 +93,7 @@ private:
QRegion dirtyRegion; // In unscaled coordinates
QImage *asImage();
+ qreal devicePixelRatio() const { return m_devicePixelRatio; }
private:
qreal m_devicePixelRatio;
diff --git a/src/plugins/platforms/cocoa/qcocoabackingstore.mm b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
index 8e4e928bc5..d42a723b47 100644
--- a/src/plugins/platforms/cocoa/qcocoabackingstore.mm
+++ b/src/plugins/platforms/cocoa/qcocoabackingstore.mm
@@ -460,12 +460,29 @@ void QCALayerBackingStore::flush(QWindow *flushedWindow, const QRegion &region,
NSView *backingStoreView = static_cast<QCocoaWindow *>(window()->handle())->view();
NSView *flushedView = static_cast<QCocoaWindow *>(flushedWindow->handle())->view();
+ // If the backingstore is just flushed, without being painted to first, then we may
+ // end in a situation where the backingstore is flushed to a layer with a different
+ // scale factor than the one it was created for in beginPaint. This is the client's
+ // fault in not picking up the change in scale factor of the window and re-painting
+ // the backingstore accordingly. To smoothing things out, we warn about this situation,
+ // and change the layer's contentsScale to match the scale of the back buffer, so that
+ // we at least cover the whole layer. This is necessary since we set the view's
+ // contents placement policy to NSViewLayerContentsPlacementTopLeft, which means
+ // AppKit will not do any scaling on our behalf.
+ if (m_buffers.back()->devicePixelRatio() != flushedView.layer.contentsScale) {
+ qCWarning(lcQpaBackingStore) << "Back buffer dpr of" << m_buffers.back()->devicePixelRatio()
+ << "doesn't match" << flushedView.layer << "contents scale of" << flushedView.layer.contentsScale
+ << "- updating layer to match.";
+ flushedView.layer.contentsScale = m_buffers.back()->devicePixelRatio();
+ }
+
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.
+ // to flush the transaction and persist the layer changes to the window server, or
+ // we've been asked to flush without painting anything. The layer already knows about
+ // the back buffer, and we don't need to re-apply it to pick up any possible surface
+ // changes, so bail out early.
qCInfo(lcQpaBackingStore).nospace() << "Skipping flush of " << flushedView
<< ", layer already reflects back buffer";
return;
diff --git a/src/plugins/platforms/cocoa/qnsview_drawing.mm b/src/plugins/platforms/cocoa/qnsview_drawing.mm
index cb1799b039..69d36ef61e 100644
--- a/src/plugins/platforms/cocoa/qnsview_drawing.mm
+++ b/src/plugins/platforms/cocoa/qnsview_drawing.mm
@@ -154,6 +154,7 @@
<< "due to being" << ([self layerExplicitlyRequested] ? "explicitly requested"
: [self shouldUseMetalLayer] ? "needed by surface type" : "enabled by macOS");
[super setLayer:layer];
+ layer.delegate = self;
}
- (NSViewLayerContentsRedrawPolicy)layerContentsRedrawPolicy
diff --git a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
index 48469b0f8c..c8a1ddf9b9 100644
--- a/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfsintegration.cpp
@@ -199,6 +199,10 @@ QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWindow *window) const
QEglFSWindow *w = qt_egl_device_integration()->createWindow(window);
w->create();
+ const auto showWithoutActivating = window->property("_q_showWithoutActivating");
+ if (showWithoutActivating.isValid() && showWithoutActivating.toBool())
+ return w;
+
// Activate only the window for the primary screen to make input work
if (window->type() != Qt::ToolTip && window->screen() == QGuiApplication::primaryScreen())
w->requestActivateWindow();
diff --git a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp
index 98e9ee4728..c1d5af47aa 100644
--- a/src/plugins/platforms/eglfs/api/qeglfswindow.cpp
+++ b/src/plugins/platforms/eglfs/api/qeglfswindow.cpp
@@ -167,6 +167,9 @@ void QEglFSWindow::create()
void QEglFSWindow::destroy()
{
+ if (!m_flags.testFlag(Created))
+ return; // already destroyed
+
#ifndef QT_NO_OPENGL
QOpenGLCompositor::instance()->removeWindow(this);
#endif
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h
index a19cf7e8bc..ee4b7978f1 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms/qeglfskmsgbmwindow.h
@@ -55,6 +55,9 @@ public:
: QEglFSWindow(w),
m_integration(integration)
{ }
+
+ ~QEglFSKmsGbmWindow() { destroy(); }
+
void resetSurface() override;
void invalidateSurface() override;
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
index ef732f9832..2c6b4245b7 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_egldevice/qeglfskmsegldeviceintegration.cpp
@@ -117,6 +117,8 @@ public:
, m_framePending(false)
{ }
+ ~QEglFSKmsEglDeviceWindow() { destroy(); }
+
void invalidateSurface() override;
void resetSurface() override;
void flip();
diff --git a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp
index 0d9b6b6290..d1250ec9bf 100644
--- a/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp
+++ b/src/plugins/platforms/eglfs/deviceintegration/eglfs_kms_vsp2/qeglfskmsvsp2integration.cpp
@@ -205,6 +205,9 @@ public:
: QEglFSWindow(w)
, m_integration(integration)
{}
+
+ ~QEglFSKmsVsp2Window() { destroy(); }
+
void resetSurface() override;
void invalidateSurface() override;
const QEglFSKmsVsp2Integration *m_integration;
diff --git a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp
index 229ff92894..e1a41c0ede 100644
--- a/src/plugins/platforms/windows/qwindowsdropdataobject.cpp
+++ b/src/plugins/platforms/windows/qwindowsdropdataobject.cpp
@@ -41,6 +41,7 @@
#include <QtCore/qurl.h>
#include <QtCore/qmimedata.h>
+#include "qwindowsmime.h"
QT_BEGIN_NAMESPACE
@@ -48,8 +49,9 @@ QT_BEGIN_NAMESPACE
\class QWindowsDropDataObject
\brief QWindowsOleDataObject subclass specialized for handling Drag&Drop.
- Only allows "text/uri-list" data to be exported as CF_HDROP, to allow dropped
- files to be attached to Office applications (instead of adding an URL link).
+ Prevents "text/uri-list" data for local files from being exported as text
+ or URLs, to allow dropped files to be attached to Office applications
+ (instead of creating local hyperlinks).
\internal
\ingroup qt-lighthouse-win
@@ -80,14 +82,22 @@ QWindowsDropDataObject::QueryGetData(LPFORMATETC pformatetc)
return QWindowsOleDataObject::QueryGetData(pformatetc);
}
-// If the data is text/uri-list for local files, tell we can only export it as CF_HDROP.
+// If the data is "text/uri-list" only, and all URIs are for local files,
+// we prevent it from being exported as text or URLs, to make target applications
+// like MS Office attach or open the files instead of creating local hyperlinks.
bool QWindowsDropDataObject::shouldIgnore(LPFORMATETC pformatetc) const
{
QMimeData *dropData = mimeData();
- if (dropData && dropData->hasFormat(QStringLiteral("text/uri-list")) && (pformatetc->cfFormat != CF_HDROP)) {
- QList<QUrl> urls = dropData->urls();
- return std::any_of(urls.cbegin(), urls.cend(), [] (const QUrl &u) { return u.isLocalFile(); });
+ if (dropData && dropData->formats().size() == 1 && dropData->hasUrls()) {
+ QString formatName = QWindowsMimeConverter::clipboardFormatName(pformatetc->cfFormat);
+ if (pformatetc->cfFormat == CF_UNICODETEXT
+ || pformatetc->cfFormat == CF_TEXT
+ || formatName == QStringLiteral("UniformResourceLocator")
+ || formatName == QStringLiteral("UniformResourceLocatorW")) {
+ QList<QUrl> urls = dropData->urls();
+ return std::all_of(urls.cbegin(), urls.cend(), [] (const QUrl &u) { return u.isLocalFile(); });
+ }
}
return false;
diff --git a/src/plugins/platforms/windows/qwindowskeymapper.cpp b/src/plugins/platforms/windows/qwindowskeymapper.cpp
index c050369801..c5af4d8042 100644
--- a/src/plugins/platforms/windows/qwindowskeymapper.cpp
+++ b/src/plugins/platforms/windows/qwindowskeymapper.cpp
@@ -879,21 +879,16 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con
#if defined(WM_APPCOMMAND)
const int cmd = GET_APPCOMMAND_LPARAM(msg.lParam);
// QTBUG-57198, do not send mouse-synthesized commands as key events in addition
+ bool skipPressRelease = false;
switch (GET_DEVICE_LPARAM(msg.lParam)) {
case FAPPCOMMAND_MOUSE:
return false;
case FAPPCOMMAND_KEY:
- // QTBUG-62838, swallow WM_KEYDOWN, WM_KEYUP for commands that are
- // reflected in VK(s) like VK_MEDIA_NEXT_TRACK. Don't do that for
- // APPCOMMAND_BROWSER_HOME as that one does not trigger two events
- if (cmd != APPCOMMAND_BROWSER_HOME) {
- MSG peekedMsg;
- if (PeekMessage(&peekedMsg, msg.hwnd, 0, 0, PM_NOREMOVE)
- && peekedMsg.message == WM_KEYDOWN) {
- PeekMessage(&peekedMsg, msg.hwnd, 0, 0, PM_REMOVE);
- PeekMessage(&peekedMsg, msg.hwnd, 0, 0, PM_REMOVE);
- }
- }
+ // QTBUG-62838, use WM_KEYDOWN/WM_KEYUP for commands that are reflected
+ // in VK(s) like VK_MEDIA_NEXT_TRACK, to get correct codes and autorepeat.
+ // Don't do that for APPCOMMAND_BROWSER_HOME as that one does not trigger two events.
+ if (cmd != APPCOMMAND_BROWSER_HOME)
+ skipPressRelease = true;
break;
}
@@ -908,7 +903,8 @@ bool QWindowsKeyMapper::translateMultimediaKeyEventInternal(QWindow *window, con
return false;
const int qtKey = int(CmdTbl[cmd]);
- sendExtendedPressRelease(receiver, qtKey, Qt::KeyboardModifier(state), 0, 0, 0);
+ if (!skipPressRelease)
+ sendExtendedPressRelease(receiver, qtKey, Qt::KeyboardModifier(state), 0, 0, 0);
// QTBUG-43343: Make sure to return false if Qt does not handle the key, otherwise,
// the keys are not passed to the active media player.
# if QT_CONFIG(shortcut)
diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp
index 96e34fb44c..030d8d1e0f 100644
--- a/src/plugins/platforms/windows/qwindowsmime.cpp
+++ b/src/plugins/platforms/windows/qwindowsmime.cpp
@@ -1087,7 +1087,10 @@ bool QWindowsMimeImage::canConvertFromMime(const FORMATETC &formatetc, const QMi
const QImage image = qvariant_cast<QImage>(mimeData->imageData());
if (image.isNull())
return false;
- return cf == CF_DIBV5 || (cf == CF_DIB) || cf == int(CF_PNG);
+ // QTBUG-64322: Use PNG only for transparent images as otherwise MS PowerPoint
+ // cannot handle it.
+ return cf == CF_DIBV5 || cf == CF_DIB
+ || (cf == int(CF_PNG) && image.hasAlphaChannel());
}
bool QWindowsMimeImage::convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const
diff --git a/src/plugins/platforms/windows/qwindowspointerhandler.cpp b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
index f1960f1585..9a8b5d5121 100644
--- a/src/plugins/platforms/windows/qwindowspointerhandler.cpp
+++ b/src/plugins/platforms/windows/qwindowspointerhandler.cpp
@@ -250,6 +250,23 @@ static Qt::MouseButtons mouseButtonsFromKeyState(WPARAM keyState)
return result;
}
+static Qt::MouseButtons queryMouseButtons()
+{
+ Qt::MouseButtons result = Qt::NoButton;
+ const bool mouseSwapped = GetSystemMetrics(SM_SWAPBUTTON);
+ if (GetAsyncKeyState(VK_LBUTTON) < 0)
+ result |= mouseSwapped ? Qt::RightButton: Qt::LeftButton;
+ if (GetAsyncKeyState(VK_RBUTTON) < 0)
+ result |= mouseSwapped ? Qt::LeftButton : Qt::RightButton;
+ if (GetAsyncKeyState(VK_MBUTTON) < 0)
+ result |= Qt::MidButton;
+ if (GetAsyncKeyState(VK_XBUTTON1) < 0)
+ result |= Qt::XButton1;
+ if (GetAsyncKeyState(VK_XBUTTON2) < 0)
+ result |= Qt::XButton2;
+ return result;
+}
+
static QWindow *getWindowUnderPointer(QWindow *window, QPoint globalPos)
{
QWindow *currentWindowUnderPointer = QWindowsScreen::windowAt(globalPos, CWP_SKIPINVISIBLE | CWP_SKIPTRANSPARENT);
@@ -531,7 +548,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
if (!QWindowsContext::user32dll.getPointerDeviceRects(penInfo->pointerInfo.sourceDevice, &pRect, &dRect))
return false;
- const quint32 pointerId = penInfo->pointerInfo.pointerId;
+ const qint64 sourceDevice = (qint64)penInfo->pointerInfo.sourceDevice;
const QPoint globalPos = QPoint(penInfo->pointerInfo.ptPixelLocation.x, penInfo->pointerInfo.ptPixelLocation.y);
const QPoint localPos = QWindowsGeometryHint::mapFromGlobal(hwnd, globalPos);
const QPointF hiResGlobalPos = QPointF(dRect.left + qreal(penInfo->pointerInfo.ptHimetricLocation.x - pRect.left)
@@ -547,7 +564,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
if (QWindowsContext::verbose > 1)
qCDebug(lcQpaEvents).noquote().nospace() << showbase
- << __FUNCTION__ << " pointerId=" << pointerId
+ << __FUNCTION__ << " sourceDevice=" << sourceDevice
<< " globalPos=" << globalPos << " localPos=" << localPos << " hiResGlobalPos=" << hiResGlobalPos
<< " message=" << hex << msg.message
<< " flags=" << hex << penInfo->pointerInfo.pointerFlags;
@@ -570,7 +587,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
switch (msg.message) {
case WM_POINTERENTER: {
- QWindowSystemInterface::handleTabletEnterProximityEvent(device, type, pointerId);
+ QWindowSystemInterface::handleTabletEnterProximityEvent(device, type, sourceDevice);
m_windowUnderPointer = window;
// The local coordinates may fall outside the window.
// Wait until the next update to send the enter event.
@@ -583,12 +600,12 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
m_windowUnderPointer = nullptr;
m_currentWindow = nullptr;
}
- QWindowSystemInterface::handleTabletLeaveProximityEvent(device, type, pointerId);
+ QWindowSystemInterface::handleTabletLeaveProximityEvent(device, type, sourceDevice);
break;
case WM_POINTERDOWN:
case WM_POINTERUP:
case WM_POINTERUPDATE: {
- QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(pointerId).target; // Pass to window that grabbed it.
+ QWindow *target = QGuiApplicationPrivate::tabletDevicePoint(sourceDevice).target; // Pass to window that grabbed it.
if (!target && m_windowUnderPointer)
target = m_windowUnderPointer;
if (!target)
@@ -607,7 +624,7 @@ bool QWindowsPointerHandler::translatePenEvent(QWindow *window, HWND hwnd, QtWin
QWindowSystemInterface::handleTabletEvent(target, localPos, hiResGlobalPos, device, type, mouseButtons,
pressure, xTilt, yTilt, tangentialPressure, rotation, z,
- pointerId, keyModifiers);
+ sourceDevice, keyModifiers);
return false; // Allow mouse messages to be generated.
}
}
@@ -681,7 +698,6 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
}
const Qt::KeyboardModifiers keyModifiers = QWindowsKeyMapper::queryKeyboardModifiers();
- const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
QWindow *currentWindowUnderPointer = getWindowUnderPointer(window, globalPos);
if (et == QtWindows::MouseWheelEvent)
@@ -709,7 +725,8 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
const MouseEvent mouseEvent = eventFromMsg(msg);
if (mouseEvent.type >= QEvent::NonClientAreaMouseMove && mouseEvent.type <= QEvent::NonClientAreaMouseButtonDblClick) {
- QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, mouseButtons,
+ const Qt::MouseButtons nonclientButtons = queryMouseButtons();
+ QWindowSystemInterface::handleFrameStrutMouseEvent(window, localPos, globalPos, nonclientButtons,
mouseEvent.button, mouseEvent.type, keyModifiers, source);
return false; // Allow further event processing
}
@@ -725,6 +742,8 @@ bool QWindowsPointerHandler::translateMouseEvent(QWindow *window,
return true;
}
+ const Qt::MouseButtons mouseButtons = mouseButtonsFromKeyState(msg.wParam);
+
handleCaptureRelease(window, currentWindowUnderPointer, hwnd, mouseEvent.type, mouseButtons);
handleEnterLeave(window, currentWindowUnderPointer, globalPos);
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
index 85a931e015..c7c0deab3f 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp
@@ -113,6 +113,9 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event
case QAccessible::ValueChanged:
QWindowsUiaMainProvider::notifyValueChange(static_cast<QAccessibleValueChangeEvent *>(event));
break;
+ case QAccessible::SelectionAdd:
+ QWindowsUiaMainProvider::notifySelectionChange(event);
+ break;
case QAccessible::TextAttributeChanged:
case QAccessible::TextColumnChanged:
case QAccessible::TextInserted:
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index fad83fb165..44328492a6 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -146,9 +146,33 @@ void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *eve
void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *event)
{
if (QAccessibleInterface *accessible = event->accessibleInterface()) {
- if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
- // Notifies changes in values of controls supporting the value interface.
+ if (accessible->role() == QAccessible::ComboBox && accessible->childCount() > 0) {
+ QAccessibleInterface *listacc = accessible->child(0);
+ if (listacc && listacc->role() == QAccessible::List) {
+ int count = listacc->childCount();
+ for (int i = 0; i < count; ++i) {
+ QAccessibleInterface *item = listacc->child(i);
+ if (item && item->text(QAccessible::Name) == event->value()) {
+ if (!item->state().selected) {
+ if (QAccessibleActionInterface *actionInterface = item->actionInterface())
+ actionInterface->doAction(QAccessibleActionInterface::toggleAction());
+ }
+ break;
+ }
+ }
+ }
+ }
+ if (event->value().type() == QVariant::String) {
+ if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
+ // Notifies changes in string values.
+ VARIANT oldVal, newVal;
+ clearVariant(&oldVal);
+ setVariantString(event->value().toString(), &newVal);
+ QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal);
+ }
+ } else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
+ // Notifies changes in values of controls supporting the value interface.
VARIANT oldVal, newVal;
clearVariant(&oldVal);
setVariantDouble(valueInterface->currentValue().toDouble(), &newVal);
@@ -158,6 +182,15 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
}
}
+void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event)
+{
+ if (QAccessibleInterface *accessible = event->accessibleInterface()) {
+ if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
+ QWindowsUiaWrapper::instance()->raiseAutomationEvent(provider, UIA_SelectionItem_ElementSelectedEventId);
+ }
+ }
+}
+
// Notifies changes in text content and selection state of text controls.
void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
{
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
index 325d5b3de4..df0d60f9c9 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h
@@ -68,6 +68,7 @@ public:
static void notifyFocusChange(QAccessibleEvent *event);
static void notifyStateChange(QAccessibleStateChangeEvent *event);
static void notifyValueChange(QAccessibleValueChangeEvent *event);
+ static void notifySelectionChange(QAccessibleEvent *event);
static void notifyTextChange(QAccessibleEvent *event);
// IUnknown
diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
index 476de6d1e5..4adf662152 100644
--- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp
@@ -270,7 +270,9 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share)
// ES does not support any format option
m_format.setOptions(QSurfaceFormat::FormatOptions());
}
-
+ // Robustness must match that of the shared context.
+ if (share && share->format().testOption(QSurfaceFormat::ResetNotification))
+ m_format.setOption(QSurfaceFormat::ResetNotification);
Q_ASSERT(glVersions.count() > 0);
for (int i = 0; !m_context && i < glVersions.count(); i++) {
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index d0e05c1e20..6d6648c1fa 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -1156,66 +1156,6 @@ static QStyleHelper::WidgetSizePolicy qt_aqua_guess_size(const QWidget *widg, QS
}
#endif
-static NSColor *qt_convertColorForContext(CGContextRef context, NSColor *color)
-{
- Q_ASSERT(color);
- Q_ASSERT(context);
-
- CGColorSpaceRef targetCGColorSpace = CGBitmapContextGetColorSpace(context);
- NSColorSpace *targetNSColorSpace = [[NSColorSpace alloc] initWithCGColorSpace:targetCGColorSpace];
- NSColor *adjusted = [color colorUsingColorSpace:targetNSColorSpace];
- [targetNSColorSpace release];
-
- return adjusted;
-}
-
-static NSColor *qt_colorForContext(CGContextRef context, const CGFloat (&rgba)[4])
-{
- Q_ASSERT(context);
-
- auto colorSpace = CGBitmapContextGetColorSpace(context);
- if (!colorSpace)
- return nil;
-
- return qt_convertColorForContext(context, [NSColor colorWithSRGBRed:rgba[0] green:rgba[1] blue:rgba[2] alpha:rgba[3]]);
-}
-
-static void qt_drawDisclosureButton(CGContextRef context, NSInteger state, bool selected, CGRect rect)
-{
- Q_ASSERT(context);
-
- static const CGFloat gray[] = {0.55, 0.55, 0.55, 0.97};
- static const CGFloat white[] = {1.0, 1.0, 1.0, 0.9};
-
- NSColor *fillColor = qt_colorForContext(context, selected ? white : gray);
- [fillColor setFill];
-
- if (state == NSOffState) {
- static NSBezierPath *triangle = [[NSBezierPath alloc] init];
- [triangle removeAllPoints];
- // In off state, a disclosure button is an equilateral triangle
- // ('pointing' to the right) with a bound rect that can be described
- // as NSMakeRect(0, 0, 8, 9). Inside the 'rect' it's translated by
- // (2, 4).
- [triangle moveToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 4)];
- [triangle lineToPoint:NSMakePoint(rect.origin.x + 2, rect.origin.y + 4 + 9)];
- [triangle lineToPoint:NSMakePoint(rect.origin.x + 2 + 8, rect.origin.y + 4 + 4.5)];
- [triangle closePath];
- [triangle fill];
- } else {
- static NSBezierPath *openTriangle = [[NSBezierPath alloc] init];
- [openTriangle removeAllPoints];
- // In 'on' state, the button is an equilateral triangle (looking down)
- // with the bounding rect NSMakeRect(0, 0, 9, 8). Inside the 'rect'
- // it's translated by (1, 4).
- [openTriangle moveToPoint:NSMakePoint(rect.origin.x + 1, rect.origin.y + 4 + 8)];
- [openTriangle lineToPoint:NSMakePoint(rect.origin.x + 1 + 9, rect.origin.y + 4 + 8)];
- [openTriangle lineToPoint:NSMakePoint(rect.origin.x + 1 + 4.5, rect.origin.y + 4)];
- [openTriangle closePath];
- [openTriangle fill];
- }
-}
-
void QMacStylePrivate::drawFocusRing(QPainter *p, const QRectF &targetRect, int hMargin, int vMargin, const CocoaControl &cw) const
{
QPainterPath focusRingPath;
@@ -3301,15 +3241,8 @@ void QMacStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, QPai
CGContextScaleCTM(cg, 1, -1);
CGContextTranslateCTM(cg, -rect.origin.x, -rect.origin.y);
- if (QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSMojave && !qt_mac_applicationIsInDarkMode()) {
- // When the real system theme is one of the 'Dark' themes, and an application forces the 'Aqua' theme,
- // under some conditions (see QTBUG-74515 for more details) NSButtonCell seems to select the 'Dark'
- // code path and is becoming transparent, thus 'invisible' on the white background. To workaround this,
- // we draw the disclose triangle manually:
- qt_drawDisclosureButton(cg, triangleCell.state, (opt->state & State_Selected) && viewHasFocus, rect);
- } else {
- [triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]];
- }
+ [triangleCell drawBezelWithFrame:NSRectFromCGRect(rect) inView:[triangleCell controlView]];
+
d->restoreNSGraphicsContext(cg);
break; }
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index 6e53ea94f3..713f022bdd 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -11343,7 +11343,7 @@ void QGraphicsItemEffectSourcePrivate::draw(QPainter *painter)
}
// sourceRect must be in the given coordinate system
-QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const
+QRectF QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded) const
{
QRectF effectRectF;
@@ -11371,7 +11371,7 @@ QRect QGraphicsItemEffectSourcePrivate::paddedEffectRect(Qt::CoordinateSystem sy
*unpadded = true;
}
- return effectRectF.toAlignedRect();
+ return effectRectF;
}
QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QPoint *offset,
@@ -11389,7 +11389,8 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
bool unpadded;
const QRectF sourceRect = boundingRect(system);
- QRect effectRect = paddedEffectRect(system, mode, sourceRect, &unpadded);
+ QRectF effectRectF = paddedEffectRect(system, mode, sourceRect, &unpadded);
+ QRect effectRect = effectRectF.toAlignedRect();
if (offset)
*offset = effectRect.topLeft();
@@ -11405,7 +11406,9 @@ QPixmap QGraphicsItemEffectSourcePrivate::pixmap(Qt::CoordinateSystem system, QP
if (effectRect.isEmpty())
return QPixmap();
- QPixmap pixmap(effectRect.size());
+ const auto dpr = info ? info->painter->device()->devicePixelRatioF() : 1.0;
+ QPixmap pixmap(QRectF(effectRectF.topLeft(), effectRectF.size() * dpr).toAlignedRect().size());
+ pixmap.setDevicePixelRatio(dpr);
pixmap.fill(Qt::transparent);
QPainter pixmapPainter(&pixmap);
pixmapPainter.setRenderHints(info ? info->painter->renderHints() : QPainter::TextAntialiasing);
diff --git a/src/widgets/graphicsview/qgraphicsitem_p.h b/src/widgets/graphicsview/qgraphicsitem_p.h
index a2c3774f65..92d85f7125 100644
--- a/src/widgets/graphicsview/qgraphicsitem_p.h
+++ b/src/widgets/graphicsview/qgraphicsitem_p.h
@@ -644,7 +644,7 @@ public:
QPixmap pixmap(Qt::CoordinateSystem system,
QPoint *offset,
QGraphicsEffect::PixmapPadMode mode) const override;
- QRect paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = nullptr) const;
+ QRectF paddedEffectRect(Qt::CoordinateSystem system, QGraphicsEffect::PixmapPadMode mode, const QRectF &sourceRect, bool *unpadded = nullptr) const;
QGraphicsItem *item;
QGraphicsItemPaintInfo *info;
diff --git a/src/widgets/graphicsview/qgraphicsscene.cpp b/src/widgets/graphicsview/qgraphicsscene.cpp
index 19d9f25307..3897823e98 100644
--- a/src/widgets/graphicsview/qgraphicsscene.cpp
+++ b/src/widgets/graphicsview/qgraphicsscene.cpp
@@ -4852,7 +4852,7 @@ void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *
&& painter->worldTransform().type() <= QTransform::TxTranslate)
{
QRectF sourceRect = sourced->boundingRect(Qt::DeviceCoordinates);
- QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect);
+ QRect effectRect = sourced->paddedEffectRect(Qt::DeviceCoordinates, sourced->currentCachedMode(), sourceRect).toAlignedRect();
sourced->setCachedOffset(effectRect.topLeft());
} else {
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index 62abf56751..99309633a7 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -2283,13 +2283,15 @@ void QHeaderViewPrivate::_q_sectionsChanged(const QList<QPersistentModelIndex> &
: index.row());
// the new visualIndices are already adjusted / reset by initializeSections()
const int newVisualIndex = visualIndex(newLogicalIndex);
- auto &newSection = sectionItems[newVisualIndex];
- newSection = item.section;
-
- if (newSection.isHidden) {
- // otherwise setSectionHidden will return without doing anything
- newSection.isHidden = false;
- q->setSectionHidden(newLogicalIndex, true);
+ if (newVisualIndex < sectionItems.count()) {
+ auto &newSection = sectionItems[newVisualIndex];
+ newSection = item.section;
+
+ if (newSection.isHidden) {
+ // otherwise setSectionHidden will return without doing anything
+ newSection.isHidden = false;
+ q->setSectionHidden(newLogicalIndex, true);
+ }
}
}
diff --git a/src/widgets/itemviews/qlistwidget.cpp b/src/widgets/itemviews/qlistwidget.cpp
index a9899983c2..e46d25bef1 100644
--- a/src/widgets/itemviews/qlistwidget.cpp
+++ b/src/widgets/itemviews/qlistwidget.cpp
@@ -650,11 +650,13 @@ QListWidgetItem::QListWidgetItem(const QString &text, QListWidget *listview, int
|Qt::ItemIsEnabled
|Qt::ItemIsDragEnabled)
{
+ QListModel *model = listModel();
{
QSignalBlocker b(view);
+ QSignalBlocker bm(model);
setData(Qt::DisplayRole, text);
}
- if (QListModel *model = listModel())
+ if (model)
model->insert(model->rowCount(), this);
}
@@ -683,12 +685,14 @@ QListWidgetItem::QListWidgetItem(const QIcon &icon,const QString &text,
|Qt::ItemIsEnabled
|Qt::ItemIsDragEnabled)
{
+ QListModel *model = listModel();
{
QSignalBlocker b(view);
+ QSignalBlocker bm(model);
setData(Qt::DisplayRole, text);
setData(Qt::DecorationRole, icon);
}
- if (QListModel *model = listModel())
+ if (model)
model->insert(model->rowCount(), this);
}
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index cf15614680..374ea53726 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -1448,7 +1448,8 @@ bool QOpenGLWidget::event(QEvent *e)
{
// Special case: did grabFramebuffer() for a hidden widget that then became visible.
// Recreate all resources since the context now needs to share with the TLW's.
- d->reset();
+ if (!qGuiApp->testAttribute(Qt::AA_ShareOpenGLContexts))
+ d->reset();
}
if (!d->initialized && !size().isEmpty() && window()->windowHandle()) {
d->initialize();
diff --git a/src/widgets/styles/qstylesheetstyle.cpp b/src/widgets/styles/qstylesheetstyle.cpp
index 956c2be3a9..9c744000bd 100644
--- a/src/widgets/styles/qstylesheetstyle.cpp
+++ b/src/widgets/styles/qstylesheetstyle.cpp
@@ -2908,7 +2908,10 @@ void QStyleSheetStyle::polish(QPalette &pal)
void QStyleSheetStyle::repolish(QWidget *w)
{
- QList<const QObject *> children = w->findChildren<const QObject *>(QString());
+ QList<const QObject *> children;
+ children.reserve(w->children().size() + 1);
+ for (auto child: qAsConst(w->children()))
+ children.append(child);
children.append(w);
styleSheetCaches->styleSheetCache.remove(w);
updateObjects(children);
diff --git a/src/widgets/util/qsystemtrayicon_p.h b/src/widgets/util/qsystemtrayicon_p.h
index 5bdf020a47..e31532ea19 100644
--- a/src/widgets/util/qsystemtrayicon_p.h
+++ b/src/widgets/util/qsystemtrayicon_p.h
@@ -69,6 +69,7 @@
QT_BEGIN_NAMESPACE
class QSystemTrayIconSys;
+class QSystemTrayWatcher;
class QPlatformSystemTrayIcon;
class QToolButton;
class QLabel;
@@ -90,6 +91,8 @@ public:
void showMessage_sys(const QString &title, const QString &msg, const QIcon &icon,
QSystemTrayIcon::MessageIcon msgIcon, int msecs);
+ void destroyIcon();
+
static bool isSystemTrayAvailable_sys();
static bool supportsMessages_sys();
@@ -101,6 +104,7 @@ public:
QSystemTrayIconSys *sys;
QPlatformSystemTrayIcon *qpa_sys;
bool visible;
+ QSystemTrayWatcher *trayWatcher;
private:
void install_sys_qpa();
diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp
index 86532456c7..70e5f3678e 100644
--- a/src/widgets/util/qsystemtrayicon_x11.cpp
+++ b/src/widgets/util/qsystemtrayicon_x11.cpp
@@ -92,9 +92,6 @@ protected:
virtual void resizeEvent(QResizeEvent *) override;
virtual void moveEvent(QMoveEvent *) override;
-private slots:
- void systemTrayWindowChanged(QScreen *screen);
-
private:
QSystemTrayIcon *q;
};
@@ -116,15 +113,6 @@ QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *qIn)
setMouseTracking(true);
}
-void QSystemTrayIconSys::systemTrayWindowChanged(QScreen *)
-{
- if (!locateSystemTray()) {
- QBalloonTip::hideBalloon();
- hide(); // still no luck
- destroy();
- }
-}
-
QRect QSystemTrayIconSys::globalGeometry() const
{
return QRect(mapToGlobal(QPoint(0, 0)), size());
@@ -199,10 +187,41 @@ void QSystemTrayIconSys::resizeEvent(QResizeEvent *event)
}
////////////////////////////////////////////////////////////////////////////
+class QSystemTrayWatcher: public QObject
+{
+ Q_OBJECT
+public:
+ QSystemTrayWatcher(QSystemTrayIcon *trayIcon)
+ : QObject(trayIcon)
+ , mTrayIcon(trayIcon)
+ {
+ // This code uses string-based syntax because we want to connect to a signal
+ // which is defined in XCB plugin - QXcbNativeInterface::systemTrayWindowChanged().
+ connect(qGuiApp->platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)),
+ this, SLOT(systemTrayWindowChanged(QScreen*)));
+ }
+
+private slots:
+ void systemTrayWindowChanged(QScreen *)
+ {
+ auto icon = static_cast<QSystemTrayIconPrivate *>(QObjectPrivate::get(mTrayIcon));
+ icon->destroyIcon();
+ if (icon->visible && locateSystemTray()) {
+ icon->sys = new QSystemTrayIconSys(mTrayIcon);
+ icon->sys->show();
+ }
+ }
+
+private:
+ QSystemTrayIcon *mTrayIcon = nullptr;
+};
+////////////////////////////////////////////////////////////////////////////
+
QSystemTrayIconPrivate::QSystemTrayIconPrivate()
: sys(0),
qpa_sys(QGuiApplicationPrivate::platformTheme()->createPlatformSystemTrayIcon()),
- visible(false)
+ visible(false),
+ trayWatcher(nullptr)
{
}
@@ -213,16 +232,21 @@ QSystemTrayIconPrivate::~QSystemTrayIconPrivate()
void QSystemTrayIconPrivate::install_sys()
{
+ Q_Q(QSystemTrayIcon);
+
if (qpa_sys) {
install_sys_qpa();
return;
}
- Q_Q(QSystemTrayIcon);
- if (!sys && locateSystemTray()) {
- sys = new QSystemTrayIconSys(q);
- QObject::connect(QGuiApplication::platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*)),
- sys, SLOT(systemTrayWindowChanged(QScreen*)));
- sys->show();
+
+ if (!sys) {
+ if (!trayWatcher)
+ trayWatcher = new QSystemTrayWatcher(q);
+
+ if (locateSystemTray()) {
+ sys = new QSystemTrayIconSys(q);
+ sys->show();
+ }
}
}
@@ -241,14 +265,21 @@ void QSystemTrayIconPrivate::remove_sys()
remove_sys_qpa();
return;
}
+
+ destroyIcon();
+}
+
+void QSystemTrayIconPrivate::destroyIcon()
+{
if (!sys)
return;
QBalloonTip::hideBalloon();
- sys->hide(); // this should do the trick, but...
- delete sys; // wm may resize system tray only for DestroyEvents
- sys = 0;
+ sys->hide();
+ delete sys;
+ sys = nullptr;
}
+
void QSystemTrayIconPrivate::updateIcon_sys()
{
if (qpa_sys) {
diff --git a/src/widgets/widgets/qplaintextedit.cpp b/src/widgets/widgets/qplaintextedit.cpp
index dc8765ad88..bc1ff78de0 100644
--- a/src/widgets/widgets/qplaintextedit.cpp
+++ b/src/widgets/widgets/qplaintextedit.cpp
@@ -1239,6 +1239,8 @@ void QPlainTextEditPrivate::ensureViewportLayouted()
This property gets and sets the plain text editor's contents. The previous
contents are removed and undo/redo history is reset when this property is set.
+ currentCharFormat() is also reset, unless textCursor() is already at the
+ beginning of the document.
By default, for an editor with no contents, this property contains an empty string.
*/
@@ -1518,7 +1520,12 @@ void QPlainTextEdit::paste()
/*!
Deletes all the text in the text edit.
- Note that the undo/redo history is cleared by this function.
+ Notes:
+ \list
+ \li The undo/redo history is also cleared.
+ \li currentCharFormat() is reset, unless textCursor()
+ is already at the beginning of the document.
+ \endlist
\sa cut(), setPlainText()
*/
@@ -1651,7 +1658,12 @@ void QPlainTextEdit::timerEvent(QTimerEvent *e)
\a text is interpreted as plain text.
- Note that the undo/redo history is cleared by this function.
+ Notes:
+ \list
+ \li The undo/redo history is also cleared.
+ \li currentCharFormat() is reset, unless textCursor()
+ is already at the beginning of the document.
+ \endlist
\sa toPlainText()
*/
diff --git a/src/widgets/widgets/qtextedit.cpp b/src/widgets/widgets/qtextedit.cpp
index 4a06f58b4a..9e134493b5 100644
--- a/src/widgets/widgets/qtextedit.cpp
+++ b/src/widgets/widgets/qtextedit.cpp
@@ -556,7 +556,8 @@ void QTextEditPrivate::_q_ensureVisible(const QRectF &_rect)
This property gets and sets the text editor's contents as plain
text. Previous contents are removed and undo/redo history is reset
- when the property is set.
+ when the property is set. currentCharFormat() is also reset, unless
+ textCursor() is already at the beginning of the document.
If the text edit has another content type, it will not be replaced
by plain text if you call toPlainText(). The only exception to this
@@ -1034,7 +1035,12 @@ void QTextEdit::paste()
/*!
Deletes all the text in the text edit.
- Note that the undo/redo history is cleared by this function.
+ Notes:
+ \list
+ \li The undo/redo history is also cleared.
+ \li currentCharFormat() is reset, unless textCursor()
+ is already at the beginning of the document.
+ \endlist
\sa cut(), setPlainText(), setHtml()
*/
@@ -1139,9 +1145,13 @@ void QTextEdit::timerEvent(QTimerEvent *e)
Changes the text of the text edit to the string \a text.
Any previous text is removed.
- \a text is interpreted as plain text.
-
- Note that the undo/redo history is cleared by this function.
+ Notes:
+ \list
+ \li \a text is interpreted as plain text.
+ \li The undo/redo history is also cleared.
+ \li currentCharFormat() is reset, unless textCursor()
+ is already at the beginning of the document.
+ \endlist
\sa toPlainText()
*/
@@ -1175,7 +1185,8 @@ QString QTextEdit::toPlainText() const
setHtml() changes the text of the text edit. Any previous text is
removed and the undo/redo history is cleared. The input text is
- interpreted as rich text in html format.
+ interpreted as rich text in html format. currentCharFormat() is also
+ reset, unless textCursor() is already at the beginning of the document.
\note It is the responsibility of the caller to make sure that the
text is correctly decoded when a QString containing HTML is created