diff options
Diffstat (limited to 'src')
41 files changed, 642 insertions, 182 deletions
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index ddba460b06..6aa3eb305b 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -41,11 +41,11 @@ #include <stddef.h> -#define QT_VERSION_STR "5.5.0" +#define QT_VERSION_STR "5.6.0" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x050500 +#define QT_VERSION 0x050600 /* can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)) */ diff --git a/src/corelib/io/qdatastream.h b/src/corelib/io/qdatastream.h index 436bf8dd57..b87dbe4784 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/io/qdatastream.h @@ -83,10 +83,11 @@ public: Qt_5_3 = Qt_5_2, Qt_5_4 = 16, Qt_5_5 = Qt_5_4, -#if QT_VERSION >= 0x050600 + Qt_5_6 = Qt_5_5, +#if QT_VERSION >= 0x050700 #error Add the datastream version for this Qt version and update Qt_DefaultCompiledVersion #endif - Qt_DefaultCompiledVersion = Qt_5_5 + Qt_DefaultCompiledVersion = Qt_5_6 }; enum ByteOrder { diff --git a/src/corelib/kernel/qcoreevent.cpp b/src/corelib/kernel/qcoreevent.cpp index b2b22ad99c..0a68de8871 100644 --- a/src/corelib/kernel/qcoreevent.cpp +++ b/src/corelib/kernel/qcoreevent.cpp @@ -150,7 +150,7 @@ QT_BEGIN_NAMESPACE \value HoverLeave The mouse cursor leaves a hover widget (QHoverEvent). \value HoverMove The mouse cursor moves inside a hover widget (QHoverEvent). \value IconDrag The main icon of a window has been dragged away (QIconDragEvent). - \value IconTextChange Widget's icon text has been changed. + \value IconTextChange Widget's icon text has been changed. (Deprecated) \value InputMethod An input method is being used (QInputMethodEvent). \value InputMethodQuery A input method query event (QInputMethodQueryEvent) \value KeyboardLayoutChange The keyboard layout has changed. diff --git a/src/corelib/kernel/qcoreevent.h b/src/corelib/kernel/qcoreevent.h index c208eb1180..53da4a849b 100644 --- a/src/corelib/kernel/qcoreevent.h +++ b/src/corelib/kernel/qcoreevent.h @@ -133,7 +133,7 @@ public: EnabledChange = 98, // enabled state has changed ActivationChange = 99, // window activation has changed StyleChange = 100, // style has changed - IconTextChange = 101, // icon text has changed + IconTextChange = 101, // icon text has changed. Deprecated. ModifiedChange = 102, // modified state has changed MouseTrackingChange = 109, // mouse tracking state has changed diff --git a/src/corelib/kernel/qjni.cpp b/src/corelib/kernel/qjni.cpp index 694463b9d8..2290a74c31 100644 --- a/src/corelib/kernel/qjni.cpp +++ b/src/corelib/kernel/qjni.cpp @@ -204,6 +204,15 @@ static jfieldID getCachedFieldID(JNIEnv *env, } } +void QJNILocalRefDeleter::cleanup(jobject obj) +{ + if (obj == 0) + return; + + QJNIEnvironmentPrivate env; + env->DeleteLocalRef(obj); +} + class QJNIEnvironmentPrivateTLS { public: @@ -2258,4 +2267,3 @@ bool QJNIObjectPrivate::isSameObject(const QJNIObjectPrivate &other) const } QT_END_NAMESPACE - diff --git a/src/corelib/kernel/qjni_p.h b/src/corelib/kernel/qjni_p.h index e79caed5b8..ae9c7c3a7e 100644 --- a/src/corelib/kernel/qjni_p.h +++ b/src/corelib/kernel/qjni_p.h @@ -51,6 +51,14 @@ QT_BEGIN_NAMESPACE +struct Q_CORE_EXPORT QJNILocalRefDeleter +{ + static void cleanup(jobject obj); +}; + +// To simplify this we only define it for jobjects. +typedef QScopedPointer<_jobject, QJNILocalRefDeleter> QJNIScopedLocalRef; + class Q_CORE_EXPORT QJNIEnvironmentPrivate { public: diff --git a/src/corelib/plugin/qpluginloader.cpp b/src/corelib/plugin/qpluginloader.cpp index 8ed9199c60..2800656c13 100644 --- a/src/corelib/plugin/qpluginloader.cpp +++ b/src/corelib/plugin/qpluginloader.cpp @@ -273,6 +273,13 @@ bool QPluginLoader::isLoaded() const #if defined(QT_SHARED) static QString locatePlugin(const QString& fileName) { + const bool isAbsolute = QDir::isAbsolutePath(fileName); + if (isAbsolute) { + QFileInfo fi(fileName); + if (fi.isFile()) { + return fi.canonicalFilePath(); + } + } QStringList prefixes = QLibraryPrivate::prefixes_sys(); prefixes.prepend(QString()); QStringList suffixes = QLibraryPrivate::suffixes_sys(QString()); @@ -281,12 +288,18 @@ static QString locatePlugin(const QString& fileName) // Split up "subdir/filename" const int slash = fileName.lastIndexOf('/'); const QString baseName = fileName.mid(slash + 1); - const QString basePath = fileName.left(slash + 1); // keep the '/' + const QString basePath = isAbsolute ? QString() : fileName.left(slash + 1); // keep the '/' const bool debug = qt_debug_component(); - QStringList paths = QCoreApplication::libraryPaths(); - paths.prepend(QStringLiteral("./")); // search in current dir first + QStringList paths; + if (isAbsolute) { + paths.append(fileName.left(slash)); // don't include the '/' + } else { + paths = QCoreApplication::libraryPaths(); + paths.prepend(QStringLiteral(".")); // search in current dir first + } + foreach (const QString &path, paths) { foreach (const QString &prefix, prefixes) { foreach (const QString &suffix, suffixes) { @@ -337,12 +350,7 @@ void QPluginLoader::setFileName(const QString &fileName) did_load = false; } - QFileInfo fi(fileName); - QString fn; - if (fi.isAbsolute()) - fn = fi.canonicalFilePath(); - else - fn = locatePlugin(fileName); + const QString fn = locatePlugin(fileName); d = QLibraryPrivate::findOrCreate(fn, QString(), lh); if (!fn.isEmpty()) diff --git a/src/corelib/tools/qcommandlineoption.cpp b/src/corelib/tools/qcommandlineoption.cpp index 7f898f68a8..51723f4a57 100644 --- a/src/corelib/tools/qcommandlineoption.cpp +++ b/src/corelib/tools/qcommandlineoption.cpp @@ -42,6 +42,7 @@ class QCommandLineOptionPrivate : public QSharedData { public: inline QCommandLineOptionPrivate() + : hidden(false) { } void setNames(const QStringList &nameList); @@ -58,6 +59,9 @@ public: //! The list of default values used for this option. QStringList defaultValues; + + //! Show or hide in --help + bool hidden; }; /*! @@ -362,4 +366,30 @@ QStringList QCommandLineOption::defaultValues() const return d->defaultValues; } +/*! + Sets whether to hide this option in the user-visible help output. + + All options are visible by default. Setting \a hidden to true for + a particular option makes it internal, i.e. not listed in the help output. + + \since 5.6 + \sa isHidden + */ +void QCommandLineOption::setHidden(bool hide) +{ + d->hidden = hide; +} + +/*! + Returns true if this option is omitted from the help output, + false if the option is listed. + + \since 5.6 + \sa setHidden() + */ +bool QCommandLineOption::isHidden() const +{ + return d->hidden; +} + QT_END_NAMESPACE diff --git a/src/corelib/tools/qcommandlineoption.h b/src/corelib/tools/qcommandlineoption.h index cf4160ecd2..85fc5ca6dd 100644 --- a/src/corelib/tools/qcommandlineoption.h +++ b/src/corelib/tools/qcommandlineoption.h @@ -77,6 +77,9 @@ public: void setDefaultValues(const QStringList &defaultValues); QStringList defaultValues() const; + void setHidden(bool hidden); + bool isHidden() const; + private: QSharedDataPointer<QCommandLineOptionPrivate> d; }; diff --git a/src/corelib/tools/qcommandlineparser.cpp b/src/corelib/tools/qcommandlineparser.cpp index 21bc14a272..7e49253f9b 100644 --- a/src/corelib/tools/qcommandlineparser.cpp +++ b/src/corelib/tools/qcommandlineparser.cpp @@ -53,6 +53,7 @@ class QCommandLineParserPrivate public: inline QCommandLineParserPrivate() : singleDashWordOptionMode(QCommandLineParser::ParseAsCompactedShortOptions), + optionsAfterPositionalArgumentsMode(QCommandLineParser::ParseAsOptions), builtinVersionOption(false), builtinHelpOption(false), needsParsing(true) @@ -103,6 +104,9 @@ public: //! The parsing mode for "-abc" QCommandLineParser::SingleDashWordOptionMode singleDashWordOptionMode; + //! How to parse "arg -option" + QCommandLineParser::OptionsAfterPositionalArgumentsMode optionsAfterPositionalArgumentsMode; + //! Whether addVersionOption was called bool builtinVersionOption; @@ -299,6 +303,41 @@ void QCommandLineParser::setSingleDashWordOptionMode(QCommandLineParser::SingleD } /*! + \enum QCommandLineParser::OptionsAfterPositionalArgumentsMode + + This enum describes the way the parser interprets options that + occur after positional arguments. + + \value ParseAsOptions \c{application argument --opt -t} is interpreted as setting + the options \c{opt} and \c{t}, just like \c{application --opt -t argument} would do. + This is the default parsing mode. In order to specify that \c{--opt} and \c{-t} + are positional arguments instead, the user can use \c{--}, as in + \c{application argument -- --opt -t}. + + \value ParseAsPositionalArguments \c{application argument --opt} is interpreted as + having two positional arguments, \c{argument} and \c{--opt}. + This mode is useful for executables that aim to launch other executables + (e.g. wrappers, debugging tools, etc.) or that support internal commands + followed by options for the command. \c{argument} is the name of the command, + and all options occurring after it can be collected and parsed by another + command line parser, possibly in another executable. + + \sa setOptionsAfterPositionalArgumentsMode() + + \since 5.5 +*/ + +/*! + Sets the parsing mode to \a parsingMode. + This must be called before process() or parse(). + \since 5.5 +*/ +void QCommandLineParser::setOptionsAfterPositionalArgumentsMode(QCommandLineParser::OptionsAfterPositionalArgumentsMode parsingMode) +{ + d->optionsAfterPositionalArgumentsMode = parsingMode; +} + +/*! Adds the option \a option to look for while parsing. Returns \c true if adding the option was successful; otherwise returns \c false. @@ -640,7 +679,7 @@ bool QCommandLineParserPrivate::parse(const QStringList &args) const QLatin1Char dashChar('-'); const QLatin1Char assignChar('='); - bool doubleDashFound = false; + bool forcePositional = false; errorText.clear(); positionalArgumentList.clear(); optionNames.clear(); @@ -658,7 +697,7 @@ bool QCommandLineParserPrivate::parse(const QStringList &args) for (; argumentIterator != args.end() ; ++argumentIterator) { QString argument = *argumentIterator; - if (doubleDashFound) { + if (forcePositional) { positionalArgumentList.append(argument); } else if (argument.startsWith(doubleDashString)) { if (argument.length() > 2) { @@ -670,7 +709,7 @@ bool QCommandLineParserPrivate::parse(const QStringList &args) error = true; } } else { - doubleDashFound = true; + forcePositional = true; } } else if (argument.startsWith(dashChar)) { if (argument.size() == 1) { // single dash ("stdin") @@ -722,6 +761,8 @@ bool QCommandLineParserPrivate::parse(const QStringList &args) } } else { positionalArgumentList.append(argument); + if (optionsAfterPositionalArgumentsMode == QCommandLineParser::ParseAsPositionalArguments) + forcePositional = true; } if (argumentIterator == args.end()) break; @@ -1062,6 +1103,8 @@ QString QCommandLineParserPrivate::helpText() const ++longestOptionNameString; for (int i = 0; i < commandLineOptionList.count(); ++i) { const QCommandLineOption &option = commandLineOptionList.at(i); + if (option.isHidden()) + continue; text += wrapText(optionNameList.at(i), longestOptionNameString, option.description()); } if (!positionalArgumentDefinitions.isEmpty()) { diff --git a/src/corelib/tools/qcommandlineparser.h b/src/corelib/tools/qcommandlineparser.h index 91a799b4d5..8c528ba69e 100644 --- a/src/corelib/tools/qcommandlineparser.h +++ b/src/corelib/tools/qcommandlineparser.h @@ -57,6 +57,12 @@ public: }; void setSingleDashWordOptionMode(SingleDashWordOptionMode parsingMode); + enum OptionsAfterPositionalArgumentsMode { + ParseAsOptions, + ParseAsPositionalArguments + }; + void setOptionsAfterPositionalArgumentsMode(OptionsAfterPositionalArgumentsMode mode); + bool addOption(const QCommandLineOption &commandLineOption); bool addOptions(const QList<QCommandLineOption> &options); diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index bcfa48e666..be1adfbee1 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -923,13 +923,11 @@ void QNetworkReplyImpl::abort() QNetworkReply::close(); - if (d->state != QNetworkReplyPrivate::Finished) { - // call finished which will emit signals - d->error(OperationCanceledError, tr("Operation canceled")); - if (d->state == QNetworkReplyPrivate::WaitingForSession) - d->state = QNetworkReplyPrivate::Working; - d->finished(); - } + // call finished which will emit signals + d->error(OperationCanceledError, tr("Operation canceled")); + if (d->state == QNetworkReplyPrivate::WaitingForSession) + d->state = QNetworkReplyPrivate::Working; + d->finished(); d->state = QNetworkReplyPrivate::Aborted; // finished may access the backend diff --git a/src/platformheaders/xcbfunctions/qxcbfunctionshelper.h b/src/platformheaders/xcbfunctions/qxcbfunctionshelper.h new file mode 100644 index 0000000000..a9d734a387 --- /dev/null +++ b/src/platformheaders/xcbfunctions/qxcbfunctionshelper.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBFUNCTIONHELPER_H +#define QXCBFUNCTIONHELPER_H + +#include <QtCore/QByteArray> +#include <QtGui/QGuiApplication> + +QT_BEGIN_NAMESPACE + +namespace QXcbFunctionsHelper +{ + +template<typename ReturnT, typename FunctionT> +ReturnT callPlatformFunction(const QByteArray &functionName) +{ + FunctionT func = reinterpret_cast<FunctionT>(QGuiApplication::platformFunction(functionName)); + return func ? func() : ReturnT(); +} + +template<typename ReturnT, typename FunctionT, typename Arg1> +ReturnT callPlatformFunction(const QByteArray &functionName, Arg1 a1) +{ + FunctionT func = reinterpret_cast<FunctionT>(QGuiApplication::platformFunction(functionName)); + return func ? func(a1) : ReturnT(); +} + +template<typename ReturnT, typename FunctionT, typename Arg1, typename Arg2> +ReturnT callPlatformFunction(const QByteArray &functionName, Arg1 a1, Arg2 a2) +{ + FunctionT func = reinterpret_cast<FunctionT>(QGuiApplication::platformFunction(functionName)); + return func ? func(a1, a2) : ReturnT(); +} + +template<typename ReturnT, typename FunctionT, typename Arg1, typename Arg2, typename Arg3> +ReturnT callPlatformFunction(const QByteArray &functionName, Arg1 a1, Arg2 a2, Arg3 a3) +{ + FunctionT func = reinterpret_cast<FunctionT>(QGuiApplication::platformFunction(functionName)); + return func ? func(a1, a2, a3) : ReturnT(); +} + +template<typename ReturnT, typename FunctionT, typename Arg1, typename Arg2, typename Arg3, typename Arg4> +ReturnT callPlatformFunction(const QByteArray &functionName, Arg1 a1, Arg2 a2, Arg3 a3, Arg4 a4) +{ + FunctionT func = reinterpret_cast<FunctionT>(QGuiApplication::platformFunction(functionName)); + return func ? func(a1, a2, a3, a4) : ReturnT(); +} + +} + +QT_END_NAMESPACE + +#endif /*QXCBFUNCTIONHELPER_H*/ diff --git a/src/platformheaders/xcbfunctions/qxcbintegrationfunctions.h b/src/platformheaders/xcbfunctions/qxcbintegrationfunctions.h new file mode 100644 index 0000000000..87e19e6a45 --- /dev/null +++ b/src/platformheaders/xcbfunctions/qxcbintegrationfunctions.h @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBINTEGRATIONFUNCTIONS_H +#define QXCBINTEGRATIONFUNCTIONS_H + +#include "qxcbfunctionshelper.h" + +QT_BEGIN_NAMESPACE + +class QXcbIntegrationFunctions +{ +public: + typedef bool (*XEmbedSystemTrayVisualHasAlphaChannel)(); + static const QByteArray xEmbedSystemTrayVisualHasAlphaChannelIdentifier() { return QByteArrayLiteral("XcbXEmbedSystemTrayVisualHasAlphaChannel"); } + static bool xEmbedSystemTrayVisualHasAlphaChannel() + { + return QXcbFunctionsHelper::callPlatformFunction<bool, XEmbedSystemTrayVisualHasAlphaChannel>(xEmbedSystemTrayVisualHasAlphaChannelIdentifier()); + } +}; + +QT_END_NAMESPACE + +#endif /*QXCBINTEGRATIONFUNCTIONS_H*/ diff --git a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h index f9008039a1..accd64f170 100644 --- a/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h +++ b/src/platformheaders/xcbfunctions/qxcbwindowfunctions.h @@ -34,8 +34,7 @@ #ifndef QXCBWINDOWFUNCTIONS_H #define QXCBWINDOWFUNCTIONS_H -#include <QtCore/QByteArray> -#include <QtGui/QGuiApplication> +#include "qxcbfunctionshelper.h" QT_BEGIN_NAMESPACE @@ -65,12 +64,37 @@ public: typedef void (*SetWmWindowType)(QWindow *window, QXcbWindowFunctions::WmWindowTypes windowType); static const QByteArray setWmWindowTypeIdentifier() { return QByteArrayLiteral("XcbSetWmWindowType"); } - static void setWmWindowType(QWindow *window, WmWindowType type) { - SetWmWindowType func = reinterpret_cast<SetWmWindowType>(QGuiApplication::platformFunction(setWmWindowTypeIdentifier())); - if (func) - func(window, type); + return QXcbFunctionsHelper::callPlatformFunction<void, SetWmWindowType, QWindow *, WmWindowType>(setWmWindowTypeIdentifier(), window, type); + } + + typedef void (*SetWmWindowIconText)(QWindow *window, const QString &text); + static const QByteArray setWmWindowIconTextIdentifier() { return QByteArrayLiteral("XcbSetWmWindowIconText"); } + static void setWmWindowIconText(QWindow *window, const QString &text) + { + return QXcbFunctionsHelper::callPlatformFunction<void, SetWmWindowIconText, QWindow *, const QString &>(setWmWindowIconTextIdentifier(), window, text); + } + + typedef void (*SetParentRelativeBackPixmap)(const QWindow *window); + static const QByteArray setParentRelativeBackPixmapIdentifier() { return QByteArrayLiteral("XcbSetParentRelativeBackPixmap"); } + static void setParentRelativeBackPixmap(const QWindow *window) + { + return QXcbFunctionsHelper::callPlatformFunction<void, SetParentRelativeBackPixmap, const QWindow *>(setParentRelativeBackPixmapIdentifier(), window); + } + + typedef bool (*RequestSystemTrayWindowDock)(const QWindow *window); + static const QByteArray requestSystemTrayWindowDockIdentifier() { return QByteArrayLiteral("XcbRequestSystemTrayWindowDockIdentifier"); } + static bool requestSystemTrayWindowDock(const QWindow *window) + { + return QXcbFunctionsHelper::callPlatformFunction<bool, RequestSystemTrayWindowDock, const QWindow *>(requestSystemTrayWindowDockIdentifier(), window); + } + + typedef QRect (*SystemTrayWindowGlobalGeometry)(const QWindow *window); + static const QByteArray systemTrayWindowGlobalGeometryIdentifier() { return QByteArrayLiteral("XcbSystemTrayWindowGlobalGeometryIdentifier"); } + static QRect systemTrayWindowGlobalGeometry(const QWindow *window) + { + return QXcbFunctionsHelper::callPlatformFunction<QRect, SystemTrayWindowGlobalGeometry, const QWindow *>(systemTrayWindowGlobalGeometryIdentifier(), window); } }; diff --git a/src/platformheaders/xcbfunctions/xcbfunctions.pri b/src/platformheaders/xcbfunctions/xcbfunctions.pri index 8844913cd1..7f611d80bd 100644 --- a/src/platformheaders/xcbfunctions/xcbfunctions.pri +++ b/src/platformheaders/xcbfunctions/xcbfunctions.pri @@ -1 +1,3 @@ -HEADERS += $$PWD/qxcbwindowfunctions.h +HEADERS += \ + $$PWD/qxcbwindowfunctions.h \ + $$PWD/qxcbintegrationfunctions.h diff --git a/src/platformsupport/fbconvenience/qfbbackingstore.cpp b/src/platformsupport/fbconvenience/qfbbackingstore.cpp index bf9beac894..2800a81507 100644 --- a/src/platformsupport/fbconvenience/qfbbackingstore.cpp +++ b/src/platformsupport/fbconvenience/qfbbackingstore.cpp @@ -46,7 +46,7 @@ QFbBackingStore::QFbBackingStore(QWindow *window) if (window->handle()) (static_cast<QFbWindow *>(window->handle()))->setBackingStore(this); else - (static_cast<QFbScreen *>(window->screen()->handle()))->addBackingStore(this); + (static_cast<QFbScreen *>(window->screen()->handle()))->addPendingBackingStore(this); } QFbBackingStore::~QFbBackingStore() diff --git a/src/platformsupport/fbconvenience/qfbscreen.cpp b/src/platformsupport/fbconvenience/qfbscreen.cpp index 04aa9f2fae..566f84c9ea 100644 --- a/src/platformsupport/fbconvenience/qfbscreen.cpp +++ b/src/platformsupport/fbconvenience/qfbscreen.cpp @@ -74,15 +74,15 @@ bool QFbScreen::event(QEvent *event) void QFbScreen::addWindow(QFbWindow *window) { mWindowStack.prepend(window); - if (!mBackingStores.isEmpty()) { + if (!mPendingBackingStores.isEmpty()) { //check if we have a backing store for this window - for (int i = 0; i < mBackingStores.size(); ++i) { - QFbBackingStore *bs = mBackingStores.at(i); + for (int i = 0; i < mPendingBackingStores.size(); ++i) { + QFbBackingStore *bs = mPendingBackingStores.at(i); // this gets called during QWindow::create() at a point where the // invariant (window->handle()->window() == window) is broken if (bs->window() == window->window()) { window->setBackingStore(bs); - mBackingStores.removeAt(i); + mPendingBackingStores.removeAt(i); break; } } @@ -295,5 +295,14 @@ QRegion QFbScreen::doRedraw() return touchedRegion; } +QFbWindow *QFbScreen::windowForId(WId wid) const +{ + for (int i = 0; i < mWindowStack.count(); ++i) + if (mWindowStack[i]->winId() == wid) + return mWindowStack[i]; + + return 0; +} + QT_END_NAMESPACE diff --git a/src/platformsupport/fbconvenience/qfbscreen_p.h b/src/platformsupport/fbconvenience/qfbscreen_p.h index 7f2db51b00..17b2cab43d 100644 --- a/src/platformsupport/fbconvenience/qfbscreen_p.h +++ b/src/platformsupport/fbconvenience/qfbscreen_p.h @@ -80,7 +80,7 @@ public: virtual void lower(QFbWindow *window); virtual void topWindowChanged(QWindow *) {} - void addBackingStore(QFbBackingStore *bs) {mBackingStores << bs;} + void addPendingBackingStore(QFbBackingStore *bs) { mPendingBackingStores << bs; } void scheduleUpdate(); @@ -89,13 +89,14 @@ public slots: void setPhysicalSize(const QSize &size); void setGeometry(const QRect &rect); -protected slots: +protected: virtual QRegion doRedraw(); -protected: void initializeCompositor(); bool event(QEvent *event); + QFbWindow *windowForId(WId wid) const; + QList<QFbWindow *> mWindowStack; QRegion mRepaintRegion; bool mUpdatePending; @@ -113,7 +114,7 @@ private: QPainter *mCompositePainter; QVector<QPair<QRect, int> > mCachedRects; - QList <QFbBackingStore*> mBackingStores; + QList<QFbBackingStore*> mPendingBackingStores; friend class QFbWindow; bool mIsUpToDate; diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index dd9d7d10ff..e4794f8674 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -269,6 +269,7 @@ public: // for QNSView bool m_inConstructor; bool m_inSetVisible; bool m_inSetGeometry; + bool m_inSetStyleMask; #ifndef QT_NO_OPENGL QCocoaGLContext *m_glContext; #endif diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 64e599ae08..b9a09d03b5 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -374,6 +374,7 @@ QCocoaWindow::QCocoaWindow(QWindow *tlw) , m_inConstructor(true) , m_inSetVisible(false) , m_inSetGeometry(false) + , m_inSetStyleMask(false) #ifndef QT_NO_OPENGL , m_glContext(0) #endif @@ -869,10 +870,14 @@ void QCocoaWindow::setWindowFlags(Qt::WindowFlags flags) if (m_nsWindow && !m_isNSWindowChild) { NSUInteger styleMask = windowStyleMask(flags); NSInteger level = this->windowLevel(flags); + // While setting style mask we can have -updateGeometry calls on a content + // view with null geometry, reporting an invalid coordinates as a result. + m_inSetStyleMask = true; [m_nsWindow setStyleMask:styleMask]; + m_inSetStyleMask = false; [m_nsWindow setLevel:level]; setWindowShadow(flags); - if (!(styleMask & NSBorderlessWindowMask)) { + if (!(flags & Qt::FramelessWindowHint)) { setWindowTitle(window()->title()); } diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index cfd2eeb837..39bd5d486c 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -345,6 +345,12 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil; if (m_platformWindow->m_nsWindow && geometry == m_platformWindow->geometry()) return; + // It can happen that self.window is nil (if we are changing + // styleMask from/to borderless and content view is being re-parented) + // - this results in an invalid coordinates. + if (m_platformWindow->m_inSetStyleMask && !self.window) + return; + #ifdef QT_COCOA_ENABLE_WINDOW_DEBUG qDebug() << "QNSView::udpateGeometry" << m_platformWindow << geometry; #endif diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp index 1c3854182f..5407fa66dc 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.cpp @@ -33,6 +33,7 @@ #include "qlinuxfbscreen.h" #include <QtPlatformSupport/private/qfbcursor_p.h> +#include <QtPlatformSupport/private/qfbwindow_p.h> #include <QtCore/QRegularExpression> #include <QtGui/QPainter> @@ -421,5 +422,32 @@ QRegion QLinuxFbScreen::doRedraw() return touched; } +// grabWindow() grabs "from the screen" not from the backingstores. +// In linuxfb's case it will also include the mouse cursor. +QPixmap QLinuxFbScreen::grabWindow(WId wid, int x, int y, int width, int height) const +{ + if (!wid) { + if (width < 0) + width = mFbScreenImage.width() - x; + if (height < 0) + height = mFbScreenImage.height() - y; + return QPixmap::fromImage(mFbScreenImage).copy(x, y, width, height); + } + + QFbWindow *window = windowForId(wid); + if (window) { + const QRect geom = window->geometry(); + if (width < 0) + width = geom.width() - x; + if (height < 0) + height = geom.height() - y; + QRect rect(geom.topLeft() + QPoint(x, y), QSize(width, height)); + rect &= window->geometry(); + return QPixmap::fromImage(mFbScreenImage).copy(rect); + } + + return QPixmap(); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/linuxfb/qlinuxfbscreen.h b/src/plugins/platforms/linuxfb/qlinuxfbscreen.h index 0cb9961599..1adce2189b 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbscreen.h +++ b/src/plugins/platforms/linuxfb/qlinuxfbscreen.h @@ -50,7 +50,8 @@ public: bool initialize(); -public slots: + QPixmap grabWindow(WId wid, int x, int y, int width, int height) const Q_DECL_OVERRIDE; + QRegion doRedraw() Q_DECL_OVERRIDE; private: 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 0caec50c94..2bc9c00a94 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -188,16 +188,18 @@ void QGLXContext::init(QXcbScreen *screen, QPlatformOpenGLContext *share) Window window = 0; // Temporary window used to query OpenGL context if (config) { + const QByteArrayList glxExt = QByteArray(glXQueryExtensionsString(m_display, screen->screenNumber())).split(' '); + // Resolve entry point for glXCreateContextAttribsARB glXCreateContextAttribsARBProc glXCreateContextAttribsARB = 0; - glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); + if (glxExt.contains("GLX_ARB_create_context")) + glXCreateContextAttribsARB = (glXCreateContextAttribsARBProc) glXGetProcAddress((const GLubyte*)"glXCreateContextAttribsARB"); - QList<QByteArray> glxExt = QByteArray(glXQueryExtensionsString(m_display, screen->screenNumber())).split(' '); - bool supportsProfiles = glxExt.contains("GLX_ARB_create_context_profile"); + const bool supportsProfiles = glxExt.contains("GLX_ARB_create_context_profile"); // Use glXCreateContextAttribsARB if available // Also, GL ES context creation requires GLX_EXT_create_context_es2_profile - if (glxExt.contains("GLX_ARB_create_context") && glXCreateContextAttribsARB != 0 + if (glXCreateContextAttribsARB != 0 && (m_format.renderableType() != QSurfaceFormat::OpenGLES || (supportsProfiles && glxExt.contains("GLX_EXT_create_context_es2_profile")))) { // Try to create an OpenGL context for each known OpenGL version in descending // order from the requested version. diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp index da973b5313..7ec5851737 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -1806,10 +1806,11 @@ bool QXcbConnection::xi2PrepareXIGenericDeviceEvent(xcb_ge_event_t *ev, int opCo } #endif // defined(XCB_USE_XINPUT2) -QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() +QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() const { if (!m_systemTrayTracker) { - if ( (m_systemTrayTracker = QXcbSystemTrayTracker::create(this)) ) { + QXcbConnection *self = const_cast<QXcbConnection *>(this); + if ((self->m_systemTrayTracker = QXcbSystemTrayTracker::create(self))) { connect(m_systemTrayTracker, SIGNAL(systemTrayWindowChanged(QScreen*)), QGuiApplication::platformNativeInterface(), SIGNAL(systemTrayWindowChanged(QScreen*))); } @@ -1817,6 +1818,22 @@ QXcbSystemTrayTracker *QXcbConnection::systemTrayTracker() return m_systemTrayTracker; } +bool QXcbConnection::xEmbedSystemTrayAvailable() +{ + if (!QGuiApplicationPrivate::platformIntegration()) + return false; + QXcbConnection *connection = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration())->defaultConnection(); + return connection->systemTrayTracker(); +} + +bool QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel() +{ + if (!QGuiApplicationPrivate::platformIntegration()) + return false; + QXcbConnection *connection = static_cast<QXcbIntegration *>(QGuiApplicationPrivate::platformIntegration())->defaultConnection(); + return connection->systemTrayTracker() && connection->systemTrayTracker()->visualHasAlphaChannel(); +} + bool QXcbConnection::event(QEvent *e) { if (e->type() == QEvent::User + 1) { diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h index a3c8c0b95e..97c2590708 100644 --- a/src/plugins/platforms/xcb/qxcbconnection.h +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -463,7 +463,9 @@ public: QXcbNativeInterface *nativeInterface() const { return m_nativeInterface; } - QXcbSystemTrayTracker *systemTrayTracker(); + QXcbSystemTrayTracker *systemTrayTracker() const; + static bool xEmbedSystemTrayAvailable(); + static bool xEmbedSystemTrayVisualHasAlphaChannel(); #ifdef XCB_USE_XINPUT2 void handleEnterEvent(const xcb_enter_notify_event_t *); @@ -474,6 +476,7 @@ public: bool canGrab() const { return m_canGrabServer; } QXcbGlIntegration *glIntegration() const { return m_glIntegration; } + protected: bool event(QEvent *e) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp index 0688898cae..c6aa25350d 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -47,6 +47,7 @@ #include <QtGui/qscreen.h> #include <QtPlatformHeaders/qxcbwindowfunctions.h> +#include <QtPlatformHeaders/qxcbintegrationfunctions.h> #ifndef QT_NO_DBUS #include "QtPlatformSupport/private/qdbusmenuconnection_p.h" @@ -85,8 +86,7 @@ static int resourceType(const QByteArray &key) QXcbNativeInterface::QXcbNativeInterface() : m_genericEventFilterType(QByteArrayLiteral("xcb_generic_event_t")), - m_sysTraySelectionAtom(XCB_ATOM_NONE), - m_systrayVisualId(XCB_NONE) + m_sysTraySelectionAtom(XCB_ATOM_NONE) { } @@ -109,22 +109,12 @@ bool QXcbNativeInterface::systemTrayAvailable(const QScreen *screen) const bool QXcbNativeInterface::requestSystemTrayWindowDock(const QWindow *window) { - const QPlatformWindow *platformWindow = window->handle(); - if (!platformWindow) - return false; - QXcbSystemTrayTracker *trayTracker = systemTrayTracker(window->screen()); - if (!trayTracker) - return false; - trayTracker->requestSystemTrayWindowDock(static_cast<const QXcbWindow *>(platformWindow)->xcb_window()); - return true; + return QXcbWindow::requestSystemTrayWindowDockStatic(window); } QRect QXcbNativeInterface::systemTrayWindowGlobalGeometry(const QWindow *window) { - if (const QPlatformWindow *platformWindow = window->handle()) - if (const QXcbSystemTrayTracker *trayTracker = systemTrayTracker(window->screen())) - return trayTracker->systemTrayWindowGlobalGeometry(static_cast<const QXcbWindow *>(platformWindow)->xcb_window()); - return QRect(); + return QXcbWindow::systemTrayWindowGlobalGeometryStatic(window); } xcb_window_t QXcbNativeInterface::locateSystemTray(xcb_connection_t *conn, const QXcbScreen *screen) @@ -155,54 +145,14 @@ xcb_window_t QXcbNativeInterface::locateSystemTray(xcb_connection_t *conn, const return selection_window; } -bool QXcbNativeInterface::systrayVisualHasAlphaChannel() { - const QXcbScreen *screen = static_cast<QXcbScreen *>(QGuiApplication::primaryScreen()->handle()); - - if (m_systrayVisualId == XCB_NONE) { - xcb_connection_t *xcb_conn = screen->xcb_connection(); - xcb_atom_t tray_atom = screen->atom(QXcbAtom::_NET_SYSTEM_TRAY_VISUAL); - - xcb_window_t systray_window = locateSystemTray(xcb_conn, screen); - if (systray_window == XCB_WINDOW_NONE) - return false; - - // Get the xcb property for the _NET_SYSTEM_TRAY_VISUAL atom - xcb_get_property_cookie_t systray_atom_cookie; - xcb_get_property_reply_t *systray_atom_reply; - - systray_atom_cookie = xcb_get_property_unchecked(xcb_conn, false, systray_window, - tray_atom, XCB_ATOM_VISUALID, 0, 1); - systray_atom_reply = xcb_get_property_reply(xcb_conn, systray_atom_cookie, 0); - - if (!systray_atom_reply) - return false; - - if (systray_atom_reply->value_len > 0 && xcb_get_property_value_length(systray_atom_reply) > 0) { - xcb_visualid_t * vids = (uint32_t *)xcb_get_property_value(systray_atom_reply); - m_systrayVisualId = vids[0]; - } - - free(systray_atom_reply); - } - - if (m_systrayVisualId != XCB_NONE) { - quint8 depth = screen->depthOfVisual(m_systrayVisualId); - return depth == 32; - } else { - return false; - } +bool QXcbNativeInterface::systrayVisualHasAlphaChannel() +{ + return QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel(); } -void QXcbNativeInterface::setParentRelativeBackPixmap(const QWindow *qwindow) +void QXcbNativeInterface::setParentRelativeBackPixmap(QWindow *window) { - if (const QPlatformWindow *platformWindow = qwindow->handle()) { - const QXcbWindow *qxwindow = static_cast<const QXcbWindow *>(platformWindow); - xcb_connection_t *xcb_conn = qxwindow->xcb_connection(); - - const quint32 mask = XCB_CW_BACK_PIXMAP; - const quint32 values[] = { XCB_BACK_PIXMAP_PARENT_RELATIVE }; - Q_XCB_CALL(xcb_change_window_attributes(xcb_conn, qxwindow->xcb_window(), mask, values)); - } + QXcbWindow::setParentRelativeBackPixmapStatic(window); } void *QXcbNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString) @@ -378,9 +328,24 @@ QFunctionPointer QXcbNativeInterface::platformFunction(const QByteArray &functio return func; //case sensitive - if (function == QXcbWindowFunctions::setWmWindowTypeIdentifier()) { - return QFunctionPointer(QXcbWindow::setWmWindowTypeStatic); - } + if (function == QXcbWindowFunctions::setWmWindowTypeIdentifier()) + return QFunctionPointer(QXcbWindowFunctions::SetWmWindowType(QXcbWindow::setWmWindowTypeStatic)); + + if (function == QXcbWindowFunctions::setWmWindowIconTextIdentifier()) + return QFunctionPointer(QXcbWindowFunctions::SetWmWindowIconText(QXcbWindow::setWindowIconTextStatic)); + + if (function == QXcbWindowFunctions::setParentRelativeBackPixmapIdentifier()) + return QFunctionPointer(QXcbWindowFunctions::SetParentRelativeBackPixmap(QXcbWindow::setParentRelativeBackPixmapStatic)); + + if (function == QXcbWindowFunctions::requestSystemTrayWindowDockIdentifier()) + return QFunctionPointer(QXcbWindowFunctions::RequestSystemTrayWindowDock(QXcbWindow::requestSystemTrayWindowDockStatic)); + + if (function == QXcbWindowFunctions::systemTrayWindowGlobalGeometryIdentifier()) + return QFunctionPointer(QXcbWindowFunctions::SystemTrayWindowGlobalGeometry(QXcbWindow::systemTrayWindowGlobalGeometryStatic)); + + if (function == QXcbIntegrationFunctions::xEmbedSystemTrayVisualHasAlphaChannelIdentifier()) + return QFunctionPointer(QXcbIntegrationFunctions::XEmbedSystemTrayVisualHasAlphaChannel(QXcbConnection::xEmbedSystemTrayVisualHasAlphaChannel)); + return Q_NULLPTR; } diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h index 64da388258..b6c207785f 100644 --- a/src/plugins/platforms/xcb/qxcbnativeinterface.h +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h @@ -104,7 +104,7 @@ public: Q_INVOKABLE void beep(); Q_INVOKABLE bool systemTrayAvailable(const QScreen *screen) const; - Q_INVOKABLE void setParentRelativeBackPixmap(const QWindow *window); + Q_INVOKABLE void setParentRelativeBackPixmap(QWindow *window); Q_INVOKABLE bool systrayVisualHasAlphaChannel(); Q_INVOKABLE bool requestSystemTrayWindowDock(const QWindow *window); Q_INVOKABLE QRect systemTrayWindowGlobalGeometry(const QWindow *window); @@ -120,7 +120,6 @@ private: const QByteArray m_genericEventFilterType; xcb_atom_t m_sysTraySelectionAtom; - xcb_visualid_t m_systrayVisualId; static QXcbScreen *qPlatformScreenForWindow(QWindow *window); diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp index a4fdd70b79..1f217e8de7 100644 --- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp +++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.cpp @@ -63,14 +63,14 @@ QXcbSystemTrayTracker *QXcbSystemTrayTracker::create(QXcbConnection *connection) const xcb_atom_t selection = connection->internAtom(netSysTray.constData()); if (!selection) return 0; - return new QXcbSystemTrayTracker(connection, trayAtom, selection, connection); + + return new QXcbSystemTrayTracker(connection, trayAtom, selection); } QXcbSystemTrayTracker::QXcbSystemTrayTracker(QXcbConnection *connection, xcb_atom_t trayAtom, - xcb_atom_t selection, - QObject *parent) - : QObject(parent) + xcb_atom_t selection) + : QObject(connection) , m_selection(selection) , m_trayAtom(trayAtom) , m_connection(connection) @@ -125,6 +125,7 @@ xcb_window_t QXcbSystemTrayTracker::trayWindow() // does not work for the QWindow parented on the tray. QRect QXcbSystemTrayTracker::systemTrayWindowGlobalGeometry(xcb_window_t window) const { + xcb_connection_t *conn = m_connection->xcb_connection(); xcb_get_geometry_reply_t *geomReply = xcb_get_geometry_reply(conn, xcb_get_geometry(conn, window), 0); @@ -161,9 +162,43 @@ void QXcbSystemTrayTracker::handleDestroyNotifyEvent(const xcb_destroy_notify_ev { if (event->window == m_trayWindow) { m_connection->removeWindowEventListener(m_trayWindow); - m_trayWindow = 0; + m_trayWindow = XCB_WINDOW_NONE; emitSystemTrayWindowChanged(); } } +bool QXcbSystemTrayTracker::visualHasAlphaChannel() +{ + if (m_trayWindow == XCB_WINDOW_NONE) + return false; + + xcb_atom_t tray_atom = m_connection->atom(QXcbAtom::_NET_SYSTEM_TRAY_VISUAL); + + // Get the xcb property for the _NET_SYSTEM_TRAY_VISUAL atom + xcb_get_property_cookie_t systray_atom_cookie; + xcb_get_property_reply_t *systray_atom_reply; + + systray_atom_cookie = xcb_get_property_unchecked(m_connection->xcb_connection(), false, m_trayWindow, + tray_atom, XCB_ATOM_VISUALID, 0, 1); + systray_atom_reply = xcb_get_property_reply(m_connection->xcb_connection(), systray_atom_cookie, 0); + + if (!systray_atom_reply) + return false; + + xcb_visualid_t systrayVisualId = XCB_NONE; + if (systray_atom_reply->value_len > 0 && xcb_get_property_value_length(systray_atom_reply) > 0) { + xcb_visualid_t * vids = (uint32_t *)xcb_get_property_value(systray_atom_reply); + systrayVisualId = vids[0]; + } + + free(systray_atom_reply); + + if (systrayVisualId != XCB_NONE) { + quint8 depth = m_connection->primaryScreen()->depthOfVisual(systrayVisualId); + return depth == 32; + } + + return false; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qxcbsystemtraytracker.h b/src/plugins/platforms/xcb/qxcbsystemtraytracker.h index 9c20f1729a..b619afb9c4 100644 --- a/src/plugins/platforms/xcb/qxcbsystemtraytracker.h +++ b/src/plugins/platforms/xcb/qxcbsystemtraytracker.h @@ -57,14 +57,14 @@ public: void handleDestroyNotifyEvent(const xcb_destroy_notify_event_t *) Q_DECL_OVERRIDE; + bool visualHasAlphaChannel(); signals: void systemTrayWindowChanged(QScreen *screen); private: explicit QXcbSystemTrayTracker(QXcbConnection *connection, xcb_atom_t trayAtom, - xcb_atom_t selection, - QObject *parent = 0); + xcb_atom_t selection); static xcb_window_t locateTrayWindow(const QXcbConnection *connection, xcb_atom_t selection); void emitSystemTrayWindowChanged(); diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index e2b104e3f1..6d2f5276b3 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -46,6 +46,7 @@ #include "qxcbwmsupport.h" #include "qxcbimage.h" #include "qxcbnativeinterface.h" +#include "qxcbsystemtraytracker.h" #include <qpa/qplatformintegration.h> @@ -1392,10 +1393,22 @@ void QXcbWindow::setWindowTitle(const QString &title) xcb_flush(xcb_connection()); } +void QXcbWindow::setWindowIconText(const QString &title) +{ + const QByteArray ba = title.toUtf8(); + Q_XCB_CALL(xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_NET_WM_ICON_NAME), + atom(QXcbAtom::UTF8_STRING), + 8, + ba.length(), + ba.constData())); +} + void QXcbWindow::setWindowIcon(const QIcon &icon) { QVector<quint32> icon_data; - if (!icon.isNull()) { QList<QSize> availableSizes = icon.availableSizes(); if (availableSizes.isEmpty()) { @@ -1560,6 +1573,12 @@ void QXcbWindow::setWmWindowTypeStatic(QWindow *window, QXcbWindowFunctions::WmW window->setProperty(wm_window_type_property_id, QVariant::fromValue(static_cast<int>(windowTypes))); } +void QXcbWindow::setWindowIconTextStatic(QWindow *window, const QString &text) +{ + if (window->handle()) + static_cast<QXcbWindow *>(window->handle())->setWindowIconText(text); +} + QXcbWindowFunctions::WmWindowTypes QXcbWindow::wmWindowTypes() const { QXcbWindowFunctions::WmWindowTypes result(0); @@ -1676,6 +1695,48 @@ void QXcbWindow::setWmWindowType(QXcbWindowFunctions::WmWindowTypes types) xcb_flush(xcb_connection()); } +void QXcbWindow::setParentRelativeBackPixmapStatic(QWindow *window) +{ + if (window->handle()) + static_cast<QXcbWindow *>(window->handle())->setParentRelativeBackPixmap(); +} + +void QXcbWindow::setParentRelativeBackPixmap() +{ + const quint32 mask = XCB_CW_BACK_PIXMAP; + const quint32 values[] = { XCB_BACK_PIXMAP_PARENT_RELATIVE }; + Q_XCB_CALL(xcb_change_window_attributes(xcb_connection(), m_window, mask, values)); +} + +bool QXcbWindow::requestSystemTrayWindowDockStatic(const QWindow *window) +{ + if (window->handle()) + return static_cast<QXcbWindow *>(window->handle())->requestSystemTrayWindowDock(); + return false; +} + +bool QXcbWindow::requestSystemTrayWindowDock() const +{ + if (!connection()->systemTrayTracker()) + return false; + connection()->systemTrayTracker()->requestSystemTrayWindowDock(m_window); + return true; +} + +QRect QXcbWindow::systemTrayWindowGlobalGeometryStatic(const QWindow *window) +{ + if (window->handle()) + return static_cast<QXcbWindow *>(window->handle())->systemTrayWindowGlobalGeometry(); + return QRect(); +} + +QRect QXcbWindow::systemTrayWindowGlobalGeometry() const +{ + if (!connection()->systemTrayTracker()) + return QRect(); + return connection()->systemTrayTracker()->systemTrayWindowGlobalGeometry(m_window); +} + class ExposeCompressor { public: diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 8f78be573c..cd3c091973 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -86,6 +86,7 @@ public: QPoint mapFromGlobal(const QPoint &pos) const Q_DECL_OVERRIDE; void setWindowTitle(const QString &title) Q_DECL_OVERRIDE; + void setWindowIconText(const QString &title); void setWindowIcon(const QIcon &icon) Q_DECL_OVERRIDE; void raise() Q_DECL_OVERRIDE; void lower() Q_DECL_OVERRIDE; @@ -142,6 +143,17 @@ public: QXcbWindowFunctions::WmWindowTypes wmWindowTypes() const; void setWmWindowType(QXcbWindowFunctions::WmWindowTypes types); + static void setWindowIconTextStatic(QWindow *window, const QString &text); + + static void setParentRelativeBackPixmapStatic(QWindow *window); + void setParentRelativeBackPixmap(); + + static bool requestSystemTrayWindowDockStatic(const QWindow *window); + bool requestSystemTrayWindowDock() const; + + static QRect systemTrayWindowGlobalGeometryStatic(const QWindow *window); + QRect systemTrayWindowGlobalGeometry() const; + bool needsSync() const; void postSyncWindowRequest(); diff --git a/src/tools/qdoc/config.cpp b/src/tools/qdoc/config.cpp index 5ab3cb0d7d..e3b2f0325d 100644 --- a/src/tools/qdoc/config.cpp +++ b/src/tools/qdoc/config.cpp @@ -912,8 +912,10 @@ QStringList Config::loadMaster(const QString& fileName) */ void Config::load(Location location, const QString& fileName) { - pushWorkingDir(QFileInfo(fileName).path()); - QDir::setCurrent(QFileInfo(fileName).path()); + QFileInfo fileInfo(fileName); + QString path = fileInfo.canonicalPath(); + pushWorkingDir(path); + QDir::setCurrent(path); QRegExp keySyntax(QLatin1String("\\w+(?:\\.\\w+)*")); #define SKIP_CHAR() \ @@ -935,7 +937,7 @@ void Config::load(Location location, const QString& fileName) if (location.depth() > 16) location.fatal(tr("Too many nested includes")); - QFile fin(fileName); + QFile fin(fileInfo.fileName()); if (!fin.open(QFile::ReadOnly | QFile::Text)) { if (!Config::installDir.isEmpty()) { int prefix = location.filePath().length() - location.fileName().length(); @@ -1030,7 +1032,7 @@ void Config::load(Location location, const QString& fileName) /* Here is the recursive call. */ - load(location, QFileInfo(QFileInfo(fileName).dir(), includeFile).filePath()); + load(location, QFileInfo(QDir(path), includeFile).filePath()); } else { /* diff --git a/src/tools/qdoc/helpprojectwriter.cpp b/src/tools/qdoc/helpprojectwriter.cpp index 90b1d9cfe3..2ae952a962 100644 --- a/src/tools/qdoc/helpprojectwriter.cpp +++ b/src/tools/qdoc/helpprojectwriter.cpp @@ -107,13 +107,13 @@ void HelpProjectWriter::reset(const Config &config, subproject.sortPages = config.getBool(subprefix + "sortPages"); subproject.type = config.getString(subprefix + "type"); readSelectors(subproject, config.getStringList(subprefix + "selectors")); - project.subprojects[name] = subproject; + project.subprojects.append(subproject); } if (project.subprojects.isEmpty()) { SubProject subproject; readSelectors(subproject, config.getStringList(prefix + "selectors")); - project.subprojects.insert(QString(), subproject); + project.subprojects.insert(0, subproject); } projects.append(project); @@ -260,16 +260,16 @@ bool HelpProjectWriter::generateSection(HelpProject &project, // Only add nodes to the set for each subproject if they match a selector. // Those that match will be listed in the table of contents. - foreach (const QString &name, project.subprojects.keys()) { - SubProject subproject = project.subprojects[name]; + for (int i = 0; i < project.subprojects.length(); i++) { + SubProject subproject = project.subprojects[i]; // No selectors: accept all nodes. if (subproject.selectors.isEmpty()) { - project.subprojects[name].nodes[objName] = node; + project.subprojects[i].nodes[objName] = node; } else if (subproject.selectors.contains(node->type())) { // Accept only the node types in the selectors hash. if (node->type() != Node::Document) - project.subprojects[name].nodes[objName] = node; + project.subprojects[i].nodes[objName] = node; else { // Accept only fake nodes with subtypes contained in the selector's // mask. @@ -278,7 +278,7 @@ bool HelpProjectWriter::generateSection(HelpProject &project, docNode->subType() != Node::ExternalPage && !docNode->fullTitle().isEmpty()) { - project.subprojects[name].nodes[objName] = node; + project.subprojects[i].nodes[objName] = node; } } } @@ -713,8 +713,8 @@ void HelpProjectWriter::generateProject(HelpProject &project) generateSections(project, writer, rootNode); - foreach (const QString &name, project.subprojects.keys()) { - SubProject subproject = project.subprojects[name]; + for (int i = 0; i < project.subprojects.length(); i++) { + SubProject subproject = project.subprojects[i]; if (subproject.type == QLatin1String("manual")) { @@ -769,13 +769,12 @@ void HelpProjectWriter::generateProject(HelpProject &project) } else { - if (!name.isEmpty()) { - writer.writeStartElement("section"); - QString indexPath = gen_->fullDocumentLocation(qdb_->findNodeForTarget(subproject.indexTitle, 0), + writer.writeStartElement("section"); + QString indexPath = gen_->fullDocumentLocation(qdb_->findNodeForTarget(subproject.indexTitle, 0), false); - writer.writeAttribute("ref", indexPath); - writer.writeAttribute("title", subproject.title); - } + writer.writeAttribute("ref", indexPath); + writer.writeAttribute("title", subproject.title); + if (subproject.sortPages) { QStringList titles = subproject.nodes.keys(); titles.sort(); @@ -815,8 +814,7 @@ void HelpProjectWriter::generateProject(HelpProject &project) } } - if (!name.isEmpty()) - writer.writeEndElement(); // section + writer.writeEndElement(); // section } } diff --git a/src/tools/qdoc/helpprojectwriter.h b/src/tools/qdoc/helpprojectwriter.h index efc2596296..8f21238c2a 100644 --- a/src/tools/qdoc/helpprojectwriter.h +++ b/src/tools/qdoc/helpprojectwriter.h @@ -70,7 +70,7 @@ struct HelpProject QSet<QString> filterAttributes; QHash<QString, QSet<QString> > customFilters; QSet<QString> excluded; - QMap<QString, SubProject> subprojects; + QList<SubProject> subprojects; QHash<const Node *, QSet<Node::Status> > memberStatus; bool includeIndexNodes; }; diff --git a/src/tools/qdoc/main.cpp b/src/tools/qdoc/main.cpp index 74d706efe1..4a99ec39de 100644 --- a/src/tools/qdoc/main.cpp +++ b/src/tools/qdoc/main.cpp @@ -227,6 +227,8 @@ static void processQdocconfFile(const QString &fileName) config.setStringList(CONFIG_AUTOLINKERRORS, QStringList(autolinkErrors ? "true" : "false")); config.setStringList(CONFIG_OBSOLETELINKS, QStringList(obsoleteLinks ? "true" : "false")); + prevCurrentDir = QDir::currentPath(); + /* With the default configuration values in place, load the qdoc configuration file. Note that the configuration @@ -236,7 +238,6 @@ static void processQdocconfFile(const QString &fileName) in the file being processed, mainly for error reporting purposes. */ - currentDir = QFileInfo(fileName).path(); Location::initialize(config); config.load(fileName); QString project = config.getString(CONFIG_PROJECT); @@ -248,7 +249,6 @@ static void processQdocconfFile(const QString &fileName) config.setStringList(CONFIG_DEFINES,defs); Location::terminate(); - prevCurrentDir = QDir::currentPath(); currentDir = QFileInfo(fileName).path(); if (!currentDir.isEmpty()) QDir::setCurrent(currentDir); diff --git a/src/widgets/accessible/qaccessiblewidgets.cpp b/src/widgets/accessible/qaccessiblewidgets.cpp index 7080dd6f8d..c598a5b4cb 100644 --- a/src/widgets/accessible/qaccessiblewidgets.cpp +++ b/src/widgets/accessible/qaccessiblewidgets.cpp @@ -667,12 +667,25 @@ QRect QAccessibleTextWidget::characterRect(int offset) const if (line.isValid()) { qreal x = line.cursorToX(relativeOffset); - QFontMetrics fm(textCursor().charFormat().font()); + + QTextCharFormat format; + QTextBlock::iterator iter = block.begin(); + if (iter.atEnd()) + format = block.charFormat(); + else { + while (!iter.atEnd() && !iter.fragment().contains(offset)) + ++iter; + if (iter.atEnd()) // newline should have same format as preceding character + --iter; + format = iter.fragment().charFormat(); + } + + QFontMetrics fm(format.font()); const QString ch = text(offset, offset + 1); if (!ch.isEmpty()) { int w = fm.width(ch); int h = fm.height(); - r = QRect(layoutPosition.x() + x, layoutPosition.y() + line.y(), + r = QRect(layoutPosition.x() + x, layoutPosition.y() + line.y() + line.ascent() + fm.descent() - h, w, h); r.moveTo(viewport()->mapToGlobal(r.topLeft())); } @@ -776,7 +789,45 @@ QString QAccessibleTextWidget::attributes(int offset, int *startOffset, int *end QFont::Style style = charFormat.font().style(); attrs["font-style"] = QString::fromLatin1((style == QFont::StyleItalic) ? "italic" : ((style == QFont::StyleOblique) ? "oblique": "normal")); - attrs["text-underline-style"] = QString::fromLatin1(charFormat.font().underline() ? "solid" : "none"); + QTextCharFormat::UnderlineStyle underlineStyle = charFormat.underlineStyle(); + if (underlineStyle == QTextCharFormat::NoUnderline && charFormat.font().underline()) // underline could still be set in the default font + underlineStyle = QTextCharFormat::SingleUnderline; + QString underlineStyleValue; + switch (underlineStyle) { + case QTextCharFormat::NoUnderline: + break; + case QTextCharFormat::SingleUnderline: + underlineStyleValue = QStringLiteral("solid"); + break; + case QTextCharFormat::DashUnderline: + underlineStyleValue = QStringLiteral("dash"); + break; + case QTextCharFormat::DotLine: + underlineStyleValue = QStringLiteral("dash"); + break; + case QTextCharFormat::DashDotLine: + underlineStyleValue = QStringLiteral("dot-dash"); + break; + case QTextCharFormat::DashDotDotLine: + underlineStyleValue = QStringLiteral("dot-dot-dash"); + break; + case QTextCharFormat::WaveUnderline: + underlineStyleValue = QStringLiteral("wave"); + break; + case QTextCharFormat::SpellCheckUnderline: + underlineStyleValue = QStringLiteral("wave"); // this is not correct, but provides good approximation at least + break; + default: + qWarning() << "Unknown QTextCharFormat::​UnderlineStyle value " << underlineStyle << " could not be translated to IAccessible2 value"; + break; + } + if (!underlineStyleValue.isNull()) { + attrs["text-underline-style"] = underlineStyleValue; + attrs["text-underline-type"] = QStringLiteral("single"); // if underlineStyleValue is set, there is an underline, and Qt does not support other than single ones + } // else both are "none" which is the default - no need to set them + + if (block.textDirection() == Qt::RightToLeft) + attrs["writing-mode"] = QStringLiteral("rl"); QTextCharFormat::VerticalAlignment alignment = charFormat.verticalAlignment(); attrs["text-position"] = QString::fromLatin1((alignment == QTextCharFormat::AlignSubScript) ? "sub" : ((alignment == QTextCharFormat::AlignSuperScript) ? "super" : "baseline" )); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 65b861bc68..6d8bad3149 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -100,6 +100,7 @@ #include "qwindowcontainer_p.h" +#include <QtPlatformHeaders/qxcbwindowfunctions.h> // widget/widget data creation count //#define QWIDGET_EXTRA_DEBUG @@ -704,7 +705,7 @@ void QWidget::setAutoFillBackground(bool enabled) close(). \row \li Top-level windows \li - \l windowModified, \l windowTitle, \l windowIcon, \l windowIconText, + \l windowModified, \l windowTitle, \l windowIcon, \l isActiveWindow, activateWindow(), \l minimized, showMinimized(), \l maximized, showMaximized(), \l fullScreen, showFullScreen(), showNormal(). @@ -5934,7 +5935,7 @@ void QWidget::unsetLocale() window title, if set. This is done by the QPA plugin, so it is shown to the user, but isn't part of the windowTitle string. - \sa windowIcon, windowIconText, windowModified, windowFilePath + \sa windowIcon, windowModified, windowFilePath */ QString QWidget::windowTitle() const { @@ -6029,7 +6030,11 @@ void QWidgetPrivate::setWindowIconText_helper(const QString &title) void QWidgetPrivate::setWindowIconText_sys(const QString &iconText) { - Q_UNUSED(iconText); + Q_Q(QWidget); + // ### The QWidget property is deprecated, but the XCB window function is not. + // It should remain available for the rare application that needs it. + if (QWindow *window = q->windowHandle()) + QXcbWindowFunctions::setWmWindowIconText(window, iconText); } /*! @@ -6039,6 +6044,9 @@ void QWidgetPrivate::setWindowIconText_sys(const QString &iconText) new \a iconText as an argument. \since 5.2 + \obsolete + + This signal is deprecated. */ void QWidget::setWindowIconText(const QString &iconText) @@ -6089,7 +6097,7 @@ void QWidget::setWindowTitle(const QString &title) has been set, windowIcon() returns the application icon (QApplication::windowIcon()). - \sa windowIconText, windowTitle + \sa windowTitle */ QIcon QWidget::windowIcon() const { @@ -6149,10 +6157,15 @@ void QWidgetPrivate::setWindowIcon_sys() /*! \property QWidget::windowIconText - \brief the widget's icon text + \brief the text to be displayed on the icon of a minimized window This property only makes sense for windows. If no icon - text has been set, this functions returns an empty string. + text has been set, this accessor returns an empty string. + It is only implemented on the X11 platform, and only certain + window managers use this window property. + + \obsolete + This property is deprecated. \sa windowIcon, windowTitle */ diff --git a/src/widgets/kernel/qwidget.h b/src/widgets/kernel/qwidget.h index c3913e9d45..d49551f4f4 100644 --- a/src/widgets/kernel/qwidget.h +++ b/src/widgets/kernel/qwidget.h @@ -165,7 +165,7 @@ class Q_WIDGETS_EXPORT QWidget : public QObject, public QPaintDevice Q_PROPERTY(bool acceptDrops READ acceptDrops WRITE setAcceptDrops) Q_PROPERTY(QString windowTitle READ windowTitle WRITE setWindowTitle NOTIFY windowTitleChanged DESIGNABLE isWindow) Q_PROPERTY(QIcon windowIcon READ windowIcon WRITE setWindowIcon NOTIFY windowIconChanged DESIGNABLE isWindow) - Q_PROPERTY(QString windowIconText READ windowIconText WRITE setWindowIconText NOTIFY windowIconTextChanged DESIGNABLE isWindow) + Q_PROPERTY(QString windowIconText READ windowIconText WRITE setWindowIconText NOTIFY windowIconTextChanged DESIGNABLE isWindow) // deprecated Q_PROPERTY(double windowOpacity READ windowOpacity WRITE setWindowOpacity DESIGNABLE isWindow) Q_PROPERTY(bool windowModified READ isWindowModified WRITE setWindowModified DESIGNABLE isWindow) #ifndef QT_NO_TOOLTIP diff --git a/src/widgets/util/qsystemtrayicon_x11.cpp b/src/widgets/util/qsystemtrayicon_x11.cpp index 2b153d53d9..2752c56c65 100644 --- a/src/widgets/util/qsystemtrayicon_x11.cpp +++ b/src/widgets/util/qsystemtrayicon_x11.cpp @@ -52,6 +52,8 @@ #include <private/qguiapplication_p.h> #include <qdebug.h> +#include <QtPlatformHeaders/qxcbwindowfunctions.h> +#include <QtPlatformHeaders/qxcbintegrationfunctions.h> #ifndef QT_NO_SYSTEMTRAYICON QT_BEGIN_NAMESPACE @@ -112,17 +114,11 @@ QSystemTrayIconSys::QSystemTrayIconSys(QSystemTrayIcon *qIn) // window to ParentRelative (so that it inherits the background of its X11 parent window), call // xcb_clear_region before painting (so that the inherited background is visible) and then grab // the just-drawn background from the X11 server. - bool hasAlphaChannel = false; - QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(), - "systrayVisualHasAlphaChannel", Qt::DirectConnection, - Q_RETURN_ARG(bool, hasAlphaChannel)); + bool hasAlphaChannel = QXcbIntegrationFunctions::xEmbedSystemTrayVisualHasAlphaChannel(); setAttribute(Qt::WA_TranslucentBackground, hasAlphaChannel); if (!hasAlphaChannel) { createWinId(); - QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(), - "setParentRelativeBackPixmap", Qt::DirectConnection, - Q_ARG(const QWindow *, windowHandle()) - ); + QXcbWindowFunctions::setParentRelativeBackPixmap(windowHandle()); // XXX: This is actually required, but breaks things ("QWidget::paintEngine: Should no // longer be called"). Why is this needed? When the widget is drawn, we use tricks to grab @@ -143,15 +139,9 @@ bool QSystemTrayIconSys::addToTray() createWinId(); setMouseTracking(true); - bool requestResult = false; - if (!QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(), - "requestSystemTrayWindowDock", Qt::DirectConnection, - Q_RETURN_ARG(bool, requestResult), - Q_ARG(const QWindow *, windowHandle())) - || !requestResult) { - qWarning("requestSystemTrayWindowDock failed."); + if (!QXcbWindowFunctions::requestSystemTrayWindowDock(windowHandle())) return false; - } + if (!background.isNull()) background = QPixmap(); show(); @@ -171,15 +161,7 @@ void QSystemTrayIconSys::systemTrayWindowChanged(QScreen *) QRect QSystemTrayIconSys::globalGeometry() const { - QRect result; - if (!QMetaObject::invokeMethod(QGuiApplication::platformNativeInterface(), - "systemTrayWindowGlobalGeometry", Qt::DirectConnection, - Q_RETURN_ARG(QRect, result), - Q_ARG(const QWindow *, windowHandle())) - || !result.isValid()) { - qWarning("systemTrayWindowGlobalGeometry failed."); - } - return result; + return QXcbWindowFunctions::systemTrayWindowGlobalGeometry(windowHandle()); } void QSystemTrayIconSys::mousePressEvent(QMouseEvent *ev) |