diff options
author | Liang Qi <liang.qi@theqtcompany.com> | 2015-11-23 07:13:00 +0100 |
---|---|---|
committer | Liang Qi <liang.qi@theqtcompany.com> | 2015-11-23 07:13:00 +0100 |
commit | 1ed7a67a4cef8350103e4ea33b4bbd084f5d4c2d (patch) | |
tree | 03dd7b6f8d9ccc02da6d0d882793ec62c71b00f7 /src | |
parent | dbb7817e13bc7f7ccb8f04b00a65eb3dcf8d25f8 (diff) | |
parent | 6a2b17eeec2d171d2afa17bdbc36456346bfd13b (diff) |
Merge remote-tracking branch 'origin/5.6' into dev
Conflicts:
src/corelib/kernel/qcoreapplication.cpp
src/corelib/thread/qthread_unix.cpp
Change-Id: Ia08d613c3f0bd08cb6dc3e3a57257207dfd4a099
Diffstat (limited to 'src')
52 files changed, 587 insertions, 402 deletions
diff --git a/src/3rdparty/freetype/freetype.pro b/src/3rdparty/freetype/freetype.pro index a32579e0f9..e9436febc6 100644 --- a/src/3rdparty/freetype/freetype.pro +++ b/src/3rdparty/freetype/freetype.pro @@ -67,5 +67,9 @@ contains(QT_CONFIG, system-zlib) { DEFINES += FT_CONFIG_OPTION_SYSTEM_ZLIB include($$PWD/../zlib_dependency.pri) } +contains(QT_CONFIG, system-png) { + DEFINES += FT_CONFIG_OPTION_USE_PNG + include($$PWD/../png_dependency.pri) +} DEFINES += TT_CONFIG_OPTION_SUBPIXEL_HINTING diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index 53206cfb8c..e64ee04134 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -66,8 +66,12 @@ #ifndef QT_NO_QOBJECT #if defined(Q_OS_UNIX) -# if !defined(QT_NO_GLIB) -# include "qeventdispatcher_glib_p.h" +# if defined(Q_OS_OSX) +# include "qeventdispatcher_cf_p.h" +# else +# if !defined(QT_NO_GLIB) +# include "qeventdispatcher_glib_p.h" +# endif # endif # include "qeventdispatcher_unix_p.h" #endif @@ -469,12 +473,21 @@ void QCoreApplicationPrivate::createEventDispatcher() { Q_Q(QCoreApplication); #if defined(Q_OS_UNIX) -# if !defined(QT_NO_GLIB) +# if defined(Q_OS_OSX) + bool ok = false; + int value = qEnvironmentVariableIntValue("QT_EVENT_DISPATCHER_CORE_FOUNDATION", &ok); + if (ok && value > 0) + eventDispatcher = new QEventDispatcherCoreFoundation(q); + else + eventDispatcher = new QEventDispatcherUNIX(q); +# elif !defined(QT_NO_GLIB) if (qEnvironmentVariableIsEmpty("QT_NO_GLIB") && QEventDispatcherGlib::versionSupported()) eventDispatcher = new QEventDispatcherGlib(q); else -# endif eventDispatcher = new QEventDispatcherUNIX(q); +# else + eventDispatcher = new QEventDispatcherUNIX(q); +# endif #elif defined(Q_OS_WINRT) eventDispatcher = new QEventDispatcherWinRT(q); #elif defined(Q_OS_WIN) @@ -613,8 +626,9 @@ void QCoreApplicationPrivate::initLocale() The command line arguments which are passed to QCoreApplication's constructor should be accessed using the arguments() function. - Note that some arguments supplied by the user may have been - processed and removed by QCoreApplication. + + \note QCoreApplication removes option \c -qmljsdebugger="...". It parses the + argument of \c qmljsdebugger, and then removes this option plus its argument. For more advanced command line option handling, create a QCommandLineParser. diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm index 240dfed79f..8422345968 100644 --- a/src/corelib/kernel/qeventdispatcher_cf.mm +++ b/src/corelib/kernel/qeventdispatcher_cf.mm @@ -49,6 +49,8 @@ # include <UIKit/UIApplication.h> #endif +QT_USE_NAMESPACE + @interface RunLoopModeTracker : NSObject { QStack<CFStringRef> m_runLoopModes; } @@ -119,7 +121,6 @@ static CFStringRef runLoopMode(NSDictionary *dictionary) @end QT_BEGIN_NAMESPACE -QT_USE_NAMESPACE class RunLoopDebugger : public QObject { diff --git a/src/corelib/mimetypes/qmimeprovider.cpp b/src/corelib/mimetypes/qmimeprovider.cpp index ebaa1b069c..e0fe144c26 100644 --- a/src/corelib/mimetypes/qmimeprovider.cpp +++ b/src/corelib/mimetypes/qmimeprovider.cpp @@ -578,11 +578,8 @@ void QMimeBinaryProvider::loadMimeTypePrivate(QMimeTypePrivate &data) QString mainPattern; const QString preferredLanguage = QLocale::system().name(); - QListIterator<QString> mimeFilesIter(mimeFiles); - mimeFilesIter.toBack(); - while (mimeFilesIter.hasPrevious()) { // global first, then local. - const QString fullPath = mimeFilesIter.previous(); - QFile qfile(fullPath); + for (QStringList::const_reverse_iterator it = mimeFiles.crbegin(), end = mimeFiles.crend(); it != end; ++it) { // global first, then local. + QFile qfile(*it); if (!qfile.open(QFile::ReadOnly)) continue; diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index f7545b5bcb..9924bef8f5 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -54,7 +54,9 @@ namespace { // avoid duplicate QStringLiteral data: inline QString iidKeyLiteral() { return QStringLiteral("IID"); } +#ifdef QT_SHARED inline QString versionKeyLiteral() { return QStringLiteral("version"); } +#endif inline QString metaDataKeyLiteral() { return QStringLiteral("MetaData"); } inline QString keysKeyLiteral() { return QStringLiteral("Keys"); } diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index cc0476461f..9329c515af 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -36,9 +36,14 @@ #include "qplatformdefs.h" #include <private/qcoreapplication_p.h> +#include <private/qcore_unix_p.h> -#if !defined(QT_NO_GLIB) -# include "../kernel/qeventdispatcher_glib_p.h" +#if defined(Q_OS_OSX) +# include <private/qeventdispatcher_cf_p.h> +#else +# if !defined(QT_NO_GLIB) +# include "../kernel/qeventdispatcher_glib_p.h" +# endif #endif #include <private/qeventdispatcher_unix_p.h> @@ -243,14 +248,23 @@ typedef void*(*QtThreadCallback)(void*); void QThreadPrivate::createEventDispatcher(QThreadData *data) { -#if !defined(QT_NO_GLIB) +#if defined(Q_OS_OSX) + bool ok = false; + int value = qEnvironmentVariableIntValue("QT_EVENT_DISPATCHER_CORE_FOUNDATION", &ok); + if (ok && value > 0) + data->eventDispatcher.storeRelease(new QEventDispatcherCoreFoundation); + else + data->eventDispatcher.storeRelease(new QEventDispatcherUNIX); +#elif !defined(QT_NO_GLIB) if (qEnvironmentVariableIsEmpty("QT_NO_GLIB") && qEnvironmentVariableIsEmpty("QT_NO_THREADED_GLIB") && QEventDispatcherGlib::versionSupported()) data->eventDispatcher.storeRelease(new QEventDispatcherGlib); else -#endif + data->eventDispatcher.storeRelease(new QEventDispatcherUNIX); +#else data->eventDispatcher.storeRelease(new QEventDispatcherUNIX); +#endif data->eventDispatcher.load()->startingUp(); } diff --git a/src/corelib/tools/qlocale_win.cpp b/src/corelib/tools/qlocale_win.cpp index 574453f4ca..a5eb7ec058 100644 --- a/src/corelib/tools/qlocale_win.cpp +++ b/src/corelib/tools/qlocale_win.cpp @@ -48,6 +48,8 @@ #endif #ifdef Q_OS_WINRT +#include <qfunctions_winrt.h> + #include <wrl.h> #include <windows.foundation.h> #include <windows.foundation.collections.h> @@ -644,21 +646,53 @@ QVariant QSystemLocalePrivate::uiLanguages() } ComPtr<ABI::Windows::Foundation::Collections::IVectorView<HSTRING> > languageList; - appLanguagesStatics->get_ManifestLanguages(&languageList); - - if (!languageList) - return QStringList(); - + // Languages is a ranked list of "long names" (e.g. en-US) of preferred languages, which matches + // languages from the manifest with languages from the user's system. + HRESULT hr = appLanguagesStatics->get_Languages(&languageList); + Q_ASSERT_SUCCEEDED(hr); unsigned int size; - languageList->get_Size(&size); + hr = languageList->get_Size(&size); + Q_ASSERT_SUCCEEDED(hr); + result.reserve(size); for (unsigned int i = 0; i < size; ++i) { HString language; - languageList->GetAt(i, language.GetAddressOf()); + hr = languageList->GetAt(i, language.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); UINT32 length; PCWSTR rawString = language.GetRawBuffer(&length); result << QString::fromWCharArray(rawString, length); } + // ManifestLanguages covers all languages given in the manifest and uses short names (like "en"). + hr = appLanguagesStatics->get_ManifestLanguages(&languageList); + Q_ASSERT_SUCCEEDED(hr); + hr = languageList->get_Size(&size); + Q_ASSERT_SUCCEEDED(hr); + for (unsigned int i = 0; i < size; ++i) { + HString language; + hr = languageList->GetAt(i, language.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); + UINT32 length; + PCWSTR rawString = language.GetRawBuffer(&length); + const QString qLanguage = QString::fromWCharArray(rawString, length); + bool found = false; + // Since ApplicationLanguages:::Languages uses long names, we compare the "pre-dash" part of + // the language and filter it out, if it is already covered by a more specialized form. + foreach (const QString &lang, result) { + int dashIndex = lang.indexOf('-'); + // There will not be any long name after the first short name was found, so we can stop. + if (dashIndex == -1) + break; + + if (lang.leftRef(dashIndex) == qLanguage) { + found = true; + break; + } + } + if (!found) + result << qLanguage; + } + return result; #endif // Q_OS_WINRT } diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/xml/qxmlstream.cpp index 69e2e5d5c1..64a130e45a 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/xml/qxmlstream.cpp @@ -2622,6 +2622,13 @@ QXmlStreamEntityDeclaration::~QXmlStreamEntityDeclaration() { } +/*! \fn QXmlStreamStringRef::swap(QXmlStreamStringRef &other) + \since 5.6 + + Swaps this string reference's contents with \a other. + This function is very fast and never fails. +*/ + /*! \fn QStringRef QXmlStreamEntityDeclaration::name() const Returns the entity name. diff --git a/src/corelib/xml/qxmlstream.h b/src/corelib/xml/qxmlstream.h index 7b1ea624c5..34f26cb953 100644 --- a/src/corelib/xml/qxmlstream.h +++ b/src/corelib/xml/qxmlstream.h @@ -53,13 +53,37 @@ public: inline QXmlStreamStringRef(const QStringRef &aString) :m_string(aString.string()?*aString.string():QString()), m_position(aString.position()), m_size(aString.size()){} inline QXmlStreamStringRef(const QString &aString):m_string(aString), m_position(0), m_size(aString.size()){} - inline ~QXmlStreamStringRef(){} + +#if QT_VERSION < QT_VERSION_CHECK(6,0,0) + QXmlStreamStringRef(const QXmlStreamStringRef &other) // = default + : m_string(other.m_string), m_position(other.m_position), m_size(other.m_size) {} +#ifdef Q_COMPILER_RVALUE_REFS + QXmlStreamStringRef(QXmlStreamStringRef &&other) Q_DECL_NOTHROW // = default + : m_string(std::move(other.m_string)), m_position(other.m_position), m_size(other.m_size) {} + QXmlStreamStringRef &operator=(QXmlStreamStringRef &&other) Q_DECL_NOTHROW // = default + { swap(other); return *this; } +#endif + QXmlStreamStringRef &operator=(const QXmlStreamStringRef &other) // = default + { m_string = other.m_string; m_position = other.m_position; m_size = other.m_size; return *this; } + inline ~QXmlStreamStringRef() {} // ### this prevents (or deprecates) all the move/copy special member functions, + // ### that's why we need to provide them by hand above. We can't remove it in + // ### Qt 5, since that would change the way its passed to functions. In Qt 6, remove all. +#endif // Qt < 6.0 + + void swap(QXmlStreamStringRef &other) Q_DECL_NOTHROW + { + qSwap(m_string, other.m_string); + qSwap(m_position, other.m_position); + qSwap(m_size, other.m_size); + } + inline void clear() { m_string.clear(); m_position = m_size = 0; } inline operator QStringRef() const { return QStringRef(&m_string, m_position, m_size); } inline const QString *string() const { return &m_string; } inline int position() const { return m_position; } inline int size() const { return m_size; } }; +Q_DECLARE_SHARED_NOT_MOVABLE_UNTIL_QT6(QXmlStreamStringRef) class QXmlStreamReaderPrivate; diff --git a/src/gui/image/qppmhandler.cpp b/src/gui/image/qppmhandler.cpp index f460431c2b..7f23656c02 100644 --- a/src/gui/image/qppmhandler.cpp +++ b/src/gui/image/qppmhandler.cpp @@ -46,13 +46,21 @@ QT_BEGIN_NAMESPACE PBM/PGM/PPM (ASCII and RAW) image read/write functions *****************************************************************************/ +static void discard_pbm_line(QIODevice *d) +{ + const int buflen = 100; + char buf[buflen]; + int res = 0; + do { + res = d->readLine(buf, buflen); + } while (res > 0 && buf[res-1] != '\n'); +} + static int read_pbm_int(QIODevice *d) { char c; int val = -1; bool digit; - const int buflen = 100; - char buf[buflen]; for (;;) { if (!d->getChar(&c)) // end of file break; @@ -63,7 +71,7 @@ static int read_pbm_int(QIODevice *d) continue; } else { if (c == '#') // comment - d->readLine(buf, buflen); + discard_pbm_line(d); break; } } @@ -72,7 +80,7 @@ static int read_pbm_int(QIODevice *d) else if (isspace((uchar) c)) continue; else if (c == '#') - (void)d->readLine(buf, buflen); + discard_pbm_line(d); else break; } diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 66f1b1dfce..0b1c49dd60 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -1853,16 +1853,23 @@ void QGuiApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::Mo if (!window) return; - QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, e->modifiers, e->source); - ev.setTimestamp(e->timestamp); #ifndef QT_NO_CURSOR if (!e->synthetic()) { if (const QScreen *screen = window->screen()) - if (QPlatformCursor *cursor = screen->handle()->cursor()) + if (QPlatformCursor *cursor = screen->handle()->cursor()) { + const QPointF nativeLocalPoint = QHighDpi::toNativePixels(localPoint, screen); + const QPointF nativeGlobalPoint = QHighDpi::toNativePixels(globalPoint, screen); + QMouseEvent ev(type, nativeLocalPoint, nativeLocalPoint, nativeGlobalPoint, + button, buttons, e->modifiers, e->source); + ev.setTimestamp(e->timestamp); cursor->pointerEvent(ev); + } } #endif + QMouseEvent ev(type, localPoint, localPoint, globalPoint, button, buttons, e->modifiers, e->source); + ev.setTimestamp(e->timestamp); + if (window->d_func()->blockedByModalWindow) { // a modal window is blocking this window, don't allow mouse events through return; diff --git a/src/gui/kernel/qplatformscreen.cpp b/src/gui/kernel/qplatformscreen.cpp index d1d8eba697..8666d0a04c 100644 --- a/src/gui/kernel/qplatformscreen.cpp +++ b/src/gui/kernel/qplatformscreen.cpp @@ -90,7 +90,7 @@ QWindow *QPlatformScreen::topLevelAt(const QPoint & pos) const QWindowList list = QGuiApplication::topLevelWindows(); for (int i = list.size()-1; i >= 0; --i) { QWindow *w = list[i]; - if (w->isVisible() && w->geometry().contains(pos)) + if (w->isVisible() && QHighDpi::toNativePixels(w->geometry(), w).contains(pos)) return w; } diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index dd02e24676..5f873bfe7e 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -224,16 +224,16 @@ static inline QRect deviceRect(const QRect &rect, QWindow *window) return deviceRect; } -static QRegion deviceRegion(const QRegion ®ion, QWindow *window) +static QRegion deviceRegion(const QRegion ®ion, QWindow *window, const QPoint &offset) { - if (!(window->devicePixelRatio() > 1)) + if (offset.isNull() && window->devicePixelRatio() <= 1) return region; QVector<QRect> rects; const QVector<QRect> regionRects = region.rects(); rects.reserve(regionRects.count()); foreach (const QRect &rect, regionRects) - rects.append(deviceRect(rect, window)); + rects.append(deviceRect(rect.translated(offset), window)); QRegion deviceRegion; deviceRegion.setRects(rects.constData(), rects.count()); @@ -246,10 +246,12 @@ static inline QRect toBottomLeftRect(const QRect &topLeftRect, int windowHeight) topLeftRect.width(), topLeftRect.height()); } -static void blit(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect, - QOpenGLTextureBlitter *blitter) +static void blitTextureForWidget(const QPlatformTextureList *textures, int idx, QWindow *window, const QRect &deviceWindowRect, + QOpenGLTextureBlitter *blitter, const QPoint &offset) { - const QRect rectInWindow = textures->geometry(idx); + QRect rectInWindow = textures->geometry(idx); + // relative to the TLW, not necessarily our window (if the flush is for a native child widget), have to adjust + rectInWindow.translate(-offset); QRect clipRect = textures->clipRect(idx); if (clipRect.isEmpty()) clipRect = QRect(QPoint(0, 0), rectInWindow.size()); @@ -274,7 +276,9 @@ static void blit(const QPlatformTextureList *textures, int idx, QWindow *window, and composes using OpenGL. May be reimplemented in subclasses if there is a more efficient native way to do it. - Note that the \a offset parameter is currently unused. + \note \a region is relative to the window which may not be top-level in case + \a window corresponds to a native child widget. \a offset is the position of + the native child relative to the top-level window. */ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, @@ -282,7 +286,8 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i QPlatformTextureList *textures, QOpenGLContext *context, bool translucentBackground) { - Q_UNUSED(offset); + if (!qt_window_private(window)->receivedExpose) + return; if (!context->makeCurrent(window)) { qWarning("composeAndFlush: makeCurrent() failed"); @@ -306,7 +311,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i // Textures for renderToTexture widgets. for (int i = 0; i < textures->count(); ++i) { if (!textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) - blit(textures, i, window, deviceWindowRect, d_ptr->blitter); + blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset); } funcs->glEnable(GL_BLEND); @@ -348,17 +353,26 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i textureId = d_ptr->textureId; } else { TextureFlags flags = 0; - textureId = toTexture(deviceRegion(region, window), &d_ptr->textureSize, &flags); + textureId = toTexture(deviceRegion(region, window, offset), &d_ptr->textureSize, &flags); d_ptr->needsSwizzle = (flags & TextureSwizzle) != 0; if (flags & TextureFlip) origin = QOpenGLTextureBlitter::OriginBottomLeft; } if (textureId) { - QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(QRect(QPoint(), d_ptr->textureSize), deviceWindowRect); if (d_ptr->needsSwizzle) d_ptr->blitter->setSwizzleRB(true); - d_ptr->blitter->blit(textureId, target, origin); + // offset is usually (0, 0) unless we have native child widgets. + if (offset.isNull()) { + d_ptr->blitter->blit(textureId, QMatrix4x4(), origin); + } else { + // The backingstore is for the entire tlw. offset tells the position of the native child in the tlw. + const QRect srcRect = toBottomLeftRect(deviceWindowRect.translated(offset), d_ptr->textureSize.height()); + const QMatrix3x3 source = QOpenGLTextureBlitter::sourceTransform(deviceRect(srcRect, window), + d_ptr->textureSize, + origin); + d_ptr->blitter->blit(textureId, QMatrix4x4(), source); + } if (d_ptr->needsSwizzle) d_ptr->blitter->setSwizzleRB(false); } @@ -366,7 +380,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i // Textures for renderToTexture widgets that have WA_AlwaysStackOnTop set. for (int i = 0; i < textures->count(); ++i) { if (textures->flags(i).testFlag(QPlatformTextureList::StacksOnTop)) - blit(textures, i, window, deviceWindowRect, d_ptr->blitter); + blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset); } funcs->glDisable(GL_BLEND); @@ -413,6 +427,8 @@ QImage QPlatformBackingStore::toImage() const If the image has to be flipped (e.g. because the texture is attached to an FBO), \a flags will be set to include \c TextureFlip. + + \note \a dirtyRegion is relative to the backingstore so no adjustment is needed. */ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const { diff --git a/src/gui/text/qtextlayout.cpp b/src/gui/text/qtextlayout.cpp index d68a59fae3..9f046af47c 100644 --- a/src/gui/text/qtextlayout.cpp +++ b/src/gui/text/qtextlayout.cpp @@ -2617,7 +2617,7 @@ void QTextLine::draw(QPainter *p, const QPointF &pos, const QTextLayout::FormatR inside the line, taking account of the \a edge. If \a cursorPos is not a valid cursor position, the nearest valid - cursor position will be used instead, and cpos will be modified to + cursor position will be used instead, and \a cursorPos will be modified to point to this valid cursor position. \sa xToCursor() diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index b4eda3477e..f591abc28b 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -254,6 +254,10 @@ void QHttpNetworkConnectionChannel::handleUnexpectedEOF() close(); reply->d_func()->errorString = connection->d_func()->errorDetail(QNetworkReply::RemoteHostClosedError, socket); emit reply->finishedWithError(QNetworkReply::RemoteHostClosedError, reply->d_func()->errorString); + reply = 0; + if (protocolHandler) + protocolHandler->setReply(0); + request = QHttpNetworkRequest(); QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } else { reconnectAttempts--; diff --git a/src/network/kernel/qhostinfo_winrt.cpp b/src/network/kernel/qhostinfo_winrt.cpp index 3d2344726b..1840bebd39 100644 --- a/src/network/kernel/qhostinfo_winrt.cpp +++ b/src/network/kernel/qhostinfo_winrt.cpp @@ -33,6 +33,7 @@ #include "qhostinfo_p.h" +#include <qfunctions_winrt.h> #include <qurl.h> #include <wrl.h> @@ -49,6 +50,8 @@ using namespace ABI::Windows::Networking::Sockets; QT_BEGIN_NAMESPACE +#define E_NO_SUCH_HOST 0x80072af9 + //#define QHOSTINFO_DEBUG QHostInfo QHostInfoAgent::fromName(const QString &hostName) @@ -74,19 +77,22 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) ComPtr<IHostNameFactory> hostnameFactory; HRESULT hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), IID_PPV_ARGS(&hostnameFactory)); - Q_ASSERT_X(SUCCEEDED(hr), Q_FUNC_INFO, qPrintable(qt_error_string(hr))); + Q_ASSERT_SUCCEEDED(hr); ComPtr<IHostName> host; HStringReference hostNameRef((const wchar_t*)hostName.utf16()); - hostnameFactory->CreateHostName(hostNameRef.Get(), &host); + hr = hostnameFactory->CreateHostName(hostNameRef.Get(), &host); + Q_ASSERT_SUCCEEDED(hr); ComPtr<IDatagramSocketStatics> datagramSocketStatics; - GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &datagramSocketStatics); + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &datagramSocketStatics); + Q_ASSERT_SUCCEEDED(hr); ComPtr<IAsyncOperation<IVectorView<EndpointPair *> *>> op; - datagramSocketStatics->GetEndpointPairsAsync(host.Get(), + hr = datagramSocketStatics->GetEndpointPairsAsync(host.Get(), HString::MakeReference(L"0").Get(), &op); + Q_ASSERT_SUCCEEDED(hr); ComPtr<IVectorView<EndpointPair *>> endpointPairs; hr = op->GetResults(&endpointPairs); @@ -98,26 +104,35 @@ QHostInfo QHostInfoAgent::fromName(const QString &hostName) return results; } - if (!endpointPairs) + if (hr == E_NO_SUCH_HOST || !endpointPairs) { + results.setError(QHostInfo::HostNotFound); + results.setErrorString(tr("Host %1 could not be found.").arg(hostName)); return results; + } + Q_ASSERT_SUCCEEDED(hr); unsigned int size; - endpointPairs->get_Size(&size); + hr = endpointPairs->get_Size(&size); + Q_ASSERT_SUCCEEDED(hr); QList<QHostAddress> addresses; for (unsigned int i = 0; i < size; ++i) { ComPtr<IEndpointPair> endpointpair; - endpointPairs->GetAt(i, &endpointpair); + hr = endpointPairs->GetAt(i, &endpointpair); + Q_ASSERT_SUCCEEDED(hr); ComPtr<IHostName> remoteHost; - endpointpair->get_RemoteHostName(&remoteHost); + hr = endpointpair->get_RemoteHostName(&remoteHost); + Q_ASSERT_SUCCEEDED(hr); if (!remoteHost) continue; HostNameType type; - remoteHost->get_Type(&type); + hr = remoteHost->get_Type(&type); + Q_ASSERT_SUCCEEDED(hr); if (type == HostNameType_DomainName) continue; HString name; - remoteHost->get_CanonicalName(name.GetAddressOf()); + hr = remoteHost->get_CanonicalName(name.GetAddressOf()); + Q_ASSERT_SUCCEEDED(hr); UINT32 length; PCWSTR rawString = name.GetRawBuffer(&length); QHostAddress addr; diff --git a/src/network/kernel/qnetworkinterface_winrt.cpp b/src/network/kernel/qnetworkinterface_winrt.cpp index 18bfcaabda..1e22ab15da 100644 --- a/src/network/kernel/qnetworkinterface_winrt.cpp +++ b/src/network/kernel/qnetworkinterface_winrt.cpp @@ -89,6 +89,9 @@ static QNetworkInterfacePrivate *interfaceFromProfile(IConnectionProfile *profil ComPtr<INetworkAdapter> adapter; hr = profile->get_NetworkAdapter(&adapter); + // Indicates that no internet connection is available/the device is in airplane mode + if (hr == E_INVALIDARG) + return 0; Q_ASSERT_SUCCEEDED(hr); UINT32 type; hr = adapter->get_IanaInterfaceType(&type); diff --git a/src/platformsupport/eglconvenience/eglconvenience.pri b/src/platformsupport/eglconvenience/eglconvenience.pri index 1cab1e556f..f1e0d58a6d 100644 --- a/src/platformsupport/eglconvenience/eglconvenience.pri +++ b/src/platformsupport/eglconvenience/eglconvenience.pri @@ -23,6 +23,7 @@ contains(QT_CONFIG,egl) { $$PWD/qxlibeglintegration_p.h SOURCES += \ $$PWD/qxlibeglintegration.cpp + LIBS_PRIVATE += $$QMAKE_LIBS_X11 } CONFIG += egl } diff --git a/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h b/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h index 12787d03ae..648b129579 100644 --- a/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h +++ b/src/platformsupport/eglconvenience/qeglstreamconvenience_p.h @@ -84,6 +84,15 @@ typedef const char *(EGLAPIENTRYP PFNEGLQUERYOUTPUTPORTSTRINGEXTPROC) (EGLDispla typedef void *EGLStreamKHR; typedef quint64 EGLuint64KHR; #define EGL_NO_STREAM_KHR ((EGLStreamKHR)0) +#define EGL_STREAM_STATE_KHR 0x3214 +#define EGL_STREAM_STATE_CREATED_KHR 0x3215 +#define EGL_STREAM_STATE_CONNECTING_KHR 0x3216 +#define EGL_STREAM_STATE_EMPTY_KHR 0x3217 +#define EGL_STREAM_STATE_NEW_FRAME_AVAILABLE_KHR 0x3218 +#define EGL_STREAM_STATE_OLD_FRAME_AVAILABLE_KHR 0x3219 +#define EGL_STREAM_STATE_DISCONNECTED_KHR 0x321A +#define EGL_BAD_STREAM_KHR 0x321B +#define EGL_BAD_STATE_KHR 0x321C typedef EGLStreamKHR (EGLAPIENTRYP PFNEGLCREATESTREAMKHRPROC) (EGLDisplay dpy, const EGLint *attrib_list); typedef EGLBoolean (EGLAPIENTRYP PFNEGLDESTROYSTREAMKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream); typedef EGLBoolean (EGLAPIENTRYP PFNEGLSTREAMATTRIBKHRPROC) (EGLDisplay dpy, EGLStreamKHR stream, EGLenum attribute, EGLint value); diff --git a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp index c4ebc5c51d..76d8aab8f2 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp +++ b/src/platformsupport/input/evdevmouse/qevdevmousehandler.cpp @@ -43,6 +43,7 @@ #include <qplatformdefs.h> #include <private/qcore_unix_p.h> // overrides QT_OPEN +#include <private/qhighdpiscaling_p.h> #include <errno.h> @@ -141,7 +142,8 @@ bool QEvdevMouseHandler::getHardwareMaximum() m_hardwareHeight = absInfo.maximum - absInfo.minimum; - QRect g = QGuiApplication::primaryScreen()->virtualGeometry(); + QScreen *primaryScreen = QGuiApplication::primaryScreen(); + QRect g = QHighDpi::toNativePixels(primaryScreen->virtualGeometry(), primaryScreen); m_hardwareScalerX = static_cast<qreal>(m_hardwareWidth) / (g.right() - g.left()); m_hardwareScalerY = static_cast<qreal>(m_hardwareHeight) / (g.bottom() - g.top()); diff --git a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp index 805397f021..68db0b26ba 100644 --- a/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp +++ b/src/platformsupport/input/evdevmouse/qevdevmousemanager.cpp @@ -41,6 +41,7 @@ #include <QtPlatformSupport/private/qdevicediscovery_p.h> #include <private/qguiapplication_p.h> #include <private/qinputdevicemanager_p_p.h> +#include <private/qhighdpiscaling_p.h> QT_BEGIN_NAMESPACE @@ -106,7 +107,8 @@ QEvdevMouseManager::~QEvdevMouseManager() void QEvdevMouseManager::clampPosition() { // clamp to screen geometry - QRect g = QGuiApplication::primaryScreen()->virtualGeometry(); + QScreen *primaryScreen = QGuiApplication::primaryScreen(); + QRect g = QHighDpi::toNativePixels(primaryScreen->virtualGeometry(), primaryScreen); if (m_x + m_xoffset < g.left()) m_x = g.left() - m_xoffset; else if (m_x + m_xoffset > g.right()) diff --git a/src/platformsupport/input/libinput/qlibinputpointer.cpp b/src/platformsupport/input/libinput/qlibinputpointer.cpp index 48e5a6cf1c..55339a841a 100644 --- a/src/platformsupport/input/libinput/qlibinputpointer.cpp +++ b/src/platformsupport/input/libinput/qlibinputpointer.cpp @@ -36,6 +36,7 @@ #include <QtGui/QGuiApplication> #include <QtGui/QScreen> #include <qpa/qwindowsysteminterface.h> +#include <private/qhighdpiscaling_p.h> QT_BEGIN_NAMESPACE @@ -81,7 +82,8 @@ void QLibInputPointer::processMotion(libinput_event_pointer *e) { const double dx = libinput_event_pointer_get_dx(e); const double dy = libinput_event_pointer_get_dy(e); - const QRect g = QGuiApplication::primaryScreen()->virtualGeometry(); + QScreen * const primaryScreen = QGuiApplication::primaryScreen(); + const QRect g = QHighDpi::toNativePixels(primaryScreen->virtualGeometry(), primaryScreen); m_pos.setX(qBound(g.left(), qRound(m_pos.x() + dx), g.right())); m_pos.setY(qBound(g.top(), qRound(m_pos.y() + dy), g.bottom())); @@ -110,7 +112,9 @@ void QLibInputPointer::processAxis(libinput_event_pointer *e) void QLibInputPointer::setPos(const QPoint &pos) { - const QRect g = QGuiApplication::primaryScreen()->virtualGeometry(); + QScreen * const primaryScreen = QGuiApplication::primaryScreen(); + const QRect g = QHighDpi::toNativePixels(primaryScreen->virtualGeometry(), primaryScreen); + m_pos.setX(qBound(g.left(), pos.x(), g.right())); m_pos.setY(qBound(g.top(), pos.y(), g.bottom())); } diff --git a/src/plugins/bearer/generic/qgenericengine.cpp b/src/plugins/bearer/generic/qgenericengine.cpp index 7f56846179..1e424dc223 100644 --- a/src/plugins/bearer/generic/qgenericengine.cpp +++ b/src/plugins/bearer/generic/qgenericengine.cpp @@ -201,6 +201,9 @@ static QNetworkConfiguration::BearerType qGetInterfaceType(const QString &interf ComPtr<INetworkAdapter> adapter; hr = profile->get_NetworkAdapter(&adapter); + // Indicates that no internet connection is available/the device is in airplane mode + if (hr == E_INVALIDARG) + return QNetworkConfiguration::BearerUnknown; Q_ASSERT_SUCCEEDED(hr); GUID id; hr = adapter->get_NetworkAdapterId(&id); diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp index b86dfa3546..3bd6e76c52 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dintegration.cpp @@ -39,12 +39,12 @@ #include "qwindowsdirect2dwindow.h" #include "qwindowscontext.h" -#include "qwindowsguieventdispatcher.h" #include <qplatformdefs.h> #include <QtCore/QCoreApplication> #include <QtGui/private/qpixmap_raster_p.h> #include <QtGui/qpa/qwindowsysteminterface.h> +#include <QtPlatformSupport/private/qwindowsguieventdispatcher_p.h> QT_BEGIN_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp index 10c8091815..064b9f6306 100644 --- a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp @@ -219,6 +219,11 @@ QDpi QEGLDeviceIntegration::logicalDpi() const 25.4 * s.height() / ps.height()); } +qreal QEGLDeviceIntegration::pixelDensity() const +{ + return logicalDpi().first / qreal(100); +} + Qt::ScreenOrientation QEGLDeviceIntegration::nativeOrientation() const { return Qt::PrimaryOrientation; diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h index 97082df7f5..5ec98b37d1 100644 --- a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h +++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.h @@ -75,6 +75,7 @@ public: virtual QSizeF physicalScreenSize() const; virtual QSize screenSize() const; virtual QDpi logicalDpi() const; + virtual qreal pixelDensity() const; virtual Qt::ScreenOrientation nativeOrientation() const; virtual Qt::ScreenOrientation orientation() const; virtual int screenDepth() const; diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp index 6f8d0b88dd..a14e68b667 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp +++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp @@ -82,6 +82,11 @@ QDpi QEglFSScreen::logicalDpi() const return qt_egl_device_integration()->logicalDpi(); } +qreal QEglFSScreen::pixelDensity() const +{ + return qt_egl_device_integration()->pixelDensity(); +} + Qt::ScreenOrientation QEglFSScreen::nativeOrientation() const { return qt_egl_device_integration()->nativeOrientation(); diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.h b/src/plugins/platforms/eglfs/qeglfsscreen.h index 44e9da4a5a..8f1d87ea25 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.h +++ b/src/plugins/platforms/eglfs/qeglfsscreen.h @@ -55,6 +55,7 @@ public: QSizeF physicalSize() const Q_DECL_OVERRIDE; QDpi logicalDpi() const Q_DECL_OVERRIDE; + qreal pixelDensity() const Q_DECL_OVERRIDE; Qt::ScreenOrientation nativeOrientation() const Q_DECL_OVERRIDE; Qt::ScreenOrientation orientation() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/ios/qiosscreen.h b/src/plugins/platforms/ios/qiosscreen.h index a0aa922a31..f31be9756c 100644 --- a/src/plugins/platforms/ios/qiosscreen.h +++ b/src/plugins/platforms/ios/qiosscreen.h @@ -73,7 +73,7 @@ private: QRect m_geometry; QRect m_availableGeometry; int m_depth; - uint m_unscaledDpi; + uint m_pixelDensity; QSizeF m_physicalSize; QIOSOrientationListener *m_orientationListener; }; diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm index 3e16efcd22..5cb06d591d 100644 --- a/src/plugins/platforms/ios/qiosscreen.mm +++ b/src/plugins/platforms/ios/qiosscreen.mm @@ -170,23 +170,28 @@ QIOSScreen::QIOSScreen(UIScreen *screen) if (screen == [UIScreen mainScreen]) { QString deviceIdentifier = deviceModelIdentifier(); - if (deviceIdentifier == QLatin1String("iPhone2,1") /* iPhone 3GS */ - || deviceIdentifier == QLatin1String("iPod3,1") /* iPod touch 3G */) { + // Based on https://en.wikipedia.org/wiki/List_of_iOS_devices#Display + + // iPhone (1st gen), 3G, 3GS, and iPod Touch (1st–3rd gen) are 18-bit devices + if (deviceIdentifier.contains(QRegularExpression("^(iPhone1,[12]|iPhone2,1|iPod[1-3],1)$"))) m_depth = 18; - } else { + else m_depth = 24; - } - if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad - && !deviceIdentifier.contains(QRegularExpression("^iPad2,[567]$")) /* excluding iPad Mini */) { - m_unscaledDpi = 132; + if (deviceIdentifier.contains(QRegularExpression("^iPhone(7,1|8,2)$"))) { + // iPhone 6 Plus or iPhone 6S Plus + m_pixelDensity = 401; + } else if (deviceIdentifier.contains(QRegularExpression("^iPad(1,1|2,[1-4]|3,[1-6]|4,[1-3]|5,[3-4]|6,[7-8])$"))) { + // All iPads except the iPad Mini series + m_pixelDensity = 132 * devicePixelRatio(); } else { - m_unscaledDpi = 163; // Regular iPhone DPI + // All non-Plus iPhones, and iPad Minis + m_pixelDensity = 163 * devicePixelRatio(); } } else { // External display, hard to say m_depth = 24; - m_unscaledDpi = 96; + m_pixelDensity = 96; } for (UIWindow *existingWindow in [[UIApplication sharedApplication] windows]) { @@ -249,7 +254,7 @@ void QIOSScreen::updateProperties() if (m_geometry != previousGeometry) { const qreal millimetersPerInch = 25.4; - m_physicalSize = QSizeF(m_geometry.size()) / m_unscaledDpi * millimetersPerInch; + m_physicalSize = QSizeF(m_geometry.size() * devicePixelRatio()) / m_pixelDensity * millimetersPerInch; } // At construction time, we don't yet have an associated QScreen, but we still want diff --git a/src/plugins/platforms/windows/openglblacklists/default.json b/src/plugins/platforms/windows/openglblacklists/default.json index a5d42719a9..1e003e2d15 100644 --- a/src/plugins/platforms/windows/openglblacklists/default.json +++ b/src/plugins/platforms/windows/openglblacklists/default.json @@ -57,9 +57,9 @@ }, { "id": 5, - "description": "Intel GMA 3150 crashes (QTBUG-43243)", + "description": "Intel GMA 3150 (QTBUG-43243), Mobile Intel 945GM (QTBUG-47435) crash", "vendor_id": "0x8086", - "device_id": [ "0xA001", "0xA011" ], + "device_id": [ "0xA001", "0xA011", "0x27A0" ], "os": { "type": "win" }, diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index 3f19e4401a..bd5c35037d 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -84,7 +84,8 @@ void QWindowsBackingStore::flush(QWindow *window, const QRegion ®ion, if ((flags & Qt::FramelessWindowHint) && QWindowsWindow::setWindowLayered(rw->handle(), flags, hasAlpha, rw->opacity()) && hasAlpha) { // Windows with alpha: Use blend function to update. QRect r = QHighDpi::toNativePixels(window->frameGeometry(), window); - QPoint frameOffset(QHighDpi::toNativePixels(QPoint(window->frameMargins().left(), window->frameMargins().top()), window)); + QPoint frameOffset(QHighDpi::toNativePixels(QPoint(window->frameMargins().left(), window->frameMargins().top()), + static_cast<const QWindow *>(Q_NULLPTR))); QRect dirtyRect = br.translated(offset + frameOffset); SIZE size = {r.width(), r.height()}; diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 1fbef61029..800b79347c 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -67,19 +67,14 @@ Q_GUI_EXPORT HBITMAP qt_createIconMask(const QBitmap &bitmap); \ingroup qt-lighthouse-win */ -QWindowsCursorCacheKey::QWindowsCursorCacheKey(const QCursor &c) - : shape(c.shape()), bitmapCacheKey(0), maskCacheKey(0) +QWindowsPixmapCursorCacheKey::QWindowsPixmapCursorCacheKey(const QCursor &c) + : bitmapCacheKey(c.pixmap().cacheKey()), maskCacheKey(0) { - if (shape == Qt::BitmapCursor) { - const qint64 pixmapCacheKey = c.pixmap().cacheKey(); - if (pixmapCacheKey) { - bitmapCacheKey = pixmapCacheKey; - } else { - Q_ASSERT(c.bitmap()); - Q_ASSERT(c.mask()); - bitmapCacheKey = c.bitmap()->cacheKey(); - maskCacheKey = c.mask()->cacheKey(); - } + if (!bitmapCacheKey) { + Q_ASSERT(c.bitmap()); + Q_ASSERT(c.mask()); + bitmapCacheKey = c.bitmap()->cacheKey(); + maskCacheKey = c.mask()->cacheKey(); } } @@ -206,6 +201,17 @@ static HCURSOR createBitmapCursor(const QImage &bbits, const QImage &mbits, #endif } +// Create a cursor from image and mask of the format QImage::Format_Mono. +static HCURSOR createBitmapCursor(const QCursor &cursor) +{ + Q_ASSERT(cursor.shape() == Qt::BitmapCursor && cursor.bitmap()); + const QImage bbits = cursor.bitmap()->toImage().convertToFormat(QImage::Format_Mono); + const QImage mbits = cursor.mask()->toImage().convertToFormat(QImage::Format_Mono); + const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1)); + const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1)); + return createBitmapCursor(bbits, mbits, cursor.hotSpot(), invb, invm); +} + static inline QSize systemCursorSize() { return QSize(GetSystemMetrics(SM_CXCURSOR), GetSystemMetrics(SM_CYCURSOR)); } static inline QSize standardCursorSize() { return QSize(32, 32); } @@ -215,7 +221,7 @@ static inline QSize standardCursorSize() { return QSize(32, 32); } // createBitmapCursor() only work for standard sizes (32,48,64...), which does // not work when scaling the 16x16 openhand cursor bitmaps to 150% (resulting // in a non-standard 24x24 size). -static QCursor createPixmapCursorFromData(const QSize &systemCursorSize, +static QWindowsCursor::PixmapCursor createPixmapCursorFromData(const QSize &systemCursorSize, // The cursor size the bitmap is targeted for const QSize &bitmapTargetCursorSize, // The actual size of the bitmap data @@ -233,10 +239,10 @@ static QCursor createPixmapCursorFromData(const QSize &systemCursorSize, rawImage = rawImage.transformed(transform, Qt::SmoothTransformation); } const QPoint hotSpot(rawImage.width() / 2, rawImage.height() / 2); - return QCursor(rawImage, hotSpot.x(), hotSpot.y()); + return QWindowsCursor::PixmapCursor(rawImage, hotSpot); } -QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) +QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) { // Non-standard Windows cursors are created from bitmaps static const uchar vsplit_bits[] = { @@ -412,14 +418,14 @@ QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) case Qt::ClosedHandCursor: return createPixmapCursorFromData(systemCursorSize(), standardCursorSize(), 16, closedhand_bits, closedhandm_bits); case Qt::DragCopyCursor: - return QCursor(QPixmap(copyDragCursorXpmC), 0, 0); + return QWindowsCursor::PixmapCursor(QPixmap(copyDragCursorXpmC), QPoint(0, 0)); case Qt::DragMoveCursor: - return QCursor(QPixmap(moveDragCursorXpmC), 0, 0); + return QWindowsCursor::PixmapCursor(QPixmap(moveDragCursorXpmC), QPoint(0, 0)); case Qt::DragLinkCursor: - return QCursor(QPixmap(linkDragCursorXpmC), 0, 0); + return QWindowsCursor::PixmapCursor(QPixmap(linkDragCursorXpmC), QPoint(0, 0)); } - return QCursor(); + return QWindowsCursor::PixmapCursor(); } #else // Q_OS_WINCE || QT_NO_IMAGEFORMAT_PNG struct QWindowsCustomPngCursor { @@ -430,7 +436,7 @@ struct QWindowsCustomPngCursor { int hotSpotY; }; -QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) +QWindowsCursor::PixmapCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) { static const QWindowsCustomPngCursor pngCursors[] = { { Qt::SplitVCursor, 32, "splitvcursor_32.png", 11, 11 }, @@ -473,11 +479,11 @@ QCursor QWindowsCursor::customCursor(Qt::CursorShape cursorShape) } if (!bestFit) - return QCursor(); + return PixmapCursor(); const QPixmap rawImage(QStringLiteral(":/qt-project.org/windows/cursors/images/") + QString::fromLatin1(bestFit->fileName)); - return QCursor(rawImage, bestFit->hotSpotX, bestFit->hotSpotY); + return PixmapCursor(rawImage, QPoint(bestFit->hotSpotX, bestFit->hotSpotY)); } #endif // Q_OS_WINCE || QT_NO_IMAGEFORMAT_PNG @@ -486,8 +492,10 @@ struct QWindowsStandardCursorMapping { LPCWSTR resource; }; -HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c) +HCURSOR QWindowsCursor::createCursorFromShape(Qt::CursorShape cursorShape) { + Q_ASSERT(cursorShape != Qt::BitmapCursor); + static const QWindowsStandardCursorMapping standardCursors[] = { { Qt::ArrowCursor, IDC_ARROW}, { Qt::UpArrowCursor, IDC_UPARROW }, @@ -505,18 +513,7 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c) { Qt::PointingHandCursor, IDC_HAND } }; - const Qt::CursorShape cursorShape = c.shape(); switch (cursorShape) { - case Qt::BitmapCursor: { - const QPixmap pixmap = c.pixmap(); - if (!pixmap.isNull()) - return QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot()); - const QImage bbits = c.bitmap()->toImage().convertToFormat(QImage::Format_Mono); - const QImage mbits = c.mask()->toImage().convertToFormat(QImage::Format_Mono); - const bool invb = bbits.colorCount() > 1 && qGray(bbits.color(0)) < qGray(bbits.color(1)); - const bool invm = mbits.colorCount() > 1 && qGray(mbits.color(0)) < qGray(mbits.color(1)); - return createBitmapCursor(bbits, mbits, c.hotSpot(), invb, invm); - } case Qt::BlankCursor: { QImage blank = QImage(systemCursorSize(), QImage::Format_Mono); blank.fill(0); // ignore color table @@ -529,7 +526,7 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c) case Qt::DragCopyCursor: case Qt::DragMoveCursor: case Qt::DragLinkCursor: - return createSystemCursor(customCursor(cursorShape)); + return QWindowsCursor::createPixmapCursor(customCursor(cursorShape)); default: break; } @@ -554,37 +551,41 @@ HCURSOR QWindowsCursor::createSystemCursor(const QCursor &c) \brief Return cached standard cursor resources or create new ones. */ -QWindowsWindowCursor QWindowsCursor::standardWindowCursor(Qt::CursorShape shape) +CursorHandlePtr QWindowsCursor::standardWindowCursor(Qt::CursorShape shape) { - const QWindowsCursorCacheKey key(shape); - CursorCache::iterator it = m_cursorCache.find(key); - if (it == m_cursorCache.end()) - it = m_cursorCache.insert(key, QWindowsWindowCursor(QCursor(shape))); - return it.value(); + StandardCursorCache::Iterator it = m_standardCursorCache.find(shape); + if (it == m_standardCursorCache.end()) { + if (const HCURSOR hc = QWindowsCursor::createCursorFromShape(shape)) + it = m_standardCursorCache.insert(shape, CursorHandlePtr(new CursorHandle(hc))); + } + return it != m_standardCursorCache.end() ? it.value() : CursorHandlePtr(new CursorHandle); } /*! \brief Return cached pixmap cursor or create new one. */ -QWindowsWindowCursor QWindowsCursor::pixmapWindowCursor(const QCursor &c) +CursorHandlePtr QWindowsCursor::pixmapWindowCursor(const QCursor &c) { - const QWindowsCursorCacheKey cacheKey(c); - CursorCache::iterator it = m_cursorCache.find(cacheKey); - if (it == m_cursorCache.end()) { - if (m_cursorCache.size() > 50) { + const QWindowsPixmapCursorCacheKey cacheKey(c); + PixmapCursorCache::iterator it = m_pixmapCursorCache.find(cacheKey); + if (it == m_pixmapCursorCache.end()) { + if (m_pixmapCursorCache.size() > 50) { // Prevent the cursor cache from growing indefinitely hitting GDI resource // limits if new pixmap cursors are created repetitively by purging out // all-noncurrent pixmap cursors (QTBUG-43515) const HCURSOR currentCursor = GetCursor(); - for (it = m_cursorCache.begin(); it != m_cursorCache.end() ; ) { - if (it.key().bitmapCacheKey && it.value().handle() != currentCursor) - it = m_cursorCache.erase(it); + for (it = m_pixmapCursorCache.begin(); it != m_pixmapCursorCache.end() ; ) { + if (it.value()->handle() != currentCursor) + it = m_pixmapCursorCache.erase(it); else ++it; } } - it = m_cursorCache.insert(cacheKey, QWindowsWindowCursor(c)); + const QPixmap pixmap = c.pixmap(); + const HCURSOR hc = pixmap.isNull() + ? createBitmapCursor(c) : QWindowsCursor::createPixmapCursor(pixmap, c.hotSpot()); + it = m_pixmapCursorCache.insert(cacheKey, CursorHandlePtr(new CursorHandle(hc))); } return it.value(); } @@ -606,13 +607,13 @@ void QWindowsCursor::changeCursor(QCursor *cursorIn, QWindow *window) if (!window) return; if (!cursorIn) { - QWindowsWindow::baseWindowOf(window)->setCursor(QWindowsWindowCursor()); + QWindowsWindow::baseWindowOf(window)->setCursor(CursorHandlePtr(new CursorHandle)); return; } - const QWindowsWindowCursor wcursor = + const CursorHandlePtr wcursor = cursorIn->shape() == Qt::BitmapCursor ? pixmapWindowCursor(*cursorIn) : standardWindowCursor(cursorIn->shape()); - if (wcursor.handle()) { + if (wcursor->handle()) { QWindowsWindow::baseWindowOf(window)->setCursor(wcursor); } else { qWarning("%s: Unable to obtain system cursor for %d", @@ -658,78 +659,11 @@ void QWindowsCursor::setPos(const QPoint &pos) \brief Per-Window cursor. Contains a QCursor and manages its associated system cursor handle resource. - Based on QSharedDataPointer, so that it can be passed around and - used as a property of QWindowsBaseWindow. - \internal \ingroup qt-lighthouse-win \sa QWindowsCursor */ -class QWindowsWindowCursorData : public QSharedData -{ -public: - QWindowsWindowCursorData() : m_cursor(Qt::ArrowCursor), m_handle(0) {} - explicit QWindowsWindowCursorData(const QCursor &c); - ~QWindowsWindowCursorData(); - - const QCursor m_cursor; - const HCURSOR m_handle; -}; - -QWindowsWindowCursorData::QWindowsWindowCursorData(const QCursor &c) : - m_cursor(c), - m_handle(QWindowsCursor::createSystemCursor(c)) -{ -} - -QWindowsWindowCursorData::~QWindowsWindowCursorData() -{ - if (m_handle) - DestroyCursor(m_handle); -} - -QWindowsWindowCursor::QWindowsWindowCursor() : - m_data(new QWindowsWindowCursorData) -{ -} - -QWindowsWindowCursor::QWindowsWindowCursor(const QCursor &c) : - m_data(new QWindowsWindowCursorData(c)) -{ -} - -QWindowsWindowCursor::~QWindowsWindowCursor() -{ -} - -QWindowsWindowCursor::QWindowsWindowCursor(const QWindowsWindowCursor &rhs) : - m_data(rhs.m_data) -{ -} - -QWindowsWindowCursor & QWindowsWindowCursor::operator =(const QWindowsWindowCursor &rhs) -{ - if (this != &rhs) - m_data.operator =(rhs.m_data); - return *this; -} - -bool QWindowsWindowCursor::isNull() const -{ - return m_data->m_handle == 0; -} - -QCursor QWindowsWindowCursor::cursor() const -{ - return m_data->m_cursor; -} - -HCURSOR QWindowsWindowCursor::handle() const -{ - return m_data->m_handle; -} - QT_END_NAMESPACE #endif // !QT_NO_CURSOR diff --git a/src/plugins/platforms/windows/qwindowscursor.h b/src/plugins/platforms/windows/qwindowscursor.h index f1763ddd7d..ac9e87d1fb 100644 --- a/src/plugins/platforms/windows/qwindowscursor.h +++ b/src/plugins/platforms/windows/qwindowscursor.h @@ -37,51 +37,49 @@ #include "qtwindows_additional.h" #include <qpa/qplatformcursor.h> -#include <QtCore/QSharedDataPointer> +#include <QtCore/QSharedPointer> #include <QtCore/QHash> QT_BEGIN_NAMESPACE -class QWindowsWindowCursorData; - -struct QWindowsCursorCacheKey +struct QWindowsPixmapCursorCacheKey { - explicit QWindowsCursorCacheKey(const QCursor &c); - explicit QWindowsCursorCacheKey(Qt::CursorShape s) : shape(s), bitmapCacheKey(0), maskCacheKey(0) {} - QWindowsCursorCacheKey() : shape(Qt::CustomCursor), bitmapCacheKey(0), maskCacheKey(0) {} + explicit QWindowsPixmapCursorCacheKey(const QCursor &c); - Qt::CursorShape shape; qint64 bitmapCacheKey; qint64 maskCacheKey; }; -inline bool operator==(const QWindowsCursorCacheKey &k1, const QWindowsCursorCacheKey &k2) +inline bool operator==(const QWindowsPixmapCursorCacheKey &k1, const QWindowsPixmapCursorCacheKey &k2) { - return k1.shape == k2.shape && k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey; + return k1.bitmapCacheKey == k2.bitmapCacheKey && k1.maskCacheKey == k2.maskCacheKey; } -inline uint qHash(const QWindowsCursorCacheKey &k, uint seed) Q_DECL_NOTHROW +inline uint qHash(const QWindowsPixmapCursorCacheKey &k, uint seed) Q_DECL_NOTHROW { - return (uint(k.shape) + uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed; + return (uint(k.bitmapCacheKey) + uint(k.maskCacheKey)) ^ seed; } -class QWindowsWindowCursor +class CursorHandle { + Q_DISABLE_COPY(CursorHandle) public: - QWindowsWindowCursor(); - explicit QWindowsWindowCursor(const QCursor &c); - ~QWindowsWindowCursor(); - QWindowsWindowCursor(const QWindowsWindowCursor &c); - QWindowsWindowCursor &operator=(const QWindowsWindowCursor &c); + explicit CursorHandle(HCURSOR hcursor = Q_NULLPTR) : m_hcursor(hcursor) {} + ~CursorHandle() + { + if (m_hcursor) + DestroyCursor(m_hcursor); + } - bool isNull() const; - QCursor cursor() const; - HCURSOR handle() const; + bool isNull() const { return !m_hcursor; } + HCURSOR handle() const { return m_hcursor; } private: - QSharedDataPointer<QWindowsWindowCursorData> m_data; + const HCURSOR m_hcursor; }; +typedef QSharedPointer<CursorHandle> CursorHandlePtr; + class QWindowsCursor : public QPlatformCursor { public: @@ -91,6 +89,13 @@ public: CursorSuppressed // Cursor suppressed by touch interaction (Windows 8). }; + struct PixmapCursor { + explicit PixmapCursor(const QPixmap &pix = QPixmap(), const QPoint &h = QPoint()) : pixmap(pix), hotSpot(h) {} + + QPixmap pixmap; + QPoint hotSpot; + }; + QWindowsCursor(); void changeCursor(QCursor * widgetCursor, QWindow * widget) Q_DECL_OVERRIDE; @@ -98,18 +103,22 @@ public: void setPos(const QPoint &pos) Q_DECL_OVERRIDE; static HCURSOR createPixmapCursor(const QPixmap &pixmap, const QPoint &hotSpot); - static HCURSOR createSystemCursor(const QCursor &c); - static QCursor customCursor(Qt::CursorShape cursorShape); + static HCURSOR createPixmapCursor(const PixmapCursor &pc) { return createPixmapCursor(pc.pixmap, pc.hotSpot); } + static PixmapCursor customCursor(Qt::CursorShape cursorShape); + + static HCURSOR createCursorFromShape(Qt::CursorShape cursorShape); static QPoint mousePosition(); static CursorState cursorState(); - QWindowsWindowCursor standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor); - QWindowsWindowCursor pixmapWindowCursor(const QCursor &c); + CursorHandlePtr standardWindowCursor(Qt::CursorShape s = Qt::ArrowCursor); + CursorHandlePtr pixmapWindowCursor(const QCursor &c); private: - typedef QHash<QWindowsCursorCacheKey, QWindowsWindowCursor> CursorCache; + typedef QHash<Qt::CursorShape, CursorHandlePtr> StandardCursorCache; + typedef QHash<QWindowsPixmapCursorCacheKey, CursorHandlePtr> PixmapCursorCache; - CursorCache m_cursorCache; + StandardCursorCache m_standardCursorCache; + PixmapCursorCache m_pixmapCursorCache; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index fcd9911a56..5435c4820a 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -218,23 +218,14 @@ public: STDMETHOD(GiveFeedback)(DWORD dwEffect); private: - class DragCursorHandle { - Q_DISABLE_COPY(DragCursorHandle) - public: - DragCursorHandle(HCURSOR c) : cursor(c) {} - ~DragCursorHandle() { DestroyCursor(cursor); } - const HCURSOR cursor; - }; - typedef QSharedPointer<DragCursorHandle> DragCursorHandlePtr; - struct CursorEntry { CursorEntry() : cacheKey(0) {} - CursorEntry(const QPixmap &p, qint64 cK, const DragCursorHandlePtr &c, const QPoint &h) : + CursorEntry(const QPixmap &p, qint64 cK, const CursorHandlePtr &c, const QPoint &h) : pixmap(p), cacheKey(cK), cursor(c), hotSpot(h) {} QPixmap pixmap; qint64 cacheKey; // Cache key of cursor - DragCursorHandlePtr cursor; + CursorHandlePtr cursor; QPoint hotSpot; }; @@ -273,7 +264,7 @@ QWindowsOleDropSource::~QWindowsOleDropSource() QDebug operator<<(QDebug d, const QWindowsOleDropSource::CursorEntry &e) { d << "CursorEntry:" << e.pixmap.size() << '#' << e.cacheKey - << "HCURSOR" << e.cursor->cursor << "hotspot:" << e.hotSpot; + << "HCURSOR" << e.cursor->handle() << "hotspot:" << e.hotSpot; return d; } #endif // !QT_NO_DEBUG_STREAM @@ -343,7 +334,7 @@ void QWindowsOleDropSource::createCursors() } if (const HCURSOR sysCursor = QWindowsCursor::createPixmapCursor(newPixmap, newHotSpot)) { - const CursorEntry entry(newPixmap, cacheKey, DragCursorHandlePtr(new DragCursorHandle(sysCursor)), newHotSpot); + const CursorEntry entry(newPixmap, cacheKey, CursorHandlePtr(new CursorHandle(sysCursor)), newHotSpot); if (it == m_cursors.end()) m_cursors.insert(action, entry); else @@ -456,7 +447,7 @@ QWindowsOleDropSource::GiveFeedback(DWORD dwEffect) const CursorEntry &e = it.value(); switch (m_mode) { case MouseDrag: - SetCursor(e.cursor->cursor); + SetCursor(e.cursor->handle()); break; case TouchDrag: if (!m_touchDragWindow) @@ -718,16 +709,16 @@ QPixmap QWindowsDrag::defaultCursor(Qt::DropAction action) const switch (action) { case Qt::CopyAction: if (m_copyDragCursor.isNull()) - m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor).pixmap(); + m_copyDragCursor = QWindowsCursor::customCursor(Qt::DragCopyCursor).pixmap; return m_copyDragCursor; case Qt::TargetMoveAction: case Qt::MoveAction: if (m_moveDragCursor.isNull()) - m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor).pixmap(); + m_moveDragCursor = QWindowsCursor::customCursor(Qt::DragMoveCursor).pixmap; return m_moveDragCursor; case Qt::LinkAction: if (m_linkDragCursor.isNull()) - m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor).pixmap(); + m_linkDragCursor = QWindowsCursor::customCursor(Qt::DragLinkCursor).pixmap; return m_linkDragCursor; default: break; diff --git a/src/plugins/platforms/windows/qwindowstheme.cpp b/src/plugins/platforms/windows/qwindowstheme.cpp index 33c7ccfdce..877bdfec17 100644 --- a/src/plugins/platforms/windows/qwindowstheme.cpp +++ b/src/plugins/platforms/windows/qwindowstheme.cpp @@ -393,6 +393,8 @@ QVariant QWindowsTheme::themeHint(ThemeHint hint) const return QVariant(booleanSystemParametersInfo(SPI_GETSNAPTODEFBUTTON, false)); case ContextMenuOnMouseRelease: return QVariant(true); + case WheelScrollLines: + return dWordSystemParametersInfo(SPI_GETWHEELSCROLLLINES, 3); default: break; } diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 01e2a804bd..c49682cc26 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -928,6 +928,7 @@ QWindowsWindow::QWindowsWindow(QWindow *aWindow, const QWindowsWindowData &data) m_hdc(0), m_windowState(Qt::WindowNoState), m_opacity(1.0), + m_cursor(new CursorHandle), m_dropTarget(0), m_savedStyle(0), m_format(aWindow->requestedFormat()), @@ -2113,13 +2114,13 @@ bool QWindowsWindow::handleNonClientHitTest(const QPoint &globalPos, LRESULT *re #ifndef QT_NO_CURSOR // Return the default cursor (Arrow) from QWindowsCursor's cache. -static inline QWindowsWindowCursor defaultCursor(const QWindow *w) +static inline CursorHandlePtr defaultCursor(const QWindow *w) { if (QScreen *screen = w->screen()) if (const QPlatformScreen *platformScreen = screen->handle()) if (QPlatformCursor *cursor = platformScreen->cursor()) return static_cast<QWindowsCursor *>(cursor)->standardWindowCursor(Qt::ArrowCursor); - return QWindowsWindowCursor(Qt::ArrowCursor); + return CursorHandlePtr(new CursorHandle(QWindowsCursor::createCursorFromShape(Qt::ArrowCursor))); } // Check whether to apply a new cursor. Either the window in question is @@ -2133,7 +2134,7 @@ static inline bool applyNewCursor(const QWindow *w) for (const QWindow *p = underMouse; p ; p = p->parent()) { if (p == w) return true; - if (!QWindowsWindow::baseWindowOf(p)->cursor().isNull()) + if (!QWindowsWindow::baseWindowOf(p)->cursor()->isNull()) return false; } return false; @@ -2149,25 +2150,25 @@ static inline bool applyNewCursor(const QWindow *w) void QWindowsWindow::applyCursor() { #ifndef QT_NO_CURSOR - if (m_cursor.isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel. + if (m_cursor->isNull()) { // Recurse up to parent with non-null cursor. Set default for toplevel. if (const QWindow *p = window()->parent()) { QWindowsWindow::baseWindowOf(p)->applyCursor(); } else { - SetCursor(defaultCursor(window()).handle()); + SetCursor(defaultCursor(window())->handle()); } } else { - SetCursor(m_cursor.handle()); + SetCursor(m_cursor->handle()); } #endif } -void QWindowsWindow::setCursor(const QWindowsWindowCursor &c) +void QWindowsWindow::setCursor(const CursorHandlePtr &c) { #ifndef QT_NO_CURSOR - if (c.handle() != m_cursor.handle()) { + if (c->handle() != m_cursor->handle()) { const bool apply = applyNewCursor(window()); qCDebug(lcQpaWindows) << window() << __FUNCTION__ - << c.cursor().shape() << " doApply=" << apply; + << c->handle() << " doApply=" << apply; m_cursor = c; if (apply) applyCursor(); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 40d7a3f076..4172a3d850 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -225,9 +225,9 @@ public: #endif // !Q_OS_WINCE #ifndef QT_NO_CURSOR - QWindowsWindowCursor cursor() const { return m_cursor; } + CursorHandlePtr cursor() const { return m_cursor; } #endif - void setCursor(const QWindowsWindowCursor &c); + void setCursor(const CursorHandlePtr &c); void applyCursor(); inline bool testFlag(unsigned f) const { return (m_flags & f) != 0; } @@ -278,7 +278,7 @@ private: Qt::WindowState m_windowState; qreal m_opacity; #ifndef QT_NO_CURSOR - QWindowsWindowCursor m_cursor; + CursorHandlePtr m_cursor; #endif QWindowsOleDropTarget *m_dropTarget; unsigned m_savedStyle; diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 23bb6c16ec..9db5df995a 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -260,8 +260,10 @@ HRESULT QWinRTIntegration::onBackButtonPressed(IInspectable *, IBackPressedEvent Q_D(QWinRTIntegration); QWindow *window = d->mainScreen->topWindow(); QWindowSystemInterface::setSynchronousWindowSystemEvents(true); - const bool pressed = QWindowSystemInterface::handleKeyEvent(window, QEvent::KeyPress, Qt::Key_Back, Qt::NoModifier); - const bool released = QWindowSystemInterface::handleKeyEvent(window, QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier); + const bool pressed = QWindowSystemInterface::handleExtendedKeyEvent(window, QEvent::KeyPress, Qt::Key_Back, Qt::NoModifier, + 0, 0, 0, QString(), false, 1, false); + const bool released = QWindowSystemInterface::handleExtendedKeyEvent(window, QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier, + 0, 0, 0, QString(), false, 1, false); QWindowSystemInterface::setSynchronousWindowSystemEvents(false); args->put_Handled(pressed || released); return S_OK; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index bcc571c3c8..d76f1245e8 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -500,10 +500,7 @@ void QXcbWindow::create() properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS); properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING); - if (platformScreen->syncRequestSupported()) - m_usingSyncProtocol = supportsSyncProtocol(); - else - m_usingSyncProtocol = false; + m_usingSyncProtocol = platformScreen->syncRequestSupported(); if (m_usingSyncProtocol) properties[propertyCount++] = atom(QXcbAtom::_NET_WM_SYNC_REQUEST); diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index b2c5fa7d4d..41c4b4443d 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -176,7 +176,6 @@ public Q_SLOTS: protected: virtual void resolveFormat() { m_format = window()->requestedFormat(); } virtual void *createVisual() { return Q_NULLPTR; } - virtual bool supportsSyncProtocol() { return !window()->supportsOpenGL(); } QXcbScreen *parentScreen(); diff --git a/src/sql/models/qsqlquerymodel.cpp b/src/sql/models/qsqlquerymodel.cpp index 3faea11c70..5a1958708a 100644 --- a/src/sql/models/qsqlquerymodel.cpp +++ b/src/sql/models/qsqlquerymodel.cpp @@ -471,6 +471,7 @@ void QSqlQueryModel::setQuery(const QString &query, const QSqlDatabase &db) void QSqlQueryModel::clear() { Q_D(QSqlQueryModel); + beginResetModel(); d->error = QSqlError(); d->atEnd = true; d->query.clear(); @@ -478,6 +479,7 @@ void QSqlQueryModel::clear() d->colOffsets.clear(); d->bottom = QModelIndex(); d->headers.clear(); + endResetModel(); } /*! diff --git a/src/sql/models/qsqlrelationaltablemodel.cpp b/src/sql/models/qsqlrelationaltablemodel.cpp index 42acf6a73b..ac2d270fc8 100644 --- a/src/sql/models/qsqlrelationaltablemodel.cpp +++ b/src/sql/models/qsqlrelationaltablemodel.cpp @@ -652,9 +652,11 @@ void QSqlRelationalTableModel::revertRow(int row) void QSqlRelationalTableModel::clear() { Q_D(QSqlRelationalTableModel); + beginResetModel(); d->clearChanges(); d->relations.clear(); QSqlTableModel::clear(); + endResetModel(); } diff --git a/src/sql/models/qsqltablemodel.cpp b/src/sql/models/qsqltablemodel.cpp index b0d3e6df9d..740c1b9b5d 100644 --- a/src/sql/models/qsqltablemodel.cpp +++ b/src/sql/models/qsqltablemodel.cpp @@ -1262,8 +1262,10 @@ void QSqlTableModel::setFilter(const QString &filter) void QSqlTableModel::clear() { Q_D(QSqlTableModel); + beginResetModel(); d->clear(); QSqlQueryModel::clear(); + endResetModel(); } /*! \reimp diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index 389539bb18..3a4a3a0d63 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -645,12 +645,6 @@ void QOpenGLWidgetPaintDevice::ensureActiveTarget() GLuint QOpenGLWidgetPrivate::textureId() const { - Q_Q(const QOpenGLWidget); - if (!q->isWindow() && q->internalWinId()) { - qWarning("QOpenGLWidget cannot be used as a native child widget. Consider setting " - "Qt::WA_DontCreateNativeAncestors and Qt::AA_DontCreateNativeWidgetSiblings"); - return 0; - } return resolvedFbo ? resolvedFbo->texture() : (fbo ? fbo->texture() : 0); } diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 14eb368973..0f580f7369 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -60,6 +60,7 @@ # include <private/qmainwindowlayout_p.h> #endif #include <qpa/qplatformwindow.h> +#include <qpa/qplatformbackingstore.h> #include "private/qwidgetwindow_p.h" #include "qpainter.h" #include "qtooltip.h" @@ -1834,6 +1835,8 @@ void QWidgetPrivate::deleteTLSysExtra() delete extra->topextra->backingStore; extra->topextra->backingStore = 0; #ifndef QT_NO_OPENGL + qDeleteAll(extra->topextra->widgetTextures); + extra->topextra->widgetTextures.clear(); if (textureChildSeen && extra->topextra->shareContext) extra->topextra->shareContext->doneCurrent(); delete extra->topextra->shareContext; diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index fe65cb19c7..a78cf099ac 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -75,6 +75,7 @@ class QWidgetBackingStore; class QGraphicsProxyWidget; class QWidgetItemV2; class QOpenGLContext; +class QPlatformTextureList; class QStyle; @@ -153,6 +154,8 @@ struct QTLWExtra { QWidgetBackingStoreTracker backingStoreTracker; QBackingStore *backingStore; QPainter *sharedPainter; + QWidgetWindow *window; + QOpenGLContext *shareContext; // Implicit pointers (shared_null). QString caption; // widget caption @@ -167,6 +170,9 @@ struct QTLWExtra { QRect frameStrut; QRect normalGeometry; // used by showMin/maximized/FullScreen Qt::WindowFlags savedFlags; // Save widget flags while showing fullscreen + int initialScreenIndex; // Screen number when passing a QDesktop[Screen]Widget as parent. + + QVector<QPlatformTextureList *> widgetTextures; // *************************** Cross-platform bit fields **************************** uint opacity : 8; @@ -210,9 +216,6 @@ struct QTLWExtra { // starting position as 0,0 instead of the normal starting position. bool wasMaximized; #endif - QWidgetWindow *window; - QOpenGLContext *shareContext; - int initialScreenIndex; // Screen number when passing a QDesktop[Screen]Widget as parent. }; struct QWExtra { diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 69958636fd..55b8513072 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -79,7 +79,6 @@ void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion ®ion, QBack Q_ASSERT(widget); Q_ASSERT(backingStore); Q_ASSERT(tlw); - #if !defined(QT_NO_PAINT_DEBUG) static int flushUpdate = qEnvironmentVariableIntValue("QT_FLUSH_UPDATE"); if (flushUpdate > 0) @@ -105,13 +104,17 @@ void QWidgetBackingStore::qt_flush(QWidget *widget, const QRegion ®ion, QBack #ifndef QT_NO_OPENGL if (widgetTextures) { + Q_ASSERT(!widgetTextures->isEmpty()); + qt_window_private(tlw->windowHandle())->compositing = true; widget->window()->d_func()->sendComposeStatus(widget->window(), false); // A window may have alpha even when the app did not request // WA_TranslucentBackground. Therefore the compositor needs to know whether the app intends // to rely on translucency, in order to decide if it should clear to transparent or opaque. const bool translucentBackground = widget->testAttribute(Qt::WA_TranslucentBackground); + // Use the tlw's context, not widget's. The difference is important with native child + // widgets where tlw != widget. backingStore->handle()->composeAndFlush(widget->windowHandle(), region, offset, widgetTextures, - widget->d_func()->shareContext(), translucentBackground); + tlw->d_func()->shareContext(), translucentBackground); widget->window()->d_func()->sendComposeStatus(widget->window(), true); } else #endif @@ -741,7 +744,6 @@ void QWidgetBackingStore::updateLists(QWidget *cur) QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel) : tlw(topLevel), dirtyOnScreenWidgets(0), - widgetTextures(0), fullUpdatePending(0), updateRequestSent(0), textureListWatcher(0), @@ -761,9 +763,6 @@ QWidgetBackingStore::~QWidgetBackingStore() for (int c = 0; c < dirtyRenderToTextureWidgets.size(); ++c) resetWidget(dirtyRenderToTextureWidgets.at(c)); -#ifndef QT_NO_OPENGL - delete widgetTextures; -#endif delete dirtyOnScreenWidgets; } @@ -792,8 +791,9 @@ void QWidgetPrivate::moveRect(const QRect &rect, int dx, int dy) destRect = destRect.translated(dx, dy).intersected(clipR); const QRect sourceRect(destRect.translated(-dx, -dy)); const QRect parentRect(rect & clipR); + const bool nativeWithTextureChild = textureChildSeen && q->internalWinId(); - bool accelerateMove = accelEnv && isOpaque + bool accelerateMove = accelEnv && isOpaque && !nativeWithTextureChild #ifndef QT_NO_GRAPHICSVIEW // No accelerate move for proxy widgets. && !tlw->d_func()->extra->proxyWidget @@ -913,6 +913,95 @@ void QWidgetPrivate::scrollRect(const QRect &rect, int dx, int dy) } } +#ifndef QT_NO_OPENGL +static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatformTextureList *widgetTextures, QVector<QWidget *> *nativeChildren) +{ + QWidgetPrivate *wd = QWidgetPrivate::get(widget); + if (wd->renderToTexture) { + QPlatformTextureList::Flags flags = 0; + if (widget->testAttribute(Qt::WA_AlwaysStackOnTop)) + flags |= QPlatformTextureList::StacksOnTop; + const QRect rect(widget->mapTo(tlw, QPoint()), widget->size()); + widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags); + } + + for (int i = 0; i < wd->children.size(); ++i) { + QWidget *w = qobject_cast<QWidget *>(wd->children.at(i)); + // Stop at native widgets but store them. Stop at hidden widgets too. + if (w && !w->isWindow() && w->internalWinId()) + nativeChildren->append(w); + if (w && !w->isWindow() && !w->internalWinId() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen) + findTextureWidgetsRecursively(tlw, w, widgetTextures, nativeChildren); + } +} + +static void findAllTextureWidgetsRecursively(QWidget *tlw, QWidget *widget) +{ + // textureChildSeen does not take native child widgets into account and that's good. + if (QWidgetPrivate::get(widget)->textureChildSeen) { + QVector<QWidget *> nativeChildren; + QScopedPointer<QPlatformTextureList> tl(new QPlatformTextureList); + // Look for texture widgets (incl. widget itself) from 'widget' down, + // but skip subtrees with a parent of a native child widget. + findTextureWidgetsRecursively(tlw, widget, tl.data(), &nativeChildren); + // tl may be empty regardless of textureChildSeen if we have native or hidden children. + if (!tl->isEmpty()) + QWidgetPrivate::get(tlw)->topData()->widgetTextures.append(tl.take()); + // Native child widgets, if there was any, get their own separate QPlatformTextureList. + foreach (QWidget *ncw, nativeChildren) { + if (QWidgetPrivate::get(ncw)->textureChildSeen) + findAllTextureWidgetsRecursively(tlw, ncw); + } + } +} + +static QPlatformTextureList *widgetTexturesFor(QWidget *tlw, QWidget *widget) +{ + foreach (QPlatformTextureList *tl, QWidgetPrivate::get(tlw)->topData()->widgetTextures) { + Q_ASSERT(!tl->isEmpty()); + for (int i = 0; i < tl->count(); ++i) { + QWidget *w = static_cast<QWidget *>(tl->source(i)); + if ((w->internalWinId() && w == widget) || (!w->internalWinId() && w->nativeParentWidget() == widget)) + return tl; + } + } + return 0; +} + +// Watches one or more QPlatformTextureLists for changes in the lock state and +// triggers a backingstore sync when all the registered lists turn into +// unlocked state. This is essential when a custom composeAndFlush() +// implementation in a platform plugin is not synchronous and keeps +// holding on to the textures for some time even after returning from there. +QPlatformTextureListWatcher::QPlatformTextureListWatcher(QWidgetBackingStore *backingStore) + : m_backingStore(backingStore) +{ +} + +void QPlatformTextureListWatcher::watch(QPlatformTextureList *textureList) +{ + connect(textureList, SIGNAL(locked(bool)), SLOT(onLockStatusChanged(bool))); + m_locked[textureList] = textureList->isLocked(); +} + +bool QPlatformTextureListWatcher::isLocked() const +{ + foreach (bool v, m_locked) { + if (v) + return true; + } + return false; +} + +void QPlatformTextureListWatcher::onLockStatusChanged(bool locked) +{ + QPlatformTextureList *tl = static_cast<QPlatformTextureList *>(sender()); + m_locked[tl] = locked; + if (!isLocked()) + m_backingStore->sync(); +} +#endif // QT_NO_OPENGL + static inline bool discardSyncRequest(QWidget *tlw, QTLWExtra *tlwExtra) { if (!tlw || !tlwExtra || !tlw->testAttribute(Qt::WA_Mapped) || !tlw->isVisible()) @@ -941,7 +1030,7 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg // Nothing to repaint. if (!isDirty() && store->size().isValid()) { - qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset, widgetTextures, this); + qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset, widgetTexturesFor(tlw, tlw), this); return; } @@ -953,45 +1042,6 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg doSync(); } -#ifndef QT_NO_OPENGL -static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatformTextureList *widgetTextures) -{ - QWidgetPrivate *wd = QWidgetPrivate::get(widget); - if (wd->renderToTexture) { - QPlatformTextureList::Flags flags = 0; - if (widget->testAttribute(Qt::WA_AlwaysStackOnTop)) - flags |= QPlatformTextureList::StacksOnTop; - const QRect rect(widget->mapTo(tlw, QPoint()), widget->size()); - widgetTextures->appendTexture(widget, wd->textureId(), rect, wd->clipRect(), flags); - } - - for (int i = 0; i < wd->children.size(); ++i) { - QWidget *w = qobject_cast<QWidget *>(wd->children.at(i)); - if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen) - findTextureWidgetsRecursively(tlw, w, widgetTextures); - } -} - -QPlatformTextureListWatcher::QPlatformTextureListWatcher(QWidgetBackingStore *backingStore) - : m_locked(false), - m_backingStore(backingStore) -{ -} - -void QPlatformTextureListWatcher::watch(QPlatformTextureList *textureList) -{ - connect(textureList, SIGNAL(locked(bool)), SLOT(onLockStatusChanged(bool))); - m_locked = textureList->isLocked(); -} - -void QPlatformTextureListWatcher::onLockStatusChanged(bool locked) -{ - m_locked = locked; - if (!locked) - m_backingStore->sync(); -} -#endif // QT_NO_OPENGL - /*! Synchronizes the backing store, i.e. dirty areas are repainted and flushed. */ @@ -1019,12 +1069,19 @@ void QWidgetBackingStore::sync() if (textureListWatcher && !textureListWatcher->isLocked()) { textureListWatcher->deleteLater(); textureListWatcher = 0; - } else if (widgetTextures && widgetTextures->isLocked()) { - if (!textureListWatcher) - textureListWatcher = new QPlatformTextureListWatcher(this); - if (!textureListWatcher->isLocked()) - textureListWatcher->watch(widgetTextures); - return; + } else if (!tlwExtra->widgetTextures.isEmpty()) { + bool skipSync = false; + foreach (QPlatformTextureList *tl, tlwExtra->widgetTextures) { + if (tl->isLocked()) { + if (!textureListWatcher) + textureListWatcher = new QPlatformTextureListWatcher(this); + if (!textureListWatcher->isLocked()) + textureListWatcher->watch(tl); + skipSync = true; + } + } + if (skipSync) // cannot compose due to widget textures being in use + return; } #endif @@ -1117,13 +1174,14 @@ void QWidgetBackingStore::doSync() dirtyWidgets.clear(); #ifndef QT_NO_OPENGL - delete widgetTextures; - widgetTextures = 0; - if (tlw->d_func()->textureChildSeen) { - widgetTextures = new QPlatformTextureList; - findTextureWidgetsRecursively(tlw, tlw, widgetTextures); - } - qt_window_private(tlw->windowHandle())->compositing = widgetTextures; + // Find all render-to-texture child widgets (including self). + // The search is cut at native widget boundaries, meaning that each native child widget + // has its own list for the subtree below it. + QTLWExtra *tlwExtra = tlw->d_func()->topData(); + qDeleteAll(tlwExtra->widgetTextures); + tlwExtra->widgetTextures.clear(); + findAllTextureWidgetsRecursively(tlw, tlw); + qt_window_private(tlw->windowHandle())->compositing = false; // will get updated in qt_flush() fullUpdatePending = false; #endif @@ -1143,6 +1201,9 @@ void QWidgetBackingStore::doSync() for (int i = 0; i < paintPending.count(); ++i) { QWidget *w = paintPending[i]; w->d_func()->sendPaintEvent(w->rect()); + QWidget *npw = w->nativeParentWidget(); + if (w->internalWinId() || (npw && npw != tlw)) + markDirtyOnScreen(w->rect(), w, w->mapTo(tlw, QPoint())); } // We might have newly exposed areas on the screen if this function was @@ -1154,18 +1215,23 @@ void QWidgetBackingStore::doSync() } #ifndef QT_NO_OPENGL - if (widgetTextures && widgetTextures->count()) { - for (int i = 0; i < widgetTextures->count(); ++i) { - QWidget *w = static_cast<QWidget *>(widgetTextures->source(i)); + foreach (QPlatformTextureList *tl, tlwExtra->widgetTextures) { + for (int i = 0; i < tl->count(); ++i) { + QWidget *w = static_cast<QWidget *>(tl->source(i)); if (dirtyRenderToTextureWidgets.contains(w)) { - const QRect rect = widgetTextures->geometry(i); // mapped to the tlw already + const QRect rect = tl->geometry(i); // mapped to the tlw already dirty += rect; toClean += rect; } } } - for (int i = 0; i < dirtyRenderToTextureWidgets.count(); ++i) - resetWidget(dirtyRenderToTextureWidgets.at(i)); + for (int i = 0; i < dirtyRenderToTextureWidgets.count(); ++i) { + QWidget *w = dirtyRenderToTextureWidgets.at(i); + resetWidget(w); + QWidget *npw = w->nativeParentWidget(); + if (w->internalWinId() || (npw && npw != tlw)) + markDirtyOnScreen(w->rect(), w, w->mapTo(tlw, QPoint())); + } dirtyRenderToTextureWidgets.clear(); #endif @@ -1235,31 +1301,39 @@ void QWidgetBackingStore::doSync() */ void QWidgetBackingStore::flush(QWidget *widget) { + const bool hasDirtyOnScreenWidgets = dirtyOnScreenWidgets && !dirtyOnScreenWidgets->isEmpty(); + bool flushed = false; + + // Flush the region in dirtyOnScreen. if (!dirtyOnScreen.isEmpty()) { QWidget *target = widget ? widget : tlw; - qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTextures, this); + qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTexturesFor(tlw, tlw), this); dirtyOnScreen = QRegion(); -#ifndef QT_NO_OPENGL - if (widgetTextures && widgetTextures->count()) - return; -#endif + flushed = true; } - if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty()) { + // Render-to-texture widgets are not in dirtyOnScreen so flush if we have not done it above. + if (!flushed && !hasDirtyOnScreenWidgets) { #ifndef QT_NO_OPENGL - if (widgetTextures && widgetTextures->count()) { - QWidget *target = widget ? widget : tlw; - qt_flush(target, QRegion(), store, tlw, tlwOffset, widgetTextures, this); + if (!tlw->d_func()->topData()->widgetTextures.isEmpty()) { + QPlatformTextureList *tl = widgetTexturesFor(tlw, tlw); + if (tl) { + QWidget *target = widget ? widget : tlw; + qt_flush(target, QRegion(), store, tlw, tlwOffset, tl, this); + } } #endif - return; } + if (!hasDirtyOnScreenWidgets) + return; + for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) { QWidget *w = dirtyOnScreenWidgets->at(i); QWidgetPrivate *wd = w->d_func(); Q_ASSERT(wd->needsFlush); - qt_flush(w, *wd->needsFlush, store, tlw, tlwOffset, 0, this); + QPlatformTextureList *widgetTexturesForNative = wd->textureChildSeen ? widgetTexturesFor(tlw, w) : 0; + qt_flush(w, *wd->needsFlush, store, tlw, tlwOffset, widgetTexturesForNative, this); *wd->needsFlush = QRegion(); } dirtyOnScreenWidgets->clear(); diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h index b7ee7e4168..c45e60ef6e 100644 --- a/src/widgets/kernel/qwidgetbackingstore_p.h +++ b/src/widgets/kernel/qwidgetbackingstore_p.h @@ -71,13 +71,13 @@ class QPlatformTextureListWatcher : public QObject public: QPlatformTextureListWatcher(QWidgetBackingStore *backingStore); void watch(QPlatformTextureList *textureList); - bool isLocked() const { return m_locked; } + bool isLocked() const; private slots: void onLockStatusChanged(bool locked); private: - bool m_locked; + QHash<QPlatformTextureList *, bool> m_locked; QWidgetBackingStore *m_backingStore; }; #endif @@ -128,7 +128,6 @@ private: QVector<QWidget *> dirtyRenderToTextureWidgets; QVector<QWidget *> *dirtyOnScreenWidgets; QList<QWidget *> staticWidgets; - QPlatformTextureList *widgetTextures; QBackingStore *store; uint fullUpdatePending : 1; uint updateRequestSent : 1; diff --git a/src/widgets/styles/qcommonstyle.cpp b/src/widgets/styles/qcommonstyle.cpp index 5a08801e94..a14ca84388 100644 --- a/src/widgets/styles/qcommonstyle.cpp +++ b/src/widgets/styles/qcommonstyle.cpp @@ -265,8 +265,8 @@ void QCommonStyle::drawPrimitive(PrimitiveElement pe, const QStyleOption *opt, Q case PE_IndicatorProgressChunk: { bool vertical = false; - if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(opt)) - vertical = (pb2->orientation == Qt::Vertical); + if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) + vertical = pb->orientation == Qt::Vertical; if (!vertical) { p->fillRect(opt->rect.x(), opt->rect.y() + 3, opt->rect.width() -2, opt->rect.height() - 6, opt->palette.brush(QPalette::Highlight)); @@ -1085,7 +1085,7 @@ void QCommonStylePrivate::viewItemLayout(const QStyleOptionViewItem *opt, QRect Uses the same computation than in QTabBar::tabSizeHint */ -void QCommonStylePrivate::tabLayout(const QStyleOptionTabV3 *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const +void QCommonStylePrivate::tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *iconRect) const { Q_ASSERT(textRect); Q_ASSERT(iconRect); @@ -1391,7 +1391,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, case CE_ProgressBar: if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) { - QStyleOptionProgressBarV2 subopt = *pb; + QStyleOptionProgressBar subopt = *pb; subopt.rect = subElementRect(SE_ProgressBarGroove, pb, widget); proxy()->drawControl(CE_ProgressBarGroove, &subopt, p, widget); subopt.rect = subElementRect(SE_ProgressBarContents, pb, widget); @@ -1409,10 +1409,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, break; case CE_ProgressBarLabel: if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) { - bool vertical = false; - if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(opt)) { - vertical = (pb2->orientation == Qt::Vertical); - } + const bool vertical = pb->orientation == Qt::Vertical; if (!vertical) { QPalette::ColorRole textRole = QPalette::NoRole; if ((pb->textAlignment & Qt::AlignCenter) && pb->textVisible @@ -1437,18 +1434,12 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) { QRect rect = pb->rect; - bool vertical = false; - bool inverted = false; + const bool vertical = pb->orientation == Qt::Vertical; + const bool inverted = pb->invertedAppearance; qint64 minimum = qint64(pb->minimum); qint64 maximum = qint64(pb->maximum); qint64 progress = qint64(pb->progress); - // Get extra style options if version 2 - const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(opt); - if (pb2) { - vertical = (pb2->orientation == Qt::Vertical); - inverted = pb2->invertedAppearance; - } QMatrix m; if (vertical) { @@ -1508,7 +1499,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, int x0 = reverse ? rect.right() - ((unit_width > 1) ? unit_width : 0) : rect.x(); - QStyleOptionProgressBarV2 pbBits = *pb; + QStyleOptionProgressBar pbBits = *pb; pbBits.rect = rect; pbBits.palette = pal2; int myY = pbBits.rect.y(); @@ -1864,12 +1855,11 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, break; case CE_TabBarTabLabel: if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) { - QStyleOptionTabV3 tabV2(*tab); - QRect tr = tabV2.rect; - bool verticalTabs = tabV2.shape == QTabBar::RoundedEast - || tabV2.shape == QTabBar::RoundedWest - || tabV2.shape == QTabBar::TriangularEast - || tabV2.shape == QTabBar::TriangularWest; + QRect tr = tab->rect; + bool verticalTabs = tab->shape == QTabBar::RoundedEast + || tab->shape == QTabBar::RoundedWest + || tab->shape == QTabBar::TriangularEast + || tab->shape == QTabBar::TriangularWest; int alignment = Qt::AlignCenter | Qt::TextShowMnemonic; if (!proxy()->styleHint(SH_UnderlineShortcut, opt, widget)) @@ -1878,7 +1868,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, if (verticalTabs) { p->save(); int newX, newY, newRot; - if (tabV2.shape == QTabBar::RoundedEast || tabV2.shape == QTabBar::TriangularEast) { + if (tab->shape == QTabBar::RoundedEast || tab->shape == QTabBar::TriangularEast) { newX = tr.width() + tr.x(); newY = tr.y(); newRot = 90; @@ -1892,15 +1882,15 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, p->setTransform(m, true); } QRect iconRect; - d->tabLayout(&tabV2, widget, &tr, &iconRect); + d->tabLayout(tab, widget, &tr, &iconRect); tr = proxy()->subElementRect(SE_TabBarTabText, opt, widget); //we compute tr twice because the style may override subElementRect - if (!tabV2.icon.isNull()) { - QPixmap tabIcon = tabV2.icon.pixmap(qt_getWindow(widget), tabV2.iconSize, - (tabV2.state & State_Enabled) ? QIcon::Normal - : QIcon::Disabled, - (tabV2.state & State_Selected) ? QIcon::On - : QIcon::Off); + if (!tab->icon.isNull()) { + QPixmap tabIcon = tab->icon.pixmap(qt_getWindow(widget), tab->iconSize, + (tab->state & State_Enabled) ? QIcon::Normal + : QIcon::Disabled, + (tab->state & State_Selected) ? QIcon::On + : QIcon::Off); p->drawPixmap(iconRect.x(), iconRect.y(), tabIcon); } @@ -1908,17 +1898,17 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, if (verticalTabs) p->restore(); - if (tabV2.state & State_HasFocus) { + if (tab->state & State_HasFocus) { const int OFFSET = 1 + pixelMetric(PM_DefaultFrameWidth); int x1, x2; - x1 = tabV2.rect.left(); - x2 = tabV2.rect.right() - 1; + x1 = tab->rect.left(); + x2 = tab->rect.right() - 1; QStyleOptionFocusRect fropt; fropt.QStyleOption::operator=(*tab); - fropt.rect.setRect(x1 + 1 + OFFSET, tabV2.rect.y() + OFFSET, - x2 - x1 - 2*OFFSET, tabV2.rect.height() - 2*OFFSET); + fropt.rect.setRect(x1 + 1 + OFFSET, tab->rect.y() + OFFSET, + x2 - x1 - 2*OFFSET, tab->rect.height() - 2*OFFSET); drawPrimitive(PE_FrameFocusRect, &fropt, p, widget); } } @@ -2037,9 +2027,7 @@ void QCommonStyle::drawControl(ControlElement element, const QStyleOption *opt, } if (!dwOpt->title.isEmpty()) { - const QStyleOptionDockWidgetV2 *v2 - = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(opt); - bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + const bool verticalTitleBar = dwOpt->verticalTitleBar; if (verticalTitleBar) { r.setSize(r.size().transposed()); @@ -2475,10 +2463,7 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, case SE_ProgressBarLabel: if (const QStyleOptionProgressBar *pb = qstyleoption_cast<const QStyleOptionProgressBar *>(opt)) { int textw = 0; - bool vertical = false; - if (const QStyleOptionProgressBarV2 *pb2 = qstyleoption_cast<const QStyleOptionProgressBarV2 *>(opt)) { - vertical = (pb2->orientation == Qt::Vertical); - } + const bool vertical = pb->orientation == Qt::Vertical; if (!vertical) { if (pb->textVisible) textw = qMax(pb->fontMetrics.width(pb->text), pb->fontMetrics.width(QLatin1String("100%"))) + 6; @@ -2731,14 +2716,13 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, break; case SE_TabBarTabText: if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) { - QStyleOptionTabV3 tabV3(*tab); QRect dummyIconRect; - d->tabLayout(&tabV3, widget, &r, &dummyIconRect); + d->tabLayout(tab, widget, &r, &dummyIconRect); } break; case SE_TabBarTabLeftButton: case SE_TabBarTabRightButton: - if (const QStyleOptionTabV3 *tab = qstyleoption_cast<const QStyleOptionTabV3 *>(opt)) { + if (const QStyleOptionTab *tab = qstyleoption_cast<const QStyleOptionTab *>(opt)) { bool selected = tab->state & State_Selected; int verticalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftVertical, tab, widget); int horizontalShift = proxy()->pixelMetric(QStyle::PM_TabBarTabShiftHorizontal, tab, widget); @@ -2927,9 +2911,8 @@ QRect QCommonStyle::subElementRect(SubElement sr, const QStyleOption *opt, = qstyleoption_cast<const QStyleOptionDockWidget*>(opt); bool canClose = dwOpt == 0 ? true : dwOpt->closable; bool canFloat = dwOpt == 0 ? false : dwOpt->floatable; - const QStyleOptionDockWidgetV2 *v2 - = qstyleoption_cast<const QStyleOptionDockWidgetV2*>(opt); - bool verticalTitleBar = v2 == 0 ? false : v2->verticalTitleBar; + + const bool verticalTitleBar = dwOpt && dwOpt->verticalTitleBar; // If this is a vertical titlebar, we transpose and work as if it was // horizontal, then transpose again. diff --git a/src/widgets/styles/qcommonstyle_p.h b/src/widgets/styles/qcommonstyle_p.h index 1287528bdb..8f512f7d72 100644 --- a/src/widgets/styles/qcommonstyle_p.h +++ b/src/widgets/styles/qcommonstyle_p.h @@ -104,7 +104,7 @@ public: #endif mutable QIcon tabBarcloseButtonIcon; #ifndef QT_NO_TABBAR - void tabLayout(const QStyleOptionTabV3 *opt, const QWidget *widget, QRect *textRect, QRect *pixmapRect) const; + void tabLayout(const QStyleOptionTab *opt, const QWidget *widget, QRect *textRect, QRect *pixmapRect) const; #endif int animationFps; diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp index b29d7de5f5..27e977f027 100644 --- a/src/widgets/widgets/qmenu.cpp +++ b/src/widgets/widgets/qmenu.cpp @@ -192,11 +192,10 @@ void QMenuPrivate::syncPlatformMenu() return; QPlatformMenuItem *beforeItem = Q_NULLPTR; - QListIterator<QAction*> it(q->actions()); - it.toBack(); - while (it.hasPrevious()) { + const QList<QAction*> actions = q->actions(); + for (QList<QAction*>::const_reverse_iterator it = actions.rbegin(), end = actions.rend(); it != end; ++it) { QPlatformMenuItem *menuItem = platformMenu->createMenuItem(); - QAction *action = it.previous(); + QAction *action = *it; menuItem->setTag(reinterpret_cast<quintptr>(action)); QObject::connect(menuItem, SIGNAL(activated()), action, SLOT(trigger()), Qt::QueuedConnection); QObject::connect(menuItem, SIGNAL(hovered()), action, SIGNAL(hovered()), Qt::QueuedConnection); |