summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFrederik Gladhorn <[email protected]>2014-10-20 19:12:23 +0200
committerFrederik Gladhorn <[email protected]>2014-10-20 19:12:25 +0200
commit3361fcbc28be96262d22fd2b024c85fbcbc61462 (patch)
tree48976f337b3885971dc1976b9a27cec5e7dfa2ec /src
parentdc612acdc6577594c8f61345cea2de549d7aae34 (diff)
parent5e342f6f041208d142d97202f61179d7163eb773 (diff)
Merge remote-tracking branch 'origin/5.4' into dev
Diffstat (limited to 'src')
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java2
-rw-r--r--src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java3
-rw-r--r--src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java2
-rw-r--r--src/android/templates/res/values/libs.xml2
-rw-r--r--src/corelib/doc/qtcore.qdocconf7
-rw-r--r--src/corelib/doc/src/custom-types.qdoc22
-rw-r--r--src/corelib/global/qcompilerdetection.h7
-rw-r--r--src/corelib/global/qglobal.cpp4
-rw-r--r--src/corelib/global/qlogging.cpp5
-rw-r--r--src/corelib/io/qfiledevice.cpp4
-rw-r--r--src/corelib/io/qfilesystemmetadata_p.h3
-rw-r--r--src/corelib/io/qfsfileengine_p.h2
-rw-r--r--src/corelib/io/qloggingregistry.cpp8
-rw-r--r--src/corelib/io/qprocess.cpp7
-rw-r--r--src/corelib/io/qprocess_win.cpp2
-rw-r--r--src/corelib/io/qsettings.cpp19
-rw-r--r--src/corelib/itemmodels/qabstractitemmodel.cpp4
-rw-r--r--src/corelib/kernel/qeventdispatcher_win.cpp8
-rw-r--r--src/corelib/kernel/qeventdispatcher_win_p.h2
-rw-r--r--src/corelib/kernel/qjni.cpp65
-rw-r--r--src/corelib/kernel/qtcore_eval.cpp5
-rw-r--r--src/corelib/tools/qdatetime.cpp2
-rw-r--r--src/corelib/tools/qdatetime.h2
-rw-r--r--src/corelib/tools/qeasingcurve.cpp2
-rw-r--r--src/corelib/tools/qstring.cpp2
-rw-r--r--src/gui/kernel/qclipboard.cpp11
-rw-r--r--src/gui/kernel/qevent.cpp11
-rw-r--r--src/gui/kernel/qoffscreensurface.cpp8
-rw-r--r--src/gui/kernel/qopenglcontext.cpp10
-rw-r--r--src/gui/kernel/qopenglcontext_p.h3
-rw-r--r--src/gui/kernel/qopenglwindow.cpp17
-rw-r--r--src/gui/kernel/qplatformmenu.h5
-rw-r--r--src/gui/kernel/qwindowsysteminterface.cpp12
-rw-r--r--src/gui/opengl/opengl.pri1
-rw-r--r--src/gui/opengl/qopenglpaintdevice.cpp31
-rw-r--r--src/gui/opengl/qopenglpaintdevice.h2
-rw-r--r--src/gui/opengl/qopenglpaintdevice_p.h81
-rw-r--r--src/gui/opengl/qopenglpaintengine.cpp5
-rw-r--r--src/gui/painting/qpainter.cpp3
-rw-r--r--src/gui/text/qfont.cpp3
-rw-r--r--src/network/socket/qnativesocketengine_unix.cpp33
-rw-r--r--src/network/ssl/qsslcertificate.cpp6
-rw-r--r--src/network/ssl/qsslcertificate.h6
-rw-r--r--src/network/ssl/qsslcertificate_openssl.cpp13
-rw-r--r--src/network/ssl/qsslcertificate_qt.cpp6
-rw-r--r--src/network/ssl/qsslcontext_openssl.cpp17
-rw-r--r--src/network/ssl/qsslerror.cpp13
-rw-r--r--src/network/ssl/qsslerror.h2
-rw-r--r--src/network/ssl/qsslsocket_winrt.cpp10
-rw-r--r--src/platformsupport/eglconvenience/qeglconvenience.cpp5
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp241
-rw-r--r--src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h5
-rw-r--r--src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm50
-rw-r--r--src/platformsupport/linuxaccessibility/application.cpp4
-rw-r--r--src/plugins/bearer/connman/qconnmanengine.cpp2
-rw-r--r--src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp2
-rw-r--r--src/plugins/platforms/android/android.pro2
-rw-r--r--src/plugins/platforms/android/androiddeadlockprotector.cpp37
-rw-r--r--src/plugins/platforms/android/androiddeadlockprotector.h67
-rw-r--r--src/plugins/platforms/android/androidjniaccessibility.cpp28
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp29
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.h3
-rw-r--r--src/plugins/platforms/android/qandroidplatformclipboard.cpp16
-rw-r--r--src/plugins/platforms/android/qandroidplatformopenglwindow.cpp5
-rw-r--r--src/plugins/platforms/android/qandroidplatformscreen.cpp4
-rw-r--r--src/plugins/platforms/cocoa/qcocoaclipboard.h8
-rw-r--r--src/plugins/platforms/cocoa/qcocoaclipboard.mm16
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenu.mm9
-rw-r--r--src/plugins/platforms/cocoa/qcocoamenuitem.mm11
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm6
-rw-r--r--src/plugins/platforms/ios/qiosclipboard.h4
-rw-r--r--src/plugins/platforms/ios/qiosclipboard.mm11
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm4
-rw-r--r--src/plugins/platforms/ios/qiosmenu.mm3
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.h1
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm90
-rw-r--r--src/plugins/platforms/ios/qioswindow.h10
-rw-r--r--src/plugins/platforms/ios/qioswindow.mm37
-rw-r--r--src/plugins/platforms/ios/quiview.h4
-rw-r--r--src/plugins/platforms/ios/quiview.mm13
-rw-r--r--src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp1
-rw-r--r--src/plugins/platforms/xcb/qxcbkeyboard.cpp10
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp51
-rw-r--r--src/testlib/qbenchmarkvalgrind.cpp24
-rw-r--r--src/tools/qdoc/qdocdatabase.cpp8
-rw-r--r--src/tools/rcc/rcc.cpp15
-rw-r--r--src/widgets/itemviews/qabstractitemview.cpp5
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp105
-rw-r--r--src/widgets/kernel/qsizepolicy.h4
-rw-r--r--src/widgets/kernel/qwidget.cpp27
-rw-r--r--src/widgets/kernel/qwidget_p.h2
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp6
-rw-r--r--src/widgets/styles/qfusionstyle.cpp3
-rw-r--r--src/widgets/styles/qmacstyle_mac.mm218
-rw-r--r--src/widgets/styles/qmacstyle_mac_p_p.h9
-rw-r--r--src/widgets/widgets/qabstractscrollarea.cpp3
-rw-r--r--src/widgets/widgets/qcombobox.cpp2
-rw-r--r--src/widgets/widgets/qmenu.cpp2
-rw-r--r--src/widgets/widgets/qtoolbutton.cpp3
-rw-r--r--src/xml/sax/qxml.cpp17
100 files changed, 1195 insertions, 547 deletions
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
index 6dad8888ce8..ed5be81d80c 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtActivityDelegate.java
@@ -1090,8 +1090,6 @@ public class QtActivityDelegate
Log.e(QtNative.QtTAG, "Surface " + id +" not found!");
return;
}
-
- m_layout.requestLayout();
}
public void destroySurface(int id) {
diff --git a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java
index 6de66fe5121..80028e1b029 100644
--- a/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java
+++ b/src/android/jar/src/org/qtproject/qt5/android/QtInputConnection.java
@@ -174,6 +174,9 @@ public class QtInputConnection extends BaseInputConnection
QtExtractedText qExtractedText = QtNativeInputConnection.getExtractedText(request.hintMaxChars,
request.hintMaxLines,
flags);
+ if (qExtractedText == null)
+ return null;
+
ExtractedText extractedText = new ExtractedText();
extractedText.partialEndOffset = qExtractedText.partialEndOffset;
extractedText.partialStartOffset = qExtractedText.partialStartOffset;
diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
index e526c0a2109..0c52bc75303 100644
--- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
+++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java
@@ -99,7 +99,7 @@ import android.view.ActionMode.Callback;
public class QtActivity extends Activity
{
private final static int MINISTRO_INSTALL_REQUEST_CODE = 0xf3ee; // request code used to know when Ministro instalation is finished
- private static final int MINISTRO_API_LEVEL = 4; // Ministro api level (check IMinistro.aidl file)
+ private static final int MINISTRO_API_LEVEL = 5; // Ministro api level (check IMinistro.aidl file)
private static final int NECESSITAS_API_LEVEL = 2; // Necessitas api level used by platform plugin
private static final int QT_VERSION = 0x050100; // This app requires at least Qt version 5.1.0
diff --git a/src/android/templates/res/values/libs.xml b/src/android/templates/res/values/libs.xml
index 664ab0abecc..4d68673cb06 100644
--- a/src/android/templates/res/values/libs.xml
+++ b/src/android/templates/res/values/libs.xml
@@ -1,7 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<array name="qt_sources">
- <item>https://download.qt-project.org/ministro/android/qt5/qt-5.3</item>
+ <item>https://download.qt-project.org/ministro/android/qt5/qt-5.4</item>
</array>
<!-- The following is handled automatically by the deployment tool. It should
diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf
index 7c879cbbfde..5a14ba9088f 100644
--- a/src/corelib/doc/qtcore.qdocconf
+++ b/src/corelib/doc/qtcore.qdocconf
@@ -4,7 +4,7 @@ project = QtCore
description = Qt Core Reference Documentation
version = $QT_VERSION
-examplesinstallpath = core
+examplesinstallpath = corelib
qhp.projects = QtCore
@@ -35,10 +35,7 @@ sourcedirs += ..
exampledirs += \
../ \
snippets \
- ../../../examples/threads/ \
- ../../../examples/tools/ \
- ../../../examples/ipc/ \
- ../../../examples/json/ \
+ ../../../examples/corelib \
../../../examples/network/dnslookup
imagedirs += images
diff --git a/src/corelib/doc/src/custom-types.qdoc b/src/corelib/doc/src/custom-types.qdoc
index bac4a908290..81ce6987354 100644
--- a/src/corelib/doc/src/custom-types.qdoc
+++ b/src/corelib/doc/src/custom-types.qdoc
@@ -61,7 +61,7 @@
The following \c Message class definition includes these members:
- \snippet customtype/message.h custom type definition
+ \snippet tools/customtype/message.h custom type definition
The class also provides a constructor for normal use and two public member functions
that are used to obtain the private data.
@@ -77,7 +77,7 @@
to this class, we invoke the Q_DECLARE_METATYPE() macro on the class in the header
file where it is defined:
- \snippet customtype/message.h custom type meta-type declaration
+ \snippet tools/customtype/message.h custom type meta-type declaration
This now makes it possible for \c Message values to be stored in QVariant objects
and retrieved later. See the \l{Custom Type Example} for code that demonstrates
@@ -104,19 +104,19 @@
The \l{Queued Custom Type Example} declares a \c Block class which is registered
in the \c{main.cpp} file:
- \snippet queuedcustomtype/main.cpp main start
+ \snippet threads/queuedcustomtype/main.cpp main start
\dots
- \snippet queuedcustomtype/main.cpp register meta-type for queued communications
+ \snippet threads/queuedcustomtype/main.cpp register meta-type for queued communications
\dots
- \snippet queuedcustomtype/main.cpp main finish
+ \snippet threads/queuedcustomtype/main.cpp main finish
This type is later used in a signal-slot connection in the \c{window.cpp} file:
- \snippet queuedcustomtype/window.cpp Window constructor start
+ \snippet threads/queuedcustomtype/window.cpp Window constructor start
\dots
- \snippet queuedcustomtype/window.cpp connecting signal with custom type
+ \snippet threads/queuedcustomtype/window.cpp connecting signal with custom type
\dots
- \snippet queuedcustomtype/window.cpp Window constructor finish
+ \snippet threads/queuedcustomtype/window.cpp Window constructor finish
If a type is used in a queued connection without being registered, a warning will be
printed at the console; for example:
@@ -131,18 +131,18 @@
It is often quite useful to make a custom type printable for debugging purposes,
as in the following code:
- \snippet customtype/main.cpp printing a custom type
+ \snippet tools/customtype/main.cpp printing a custom type
This is achieved by creating a streaming operator for the type, which is often
defined in the header file for that type:
- \snippet customtype/message.h custom type streaming operator
+ \snippet tools/customtype/message.h custom type streaming operator
The implementation for the \c Message type in the \l{Custom Type Example}
goes to some effort to make the printable representation as readable as
possible:
- \snippet customtype/message.cpp custom type streaming operator
+ \snippet tools/customtype/message.cpp custom type streaming operator
The output sent to the debug stream can, of course, be made as simple or as
complicated as you like. Note that the value returned by this function is
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index ac60d47c7e6..8e52c503229 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -730,8 +730,6 @@
/* C++11 features supported in GCC 4.4: */
# define Q_COMPILER_AUTO_FUNCTION
# define Q_COMPILER_AUTO_TYPE
-# define Q_COMPILER_DEFAULT_MEMBERS
-# define Q_COMPILER_DELETE_MEMBERS
# define Q_COMPILER_EXTERN_TEMPLATES
# define Q_COMPILER_UNIFORM_INIT
# define Q_COMPILER_UNICODE_STRINGS
@@ -748,6 +746,11 @@
# define Q_COMPILER_CLASS_ENUM
# endif
# if (__GNUC__ * 100 + __GNUC_MINOR__) >= 406
+ /* Pre-4.6 compilers implement a non-final snapshot of N2346, hence default and delete
+ * functions are supported only if they are public. Starting from 4.6, GCC handles
+ * final version - the access modifier is not relevant. */
+# define Q_COMPILER_DEFAULT_MEMBERS
+# define Q_COMPILER_DELETE_MEMBERS
/* C++11 features supported in GCC 4.6: */
# define Q_COMPILER_CONSTEXPR
# define Q_COMPILER_NULLPTR
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index e86d986581a..04c38b5f272 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -2502,7 +2502,9 @@ QString QSysInfo::productVersion()
// fall through
// Android and Blackberry should not fall through to the Unix code
-#elif defined(Q_OS_ANDROID)
+#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_NO_SDK)
+ return QJNIObjectPrivate::getStaticObjectField("android/os/Build$VERSION", "RELEASE", "Ljava/lang/String;").toString();
+#elif defined(Q_OS_ANDROID) // Q_OS_ANDROID_NO_SDK
// TBD
#elif defined(Q_OS_BLACKBERRY)
deviceinfo_details_t *deviceInfo;
diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp
index 2a4f2dd4d6d..f356bab42d7 100644
--- a/src/corelib/global/qlogging.cpp
+++ b/src/corelib/global/qlogging.cpp
@@ -653,9 +653,10 @@ Q_AUTOTEST_EXPORT QByteArray qCleanupFuncinfo(QByteArray info)
int pos;
- // skip trailing [with XXX] for templates (gcc)
+ // Skip trailing [with XXX] for templates (gcc), but make
+ // sure to not affect Objective-C message names.
pos = info.size() - 1;
- if (info.endsWith(']')) {
+ if (info.endsWith(']') && !(info.startsWith('+') || info.startsWith('-'))) {
while (--pos) {
if (info.at(pos) == '[')
info.truncate(pos);
diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp
index 8691a44d8d8..8d1c59e159b 100644
--- a/src/corelib/io/qfiledevice.cpp
+++ b/src/corelib/io/qfiledevice.cpp
@@ -608,9 +608,9 @@ qint64 QFileDevice::size() const
}
/*!
- Sets the file size (in bytes) \a sz. Returns \c true if the file if the
+ Sets the file size (in bytes) \a sz. Returns \c true if the
resize succeeds; false otherwise. If \a sz is larger than the file
- currently is the new bytes will be set to 0, if \a sz is smaller the
+ currently is, the new bytes will be set to 0; if \a sz is smaller, the
file is simply truncated.
\sa size()
diff --git a/src/corelib/io/qfilesystemmetadata_p.h b/src/corelib/io/qfilesystemmetadata_p.h
index cf1218cb411..147acda3d6e 100644
--- a/src/corelib/io/qfilesystemmetadata_p.h
+++ b/src/corelib/io/qfilesystemmetadata_p.h
@@ -66,7 +66,8 @@ class QFileSystemMetaData
{
public:
QFileSystemMetaData()
- : knownFlagsMask(0)
+ : knownFlagsMask(0),
+ size_(-1)
{
}
diff --git a/src/corelib/io/qfsfileengine_p.h b/src/corelib/io/qfsfileengine_p.h
index 5d5a29243ec..3963a9cb11b 100644
--- a/src/corelib/io/qfsfileengine_p.h
+++ b/src/corelib/io/qfsfileengine_p.h
@@ -61,7 +61,7 @@ QT_BEGIN_NAMESPACE
class QFSFileEnginePrivate;
-class Q_AUTOTEST_EXPORT QFSFileEngine : public QAbstractFileEngine
+class Q_CORE_EXPORT QFSFileEngine : public QAbstractFileEngine
{
Q_DECLARE_PRIVATE(QFSFileEngine)
public:
diff --git a/src/corelib/io/qloggingregistry.cpp b/src/corelib/io/qloggingregistry.cpp
index e9ee8d94583..8af1487834d 100644
--- a/src/corelib/io/qloggingregistry.cpp
+++ b/src/corelib/io/qloggingregistry.cpp
@@ -398,9 +398,11 @@ void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat)
// hard-wired implementation of
// qt.*.debug=false
// qt.debug=false
- char c;
- if (!memcmp(cat->categoryName(), "qt", 2) && (!(c = cat->categoryName()[2]) || c == '.'))
- debug = false;
+ if (const char *categoryName = cat->categoryName()) {
+ // == "qt" or startsWith("qt.")
+ if (strcmp(categoryName, "qt") == 0 || strncmp(categoryName, "qt.", 3) == 0)
+ debug = false;
+ }
QString categoryName = QLatin1String(cat->categoryName());
foreach (const QLoggingRule &item, reg->rules) {
diff --git a/src/corelib/io/qprocess.cpp b/src/corelib/io/qprocess.cpp
index e009191be90..e76a8369547 100644
--- a/src/corelib/io/qprocess.cpp
+++ b/src/corelib/io/qprocess.cpp
@@ -538,6 +538,13 @@ void QProcessPrivate::Channel::clear()
setWorkingDirectory(). By default, processes are run in the
current working directory of the calling process.
+ The positioning and the screen Z-order of windows belonging to
+ GUI applications started with QProcess are controlled by
+ the underlying windowing system. For Qt 5 applications, the
+ positioning can be specified using the \c{-qwindowgeometry}
+ command line option; X11 applications generally accept a
+ \c{-geometry} command line option.
+
\note On QNX, setting the working directory may cause all
application threads, with the exception of the QProcess caller
thread, to temporarily freeze during the spawning process,
diff --git a/src/corelib/io/qprocess_win.cpp b/src/corelib/io/qprocess_win.cpp
index 980fb58865d..ee6b7e13f46 100644
--- a/src/corelib/io/qprocess_win.cpp
+++ b/src/corelib/io/qprocess_win.cpp
@@ -634,7 +634,7 @@ bool QProcessPrivate::drainOutputPipes()
someReadyReadEmitted |= readyReadEmitted;
if (!readOperationActive || !readyReadEmitted)
break;
- Sleep(100);
+ QThread::yieldCurrentThread();
}
return someReadyReadEmitted;
diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp
index f6cd5aa7c9a..d896da176ae 100644
--- a/src/corelib/io/qsettings.cpp
+++ b/src/corelib/io/qsettings.cpp
@@ -100,6 +100,10 @@ using namespace ABI::Windows::Storage;
#define CSIDL_APPDATA 0x001a // <username>\Application Data
#endif
+#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) && !defined(Q_OS_BLACKBERRY) && !defined(Q_OS_ANDROID)
+#define Q_XDG_PLATFORM
+#endif
+
// ************************************************************************
// QConfFile
@@ -1041,7 +1045,9 @@ static void initDefaultPaths(QMutexLocker *locker)
windowsConfigPath(CSIDL_COMMON_APPDATA) + QDir::separator());
#else
-#ifdef QT_NO_STANDARDPATHS
+#if defined(QT_NO_STANDARDPATHS) || !defined(Q_XDG_PLATFORM)
+ // Non XDG platforms (OS X, iOS, Blackberry, Android...) have used this code path erroneously
+ // for some time now. Moving away from that would require migrating existing settings.
QString userPath;
char *env = getenv("XDG_CONFIG_HOME");
if (env == 0) {
@@ -1056,6 +1062,9 @@ static void initDefaultPaths(QMutexLocker *locker)
userPath += QFile::decodeName(env);
}
#else
+ // When using a proper XDG platform, use QStandardPaths rather than the above hand-written code;
+ // it makes the use of test mode from unit tests possible.
+ // Ideally all platforms should use this, but see above for the migration issue.
QString userPath = QStandardPaths::writableLocation(QStandardPaths::GenericConfigLocation);
#endif
userPath += QLatin1Char('/');
@@ -3112,6 +3121,10 @@ bool QSettings::isWritable() const
void QSettings::setValue(const QString &key, const QVariant &value)
{
Q_D(QSettings);
+ if (key.isEmpty()) {
+ qWarning("QSettings::setValue: Empty key passed");
+ return;
+ }
QString k = d->actualKey(key);
d->set(k, value);
d->requestUpdate();
@@ -3244,6 +3257,10 @@ bool QSettings::event(QEvent *event)
QVariant QSettings::value(const QString &key, const QVariant &defaultValue) const
{
Q_D(const QSettings);
+ if (key.isEmpty()) {
+ qWarning("QSettings::value: Empty key passed");
+ return QVariant();
+ }
QVariant result = defaultValue;
QString k = d->actualKey(key);
d->get(k, &result);
diff --git a/src/corelib/itemmodels/qabstractitemmodel.cpp b/src/corelib/itemmodels/qabstractitemmodel.cpp
index 68ab03976f6..74a7ea19889 100644
--- a/src/corelib/itemmodels/qabstractitemmodel.cpp
+++ b/src/corelib/itemmodels/qabstractitemmodel.cpp
@@ -3375,7 +3375,7 @@ Qt::ItemFlags QAbstractTableModel::flags(const QModelIndex &index) const
QAbstractItemModel, it is not suitable for use with tree views; you will
need to subclass QAbstractItemModel if you want to provide a model for
that purpose. If you need to use a number of list models to manage data,
- it may be more appropriate to subclass QAbstractTableModel class instead.
+ it may be more appropriate to subclass QAbstractTableModel instead.
Simple models can be created by subclassing this class and implementing
the minimum number of required functions. For example, we could implement
@@ -3399,7 +3399,7 @@ Qt::ItemFlags QAbstractTableModel::flags(const QModelIndex &index) const
default ones provided by the roleNames() function, you must override it.
For editable list models, you must also provide an implementation of
- setData(), implement the flags() function so that it returns a value
+ setData(), and implement the flags() function so that it returns a value
containing \l{Qt::ItemFlags}{Qt::ItemIsEditable}.
Note that QAbstractListModel provides a default implementation of
diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp
index 7816edd3f96..a3d00faf31f 100644
--- a/src/corelib/kernel/qeventdispatcher_win.cpp
+++ b/src/corelib/kernel/qeventdispatcher_win.cpp
@@ -639,7 +639,6 @@ void QEventDispatcherWin32::createInternalHwnd()
{
Q_D(QEventDispatcherWin32);
- Q_ASSERT(!d->internalHwnd);
if (d->internalHwnd)
return;
d->internalHwnd = qt_create_internal_window(this);
@@ -664,9 +663,6 @@ void QEventDispatcherWin32::createInternalHwnd()
// start all normal timers
for (int i = 0; i < d->timerVec.count(); ++i)
d->registerTimer(d->timerVec.at(i));
-
- // trigger a call to sendPostedEvents()
- wakeUp();
}
QEventDispatcherWin32::QEventDispatcherWin32(QObject *parent)
@@ -686,8 +682,10 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags)
{
Q_D(QEventDispatcherWin32);
- if (!d->internalHwnd)
+ if (!d->internalHwnd) {
createInternalHwnd();
+ wakeUp(); // trigger a call to sendPostedEvents()
+ }
d->interrupt = false;
emit awake();
diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h
index f9bb06a5c58..369c2766150 100644
--- a/src/corelib/kernel/qeventdispatcher_win_p.h
+++ b/src/corelib/kernel/qeventdispatcher_win_p.h
@@ -65,8 +65,8 @@ class Q_CORE_EXPORT QEventDispatcherWin32 : public QAbstractEventDispatcher
Q_OBJECT
Q_DECLARE_PRIVATE(QEventDispatcherWin32)
+protected:
void createInternalHwnd();
- friend class QGuiEventDispatcherWin32;
public:
explicit QEventDispatcherWin32(QObject *parent = 0);
diff --git a/src/corelib/kernel/qjni.cpp b/src/corelib/kernel/qjni.cpp
index 173127b063a..452e3464d65 100644
--- a/src/corelib/kernel/qjni.cpp
+++ b/src/corelib/kernel/qjni.cpp
@@ -80,38 +80,22 @@ static QString toDotEncodedClassName(const char *className)
return QString::fromLatin1(className).replace(QLatin1Char('/'), QLatin1Char('.'));
}
-static jclass getCachedClass(const QString &classDotEnc)
+static jclass getCachedClass(const QString &classDotEnc, bool *isCached = 0)
{
QHash<QString, jclass>::iterator it = cachedClasses->find(classDotEnc);
+ const bool found = (it != cachedClasses->end());
- if (it == cachedClasses->end())
- return 0;
-
- return it.value();
-}
-
-static jclass findClass(const char *className, JNIEnv *env)
-{
- const QString &classDotEnc = toDotEncodedClassName(className);
- jclass clazz = getCachedClass(classDotEnc);
- if (clazz != 0)
- return clazz;
-
- jclass fclazz = env->FindClass(className);
- if (!exceptionCheckAndClear(env)) {
- clazz = static_cast<jclass>(env->NewGlobalRef(fclazz));
- env->DeleteLocalRef(fclazz);
- }
+ if (isCached != 0)
+ *isCached = found;
- cachedClasses->insert(classDotEnc, clazz);
- return clazz;
+ return found ? it.value() : 0;
}
-static jclass loadClass(const char *className, JNIEnv *env)
+static jclass loadClassDotEnc(const QString &classDotEnc, JNIEnv *env)
{
- const QString &classDotEnc = toDotEncodedClassName(className);
- jclass clazz = getCachedClass(classDotEnc);
- if (clazz != 0)
+ bool isCached = false;
+ jclass clazz = getCachedClass(classDotEnc, &isCached);
+ if (clazz != 0 || isCached)
return clazz;
QJNIObjectPrivate classLoader = QtAndroidPrivate::classLoader();
@@ -130,6 +114,11 @@ static jclass loadClass(const char *className, JNIEnv *env)
return clazz;
}
+inline static jclass loadClass(const char *className, JNIEnv *env)
+{
+ return loadClassDotEnc(toDotEncodedClassName(className), env);
+}
+
typedef QHash<QString, jmethodID> JMethodIDHash;
Q_GLOBAL_STATIC(JMethodIDHash, cachedMethodID)
@@ -224,12 +213,28 @@ JNIEnv *QJNIEnvironmentPrivate::operator->()
jclass QJNIEnvironmentPrivate::findClass(const char *className, JNIEnv *env)
{
- jclass clazz = 0;
- if (env != 0)
- clazz = ::findClass(className, env);
+ const QString &classDotEnc = toDotEncodedClassName(className);
+ bool isCached = false;
+ jclass clazz = getCachedClass(classDotEnc, &isCached);
+
+ const bool found = (clazz != 0) || (clazz == 0 && isCached);
+
+ if (found)
+ return clazz;
+
+ if (env != 0) { // We got an env. pointer (We expect this to be the right env. and call FindClass())
+ jclass fclazz = env->FindClass(className);
+ if (!exceptionCheckAndClear(env)) {
+ clazz = static_cast<jclass>(env->NewGlobalRef(fclazz));
+ env->DeleteLocalRef(fclazz);
+ }
+
+ if (clazz != 0)
+ cachedClasses->insert(classDotEnc, clazz);
+ }
- if (clazz == 0)
- clazz = loadClass(className, QJNIEnvironmentPrivate());
+ if (clazz == 0) // We didn't get an env. pointer or we got one with the WRONG class loader...
+ clazz = loadClassDotEnc(classDotEnc, QJNIEnvironmentPrivate());
return clazz;
}
diff --git a/src/corelib/kernel/qtcore_eval.cpp b/src/corelib/kernel/qtcore_eval.cpp
index c0f8897b3b9..eb1019534cd 100644
--- a/src/corelib/kernel/qtcore_eval.cpp
+++ b/src/corelib/kernel/qtcore_eval.cpp
@@ -111,10 +111,11 @@ static EvaluationStatus qt_eval_is_supported()
static int qt_eval_days_left()
{
- const char *expiry_date = const_cast<const char*>(qt_eval_expiry_date + 12);
+ const volatile char *const expiry_date = qt_eval_expiry_date + 12;
QDate today = QDate::currentDate();
- QDate lastday = QDate::fromString(QString::fromLatin1(expiry_date), Qt::ISODate);
+ QDate lastday = QDate::fromString(
+ QString::fromLatin1(const_cast<const char*>(expiry_date)), Qt::ISODate);
return today.daysTo(lastday);
}
diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp
index 4fa07b17d41..69d4bd7d996 100644
--- a/src/corelib/tools/qdatetime.cpp
+++ b/src/corelib/tools/qdatetime.cpp
@@ -4452,7 +4452,7 @@ QDateTime QDateTime::fromString(const QString& string, Qt::DateFormat format)
if (size == 10)
return QDateTime(date);
- isoString = isoString.right(11);
+ isoString = isoString.right(isoString.length() - 11);
int offset = 0;
// Check end of string for Time Zone definition, either Z for UTC or [+-]HH:MM for Offset
if (isoString.endsWith(QLatin1Char('Z'))) {
diff --git a/src/corelib/tools/qdatetime.h b/src/corelib/tools/qdatetime.h
index 4ef94f72d73..ec1e78c358d 100644
--- a/src/corelib/tools/qdatetime.h
+++ b/src/corelib/tools/qdatetime.h
@@ -36,7 +36,7 @@
#include <QtCore/qstring.h>
#include <QtCore/qnamespace.h>
-#include <QtCore/qsharedpointer.h>
+#include <QtCore/qshareddata.h>
#include <limits>
diff --git a/src/corelib/tools/qeasingcurve.cpp b/src/corelib/tools/qeasingcurve.cpp
index b4ecc65f29d..f7bf6ed28b3 100644
--- a/src/corelib/tools/qeasingcurve.cpp
+++ b/src/corelib/tools/qeasingcurve.cpp
@@ -1478,6 +1478,8 @@ QDataStream &operator>>(QDataStream &stream, QEasingCurve &easing)
bool hasConfig;
stream >> hasConfig;
+ delete easing.d_ptr->config;
+ easing.d_ptr->config = Q_NULLPTR;
if (hasConfig) {
QEasingCurveFunction *config = curveToFunctionObject(type);
stream >> config->_p;
diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp
index 7de7d745954..ae44e4185ab 100644
--- a/src/corelib/tools/qstring.cpp
+++ b/src/corelib/tools/qstring.cpp
@@ -8951,7 +8951,7 @@ QStringRef QStringRef::right(int n) const
{
if (uint(n) >= uint(m_size))
return *this;
- return QStringRef(m_string, n + m_position, m_size - n);
+ return QStringRef(m_string, m_size - n + m_position, n);
}
/*!
diff --git a/src/gui/kernel/qclipboard.cpp b/src/gui/kernel/qclipboard.cpp
index ec9a8fdcf0a..5be9f19b3e7 100644
--- a/src/gui/kernel/qclipboard.cpp
+++ b/src/gui/kernel/qclipboard.cpp
@@ -463,9 +463,14 @@ const QMimeData* QClipboard::mimeData(Mode mode) const
void QClipboard::setMimeData(QMimeData* src, Mode mode)
{
QPlatformClipboard *clipboard = QGuiApplicationPrivate::platformIntegration()->clipboard();
- if (!clipboard->supportsMode(mode)) return;
-
- clipboard->setMimeData(src,mode);
+ if (!clipboard->supportsMode(mode)) {
+ if (src != 0) {
+ qWarning("Data set on unsupported clipboard mode. QMimeData object will be deleted.");
+ src->deleteLater();
+ }
+ } else {
+ clipboard->setMimeData(src,mode);
+ }
}
/*!
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index f99f28d6e01..a8539e8013a 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -897,12 +897,11 @@ QWheelEvent::QWheelEvent(const QPointF &pos, const QPointF& globalPos,
when keys are pressed or released.
A key event contains a special accept flag that indicates whether
- the receiver will handle the key event. You should call ignore()
- if the key press or release event is not handled by your widget.
- A key event is propagated up the parent widget chain until a
- widget accepts it with accept() or an event filter consumes it.
- Key events for multimedia keys are ignored by default. You should
- call accept() if your widget handles those events.
+ the receiver will handle the key event. This flag is set by default,
+ so there is no need to call accept() when acting on a key event.
+ Calling ignore() on a key event will propagate it to the parent widget.
+ The event is propagated up the parent widget chain until a widget
+ accepts it or an event filter consumes it.
The QWidget::setEnable() function can be used to enable or disable
mouse and keyboard events for a widget.
diff --git a/src/gui/kernel/qoffscreensurface.cpp b/src/gui/kernel/qoffscreensurface.cpp
index 56c4fbbf8b8..5cf77de5d8f 100644
--- a/src/gui/kernel/qoffscreensurface.cpp
+++ b/src/gui/kernel/qoffscreensurface.cpp
@@ -64,6 +64,12 @@ QT_BEGIN_NAMESPACE
typically use a pixel buffer (pbuffer). If the platform doesn't implement or support
offscreen surfaces, QOffscreenSurface will use an invisible QWindow internally.
+ \note Due to the fact that QOffscreenSurface is backed by a QWindow on some platforms,
+ cross-platform applications must ensure that create() is only called on the main (GUI)
+ thread. The QOffscreenSurface is then safe to be used with
+ \l{QOpenGLContext::makeCurrent()}{makeCurrent()} on other threads, but the
+ initialization and destruction must always happen on the main (GUI) thread.
+
\note In order to create an offscreen surface that is guaranteed to be compatible with
a given context and window, make sure to set the format to the context's or the
window's actual format, that is, the QSurfaceFormat returned from
@@ -152,6 +158,8 @@ QOffscreenSurface::SurfaceType QOffscreenSurface::surfaceType() const
Call destroy() to free the platform resources if necessary.
+ \note Some platforms require this function to be called on the main (GUI) thread.
+
\sa destroy()
*/
void QOffscreenSurface::create()
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 51b4a6a079f..07a7c601fad 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -350,16 +350,6 @@ QOpenGLContext *QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context
return previous;
}
-void QOpenGLContextPrivate::setGlobalShareContext(QOpenGLContext *context)
-{
- qt_gl_set_global_share_context(context);
-}
-
-QOpenGLContext *QOpenGLContextPrivate::globalShareContext()
-{
- return qt_gl_global_share_context();
-}
-
int QOpenGLContextPrivate::maxTextureSize()
{
if (max_texture_size != -1)
diff --git a/src/gui/kernel/qopenglcontext_p.h b/src/gui/kernel/qopenglcontext_p.h
index 7c45737d0af..d5a31261766 100644
--- a/src/gui/kernel/qopenglcontext_p.h
+++ b/src/gui/kernel/qopenglcontext_p.h
@@ -241,9 +241,6 @@ public:
static QOpenGLContext *setCurrentContext(QOpenGLContext *context);
- static void setGlobalShareContext(QOpenGLContext *context);
- static QOpenGLContext *globalShareContext();
-
int maxTextureSize();
static QOpenGLContextPrivate *get(QOpenGLContext *context)
diff --git a/src/gui/kernel/qopenglwindow.cpp b/src/gui/kernel/qopenglwindow.cpp
index 2b6692c4613..158fb248dcc 100644
--- a/src/gui/kernel/qopenglwindow.cpp
+++ b/src/gui/kernel/qopenglwindow.cpp
@@ -211,8 +211,11 @@ public:
context->makeCurrent(q);
}
+ const int deviceWidth = q->width() * q->devicePixelRatio();
+ const int deviceHeight = q->height() * q->devicePixelRatio();
+ const QSize deviceSize(deviceWidth, deviceHeight);
if (updateBehavior > QOpenGLWindow::NoPartialUpdate) {
- if (!fbo || fbo->size() != q->size() * q->devicePixelRatio()) {
+ if (!fbo || fbo->size() != deviceSize) {
QOpenGLFramebufferObjectFormat fboFormat;
fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);
if (q->requestedFormat().samples() > 0) {
@@ -221,15 +224,13 @@ public:
else
qWarning("QOpenGLWindow: PartialUpdateBlend does not support multisampling");
}
- fbo.reset(new QOpenGLFramebufferObject(q->size() * q->devicePixelRatio(), fboFormat));
+ fbo.reset(new QOpenGLFramebufferObject(deviceSize, fboFormat));
markWindowAsDirty();
}
} else {
markWindowAsDirty();
}
- const int deviceWidth = q->width() * q->devicePixelRatio();
- const int deviceHeight = q->height() * q->devicePixelRatio();
paintDevice->setSize(QSize(deviceWidth, deviceHeight));
paintDevice->setDevicePixelRatio(q->devicePixelRatio());
context->functions()->glViewport(0, 0, deviceWidth, deviceHeight);
@@ -252,11 +253,13 @@ public:
context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject());
if (updateBehavior == QOpenGLWindow::PartialUpdateBlit && hasFboBlit) {
+ const int deviceWidth = q->width() * q->devicePixelRatio();
+ const int deviceHeight = q->height() * q->devicePixelRatio();
QOpenGLExtensions extensions(context.data());
extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle());
extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, context->defaultFramebufferObject());
- extensions.glBlitFramebuffer(0, 0, q->width(), q->height(),
- 0, 0, q->width(), q->height(),
+ extensions.glBlitFramebuffer(0, 0, deviceWidth, deviceHeight,
+ 0, 0, deviceWidth, deviceHeight,
GL_COLOR_BUFFER_BIT, GL_NEAREST);
} else if (updateBehavior > QOpenGLWindow::NoPartialUpdate) {
if (updateBehavior == QOpenGLWindow::PartialUpdateBlend) {
@@ -591,7 +594,7 @@ int QOpenGLWindow::metric(PaintDeviceMetric metric) const
break;
case PdmDevicePixelRatio:
if (d->paintDevice)
- return d->paintDevice->devicePixelRatio();
+ return devicePixelRatio();
break;
default:
break;
diff --git a/src/gui/kernel/qplatformmenu.h b/src/gui/kernel/qplatformmenu.h
index c832de0be64..0093ef15387 100644
--- a/src/gui/kernel/qplatformmenu.h
+++ b/src/gui/kernel/qplatformmenu.h
@@ -108,11 +108,6 @@ public:
virtual void setFont(const QFont &font) { Q_UNUSED(font); }
virtual void setMenuType(MenuType type) { Q_UNUSED(type); }
- virtual void showPopup(const QWindow *parentWindow, QPoint pos, const QPlatformMenuItem *item)
- {
- showPopup(parentWindow, QRect(pos, QSize()), item);
- }
-
virtual void showPopup(const QWindow *parentWindow, const QRect &targetRect, const QPlatformMenuItem *item)
{
Q_UNUSED(parentWindow);
diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp
index d03a3f7be81..bd95a8614f7 100644
--- a/src/gui/kernel/qwindowsysteminterface.cpp
+++ b/src/gui/kernel/qwindowsysteminterface.cpp
@@ -201,9 +201,13 @@ bool QWindowSystemInterface::tryHandleShortcutEvent(QWindow *w, ulong timestamp,
#ifndef QT_NO_SHORTCUT
QGuiApplicationPrivate::modifier_buttons = mods;
+ QObject *focus = w->focusObject();
+ if (!focus)
+ focus = w;
+
QKeyEvent qevent(QEvent::ShortcutOverride, k, mods, text, autorep, count);
qevent.setTimestamp(timestamp);
- return QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(w, &qevent);
+ return QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(focus, &qevent);
#else
Q_UNUSED(w)
Q_UNUSED(timestamp)
@@ -231,9 +235,13 @@ bool QWindowSystemInterface::tryHandleExtendedShortcutEvent(QWindow *w, ulong ti
#ifndef QT_NO_SHORTCUT
QGuiApplicationPrivate::modifier_buttons = mods;
+ QObject *focus = w->focusObject();
+ if (!focus)
+ focus = w;
+
QKeyEvent qevent(QEvent::ShortcutOverride, k, mods, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count);
qevent.setTimestamp(timestamp);
- return QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(w, &qevent);
+ return QGuiApplicationPrivate::instance()->shortcutMap.tryShortcutEvent(focus, &qevent);
#else
Q_UNUSED(w)
Q_UNUSED(timestamp)
diff --git a/src/gui/opengl/opengl.pri b/src/gui/opengl/opengl.pri
index f82401c9732..adf5428c492 100644
--- a/src/gui/opengl/opengl.pri
+++ b/src/gui/opengl/opengl.pri
@@ -11,6 +11,7 @@ contains(QT_CONFIG, opengl)|contains(QT_CONFIG, opengles2) {
opengl/qopenglframebufferobject.h \
opengl/qopenglframebufferobject_p.h \
opengl/qopenglpaintdevice.h \
+ opengl/qopenglpaintdevice_p.h \
opengl/qopenglbuffer.h \
opengl/qopenglshaderprogram.h \
opengl/qopenglextensions_p.h \
diff --git a/src/gui/opengl/qopenglpaintdevice.cpp b/src/gui/opengl/qopenglpaintdevice.cpp
index 59bca6efdf4..e908fd8e915 100644
--- a/src/gui/opengl/qopenglpaintdevice.cpp
+++ b/src/gui/opengl/qopenglpaintdevice.cpp
@@ -35,6 +35,7 @@
#include <qpaintengine.h>
#include <qthreadstorage.h>
+#include <private/qopenglpaintdevice_p.h>
#include <private/qobject_p.h>
#include <private/qopenglcontext_p.h>
#include <private/qopenglframebufferobject_p.h>
@@ -98,23 +99,6 @@ QT_BEGIN_NAMESPACE
*/
-class QOpenGLPaintDevicePrivate
-{
-public:
- QOpenGLPaintDevicePrivate(const QSize &size);
-
- QSize size;
- QOpenGLContext *ctx;
-
- qreal dpmx;
- qreal dpmy;
- qreal devicePixelRatio;
-
- bool flipped;
-
- QPaintEngine *engine;
-};
-
/*!
Constructs a QOpenGLPaintDevice.
@@ -152,6 +136,14 @@ QOpenGLPaintDevice::QOpenGLPaintDevice(int width, int height)
}
/*!
+ \internal
+ */
+QOpenGLPaintDevice::QOpenGLPaintDevice(QOpenGLPaintDevicePrivate *dd)
+ : d_ptr(dd)
+{
+}
+
+/*!
Destroys the QOpenGLPaintDevice.
*/
@@ -355,7 +347,10 @@ bool QOpenGLPaintDevice::paintFlipped() const
frame buffer object or context when different QOpenGLPaintDevice instances
are issuing draw calls alternately.
- QPainter::beginNativePainting will also trigger this method.
+ \l{QPainter::beginNativePainting()}{beginNativePainting()} will also trigger
+ this method.
+
+ The default implementation does nothing.
*/
void QOpenGLPaintDevice::ensureActiveTarget()
{
diff --git a/src/gui/opengl/qopenglpaintdevice.h b/src/gui/opengl/qopenglpaintdevice.h
index e1be9b525d5..dda3bfe43f6 100644
--- a/src/gui/opengl/qopenglpaintdevice.h
+++ b/src/gui/opengl/qopenglpaintdevice.h
@@ -44,7 +44,6 @@
QT_BEGIN_NAMESPACE
-
class QOpenGLPaintDevicePrivate;
class Q_GUI_EXPORT QOpenGLPaintDevice : public QPaintDevice
@@ -54,6 +53,7 @@ public:
QOpenGLPaintDevice();
explicit QOpenGLPaintDevice(const QSize &size);
QOpenGLPaintDevice(int width, int height);
+ QOpenGLPaintDevice(QOpenGLPaintDevicePrivate *dd);
virtual ~QOpenGLPaintDevice();
int devType() const { return QInternal::OpenGL; }
diff --git a/src/gui/opengl/qopenglpaintdevice_p.h b/src/gui/opengl/qopenglpaintdevice_p.h
new file mode 100644
index 00000000000..0b01129a84a
--- /dev/null
+++ b/src/gui/opengl/qopenglpaintdevice_p.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtGui module 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QOPENGL_PAINTDEVICE_P_H
+#define QOPENGL_PAINTDEVICE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the Qt OpenGL classes. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <qopenglpaintdevice.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLContext;
+class QPaintEngine;
+
+class Q_GUI_EXPORT QOpenGLPaintDevicePrivate
+{
+public:
+ QOpenGLPaintDevicePrivate(const QSize &size);
+ virtual ~QOpenGLPaintDevicePrivate() { }
+
+ static QOpenGLPaintDevicePrivate *get(QOpenGLPaintDevice *dev) { return dev->d_func(); }
+
+ virtual void beginPaint() { }
+ virtual void endPaint() { }
+
+public:
+ QSize size;
+ QOpenGLContext *ctx;
+
+ qreal dpmx;
+ qreal dpmy;
+ qreal devicePixelRatio;
+
+ bool flipped;
+
+ QPaintEngine *engine;
+};
+
+QT_END_NAMESPACE
+
+#endif // QOPENGL_PAINTDEVICE_P_H
diff --git a/src/gui/opengl/qopenglpaintengine.cpp b/src/gui/opengl/qopenglpaintengine.cpp
index 21bc4a95e86..c490726359b 100644
--- a/src/gui/opengl/qopenglpaintengine.cpp
+++ b/src/gui/opengl/qopenglpaintengine.cpp
@@ -59,6 +59,7 @@
#include "qopenglgradientcache_p.h"
#include "qopengltexturecache_p.h"
#include "qopenglpaintengine_p.h"
+#include "qopenglpaintdevice_p.h"
#include <string.h> //for memcpy
#include <qmath.h>
@@ -1994,6 +1995,8 @@ bool QOpenGL2PaintEngineEx::begin(QPaintDevice *pdev)
d->ctx = QOpenGLContext::currentContext();
d->ctx->d_func()->active_engine = this;
+ QOpenGLPaintDevicePrivate::get(d->device)->beginPaint();
+
d->funcs.initializeOpenGLFunctions();
for (int i = 0; i < QT_GL_VERTEX_ARRAY_TRACKED_COUNT; ++i)
@@ -2044,6 +2047,8 @@ bool QOpenGL2PaintEngineEx::end()
{
Q_D(QOpenGL2PaintEngineEx);
+ QOpenGLPaintDevicePrivate::get(d->device)->endPaint();
+
QOpenGLContext *ctx = d->ctx;
d->funcs.glUseProgram(0);
d->transferMode(BrushDrawingMode);
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index 12c7929047f..34e22a30b84 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -2597,8 +2597,7 @@ QRegion QPainter::clipRegion() const
extern QPainterPath qt_regionToPath(const QRegion &region);
/*!
- Returns the currently clip as a path. Note that the clip path is
- given in logical coordinates.
+ Returns the current clip path in logical coordinates.
\warning QPainter does not store the combined clip explicitly as
this is handled by the underlying QPaintEngine, so the path is
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index 9caebc6ec6d..54fcbac3083 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -1452,7 +1452,8 @@ qreal QFont::letterSpacing() const
Letter spacing changes the default spacing between individual
letters in the font. The spacing between the letters can be
- made smaller as well as larger.
+ made smaller as well as larger either in percentage of the
+ character width or in pixels, depending on the selected spacing type.
\sa letterSpacing(), letterSpacingType(), setWordSpacing()
*/
diff --git a/src/network/socket/qnativesocketengine_unix.cpp b/src/network/socket/qnativesocketengine_unix.cpp
index 60f971a2fbf..ad170e187c3 100644
--- a/src/network/socket/qnativesocketengine_unix.cpp
+++ b/src/network/socket/qnativesocketengine_unix.cpp
@@ -384,12 +384,15 @@ bool QNativeSocketEnginePrivate::nativeConnect(const QHostAddress &addr, quint16
sockAddrIPv6.sin6_port = htons(port);
QString scopeid = addr.scopeId();
- bool ok;
- sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok);
+
+ if (!scopeid.isEmpty()) {
+ bool ok;
+ sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok);
#ifndef QT_NO_IPV6IFNAME
- if (!ok)
- sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1());
+ if (!ok)
+ sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1());
#endif
+ }
Q_IPV6ADDR ip6 = addr.toIPv6Address();
memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &ip6, sizeof(ip6));
@@ -498,11 +501,16 @@ bool QNativeSocketEnginePrivate::nativeBind(const QHostAddress &address, quint16
memset(&sockAddrIPv6, 0, sizeof(sockAddrIPv6));
sockAddrIPv6.sin6_family = AF_INET6;
sockAddrIPv6.sin6_port = htons(port);
+ QString scopeid = address.scopeId();
+
+ if (!scopeid.isEmpty()) {
+ bool ok;
+ sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok);
#ifndef QT_NO_IPV6IFNAME
- sockAddrIPv6.sin6_scope_id = ::if_nametoindex(address.scopeId().toLatin1().data());
-#else
- sockAddrIPv6.sin6_scope_id = address.scopeId().toInt();
+ if (!ok)
+ sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1());
#endif
+ }
Q_IPV6ADDR tmp = address.toIPv6Address();
memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
sockAddrSize = sizeof(sockAddrIPv6);
@@ -917,12 +925,15 @@ qint64 QNativeSocketEnginePrivate::nativeSendDatagram(const char *data, qint64 l
Q_IPV6ADDR tmp = host.toIPv6Address();
memcpy(&sockAddrIPv6.sin6_addr.s6_addr, &tmp, sizeof(tmp));
QString scopeid = host.scopeId();
- bool ok;
- sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok);
+
+ if (!scopeid.isEmpty()) {
+ bool ok;
+ sockAddrIPv6.sin6_scope_id = scopeid.toInt(&ok);
#ifndef QT_NO_IPV6IFNAME
- if (!ok)
- sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1());
+ if (!ok)
+ sockAddrIPv6.sin6_scope_id = ::if_nametoindex(scopeid.toLatin1());
#endif
+ }
sockAddrSize = sizeof(sockAddrIPv6);
sockAddrPtr = (struct sockaddr *)&sockAddrIPv6;
} else if (host.protocol() == QAbstractSocket::IPv4Protocol) {
diff --git a/src/network/ssl/qsslcertificate.cpp b/src/network/ssl/qsslcertificate.cpp
index 8d38a5fd54e..13bddcb3ea1 100644
--- a/src/network/ssl/qsslcertificate.cpp
+++ b/src/network/ssl/qsslcertificate.cpp
@@ -662,7 +662,13 @@ QByteArray QSslCertificatePrivate::subjectInfoToString(QSslCertificate::SubjectI
return str;
}
+/*!
+ \fn uint qHash(const QSslCertificate &key, uint seed)
+ Returns the hash value for the \a key, using \a seed to seed the calculation.
+ \since 5.4
+ \relates QHash
+*/
#ifndef QT_NO_DEBUG_STREAM
QDebug operator<<(QDebug debug, const QSslCertificate &certificate)
diff --git a/src/network/ssl/qsslcertificate.h b/src/network/ssl/qsslcertificate.h
index d1290b1d428..e34ea97fc45 100644
--- a/src/network/ssl/qsslcertificate.h
+++ b/src/network/ssl/qsslcertificate.h
@@ -59,6 +59,10 @@ class QSslKey;
class QSslCertificateExtension;
class QStringList;
+class QSslCertificate;
+// qHash is a friend, but we can't use default arguments for friends (§8.3.6.4)
+Q_NETWORK_EXPORT uint qHash(const QSslCertificate &key, uint seed = 0) Q_DECL_NOTHROW;
+
class QSslCertificatePrivate;
class Q_NETWORK_EXPORT QSslCertificate
{
@@ -145,6 +149,8 @@ private:
QExplicitlySharedDataPointer<QSslCertificatePrivate> d;
friend class QSslCertificatePrivate;
friend class QSslSocketBackendPrivate;
+
+ friend Q_NETWORK_EXPORT uint qHash(const QSslCertificate &key, uint seed) Q_DECL_NOTHROW;
};
Q_DECLARE_SHARED(QSslCertificate)
diff --git a/src/network/ssl/qsslcertificate_openssl.cpp b/src/network/ssl/qsslcertificate_openssl.cpp
index 664f5eba08f..1906c72ff81 100644
--- a/src/network/ssl/qsslcertificate_openssl.cpp
+++ b/src/network/ssl/qsslcertificate_openssl.cpp
@@ -62,6 +62,17 @@ bool QSslCertificate::operator==(const QSslCertificate &other) const
return false;
}
+uint qHash(const QSslCertificate &key, uint seed) Q_DECL_NOTHROW
+{
+ if (X509 * const x509 = key.d->x509) {
+ (void)q_X509_cmp(x509, x509); // populate x509->sha1_hash
+ // (if someone knows a better way...)
+ return qHashBits(x509->sha1_hash, SHA_DIGEST_LENGTH, seed);
+ } else {
+ return seed;
+ }
+}
+
bool QSslCertificate::isNull() const
{
return d->null;
@@ -683,7 +694,7 @@ QList<QSslCertificate> QSslCertificatePrivate::certificatesFromDer(const QByteAr
#endif
int size = der.size();
- while (count == -1 || certificates.size() < count) {
+ while (size > 0 && (count == -1 || certificates.size() < count)) {
if (X509 *x509 = q_d2i_X509(0, &data, size)) {
certificates << QSslCertificate_from_X509(x509);
q_X509_free(x509);
diff --git a/src/network/ssl/qsslcertificate_qt.cpp b/src/network/ssl/qsslcertificate_qt.cpp
index 16df4a8f730..d74042a95f8 100644
--- a/src/network/ssl/qsslcertificate_qt.cpp
+++ b/src/network/ssl/qsslcertificate_qt.cpp
@@ -67,6 +67,12 @@ bool QSslCertificate::operator==(const QSslCertificate &other) const
return d->derData == other.d->derData;
}
+uint qHash(const QSslCertificate &key, uint seed) Q_DECL_NOTHROW
+{
+ // DER is the native encoding here, so toDer() is just "return d->derData":
+ return qHash(key.toDer(), seed);
+}
+
bool QSslCertificate::isNull() const
{
return d->null;
diff --git a/src/network/ssl/qsslcontext_openssl.cpp b/src/network/ssl/qsslcontext_openssl.cpp
index 26be1d56e6f..f4c6b215989 100644
--- a/src/network/ssl/qsslcontext_openssl.cpp
+++ b/src/network/ssl/qsslcontext_openssl.cpp
@@ -124,13 +124,16 @@ QSslContext* QSslContext::fromConfiguration(QSslSocket::SslMode mode, const QSsl
bool client = (mode == QSslSocket::SslClientMode);
bool reinitialized = false;
+ bool unsupportedProtocol = false;
init_context:
switch (sslContext->sslConfiguration.protocol()) {
case QSsl::SslV2:
#ifndef OPENSSL_NO_SSL2
sslContext->ctx = q_SSL_CTX_new(client ? q_SSLv2_client_method() : q_SSLv2_server_method());
#else
- sslContext->ctx = 0; // SSL 2 not supported by the system, but chosen deliberately -> error
+ // SSL 2 not supported by the system, but chosen deliberately -> error
+ sslContext->ctx = 0;
+ unsupportedProtocol = true;
#endif
break;
case QSsl::SslV3:
@@ -149,14 +152,18 @@ init_context:
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_1_client_method() : q_TLSv1_1_server_method());
#else
- sslContext->ctx = 0; // TLS 1.1 not supported by the system, but chosen deliberately -> error
+ // TLS 1.1 not supported by the system, but chosen deliberately -> error
+ sslContext->ctx = 0;
+ unsupportedProtocol = true;
#endif
break;
case QSsl::TlsV1_2:
#if OPENSSL_VERSION_NUMBER >= 0x10001000L
sslContext->ctx = q_SSL_CTX_new(client ? q_TLSv1_2_client_method() : q_TLSv1_2_server_method());
#else
- sslContext->ctx = 0; // TLS 1.2 not supported by the system, but chosen deliberately -> error
+ // TLS 1.2 not supported by the system, but chosen deliberately -> error
+ sslContext->ctx = 0;
+ unsupportedProtocol = true;
#endif
break;
}
@@ -169,7 +176,9 @@ init_context:
goto init_context;
}
- sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(QSslSocketBackendPrivate::getErrorsFromOpenSsl());
+ sslContext->errorStr = QSslSocket::tr("Error creating SSL context (%1)").arg(
+ unsupportedProtocol ? QSslSocket::tr("unsupported protocol") : QSslSocketBackendPrivate::getErrorsFromOpenSsl()
+ );
sslContext->errorCode = QSslError::UnspecifiedError;
return sslContext;
}
diff --git a/src/network/ssl/qsslerror.cpp b/src/network/ssl/qsslerror.cpp
index ff30098347c..5004e561a83 100644
--- a/src/network/ssl/qsslerror.cpp
+++ b/src/network/ssl/qsslerror.cpp
@@ -305,6 +305,19 @@ QSslCertificate QSslError::certificate() const
return d->certificate;
}
+/*!
+ Returns the hash value for the \a key, using \a seed to seed the calculation.
+ \since 5.4
+ \relates QHash
+*/
+uint qHash(const QSslError &key, uint seed) Q_DECL_NOTHROW
+{
+ // 2x boost::hash_combine inlined:
+ seed ^= qHash(key.error()) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ seed ^= qHash(key.certificate()) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
+ return seed;
+}
+
#ifndef QT_NO_DEBUG_STREAM
//class QDebug;
QDebug operator<<(QDebug debug, const QSslError &error)
diff --git a/src/network/ssl/qsslerror.h b/src/network/ssl/qsslerror.h
index d25546b68b8..c00532e2943 100644
--- a/src/network/ssl/qsslerror.h
+++ b/src/network/ssl/qsslerror.h
@@ -102,6 +102,8 @@ private:
};
Q_DECLARE_SHARED(QSslError)
+Q_NETWORK_EXPORT uint qHash(const QSslError &key, uint seed = 0) Q_DECL_NOTHROW;
+
#ifndef QT_NO_DEBUG_STREAM
class QDebug;
Q_NETWORK_EXPORT QDebug operator<<(QDebug debug, const QSslError &error);
diff --git a/src/network/ssl/qsslsocket_winrt.cpp b/src/network/ssl/qsslsocket_winrt.cpp
index c9ddd9ec1b8..da4c72be014 100644
--- a/src/network/ssl/qsslsocket_winrt.cpp
+++ b/src/network/ssl/qsslsocket_winrt.cpp
@@ -65,16 +65,6 @@ using namespace ABI::Windows::Storage::Streams;
QT_BEGIN_NAMESPACE
-// For QSet<QSslError>
-inline uint qHash(const QSslError &error, uint seed)
- Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(error)))
-{ return (qHash(error.error()) ^ seed); }
-
-// For QSet<QSslCertificate>
-inline uint qHash(const QSslCertificate &certificate, uint seed)
- Q_DECL_NOEXCEPT_EXPR(noexcept(qHash(certificate)))
-{ return (qHash(certificate.handle()) ^ seed); }
-
bool QSslSocketPrivate::s_libraryLoaded = true;
bool QSslSocketPrivate::s_loadRootCertsOnDemand = true;
bool QSslSocketPrivate::s_loadedCiphersAndCerts = false;
diff --git a/src/platformsupport/eglconvenience/qeglconvenience.cpp b/src/platformsupport/eglconvenience/qeglconvenience.cpp
index b7f4c55d3d1..80153cd18fe 100644
--- a/src/platformsupport/eglconvenience/qeglconvenience.cpp
+++ b/src/platformsupport/eglconvenience/qeglconvenience.cpp
@@ -487,6 +487,11 @@ QSizeF q_physicalScreenSizeFromFb(int framebufferDevice, const QSize &screenSize
size.setWidth(w <= 0 ? screenResolution.width() * Q_MM_PER_INCH / defaultPhysicalDpi : qreal(w));
size.setHeight(h <= 0 ? screenResolution.height() * Q_MM_PER_INCH / defaultPhysicalDpi : qreal(h));
+
+ if (w <= 0 || h <= 0)
+ qWarning("Unable to query physical screen size, defaulting to %d dpi.\n"
+ "To override, set QT_QPA_EGLFS_PHYSICAL_WIDTH "
+ "and QT_QPA_EGLFS_PHYSICAL_HEIGHT (in millimeters).", defaultPhysicalDpi);
}
return size;
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
index 62dc9a9c6b3..2b9883eb36c 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase.cpp
@@ -587,92 +587,18 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, void *usrPtr)
{
if (!usrPtr)
return 0;
- QFontDef fontDef = f;
- QFontEngineFT *engine;
FontFile *fontfile = static_cast<FontFile *> (usrPtr);
QFontEngine::FaceId fid;
fid.filename = QFile::encodeName(fontfile->fileName);
fid.index = fontfile->indexValue;
- bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
- bool forcedAntialiasSetting = !antialias;
- engine = new QFontEngineFT(fontDef);
-
- const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services();
- bool useXftConf = (services && (services->desktopEnvironment() == "GNOME" || services->desktopEnvironment() == "UNITY"));
- if (useXftConf) {
- void *antialiasResource =
- QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled",
- QGuiApplication::primaryScreen());
- int antialiasingEnabled = int(reinterpret_cast<qintptr>(antialiasResource));
- if (antialiasingEnabled > 0) {
- antialias = antialiasingEnabled - 1;
- forcedAntialiasSetting = true;
- }
- }
+ QFontEngineFT *engine = new QFontEngineFT(f);
+ engine->face_id = fid;
- QFontEngine::GlyphFormat format;
- // try and get the pattern
- FcPattern *pattern = FcPatternCreate();
+ setupFontEngine(engine, f);
- FcValue value;
- value.type = FcTypeString;
- QByteArray cs = fontDef.family.toUtf8();
- value.u.s = (const FcChar8 *)cs.data();
- FcPatternAdd(pattern,FC_FAMILY,value,true);
-
- value.u.s = (const FcChar8 *)fid.filename.data();
- FcPatternAdd(pattern,FC_FILE,value,true);
-
- value.type = FcTypeInteger;
- value.u.i = fid.index;
- FcPatternAdd(pattern,FC_INDEX,value,true);
-
- FcResult result;
-
- FcConfigSubstitute(0, pattern, FcMatchPattern);
- FcDefaultSubstitute(pattern);
-
- FcPattern *match = FcFontMatch(0, pattern, &result);
- if (match) {
- engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)f.hintingPreference, match, useXftConf));
-
- FcBool fc_autohint;
- if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch)
- engine->forceAutoHint = fc_autohint;
-
-#if defined(FT_LCD_FILTER_H)
- int lcdFilter;
- if (FcPatternGetInteger(match, FC_LCD_FILTER, 0, &lcdFilter) == FcResultMatch)
- engine->lcdFilterType = lcdFilter;
-#endif
-
- if (!forcedAntialiasSetting) {
- FcBool fc_antialias;
- if (FcPatternGetBool(match, FC_ANTIALIAS,0, &fc_antialias) == FcResultMatch)
- antialias = fc_antialias;
- }
-
- if (antialias) {
- QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None;
- if (!(f.styleStrategy & QFont::NoSubpixelAntialias))
- subpixelType = subpixelTypeFromMatch(match, useXftConf);
- engine->subpixelType = subpixelType;
-
- format = (subpixelType == QFontEngine::Subpixel_None)
- ? QFontEngine::Format_A8
- : QFontEngine::Format_A32;
- } else
- format = QFontEngine::Format_Mono;
-
- FcPatternDestroy(match);
- } else
- format = antialias ? QFontEngine::Format_A8 : QFontEngine::Format_Mono;
-
- FcPatternDestroy(pattern);
-
- if (!engine->init(fid, antialias, format) || engine->invalid()) {
+ if (!engine->init(fid, engine->antialias, engine->defaultFormat) || engine->invalid()) {
delete engine;
engine = 0;
}
@@ -686,74 +612,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QByteArray &fontData, qreal p
if (engine == 0)
return 0;
- QFontDef fontDef = engine->fontDef;
-
- bool forcedAntialiasSetting = false;
- const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services();
- bool useXftConf = (services && (services->desktopEnvironment() == "GNOME" || services->desktopEnvironment() == "UNITY"));
- if (useXftConf) {
- void *antialiasResource =
- QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled",
- QGuiApplication::primaryScreen());
- int antialiasingEnabled = int(reinterpret_cast<qintptr>(antialiasResource));
- if (antialiasingEnabled > 0) {
- engine->antialias = antialiasingEnabled - 1;
- forcedAntialiasSetting = true;
- }
- }
-
- QFontEngine::GlyphFormat format;
- // try and get the pattern
- FcPattern *pattern = FcPatternCreate();
-
- FcValue value;
- value.type = FcTypeString;
- QByteArray cs = fontDef.family.toUtf8();
- value.u.s = (const FcChar8 *)cs.data();
- FcPatternAdd(pattern,FC_FAMILY,value,true);
-
- FcResult result;
-
- FcConfigSubstitute(0, pattern, FcMatchPattern);
- FcDefaultSubstitute(pattern);
-
- FcPattern *match = FcFontMatch(0, pattern, &result);
- if (match) {
- engine->setDefaultHintStyle(defaultHintStyleFromMatch(hintingPreference, match, useXftConf));
-
- FcBool fc_autohint;
- if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch)
- engine->forceAutoHint = fc_autohint;
-
-#if defined(FT_LCD_FILTER_H)
- int lcdFilter;
- if (FcPatternGetInteger(match, FC_LCD_FILTER, 0, &lcdFilter) == FcResultMatch)
- engine->lcdFilterType = lcdFilter;
-#endif
-
- if (!forcedAntialiasSetting) {
- FcBool fc_antialias;
- if (FcPatternGetBool(match, FC_ANTIALIAS,0, &fc_antialias) == FcResultMatch)
- engine->antialias = fc_antialias;
- }
-
- if (engine->antialias) {
- QFontEngine::SubpixelAntialiasingType subpixelType = subpixelTypeFromMatch(match, useXftConf);
- engine->subpixelType = subpixelType;
-
- format = subpixelType == QFontEngine::Subpixel_None
- ? QFontEngine::Format_A8
- : QFontEngine::Format_A32;
- } else
- format = QFontEngine::Format_Mono;
- FcPatternDestroy(match);
- } else
- format = QFontEngine::Format_A8;
-
- FcPatternDestroy(pattern);
-
- engine->defaultFormat = format;
- engine->glyphFormat = format;
+ setupFontEngine(engine, engine->fontDef);
return engine;
}
@@ -947,4 +806,94 @@ QFont QFontconfigDatabase::defaultFont() const
return QFont(resolved);
}
+void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef &fontDef) const
+{
+ bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias);
+ bool forcedAntialiasSetting = !antialias;
+
+ const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services();
+ bool useXftConf = (services && (services->desktopEnvironment() == "GNOME" || services->desktopEnvironment() == "UNITY"));
+ if (useXftConf) {
+ void *antialiasResource =
+ QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled",
+ QGuiApplication::primaryScreen());
+ int antialiasingEnabled = int(reinterpret_cast<qintptr>(antialiasResource));
+ if (antialiasingEnabled > 0) {
+ antialias = antialiasingEnabled - 1;
+ forcedAntialiasSetting = true;
+ }
+ }
+
+ QFontEngine::GlyphFormat format;
+ // try and get the pattern
+ FcPattern *pattern = FcPatternCreate();
+
+ FcValue value;
+ value.type = FcTypeString;
+ QByteArray cs = fontDef.family.toUtf8();
+ value.u.s = (const FcChar8 *)cs.data();
+ FcPatternAdd(pattern,FC_FAMILY,value,true);
+
+ QFontEngine::FaceId fid = engine->faceId();
+
+ if (!fid.filename.isEmpty()) {
+ value.u.s = (const FcChar8 *)fid.filename.data();
+ FcPatternAdd(pattern,FC_FILE,value,true);
+
+ value.type = FcTypeInteger;
+ value.u.i = fid.index;
+ FcPatternAdd(pattern,FC_INDEX,value,true);
+ }
+
+ if (fontDef.pixelSize > 0.1)
+ FcPatternAddDouble(pattern, FC_PIXEL_SIZE, fontDef.pixelSize);
+
+ FcResult result;
+
+ FcConfigSubstitute(0, pattern, FcMatchPattern);
+ FcDefaultSubstitute(pattern);
+
+ FcPattern *match = FcFontMatch(0, pattern, &result);
+ if (match) {
+ engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf));
+
+ FcBool fc_autohint;
+ if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch)
+ engine->forceAutoHint = fc_autohint;
+
+#if defined(FT_LCD_FILTER_H)
+ int lcdFilter;
+ if (FcPatternGetInteger(match, FC_LCD_FILTER, 0, &lcdFilter) == FcResultMatch)
+ engine->lcdFilterType = lcdFilter;
+#endif
+
+ if (!forcedAntialiasSetting) {
+ FcBool fc_antialias;
+ if (FcPatternGetBool(match, FC_ANTIALIAS,0, &fc_antialias) == FcResultMatch)
+ antialias = fc_antialias;
+ }
+
+ if (antialias) {
+ QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None;
+ if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias))
+ subpixelType = subpixelTypeFromMatch(match, useXftConf);
+ engine->subpixelType = subpixelType;
+
+ format = (subpixelType == QFontEngine::Subpixel_None)
+ ? QFontEngine::Format_A8
+ : QFontEngine::Format_A32;
+ } else
+ format = QFontEngine::Format_Mono;
+
+ FcPatternDestroy(match);
+ } else
+ format = antialias ? QFontEngine::Format_A8 : QFontEngine::Format_Mono;
+
+ FcPatternDestroy(pattern);
+
+ engine->antialias = antialias;
+ engine->defaultFormat = format;
+ engine->glyphFormat = format;
+}
+
QT_END_NAMESPACE
diff --git a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h
index 91ecb52e7bc..745d12b825e 100644
--- a/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h
+++ b/src/platformsupport/fontdatabases/fontconfig/qfontconfigdatabase_p.h
@@ -50,6 +50,8 @@
QT_BEGIN_NAMESPACE
+class QFontEngineFT;
+
class QFontconfigDatabase : public QBasicFontDatabase
{
public:
@@ -61,6 +63,9 @@ public:
QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName);
QString resolveFontFamilyAlias(const QString &family) const;
QFont defaultFont() const;
+
+private:
+ void setupFontEngine(QFontEngineFT *engine, const QFontDef &fontDef) const;
};
QT_END_NAMESPACE
diff --git a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
index 52cb9286155..fc289579ea8 100644
--- a/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
+++ b/src/platformsupport/fontdatabases/mac/qcoretextfontdatabase.mm
@@ -759,6 +759,50 @@ static CTFontUIFontType fontTypeFromTheme(QPlatformTheme::Font f)
}
}
+static CTFontDescriptorRef fontDescriptorFromTheme(QPlatformTheme::Font f)
+{
+#ifdef Q_OS_IOS
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0) {
+ // Use Dynamic Type to resolve theme fonts if possible, to get
+ // correct font sizes and style based on user configuration.
+ NSString *textStyle = 0;
+ switch (f) {
+ case QPlatformTheme::TitleBarFont:
+ case QPlatformTheme::HeaderViewFont:
+ textStyle = UIFontTextStyleHeadline;
+ break;
+ case QPlatformTheme::MdiSubWindowTitleFont:
+ textStyle = UIFontTextStyleSubheadline;
+ break;
+ case QPlatformTheme::TipLabelFont:
+ case QPlatformTheme::SmallFont:
+ textStyle = UIFontTextStyleFootnote;
+ break;
+ case QPlatformTheme::MiniFont:
+ textStyle = UIFontTextStyleCaption2;
+ break;
+ case QPlatformTheme::FixedFont:
+ // Fall back to regular code path, as iOS doesn't provide
+ // an appropriate text style for this theme font.
+ break;
+ default:
+ textStyle = UIFontTextStyleBody;
+ break;
+ }
+
+ if (textStyle) {
+ UIFontDescriptor *desc = [UIFontDescriptor preferredFontDescriptorWithTextStyle:textStyle];
+ return static_cast<CTFontDescriptorRef>(CFBridgingRetain(desc));
+ }
+ }
+#endif // Q_OS_IOS
+
+ // OSX default case and iOS fallback case
+ CTFontUIFontType fontType = fontTypeFromTheme(f);
+ QCFType<CTFontRef> ctFont = CTFontCreateUIFontForLanguage(fontType, 0.0, NULL);
+ return CTFontCopyFontDescriptor(ctFont);
+}
+
const QHash<QPlatformTheme::Font, QFont *> &QCoreTextFontDatabase::themeFonts() const
{
if (m_themeFonts.isEmpty()) {
@@ -773,11 +817,7 @@ const QHash<QPlatformTheme::Font, QFont *> &QCoreTextFontDatabase::themeFonts()
QFont *QCoreTextFontDatabase::themeFont(QPlatformTheme::Font f) const
{
- CTFontUIFontType fontType = fontTypeFromTheme(f);
-
- QCFType<CTFontRef> ctFont = CTFontCreateUIFontForLanguage(fontType, 0.0, NULL);
- CTFontDescriptorRef fontDesc = CTFontCopyFontDescriptor(ctFont);
-
+ CTFontDescriptorRef fontDesc = fontDescriptorFromTheme(f);
FontDescription fd;
getFontDescription(fontDesc, &fd);
m_systemFontDescriptors.insert(fontDesc);
diff --git a/src/platformsupport/linuxaccessibility/application.cpp b/src/platformsupport/linuxaccessibility/application.cpp
index 856d84d1099..3e7fd45a09a 100644
--- a/src/platformsupport/linuxaccessibility/application.cpp
+++ b/src/platformsupport/linuxaccessibility/application.cpp
@@ -197,7 +197,9 @@ bool QSpiApplicationAdaptor::eventFilter(QObject *target, QEvent *event)
QKeyEvent* QSpiApplicationAdaptor::copyKeyEvent(QKeyEvent* old)
{
- return new QKeyEvent(old->type(), old->key(), old->modifiers(), old->text(), old->isAutoRepeat(), old->count());
+ return new QKeyEvent(old->type(), old->key(), old->modifiers(),
+ old->nativeScanCode(), old->nativeVirtualKey(), old->nativeModifiers(),
+ old->text(), old->isAutoRepeat(), old->count());
}
void QSpiApplicationAdaptor::notifyKeyboardListenerCallback(const QDBusMessage& message)
diff --git a/src/plugins/bearer/connman/qconnmanengine.cpp b/src/plugins/bearer/connman/qconnmanengine.cpp
index 733b6f131f8..7499df85961 100644
--- a/src/plugins/bearer/connman/qconnmanengine.cpp
+++ b/src/plugins/bearer/connman/qconnmanengine.cpp
@@ -442,7 +442,7 @@ QNetworkConfiguration::BearerType QConnmanEngine::ofonoTechToBearerType(const QS
} else if (currentTechnology == QLatin1String("hspa")) {
return QNetworkConfiguration::BearerHSPA;
} else if (currentTechnology == QLatin1String("lte")) {
- return QNetworkConfiguration::BearerWiMAX; //not exact
+ return QNetworkConfiguration::BearerLTE;
}
}
return QNetworkConfiguration::BearerUnknown;
diff --git a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
index c0aaed2525a..4e90f618765 100644
--- a/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
+++ b/src/plugins/platforminputcontexts/compose/generator/qtablegenerator.cpp
@@ -442,7 +442,7 @@ void TableGenerator::parseKeySequence(char *line)
void TableGenerator::printComposeTable() const
{
#ifdef DEBUG_GENERATOR
- if (composeTable().isEmpty())
+ if (m_composeTable.isEmpty())
return;
QString output;
diff --git a/src/plugins/platforms/android/android.pro b/src/plugins/platforms/android/android.pro
index f55bc40a55e..3c3a4b4b2ed 100644
--- a/src/plugins/platforms/android/android.pro
+++ b/src/plugins/platforms/android/android.pro
@@ -26,6 +26,7 @@ INCLUDEPATH += \
$$QT_SOURCE_TREE/src/3rdparty/android
SOURCES += $$PWD/androidplatformplugin.cpp \
+ $$PWD/androiddeadlockprotector.cpp \
$$PWD/androidjnimain.cpp \
$$PWD/androidjniaccessibility.cpp \
$$PWD/androidjniinput.cpp \
@@ -53,6 +54,7 @@ SOURCES += $$PWD/androidplatformplugin.cpp \
$$PWD/qandroideventdispatcher.cpp
HEADERS += $$PWD/qandroidplatformintegration.h \
+ $$PWD/androidandroiddeadlockprotector.h \
$$PWD/androidjnimain.h \
$$PWD/androidjniaccessibility.h \
$$PWD/androidjniinput.h \
diff --git a/src/plugins/platforms/android/androiddeadlockprotector.cpp b/src/plugins/platforms/android/androiddeadlockprotector.cpp
new file mode 100644
index 00000000000..e53e0c2447e
--- /dev/null
+++ b/src/plugins/platforms/android/androiddeadlockprotector.cpp
@@ -0,0 +1,37 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "androiddeadlockprotector.h"
+
+QAtomicInt AndroidDeadlockProtector::s_blocked(0);
+
diff --git a/src/plugins/platforms/android/androiddeadlockprotector.h b/src/plugins/platforms/android/androiddeadlockprotector.h
new file mode 100644
index 00000000000..a0a82aa9d1b
--- /dev/null
+++ b/src/plugins/platforms/android/androiddeadlockprotector.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** 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 Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/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.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef ANDROID_DEADLOCKPROTECTOR_H
+#define ANDROID_DEADLOCKPROTECTOR_H
+
+#include <QAtomicInt>
+
+QT_BEGIN_NAMESPACE
+
+class AndroidDeadlockProtector
+{
+public:
+ AndroidDeadlockProtector()
+ : m_acquired(0)
+ {
+ }
+
+ ~AndroidDeadlockProtector() {
+ if (m_acquired)
+ s_blocked.storeRelease(0);
+ }
+
+ bool acquire() {
+ m_acquired = s_blocked.testAndSetAcquire(0, 1);
+ return m_acquired;
+ }
+
+private:
+ static QAtomicInt s_blocked;
+ int m_acquired;
+};
+
+QT_END_NAMESPACE
+
+#endif // ANDROID_DEADLOCKPROTECTOR_H
+
diff --git a/src/plugins/platforms/android/androidjniaccessibility.cpp b/src/plugins/platforms/android/androidjniaccessibility.cpp
index 7229fd7af58..5c927da9c50 100644
--- a/src/plugins/platforms/android/androidjniaccessibility.cpp
+++ b/src/plugins/platforms/android/androidjniaccessibility.cpp
@@ -187,18 +187,30 @@ if (!clazz) { \
//__android_log_print(ANDROID_LOG_FATAL, m_qtTag, m_methodErrorMsg, METHOD_NAME, METHOD_SIGNATURE);
- static jstring descriptionForAccessibleObject(JNIEnv *env, jobject /*thiz*/, jint objectId)
+
+ static jstring descriptionForAccessibleObject_helper(JNIEnv *env, QAccessibleInterface *iface)
{
QString desc;
- QAccessibleInterface *iface = interfaceFromId(objectId);
if (iface && iface->isValid()) {
desc = iface->text(QAccessible::Name);
if (desc.isEmpty())
desc = iface->text(QAccessible::Description);
+ if (desc.isEmpty()) {
+ desc = iface->text(QAccessible::Value);
+ if (desc.isEmpty()) {
+ if (QAccessibleValueInterface *valueIface = iface->valueInterface()) {
+ desc= valueIface->currentValue().toString();
+ }
+ }
+ }
}
+ return env->NewString((jchar*) desc.constData(), (jsize) desc.size());
+ }
- jstring jdesc = env->NewString((jchar*) desc.constData(), (jsize) desc.size());
- return jdesc;
+ static jstring descriptionForAccessibleObject(JNIEnv *env, jobject /*thiz*/, jint objectId)
+ {
+ QAccessibleInterface *iface = interfaceFromId(objectId);
+ return descriptionForAccessibleObject_helper(env, iface);
}
static bool populateNode(JNIEnv *env, jobject /*thiz*/, jint objectId, jobject node)
@@ -216,11 +228,8 @@ if (!clazz) { \
const bool hasDecreaseAction = actions.contains(QAccessibleActionInterface::decreaseAction());
// try to fill in the text property, this is what the screen reader reads
- QString desc = iface->text(QAccessible::Value);
- if (desc.isEmpty())
- desc = iface->text(QAccessible::Name);
- if (desc.isEmpty())
- desc = iface->text(QAccessible::Description);
+ jstring jdesc = descriptionForAccessibleObject_helper(env, iface);
+
if (QAccessibleTextInterface *textIface = iface->textInterface()) {
if (m_setTextSelectionMethodID && textIface->selectionCount() > 0) {
int startSelection;
@@ -252,7 +261,6 @@ if (!clazz) { \
env->CallVoidMethod(node, m_addActionMethodID, (int)8192); // ACTION_SCROLL_BACKWARD defined in AccessibilityNodeInfo
- jstring jdesc = env->NewString((jchar*) desc.constData(), (jsize) desc.size());
//CALL_METHOD(node, "setText", "(Ljava/lang/CharSequence;)V", jdesc)
env->CallVoidMethod(node, m_setContentDescriptionMethodID, jdesc);
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index a23d05520cd..a3848c9c2b1 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -38,6 +38,7 @@
#include "androidjnimain.h"
#include "androidjniinput.h"
#include "qandroideventdispatcher.h"
+#include "androiddeadlockprotector.h"
#include <QDebug>
#include <qevent.h>
#include <qguiapplication.h>
@@ -519,6 +520,10 @@ bool QAndroidInputContext::isAnimating() const
void QAndroidInputContext::showInputPanel()
{
+ if (QGuiApplication::applicationState() != Qt::ApplicationActive) {
+ connect(qGuiApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(showInputPanelLater(Qt::ApplicationState)));
+ return;
+ }
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
if (query.isNull())
return;
@@ -541,6 +546,14 @@ void QAndroidInputContext::showInputPanel()
query->value(Qt::ImHints).toUInt());
}
+void QAndroidInputContext::showInputPanelLater(Qt::ApplicationState state)
+{
+ if (state != Qt::ApplicationActive)
+ return;
+ disconnect(qGuiApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(showInputPanelLater(Qt::ApplicationState)));
+ showInputPanel();
+}
+
void QAndroidInputContext::hideInputPanel()
{
QtAndroidInput::hideSoftwareKeyboard();
@@ -642,13 +655,13 @@ jboolean QAndroidInputContext::deleteSurroundingText(jint leftLength, jint right
// Android docs say the cursor must not move
jboolean QAndroidInputContext::finishComposingText()
{
+ if (m_composingText.isEmpty())
+ return JNI_TRUE; // not composing
+
QSharedPointer<QInputMethodQueryEvent> query = focusObjectInputMethodQueryThreadSafe();
if (query.isNull())
return JNI_FALSE;
- if (m_composingText.isEmpty())
- return JNI_TRUE; // not composing
-
const int blockPos = getBlockPosition(query);
const int localCursorPos = m_composingCursor - blockPos;
@@ -986,6 +999,9 @@ QVariant QAndroidInputContext::queryFocusObjectThreadSafe(Qt::InputMethodQuery q
const bool inMainThread = qGuiApp->thread() == QThread::currentThread();
if (QAndroidEventDispatcherStopper::stopped() && !inMainThread)
return retval;
+ AndroidDeadlockProtector protector;
+ if (!inMainThread && !protector.acquire())
+ return retval;
QMetaObject::invokeMethod(this, "queryFocusObjectUnsafe",
inMainThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection,
@@ -1003,6 +1019,9 @@ QSharedPointer<QInputMethodQueryEvent> QAndroidInputContext::focusObjectInputMet
const bool inMainThread = qGuiApp->thread() == QThread::currentThread();
if (QAndroidEventDispatcherStopper::stopped() && !inMainThread)
return QSharedPointer<QInputMethodQueryEvent>();
+ AndroidDeadlockProtector protector;
+ if (!inMainThread && !protector.acquire())
+ return QSharedPointer<QInputMethodQueryEvent>();
QInputMethodQueryEvent *queryEvent = 0;
QMetaObject::invokeMethod(this, "focusObjectInputMethodQueryUnsafe",
@@ -1040,7 +1059,9 @@ void QAndroidInputContext::sendInputMethodEventThreadSafe(QInputMethodEvent *eve
const bool inMainThread = qGuiApp->thread() == QThread::currentThread();
if (QAndroidEventDispatcherStopper::stopped() && !inMainThread)
return;
-
+ AndroidDeadlockProtector protector;
+ if (!inMainThread && !protector.acquire())
+ return;
QMetaObject::invokeMethod(this, "sendInputMethodEventUnsafe",
inMainThread ? Qt::DirectConnection : Qt::BlockingQueuedConnection,
Q_ARG(QInputMethodEvent*, event));
diff --git a/src/plugins/platforms/android/qandroidinputcontext.h b/src/plugins/platforms/android/qandroidinputcontext.h
index 670a0511397..2ebb155d2ac 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.h
+++ b/src/plugins/platforms/android/qandroidinputcontext.h
@@ -112,6 +112,9 @@ public:
public slots:
void updateCursorPosition();
+private slots:
+ void showInputPanelLater(Qt::ApplicationState);
+
private:
void sendInputMethodEventThreadSafe(QInputMethodEvent *event);
Q_INVOKABLE void sendInputMethodEventUnsafe(QInputMethodEvent *event);
diff --git a/src/plugins/platforms/android/qandroidplatformclipboard.cpp b/src/plugins/platforms/android/qandroidplatformclipboard.cpp
index 86fd152bff3..fb73db84554 100644
--- a/src/plugins/platforms/android/qandroidplatformclipboard.cpp
+++ b/src/plugins/platforms/android/qandroidplatformclipboard.cpp
@@ -44,19 +44,19 @@ QAndroidPlatformClipboard::QAndroidPlatformClipboard()
QMimeData *QAndroidPlatformClipboard::mimeData(QClipboard::Mode mode)
{
- if (QClipboard::Clipboard != mode || !QtAndroidClipboard::hasClipboardText())
- return 0;
-
- m_mimeData.setText(QtAndroidClipboard::clipboardText());
+ Q_ASSERT(supportsMode(mode));
+ m_mimeData.setText(QtAndroidClipboard::hasClipboardText()
+ ? QtAndroidClipboard::clipboardText()
+ : QString());
return &m_mimeData;
}
void QAndroidPlatformClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode)
{
- if (!data || !data->hasText() || QClipboard::Clipboard != mode)
- return;
-
- QtAndroidClipboard::setClipboardText(data->text());
+ Q_ASSERT(supportsMode(mode));
+ QtAndroidClipboard::setClipboardText(data != 0 && data->hasText() ? data->text() : QString());
+ if (data != 0)
+ data->deleteLater();
}
bool QAndroidPlatformClipboard::supportsMode(QClipboard::Mode mode) const
diff --git a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
index 8afc35c57a1..8dc8e84f0ae 100644
--- a/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
+++ b/src/plugins/platforms/android/qandroidplatformopenglwindow.cpp
@@ -37,6 +37,7 @@
#include "qandroidplatformscreen.h"
#include "androidjnimain.h"
#include "qandroideventdispatcher.h"
+#include "androiddeadlockprotector.h"
#include <QSurfaceFormat>
#include <QtGui/private/qwindow_p.h>
@@ -120,6 +121,10 @@ EGLSurface QAndroidPlatformOpenGLWindow::eglSurface(EGLConfig config)
QMutexLocker lock(&m_surfaceMutex);
if (m_nativeSurfaceId == -1) {
+ AndroidDeadlockProtector protector;
+ if (!protector.acquire())
+ return m_eglSurface;
+
const bool windowStaysOnTop = bool(window()->flags() & Qt::WindowStaysOnTopHint);
m_nativeSurfaceId = QtAndroid::createSurface(this, geometry(), windowStaysOnTop, 32);
m_surfaceWaitCondition.wait(&m_surfaceMutex);
diff --git a/src/plugins/platforms/android/qandroidplatformscreen.cpp b/src/plugins/platforms/android/qandroidplatformscreen.cpp
index 09e5d7e346e..8a07735e5f8 100644
--- a/src/plugins/platforms/android/qandroidplatformscreen.cpp
+++ b/src/plugins/platforms/android/qandroidplatformscreen.cpp
@@ -43,6 +43,7 @@
#include "qandroidplatformwindow.h"
#include "androidjnimain.h"
#include "androidjnimenu.h"
+#include "androiddeadlockprotector.h"
#include <android/bitmap.h>
#include <android/native_window_jni.h>
@@ -299,6 +300,9 @@ void QAndroidPlatformScreen::doRedraw()
QMutexLocker lock(&m_surfaceMutex);
if (m_id == -1 && m_rasterSurfaces) {
m_id = QtAndroid::createSurface(this, m_availableGeometry, true, m_depth);
+ AndroidDeadlockProtector protector;
+ if (!protector.acquire())
+ return;
m_surfaceWaitCondition.wait(&m_surfaceMutex);
}
diff --git a/src/plugins/platforms/cocoa/qcocoaclipboard.h b/src/plugins/platforms/cocoa/qcocoaclipboard.h
index 5ebdad79f1e..2c34ef9278e 100644
--- a/src/plugins/platforms/cocoa/qcocoaclipboard.h
+++ b/src/plugins/platforms/cocoa/qcocoaclipboard.h
@@ -40,8 +40,10 @@
QT_BEGIN_NAMESPACE
-class QCocoaClipboard : public QPlatformClipboard
+class QCocoaClipboard : public QObject, public QPlatformClipboard
{
+ Q_OBJECT
+
public:
QCocoaClipboard();
@@ -49,6 +51,10 @@ public:
void setMimeData(QMimeData *data, QClipboard::Mode mode = QClipboard::Clipboard);
bool supportsMode(QClipboard::Mode mode) const;
bool ownsMode(QClipboard::Mode mode) const;
+
+private Q_SLOTS:
+ void handleApplicationStateChanged(Qt::ApplicationState state);
+
protected:
QMacPasteboard *pasteboardForMode(QClipboard::Mode mode) const;
diff --git a/src/plugins/platforms/cocoa/qcocoaclipboard.mm b/src/plugins/platforms/cocoa/qcocoaclipboard.mm
index f6c424d4fdb..1a23da8a8eb 100644
--- a/src/plugins/platforms/cocoa/qcocoaclipboard.mm
+++ b/src/plugins/platforms/cocoa/qcocoaclipboard.mm
@@ -40,7 +40,6 @@
****************************************************************************/
#include "qcocoaclipboard.h"
-#include "qmacclipboard.h"
QT_BEGIN_NAMESPACE
@@ -48,7 +47,7 @@ QCocoaClipboard::QCocoaClipboard()
:m_clipboard(new QMacPasteboard(kPasteboardClipboard, QMacInternalPasteboardMime::MIME_CLIP))
,m_find(new QMacPasteboard(kPasteboardFind, QMacInternalPasteboardMime::MIME_CLIP))
{
-
+ connect(qGuiApp, &QGuiApplication::applicationStateChanged, this, &QCocoaClipboard::handleApplicationStateChanged);
}
QMimeData *QCocoaClipboard::mimeData(QClipboard::Mode mode)
@@ -94,4 +93,17 @@ QMacPasteboard *QCocoaClipboard::pasteboardForMode(QClipboard::Mode mode) const
return 0;
}
+void QCocoaClipboard::handleApplicationStateChanged(Qt::ApplicationState state)
+{
+ if (state != Qt::ApplicationActive)
+ return;
+
+ if (m_clipboard->sync())
+ emitChanged(QClipboard::Clipboard);
+ if (m_find->sync())
+ emitChanged(QClipboard::FindBuffer);
+}
+
+#include "moc_qcocoaclipboard.cpp"
+
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoamenu.mm b/src/plugins/platforms/cocoa/qcocoamenu.mm
index 736e02a3cab..d849389907f 100644
--- a/src/plugins/platforms/cocoa/qcocoamenu.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenu.mm
@@ -366,9 +366,14 @@ void QCocoaMenu::syncMenuItem(QPlatformMenuItem *menuItem)
}
bool wasMerged = cocoaItem->isMerged();
- NSMenu *oldMenu = wasMerged ? [getMenuLoader() applicationMenu] : m_nativeMenu;
- NSMenuItem *oldItem = [oldMenu itemWithTag:(NSInteger) cocoaItem];
+ NSMenu *oldMenu = m_nativeMenu;
+ if (wasMerged) {
+ QPlatformMenuItem::MenuRole role = cocoaItem->effectiveRole();
+ if (role >= QPlatformMenuItem::ApplicationSpecificRole && role < QPlatformMenuItem::CutRole)
+ oldMenu = [getMenuLoader() applicationMenu];
+ }
+ NSMenuItem *oldItem = [oldMenu itemWithTag:(NSInteger) cocoaItem];
if (cocoaItem->sync() != oldItem) {
// native item was changed for some reason
if (oldItem) {
diff --git a/src/plugins/platforms/cocoa/qcocoamenuitem.mm b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
index 3d3b6bf5980..791b0805d0a 100644
--- a/src/plugins/platforms/cocoa/qcocoamenuitem.mm
+++ b/src/plugins/platforms/cocoa/qcocoamenuitem.mm
@@ -256,8 +256,8 @@ NSMenuItem *QCocoaMenuItem::sync()
if (depth == 3 || !menubar)
break; // Menu item too deep in the hierarchy, or not connected to any menubar
- m_detectedRole = detectMenuRole(m_text);
- switch (m_detectedRole) {
+ MenuRole newDetectedRole = detectMenuRole(m_text);
+ switch (newDetectedRole) {
case QPlatformMenuItem::AboutRole:
if (m_text.indexOf(QRegExp(QString::fromLatin1("qt$"), Qt::CaseInsensitive)) == -1)
mergeItem = [loader aboutMenuItem];
@@ -271,12 +271,15 @@ NSMenuItem *QCocoaMenuItem::sync()
mergeItem = [loader quitMenuItem];
break;
default:
- if (m_detectedRole >= CutRole && m_detectedRole < RoleCount && menubar)
- mergeItem = menubar->itemForRole(m_detectedRole);
+ if (newDetectedRole >= CutRole && newDetectedRole < RoleCount && menubar)
+ mergeItem = menubar->itemForRole(newDetectedRole);
if (!m_text.isEmpty())
m_textSynced = true;
break;
}
+
+ m_detectedRole = newDetectedRole;
+
break;
}
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index 10a92667c1c..06680228bc2 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -420,12 +420,10 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
#pragma clang diagnostic ignored "-Wobjc-method-access"
enum { NSWindowOcclusionStateVisible = 1UL << 1 };
#endif
- // Older versions managed in -[QNSView viewDidMoveToWindow].
- // Support QWidgetAction in NSMenu. Mavericks only sends this notification.
- // Ideally we should support this in Qt as well, in order to disable animations
- // when the window is occluded.
if ((NSUInteger)[self.window occlusionState] & NSWindowOcclusionStateVisible)
m_platformWindow->exposeWindow();
+ else
+ m_platformWindow->obscureWindow();
#if MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9
#pragma clang diagnostic pop
#endif
diff --git a/src/plugins/platforms/ios/qiosclipboard.h b/src/plugins/platforms/ios/qiosclipboard.h
index 7d758e3a568..f532eba3dea 100644
--- a/src/plugins/platforms/ios/qiosclipboard.h
+++ b/src/plugins/platforms/ios/qiosclipboard.h
@@ -36,6 +36,7 @@
#import <UIKit/UIKit.h>
+#include <QMimeData>
#include <qpa/qplatformclipboard.h>
@class QUIClipboard;
@@ -46,6 +47,8 @@ class QIOSClipboard : public QPlatformClipboard
{
public:
QIOSClipboard();
+ ~QIOSClipboard();
+
QMimeData *mimeData(QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
void setMimeData(QMimeData *mimeData, QClipboard::Mode mode = QClipboard::Clipboard) Q_DECL_OVERRIDE;
bool supportsMode(QClipboard::Mode mode) const Q_DECL_OVERRIDE;
@@ -53,6 +56,7 @@ public:
private:
QUIClipboard *m_clipboard;
+ QMap<QClipboard::Mode, QMimeData *> m_mimeData;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/ios/qiosclipboard.mm b/src/plugins/platforms/ios/qiosclipboard.mm
index e18ad53b2c6..5ed6d3be629 100644
--- a/src/plugins/platforms/ios/qiosclipboard.mm
+++ b/src/plugins/platforms/ios/qiosclipboard.mm
@@ -194,10 +194,17 @@ QIOSClipboard::QIOSClipboard()
{
}
+QIOSClipboard::~QIOSClipboard()
+{
+ qDeleteAll(m_mimeData);
+}
+
QMimeData *QIOSClipboard::mimeData(QClipboard::Mode mode)
{
Q_ASSERT(supportsMode(mode));
- return new QIOSMimeData(mode);
+ if (!m_mimeData.contains(mode))
+ return *m_mimeData.insert(mode, new QIOSMimeData(mode));
+ return m_mimeData[mode];
}
void QIOSClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode)
@@ -209,6 +216,8 @@ void QIOSClipboard::setMimeData(QMimeData *mimeData, QClipboard::Mode mode)
pb.items = [NSArray array];
return;
}
+
+ mimeData->deleteLater();
NSMutableDictionary *pbItem = [NSMutableDictionary dictionaryWithCapacity:mimeData->formats().size()];
foreach (const QString &mimeType, mimeData->formats()) {
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index 13e91889a20..b4031543211 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -322,7 +322,7 @@ bool QIOSInputContext::isInputPanelVisible() const
void QIOSInputContext::cursorRectangleChanged()
{
- if (!m_keyboardListener->m_keyboardVisibleAndDocked)
+ if (!m_keyboardListener->m_keyboardVisibleAndDocked || !qApp->focusObject())
return;
// Check if the cursor has changed position inside the input item. Since
@@ -399,6 +399,8 @@ void QIOSInputContext::scroll(int y)
animation.toValue = [NSValue valueWithCATransform3D:translationTransform];
[rootView.layer addAnimation:animation forKey:@"AnimateSubLayerTransform"];
rootView.layer.sublayerTransform = translationTransform;
+
+ [rootView.qtViewController updateProperties];
}
completion:^(BOOL){
if (self)
diff --git a/src/plugins/platforms/ios/qiosmenu.mm b/src/plugins/platforms/ios/qiosmenu.mm
index c247c16514f..005b06547e6 100644
--- a/src/plugins/platforms/ios/qiosmenu.mm
+++ b/src/plugins/platforms/ios/qiosmenu.mm
@@ -88,8 +88,9 @@ static NSString *const kSelectorPrefix = @"_qtMenuItem_";
- (id)targetForAction:(SEL)action withSender:(id)sender
{
+ Q_UNUSED(sender);
BOOL containsPrefix = ([NSStringFromSelector(action) rangeOfString:kSelectorPrefix].location != NSNotFound);
- return (containsPrefix && [sender isKindOfClass:[UIMenuController class]]) ? self : 0;
+ return containsPrefix ? self : 0;
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.h b/src/plugins/platforms/ios/qiosviewcontroller.h
index cbb28aec0db..586edd589d7 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.h
+++ b/src/plugins/platforms/ios/qiosviewcontroller.h
@@ -41,6 +41,7 @@ class QIOSScreen;
@property (nonatomic, assign) BOOL changingOrientation;
@property (nonatomic, assign) BOOL prefersStatusBarHidden;
+@property (nonatomic, assign) UIStatusBarAnimation preferredStatusBarUpdateAnimation;
- (id)initWithQIOSScreen:(QIOSScreen *)screen;
- (void)updateProperties;
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index ca8d48bf6d6..a2d81e3b6c3 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -150,6 +150,7 @@
// Status bar may be initially hidden at startup through Info.plist
self.prefersStatusBarHidden = infoPlistValue(@"UIStatusBarHidden", false);
+ self.preferredStatusBarUpdateAnimation = UIStatusBarAnimationNone;
QObject::connect(qApp, &QGuiApplication::focusWindowChanged, [self]() {
[self updateProperties];
@@ -182,47 +183,6 @@
// -------------------------------------------------------------------------
-- (void)updateProperties
-{
- if (!isQtApplication())
- return;
-
- QWindow *focusWindow = QGuiApplication::focusWindow();
-
- // If we don't have a focus window we leave the statusbar
- // as is, so that the user can activate a new window with
- // the same window state without the status bar jumping
- // back and forth.
- if (!focusWindow)
- return;
-
- // We only care about changes to focusWindow that involves our screen
- if (!focusWindow->screen() || focusWindow->screen()->handle() != m_screen)
- return;
-
- // All decisions are based on the the top level window
- focusWindow = qt_window_private(focusWindow)->topLevelWindow();
-
- bool currentStatusBarVisibility = self.prefersStatusBarHidden;
- self.prefersStatusBarHidden = focusWindow->windowState() == Qt::WindowFullScreen;
- if (self.prefersStatusBarHidden != currentStatusBarVisibility) {
-#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
- if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0) {
- [self setNeedsStatusBarAppearanceUpdate];
- } else
-#endif
- {
- [[UIApplication sharedApplication]
- setStatusBarHidden:self.prefersStatusBarHidden
- withAnimation:UIStatusBarAnimationNone];
- }
-
- [self.view setNeedsLayout];
- }
-}
-
-// -------------------------------------------------------------------------
-
-(BOOL)shouldAutorotate
{
// Until a proper orientation and rotation API is in place, we always auto rotate.
@@ -298,6 +258,54 @@
m_screen->updateProperties();
}
+// -------------------------------------------------------------------------
+
+- (void)updateProperties
+{
+ if (!isQtApplication())
+ return;
+
+ QWindow *focusWindow = QGuiApplication::focusWindow();
+
+ // If we don't have a focus window we leave the statusbar
+ // as is, so that the user can activate a new window with
+ // the same window state without the status bar jumping
+ // back and forth.
+ if (!focusWindow)
+ return;
+
+ // We only care about changes to focusWindow that involves our screen
+ if (!focusWindow->screen() || focusWindow->screen()->handle() != m_screen)
+ return;
+
+ // All decisions are based on the the top level window
+ focusWindow = qt_window_private(focusWindow)->topLevelWindow();
+
+ bool hasScrolledRootViewDueToVirtualKeyboard =
+ !CATransform3DIsIdentity(self.view.layer.sublayerTransform);
+
+ bool currentStatusBarVisibility = self.prefersStatusBarHidden;
+ self.prefersStatusBarHidden = focusWindow->windowState() == Qt::WindowFullScreen
+ || hasScrolledRootViewDueToVirtualKeyboard;
+ self.preferredStatusBarUpdateAnimation = hasScrolledRootViewDueToVirtualKeyboard ?
+ UIStatusBarAnimationFade : UIStatusBarAnimationNone;
+
+ if (self.prefersStatusBarHidden != currentStatusBarVisibility) {
+#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
+ if (QSysInfo::MacintoshVersion >= QSysInfo::MV_IOS_7_0) {
+ [self setNeedsStatusBarAppearanceUpdate];
+ } else
+#endif
+ {
+ [[UIApplication sharedApplication]
+ setStatusBarHidden:self.prefersStatusBarHidden
+ withAnimation:self.preferredStatusBarUpdateAnimation];
+ }
+
+ [self.view setNeedsLayout];
+ }
+}
+
#if QT_IOS_PLATFORM_SDK_EQUAL_OR_ABOVE(__IPHONE_7_0)
- (UIStatusBarStyle)preferredStatusBarStyle
{
diff --git a/src/plugins/platforms/ios/qioswindow.h b/src/plugins/platforms/ios/qioswindow.h
index 5bbd76fb36b..65b4f6dd7d3 100644
--- a/src/plugins/platforms/ios/qioswindow.h
+++ b/src/plugins/platforms/ios/qioswindow.h
@@ -42,11 +42,6 @@
class QIOSContext;
class QIOSWindow;
-@interface UIView (QIOS)
-@property(readonly) QWindow *qwindow;
-@property(readonly) UIViewController *viewController;
-@end
-
QT_BEGIN_NAMESPACE
@class QUIView;
@@ -71,6 +66,8 @@ public:
void raise() { raiseOrLower(true); }
void lower() { raiseOrLower(false); }
+
+ bool shouldAutoActivateWindow() const;
void requestActivateWindow();
qreal devicePixelRatio() const;
@@ -95,9 +92,6 @@ private:
void updateWindowLevel();
bool blockedByModal();
- inline Qt::WindowType windowType() { return static_cast<Qt::WindowType>(int(window()->flags() & Qt::WindowType_Mask)); }
- inline bool windowIsPopup() { return windowType() & Qt::Popup & ~Qt::Window; }
-
friend class QIOSScreen;
};
diff --git a/src/plugins/platforms/ios/qioswindow.mm b/src/plugins/platforms/ios/qioswindow.mm
index e29ff53876c..b0c5f153067 100644
--- a/src/plugins/platforms/ios/qioswindow.mm
+++ b/src/plugins/platforms/ios/qioswindow.mm
@@ -117,24 +117,39 @@ void QIOSWindow::setVisible(bool visible)
return;
}
- if (visible) {
+ if (visible && shouldAutoActivateWindow()) {
requestActivateWindow();
- } else {
- // Activate top-most visible QWindow:
+ } else if (!visible && qGuiApp->focusWindow() == window()) {
+ // Our window was active/focus window but now hidden, so relinquish
+ // focus to the next possible window in the stack.
NSArray *subviews = m_view.viewController.view.subviews;
for (int i = int(subviews.count) - 1; i >= 0; --i) {
UIView *view = [subviews objectAtIndex:i];
- if (!view.hidden) {
- QWindow *w = view.qwindow;
- if (w && w->isTopLevel()) {
- static_cast<QIOSWindow *>(w->handle())->requestActivateWindow();
- break;
- }
- }
+ if (view.hidden)
+ continue;
+
+ QWindow *w = view.qwindow;
+ if (!w || !w->isTopLevel())
+ continue;
+
+ QIOSWindow *iosWindow = static_cast<QIOSWindow *>(w->handle());
+ if (!iosWindow->shouldAutoActivateWindow())
+ continue;
+
+ iosWindow->requestActivateWindow();
+ break;
}
}
}
+bool QIOSWindow::shouldAutoActivateWindow() const
+{
+ // We don't want to do automatic window activation for popup windows
+ // (including Tool, ToolTip and SplashScreen windows), unless they
+ // are standalone (no parent/transient parent), and hence not active.
+ return !(window()->type() & Qt::Popup) || !window()->isActive();
+}
+
void QIOSWindow::setOpacity(qreal level)
{
m_view.alpha = qBound(0.0, level, 1.0);
@@ -280,7 +295,7 @@ void QIOSWindow::raiseOrLower(bool raise)
void QIOSWindow::updateWindowLevel()
{
- Qt::WindowType type = windowType();
+ Qt::WindowType type = window()->type();
if (type == Qt::ToolTip)
m_windowLevel = 120;
diff --git a/src/plugins/platforms/ios/quiview.h b/src/plugins/platforms/ios/quiview.h
index fe71e5bed70..6550c61ad0e 100644
--- a/src/plugins/platforms/ios/quiview.h
+++ b/src/plugins/platforms/ios/quiview.h
@@ -62,7 +62,9 @@ class QIOSWindow;
- (void)clearAccessibleCache;
@end
-@interface QUIView (QtHelpers)
+@interface UIView (QtHelpers)
+- (QWindow *)qwindow;
+- (UIViewController *)viewController;
- (QIOSViewController*)qtViewController;
@end
diff --git a/src/plugins/platforms/ios/quiview.mm b/src/plugins/platforms/ios/quiview.mm
index 200b07b5fc6..c46ed4c0b1c 100644
--- a/src/plugins/platforms/ios/quiview.mm
+++ b/src/plugins/platforms/ios/quiview.mm
@@ -271,7 +271,7 @@
m_activeTouches[touch].id = m_nextTouchId++;
}
- if (m_activeTouches.size() == 1) {
+ if (m_qioswindow->shouldAutoActivateWindow() && m_activeTouches.size() == 1) {
QPlatformWindow *topLevel = m_qioswindow;
while (QPlatformWindow *p = topLevel->parent())
topLevel = p;
@@ -340,11 +340,16 @@
QWindowSystemInterface::flushWindowSystemEvents();
}
-- (id)targetForAction:(SEL)action withSender:(id)sender
+- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
// Check first if QIOSMenu should handle the action before continuing up the responder chain
- id target = [QIOSMenu::menuActionTarget() targetForAction:action withSender:sender];
- return target ? target : [super targetForAction:action withSender:sender];
+ return [QIOSMenu::menuActionTarget() targetForAction:action withSender:sender] != 0;
+}
+
+- (id)forwardingTargetForSelector:(SEL)selector
+{
+ Q_UNUSED(selector)
+ return QIOSMenu::menuActionTarget();
}
@end
diff --git a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp b/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp
index 73988b6db50..593b5eac7ac 100644
--- a/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp
+++ b/src/plugins/platforms/windows/qwindowsguieventdispatcher.cpp
@@ -62,6 +62,7 @@ QWindowsGuiEventDispatcher::QWindowsGuiEventDispatcher(QObject *parent) :
QEventDispatcherWin32(parent), m_flags(0)
{
setObjectName(QStringLiteral("QWindowsGuiEventDispatcher"));
+ createInternalHwnd(); // QTBUG-40881: Do not delay registering timers, etc. for QtMfc.
}
bool QWindowsGuiEventDispatcher::processEvents(QEventLoop::ProcessEventsFlags flags)
diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
index 7e70e7258d2..fc3443aba5e 100644
--- a/src/plugins/platforms/xcb/qxcbkeyboard.cpp
+++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp
@@ -841,8 +841,8 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
xkb_layout_index_t baseLayout = xkb_state_serialize_layout(xkb_state, XKB_STATE_LAYOUT_DEPRESSED);
xkb_layout_index_t latchedLayout = xkb_state_serialize_layout(xkb_state, XKB_STATE_LAYOUT_LATCHED);
xkb_layout_index_t lockedLayout = xkb_state_serialize_layout(xkb_state, XKB_STATE_LAYOUT_LOCKED);
- xkb_mod_index_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED);
- xkb_mod_index_t lockedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED);
+ xkb_mod_mask_t latchedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LATCHED);
+ xkb_mod_mask_t lockedMods = xkb_state_serialize_mods(xkb_state, XKB_STATE_MODS_LOCKED);
xkb_state_update_mask(kb_state, 0, latchedMods, lockedMods,
baseLayout, latchedLayout, lockedLayout);
@@ -861,6 +861,10 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
xkb_mod_index_t altMod = xkb_keymap_mod_get_index(xkb_keymap, "Alt");
xkb_mod_index_t controlMod = xkb_keymap_mod_get_index(xkb_keymap, "Control");
+ Q_ASSERT(shiftMod < 32);
+ Q_ASSERT(altMod < 32);
+ Q_ASSERT(controlMod < 32);
+
xkb_mod_mask_t depressed;
struct xkb_keymap *fallback_keymap = 0;
int qtKey = 0;
@@ -903,7 +907,7 @@ QList<int> QXcbKeyboard::possibleKeys(const QKeyEvent *event) const
Qt::KeyboardModifiers mods = modifiers & ~neededMods;
qtKey = keysymToQtKey(sym, mods, lookupString(kb_state, event->nativeScanCode()));
- if (qtKey == baseQtKey)
+ if (qtKey == baseQtKey || qtKey == 0)
continue;
result += (qtKey + mods);
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index c4cf3b44165..0c2e9d047c5 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -251,6 +251,27 @@ QXcbWindow::QXcbWindow(QWindow *window)
m_window = window->winId();
}
+#ifdef Q_COMPILER_CLASS_ENUM
+enum : quint32 {
+#else
+enum {
+#endif
+ baseEventMask
+ = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_STRUCTURE_NOTIFY
+ | XCB_EVENT_MASK_PROPERTY_CHANGE | XCB_EVENT_MASK_FOCUS_CHANGE,
+
+ defaultEventMask = baseEventMask
+ | XCB_EVENT_MASK_KEY_PRESS | XCB_EVENT_MASK_KEY_RELEASE
+ | XCB_EVENT_MASK_BUTTON_PRESS | XCB_EVENT_MASK_BUTTON_RELEASE
+ | XCB_EVENT_MASK_BUTTON_MOTION | XCB_EVENT_MASK_ENTER_WINDOW | XCB_EVENT_MASK_LEAVE_WINDOW
+ | XCB_EVENT_MASK_POINTER_MOTION,
+
+ transparentForInputEventMask = baseEventMask
+ | XCB_EVENT_MASK_VISIBILITY_CHANGE | XCB_EVENT_MASK_RESIZE_REDIRECT
+ | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
+ | XCB_EVENT_MASK_COLOR_MAP_CHANGE | XCB_EVENT_MASK_OWNER_GRAB_BUTTON
+};
+
void QXcbWindow::create()
{
destroy();
@@ -285,18 +306,7 @@ void QXcbWindow::create()
// XCB_CW_SAVE_UNDER
type == Qt::Popup || type == Qt::Tool || type == Qt::SplashScreen || type == Qt::ToolTip || type == Qt::Drawer,
// XCB_CW_EVENT_MASK
- XCB_EVENT_MASK_EXPOSURE
- | XCB_EVENT_MASK_STRUCTURE_NOTIFY
- | XCB_EVENT_MASK_KEY_PRESS
- | XCB_EVENT_MASK_KEY_RELEASE
- | XCB_EVENT_MASK_BUTTON_PRESS
- | XCB_EVENT_MASK_BUTTON_RELEASE
- | XCB_EVENT_MASK_BUTTON_MOTION
- | XCB_EVENT_MASK_ENTER_WINDOW
- | XCB_EVENT_MASK_LEAVE_WINDOW
- | XCB_EVENT_MASK_POINTER_MOTION
- | XCB_EVENT_MASK_PROPERTY_CHANGE
- | XCB_EVENT_MASK_FOCUS_CHANGE
+ defaultEventMask
};
// Parameters to XCreateWindow() are frame corner + inner size.
@@ -985,14 +995,15 @@ void QXcbWindow::setWindowFlags(Qt::WindowFlags flags)
if (type == Qt::Popup)
flags |= Qt::X11BypassWindowManagerHint;
- if (flags & Qt::WindowTransparentForInput) {
- uint32_t mask = XCB_EVENT_MASK_EXPOSURE | XCB_EVENT_MASK_VISIBILITY_CHANGE
- | XCB_EVENT_MASK_STRUCTURE_NOTIFY | XCB_EVENT_MASK_RESIZE_REDIRECT
- | XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT
- | XCB_EVENT_MASK_FOCUS_CHANGE | XCB_EVENT_MASK_PROPERTY_CHANGE
- | XCB_EVENT_MASK_COLOR_MAP_CHANGE | XCB_EVENT_MASK_OWNER_GRAB_BUTTON;
- xcb_change_window_attributes(xcb_connection(), xcb_window(), XCB_CW_EVENT_MASK, &mask);
- }
+ const quint32 mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_EVENT_MASK;
+ const quint32 values[] = {
+ // XCB_CW_OVERRIDE_REDIRECT
+ (flags & Qt::BypassWindowManagerHint) ? 1u : 0,
+ // XCB_CW_EVENT_MASK
+ (flags & Qt::WindowTransparentForInput) ? transparentForInputEventMask : defaultEventMask
+ };
+
+ xcb_change_window_attributes(xcb_connection(), xcb_window(), mask, values);
setNetWmWindowFlags(flags);
setMotifWindowFlags(flags);
diff --git a/src/testlib/qbenchmarkvalgrind.cpp b/src/testlib/qbenchmarkvalgrind.cpp
index c4807536751..f107645ab52 100644
--- a/src/testlib/qbenchmarkvalgrind.cpp
+++ b/src/testlib/qbenchmarkvalgrind.cpp
@@ -45,33 +45,15 @@
QT_BEGIN_NAMESPACE
-// Returns \c true iff a sufficiently recent valgrind is available.
+// Returns \c true if valgrind is available.
bool QBenchmarkValgrindUtils::haveValgrind()
{
#ifdef NVALGRIND
return false;
#else
QProcess process;
- QStringList args;
- args << QLatin1String("--version");
- process.start(QLatin1String("valgrind"), args);
- if (!process.waitForFinished(-1))
- return false;
- const QByteArray out = process.readAllStandardOutput();
- QRegExp rx(QLatin1String("^valgrind-([0-9]+).([0-9]+).[0-9]+"));
- if (rx.indexIn(QLatin1String(out.data())) == -1)
- return false;
- bool ok;
- const int major = rx.cap(1).toInt(&ok);
- if (!ok)
- return false;
- const int minor = rx.cap(2).toInt(&ok);
- if (!ok)
- return false;
-// return (major > 3 || (major == 3 && minor >= 3)); // v >= 3.3 for --callgrind-out-file option
- Q_UNUSED(major);
- Q_UNUSED(minor);
- return true; // skip version restriction for now
+ process.start(QLatin1String("valgrind"), QStringList(QLatin1String("--version")));
+ return process.waitForStarted() && process.waitForFinished(-1);
#endif
}
diff --git a/src/tools/qdoc/qdocdatabase.cpp b/src/tools/qdoc/qdocdatabase.cpp
index 4b4c88a1766..51908bc9e30 100644
--- a/src/tools/qdoc/qdocdatabase.cpp
+++ b/src/tools/qdoc/qdocdatabase.cpp
@@ -1264,11 +1264,11 @@ void QDocDatabase::findAllSince(InnerNode* node)
nsmap.value().insert(name,(*child));
}
}
- // Recursively find child nodes with since commands.
- if ((*child)->isInnerNode()) {
- findAllSince(static_cast<InnerNode *>(*child));
- }
}
+ // Recursively find child nodes with since commands.
+ if ((*child)->isInnerNode())
+ findAllSince(static_cast<InnerNode *>(*child));
+
++child;
}
}
diff --git a/src/tools/rcc/rcc.cpp b/src/tools/rcc/rcc.cpp
index 6d4cc12d5c9..11a99d136da 100644
--- a/src/tools/rcc/rcc.cpp
+++ b/src/tools/rcc/rcc.cpp
@@ -610,11 +610,18 @@ bool RCCResourceLibrary::addFile(const QString &alias, const RCCFileInfo &file)
const QString filename = nodes.at(nodes.size()-1);
RCCFileInfo *s = new RCCFileInfo(file);
s->m_parent = parent;
- if (parent->m_children.contains(filename)) {
- foreach (const QString &fileName, m_fileNames)
- qWarning("%s: Warning: potential duplicate alias detected: '%s'",
- qPrintable(fileName), qPrintable(filename));
+ typedef QHash<QString, RCCFileInfo*>::const_iterator ChildConstIterator;
+ const ChildConstIterator cbegin = parent->m_children.constFind(filename);
+ const ChildConstIterator cend = parent->m_children.constEnd();
+ for (ChildConstIterator it = cbegin; it != cend; ++it) {
+ if (it.key() == filename && it.value()->m_language == s->m_language &&
+ it.value()->m_country == s->m_country) {
+ foreach (const QString &name, m_fileNames)
+ qWarning("%s: Warning: potential duplicate alias detected: '%s'",
+ qPrintable(name), qPrintable(filename));
+ break;
}
+ }
parent->m_children.insertMulti(filename, s);
return true;
}
diff --git a/src/widgets/itemviews/qabstractitemview.cpp b/src/widgets/itemviews/qabstractitemview.cpp
index e20ad654413..3fbb17ff3fa 100644
--- a/src/widgets/itemviews/qabstractitemview.cpp
+++ b/src/widgets/itemviews/qabstractitemview.cpp
@@ -2405,12 +2405,11 @@ void QAbstractItemView::keyPressEvent(QKeyEvent *event)
}
break;
#endif
- case Qt::Key_A:
- if (event->modifiers() & Qt::ControlModifier) {
+ default: {
+ if (event == QKeySequence::SelectAll && selectionMode() != NoSelection) {
selectAll();
break;
}
- default: {
#ifdef Q_WS_MAC
if (event->key() == Qt::Key_O && event->modifiers() & Qt::ControlModifier && currentIndex().isValid()) {
emit activated(currentIndex());
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
index 543f59d7d1b..8a4e0c8ffdd 100644
--- a/src/widgets/kernel/qopenglwidget.cpp
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -45,6 +45,7 @@
#include <QtGui/private/qguiapplication_p.h>
#include <QtGui/private/qopenglextensions_p.h>
#include <QtGui/private/qfont_p.h>
+#include <QtGui/private/qopenglpaintdevice_p.h>
#include <QtWidgets/private/qwidget_p.h>
QT_BEGIN_NAMESPACE
@@ -239,6 +240,28 @@ QT_BEGIN_NAMESPACE
\note Avoid calling winId() on a QOpenGLWidget. This function triggers the creation of
a native window, resulting in reduced performance and possibly rendering glitches.
+ \section1 Differences to QGLWidget
+
+ Besides the main conceptual difference of being backed by a framebuffer object, there
+ are a number of smaller, internal differences between QOpenGLWidget and the older
+ QGLWidget:
+
+ \list
+
+ \li OpenGL state when invoking paintGL(). QOpenGLWidget sets up the viewport via
+ glViewport(). It does not perform any clearing.
+
+ \li Clearing when starting to paint via QPainter. Unlike regular widgets, QGLWidget
+ defaulted to a value of \c true for
+ \l{QWidget::autoFillBackground()}{autoFillBackground}. It then performed clearing to the
+ palette's background color every time QPainter::begin() was used. QOpenGLWidget does not
+ follow this: \l{QWidget::autoFillBackground()}{autoFillBackground} defaults to false,
+ like for any other widget. The only exception is when being used as a viewport for other
+ widgets like QGraphicsView. In such a case autoFillBackground will be automatically set
+ to true to ensure compatibility with QGLWidget-based viewports.
+
+ \endlist
+
\section1 Multisampling
To enable multisampling, set the number of requested samples on the
@@ -432,16 +455,26 @@ QT_BEGIN_NAMESPACE
due to resizing the widget.
*/
-class QOpenGLWidgetPaintDevice : public QOpenGLPaintDevice
+class QOpenGLWidgetPaintDevicePrivate : public QOpenGLPaintDevicePrivate
{
public:
- QOpenGLWidgetPaintDevice(QOpenGLWidget *widget) : w(widget) { }
- void ensureActiveTarget() Q_DECL_OVERRIDE;
+ QOpenGLWidgetPaintDevicePrivate(QOpenGLWidget *widget)
+ : QOpenGLPaintDevicePrivate(QSize()),
+ w(widget) { }
+
+ void beginPaint() Q_DECL_OVERRIDE;
-private:
QOpenGLWidget *w;
};
+class QOpenGLWidgetPaintDevice : public QOpenGLPaintDevice
+{
+public:
+ QOpenGLWidgetPaintDevice(QOpenGLWidget *widget)
+ : QOpenGLPaintDevice(new QOpenGLWidgetPaintDevicePrivate(widget)) { }
+ void ensureActiveTarget() Q_DECL_OVERRIDE;
+};
+
class QOpenGLWidgetPrivate : public QWidgetPrivate
{
Q_DECLARE_PUBLIC(QOpenGLWidget)
@@ -454,7 +487,8 @@ public:
initialized(false),
fakeHidden(false),
paintDevice(0),
- inBackingStorePaint(false)
+ inBackingStorePaint(false),
+ flushPending(false)
{
requestedFormat = QSurfaceFormat::defaultFormat();
}
@@ -478,6 +512,7 @@ public:
void endBackingStorePainting() Q_DECL_OVERRIDE { inBackingStorePaint = false; }
void beginCompose() Q_DECL_OVERRIDE;
void endCompose() Q_DECL_OVERRIDE;
+ void initializeViewportFramebuffer() Q_DECL_OVERRIDE;
void resizeViewportFramebuffer() Q_DECL_OVERRIDE;
void resolveSamples() Q_DECL_OVERRIDE;
@@ -490,22 +525,54 @@ public:
QOpenGLPaintDevice *paintDevice;
bool inBackingStorePaint;
QSurfaceFormat requestedFormat;
+ bool flushPending;
};
+void QOpenGLWidgetPaintDevicePrivate::beginPaint()
+{
+ // NB! autoFillBackground is and must be false by default. Otherwise we would clear on
+ // every QPainter begin() which is not desirable. This is only for legacy use cases,
+ // like using QOpenGLWidget as the viewport of a graphics view, that expect clearing
+ // with the palette's background color.
+ if (w->autoFillBackground()) {
+ QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
+ if (w->testAttribute(Qt::WA_TranslucentBackground)) {
+ f->glClearColor(0, 0, 0, 0);
+ } else {
+ QColor c = w->palette().brush(w->backgroundRole()).color();
+ float alpha = c.alphaF();
+ f->glClearColor(c.redF() * alpha, c.greenF() * alpha, c.blueF() * alpha, alpha);
+ }
+ f->glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
+ }
+}
+
void QOpenGLWidgetPaintDevice::ensureActiveTarget()
{
- QOpenGLWidgetPrivate *d = static_cast<QOpenGLWidgetPrivate *>(QWidgetPrivate::get(w));
- if (!d->initialized)
+ QOpenGLWidgetPaintDevicePrivate *d = static_cast<QOpenGLWidgetPaintDevicePrivate *>(d_ptr.data());
+ QOpenGLWidgetPrivate *wd = static_cast<QOpenGLWidgetPrivate *>(QWidgetPrivate::get(d->w));
+ if (!wd->initialized)
return;
- if (QOpenGLContext::currentContext() != d->context)
- w->makeCurrent();
+ if (QOpenGLContext::currentContext() != wd->context)
+ d->w->makeCurrent();
else
- d->fbo->bind();
+ wd->fbo->bind();
+
+ // When used as a viewport, drawing is done via opening a QPainter on the widget
+ // without going through paintEvent(). We will have to make sure a glFlush() is done
+ // before the texture is accessed also in this case.
+ wd->flushPending = true;
}
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::AA_DontCreateNativeWidgetAncestors and Siblings.";
+ return 0;
+ }
return resolvedFbo ? resolvedFbo->texture() : (fbo ? fbo->texture() : 0);
}
@@ -566,6 +633,11 @@ void QOpenGLWidgetPrivate::recreateFbo()
void QOpenGLWidgetPrivate::beginCompose()
{
Q_Q(QOpenGLWidget);
+ if (flushPending) {
+ flushPending = false;
+ q->makeCurrent();
+ context->functions()->glFlush();
+ }
emit q->aboutToCompose();
}
@@ -647,9 +719,10 @@ void QOpenGLWidgetPrivate::invokeUserPaint()
{
Q_Q(QOpenGLWidget);
QOpenGLFunctions *f = QOpenGLContext::currentContext()->functions();
- f->glViewport(0, 0, q->width() * q->devicePixelRatio(), q->height() * q->devicePixelRatio());
+ f->glViewport(0, 0, q->width() * q->devicePixelRatio(), q->height() * q->devicePixelRatio());
q->paintGL();
+ f->glFlush();
}
void QOpenGLWidgetPrivate::render()
@@ -661,7 +734,6 @@ void QOpenGLWidgetPrivate::render()
q->makeCurrent();
invokeUserPaint();
- context->functions()->glFlush();
}
extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);
@@ -680,6 +752,14 @@ QImage QOpenGLWidgetPrivate::grabFramebuffer()
return res;
}
+void QOpenGLWidgetPrivate::initializeViewportFramebuffer()
+{
+ Q_Q(QOpenGLWidget);
+ // Legacy behavior for compatibility with QGLWidget when used as a graphics view
+ // viewport: enable clearing on each painter begin.
+ q->setAutoFillBackground(true);
+}
+
void QOpenGLWidgetPrivate::resizeViewportFramebuffer()
{
Q_Q(QOpenGLWidget);
@@ -923,7 +1003,6 @@ void QOpenGLWidget::resizeEvent(QResizeEvent *e)
d->recreateFbo();
resizeGL(width(), height());
d->invokeUserPaint();
- d->context->functions()->glFlush();
d->resolveSamples();
}
diff --git a/src/widgets/kernel/qsizepolicy.h b/src/widgets/kernel/qsizepolicy.h
index 9730ec12068..41adf5c58a1 100644
--- a/src/widgets/kernel/qsizepolicy.h
+++ b/src/widgets/kernel/qsizepolicy.h
@@ -150,6 +150,10 @@ private:
quint32 data;
};
};
+#if QT_VERSION >= QT_VERSION_CHECK(6,0,0)
+// Can't add in Qt 5, as QList<QSizePolicy> would be BiC:
+Q_DECLARE_TYPEINFO(QSizePolicy, Q_PRIMITIVE_TYPE);
+#endif
Q_DECLARE_OPERATORS_FOR_FLAGS(QSizePolicy::ControlTypes)
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 00cf39bdbfe..af1745d845f 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -6543,10 +6543,15 @@ void QWidget::clearFocus()
QWidget *w = this;
while (w) {
+ // Just like setFocus(), we update (clear) the focus_child of our parents
if (w->d_func()->focus_child == this)
w->d_func()->focus_child = 0;
w = w->parentWidget();
}
+ // Since focus_child is the basis for the top level QWidgetWindow's focusObject()
+ // we need to report this change to the rest of Qt, but we match setFocus() and
+ // do it at the end of the function.
+
#ifndef QT_NO_GRAPHICSVIEW
QWExtra *topData = d_func()->extra;
if (topData && topData->proxyWidget)
@@ -6567,11 +6572,15 @@ void QWidget::clearFocus()
QAccessible::updateAccessibility(&event);
#endif
}
+ }
- if (QTLWExtra *extra = window()->d_func()->maybeTopData()) {
- if (extra->window)
- emit extra->window->focusObjectChanged(extra->window->focusObject());
- }
+ // Since we've unconditionally cleared the focus_child of our parents, we need
+ // to report this to the rest of Qt. Note that the focus_child is not the same
+ // thing as the application's focusWidget, which is why this piece of code is
+ // not inside the hasFocus() block above.
+ if (QTLWExtra *extra = window()->d_func()->maybeTopData()) {
+ if (extra->window)
+ emit extra->window->focusObjectChanged(extra->window->focusObject());
}
}
@@ -9686,7 +9695,8 @@ void QWidget::setInputMethodHints(Qt::InputMethodHints hints)
if (d->imHints == hints)
return;
d->imHints = hints;
- qApp->inputMethod()->update(Qt::ImHints);
+ if (this == qApp->focusObject())
+ qApp->inputMethod()->update(Qt::ImHints);
#endif //QT_NO_IM
}
@@ -11029,7 +11039,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
d->createTLSysExtra();
#ifndef QT_NO_IM
QWidget *focusWidget = d->effectiveFocusWidget();
- if (on && !internalWinId() && hasFocus()
+ if (on && !internalWinId() && this == qApp->focusObject()
&& focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
qApp->inputMethod()->commit();
qApp->inputMethod()->update(Qt::ImEnabled);
@@ -11038,7 +11048,7 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on)
parentWidget()->d_func()->enforceNativeChildren();
if (on && !internalWinId() && testAttribute(Qt::WA_WState_Created))
d->createWinId();
- if (isEnabled() && focusWidget->isEnabled()
+ if (isEnabled() && focusWidget->isEnabled() && this == qApp->focusObject()
&& focusWidget->testAttribute(Qt::WA_InputMethodEnabled)) {
qApp->inputMethod()->update(Qt::ImEnabled);
}
@@ -11564,7 +11574,8 @@ void QWidget::setShortcutAutoRepeat(int id, bool enable)
void QWidget::updateMicroFocus()
{
// updating everything since this is currently called for any kind of state change
- qApp->inputMethod()->update(Qt::ImQueryAll);
+ if (this == qApp->focusObject())
+ qApp->inputMethod()->update(Qt::ImQueryAll);
}
/*!
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index 75a60fe3c44..d5a91f18d6b 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -641,6 +641,8 @@ public:
}
}
static void sendComposeStatus(QWidget *w, bool end);
+ // Called on setViewport().
+ virtual void initializeViewportFramebuffer() { }
// When using a QOpenGLWidget as viewport with QAbstractScrollArea, resize events are
// filtered away from the widget. This is fine for QGLWidget but bad for QOpenGLWidget
// since the fbo must be resized. We need an alternative way to notify.
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index cd57c1611e4..d40fc84d778 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -73,8 +73,10 @@ public:
void clearFocusObject()
{
- if (QApplicationPrivate::focus_widget)
- QApplicationPrivate::focus_widget->clearFocus();
+ Q_Q(QWidgetWindow);
+ QWidget *widget = q->widget();
+ if (widget && widget->focusWidget())
+ widget->focusWidget()->clearFocus();
}
};
diff --git a/src/widgets/styles/qfusionstyle.cpp b/src/widgets/styles/qfusionstyle.cpp
index 142bd5882e1..ef3795c9a11 100644
--- a/src/widgets/styles/qfusionstyle.cpp
+++ b/src/widgets/styles/qfusionstyle.cpp
@@ -3099,7 +3099,8 @@ int QFusionStyle::pixelMetric(PixelMetric metric, const QStyleOption *option, co
val = 2;
break;
case PM_SubMenuOverlap:
- return -1; // Do not dpi-scale because the value is magic
+ val = -1;
+ break;
case PM_DockWidgetHandleExtent:
case PM_SplitterWidth:
val = 4;
diff --git a/src/widgets/styles/qmacstyle_mac.mm b/src/widgets/styles/qmacstyle_mac.mm
index a4838d57774..090716f7f9e 100644
--- a/src/widgets/styles/qmacstyle_mac.mm
+++ b/src/widgets/styles/qmacstyle_mac.mm
@@ -1113,9 +1113,9 @@ static QAquaWidgetSize qt_aqua_guess_size(const QWidget *widg, QSize large, QSiz
static void qt_drawFocusRingOnPath(CGContextRef cg, NSBezierPath *focusRingPath)
{
CGContextSaveGState(cg);
+ [NSGraphicsContext saveGraphicsState];
[NSGraphicsContext setCurrentContext:[NSGraphicsContext
graphicsContextWithGraphicsPort:(CGContextRef)cg flipped:NO]];
- [NSGraphicsContext saveGraphicsState];
NSSetFocusRingStyle(NSFocusRingOnly);
[focusRingPath setClip]; // Clear clip path to avoid artifacts when rendering the cursor at zero pos
[focusRingPath fill];
@@ -1661,10 +1661,34 @@ void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti
tdi->kind = kThemeSmallSlider;
break;
}
+
+ bool usePlainKnob = slider->tickPosition == QSlider::NoTicks
+ || slider->tickPosition == QSlider::TicksBothSides;
+
tdi->bounds = qt_hirectForQRect(slider->rect);
- tdi->min = slider->minimum;
- tdi->max = slider->maximum;
- tdi->value = slider->sliderPosition;
+ if (isScrollbar || QSysInfo::MacintoshVersion <= QSysInfo::MV_10_9) {
+ tdi->min = slider->minimum;
+ tdi->max = slider->maximum;
+ tdi->value = slider->sliderPosition;
+ } else {
+ // Fix min and max positions. HITheme seems confused when it comes to rendering
+ // a slider at those positions. We give it a hand by extending and offsetting
+ // the slider range accordingly. See also comment for CC_Slider in drawComplexControl()
+ tdi->min = 0;
+ if (slider->orientation == Qt::Horizontal)
+ tdi->max = 10 * slider->rect.width();
+ else
+ tdi->max = 10 * slider->rect.height();
+
+ if (usePlainKnob || slider->orientation == Qt::Horizontal) {
+ int endsCorrection = usePlainKnob ? 25 : 10;
+ tdi->value = (tdi->max + 2 * endsCorrection) * (slider->sliderPosition - slider->minimum)
+ / (slider->maximum - slider->minimum) - endsCorrection;
+ } else {
+ tdi->value = (tdi->max + 30) * (slider->sliderPosition - slider->minimum)
+ / (slider->maximum - slider->minimum) - 20;
+ }
+ }
tdi->attributes = kThemeTrackShowThumb;
if (slider->upsideDown)
tdi->attributes |= kThemeTrackRightToLeft;
@@ -1681,7 +1705,7 @@ void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti
// Tiger broke reverse scroll bars so put them back and "fake it"
if (isScrollbar && (tdi->attributes & kThemeTrackRightToLeft)) {
tdi->attributes &= ~kThemeTrackRightToLeft;
- tdi->value = tdi->max - slider->sliderPosition;
+ tdi->value = tdi->max - tdi->value;
}
tdi->enableState = (slider->state & QStyle::State_Enabled) ? kThemeTrackActive
@@ -1689,7 +1713,7 @@ void QMacStylePrivate::getSliderInfo(QStyle::ComplexControl cc, const QStyleOpti
if (!isScrollbar) {
if (slider->state & QStyle::QStyle::State_HasFocus)
tdi->attributes |= kThemeTrackHasFocus;
- if (slider->tickPosition == QSlider::NoTicks || slider->tickPosition == QSlider::TicksBothSides)
+ if (usePlainKnob)
tdi->trackInfo.slider.thumbDir = kThemeThumbPlain;
else if (slider->tickPosition == QSlider::TicksAbove)
tdi->trackInfo.slider.thumbDir = kThemeThumbUpward;
@@ -1811,10 +1835,17 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget, QPoint *offset) cons
NSView *bv = cocoaControls[widget];
if (!bv) {
- if (widget.first == QCocoaPopupButton)
+ if (widget.first == QCocoaPopupButton
+ || widget.first == QCocoaPullDownButton)
bv = [[NSPopUpButton alloc] init];
else if (widget.first == QCocoaComboBox)
bv = [[NSComboBox alloc] init];
+ else if (widget.first == QCocoaHorizontalSlider)
+ bv = [[NSSlider alloc] init];
+ else if (widget.first == QCocoaVerticalSlider)
+ // Cocoa sets the orientation from the view's frame
+ // at construction time, and it cannot be changed later.
+ bv = [[NSSlider alloc] initWithFrame:NSMakeRect(0, 0, 10, 100)];
else
bv = [[NSButton alloc] init];
@@ -1841,6 +1872,11 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget, QPoint *offset) cons
bc.bezelStyle = NSRoundedBezelStyle;
break;
}
+ case QCocoaPullDownButton: {
+ NSPopUpButton *bc = (NSPopUpButton *)bv;
+ bc.pullsDown = YES;
+ break;
+ }
default:
break;
}
@@ -1883,12 +1919,18 @@ NSView *QMacStylePrivate::cocoaControl(QCocoaWidget widget, QPoint *offset) cons
*offset = QPoint(7, 5);
else if (widget == QCocoaWidget(QCocoaPopupButton, QAquaSizeMini))
*offset = QPoint(2, -1);
+ else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeLarge))
+ *offset = QPoint(3, -1);
+ else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeSmall))
+ *offset = QPoint(2, 1);
+ else if (widget == QCocoaWidget(QCocoaPullDownButton, QAquaSizeMini))
+ *offset = QPoint(5, 0);
}
return bv;
}
-void QMacStylePrivate::drawNSViewInRect(NSView *view, const QRect &qtRect, QPainter *p) const
+void QMacStylePrivate::drawNSViewInRect(NSView *view, const QRect &qtRect, QPainter *p, QCocoaDrawRectBlock drawRectBlock) const
{
QMacCGContext ctx(p);
CGContextSaveGState(ctx);
@@ -1897,11 +1939,14 @@ void QMacStylePrivate::drawNSViewInRect(NSView *view, const QRect &qtRect, QPain
[NSGraphicsContext setCurrentContext:[NSGraphicsContext
graphicsContextWithGraphicsPort:ctx flipped:YES]];
- CGRect rect = CGRectMake(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height());
+ NSRect rect = NSMakeRect(qtRect.x() + 1, qtRect.y(), qtRect.width(), qtRect.height());
[backingStoreNSView addSubview:view];
- view.frame = NSRectFromCGRect(rect);
- [view drawRect:NSRectFromCGRect(rect)];
+ view.frame = rect;
+ if (drawRectBlock)
+ drawRectBlock(rect, (CGContextRef)ctx);
+ else
+ [view drawRect:rect];
[view removeFromSuperviewWithoutNeedingDisplay];
[NSGraphicsContext restoreGraphicsState];
@@ -3828,21 +3873,24 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
else if (d->pressedButton == opt->styleObject)
d->pressedButton = 0;
+ bool hasMenu = btn->features & QStyleOptionButton::HasMenu;
HIThemeButtonDrawInfo bdi;
d->initHIThemePushButton(btn, w, tds, &bdi);
if (yosemiteOrLater) {
- // HITheme is not drawing a nice focus frame around buttons.
- // We'll do it ourselves further down.
- bdi.adornment &= ~kThemeAdornmentFocus;
-
- // We can't rely on an animation existing to test for the default look. That means a bit
- // more logic (notice that the logic is slightly different for the bevel and the label).
- if (tds == kThemeStateActive
- && (btn->features & QStyleOptionButton::DefaultButton
- || (btn->features & QStyleOptionButton::AutoDefaultButton
- && d->autoDefaultButton == btn->styleObject)))
- bdi.adornment |= kThemeAdornmentDefault;
+ if (!hasMenu) {
+ // HITheme is not drawing a nice focus frame around buttons.
+ // We'll do it ourselves further down.
+ bdi.adornment &= ~kThemeAdornmentFocus;
+
+ // We can't rely on an animation existing to test for the default look. That means a bit
+ // more logic (notice that the logic is slightly different for the bevel and the label).
+ if (tds == kThemeStateActive
+ && (btn->features & QStyleOptionButton::DefaultButton
+ || (btn->features & QStyleOptionButton::AutoDefaultButton
+ && d->autoDefaultButton == btn->styleObject)))
+ bdi.adornment |= kThemeAdornmentDefault;
+ }
} else {
// the default button animation is paused meanwhile any button
// is pressed or an auto-default button is animated instead
@@ -3882,8 +3930,18 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
newRect.size.width -= QMacStylePrivate::PushButtonRightOffset - 4;
}
- bool hasMenu = btn->features & QStyleOptionButton::HasMenu;
- if (hasMenu && bdi.state == kThemeStatePressed && QSysInfo::macVersion() > QSysInfo::MV_10_6)
+ if (hasMenu && yosemiteOrLater && bdi.kind != kThemeBevelButton) {
+ QCocoaWidget w = cocoaWidgetFromHIThemeButtonKind(bdi.kind);
+ QPoint offset;
+ NSPopUpButton *pdb = (NSPopUpButton *)d->cocoaControl(QCocoaWidget(QCocoaPullDownButton, w.second), &offset);
+ [pdb highlight:(bdi.state == kThemeStatePressed)];
+ pdb.enabled = bdi.state != kThemeStateUnavailable && bdi.state != kThemeStateUnavailableInactive;
+ QRect rect = opt->rect;
+ rect.adjust(0, 0, w.second == QAquaSizeSmall ? -4 : w.second == QAquaSizeMini ? -9 : -6, 0);
+ p->translate(offset);
+ d->drawNSViewInRect(pdb, rect, p);
+ p->translate(-offset);
+ } else if (hasMenu && bdi.state == kThemeStatePressed && QSysInfo::macVersion() > QSysInfo::MV_10_6)
d->drawColorlessButton(newRect, &bdi, p, opt);
else
HIThemeDrawButton(&newRect, &bdi, cg, kHIThemeOrientationNormal, 0);
@@ -3919,7 +3977,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
qt_drawFocusRingOnPath(cg, pushButtonFocusRingPath);
}
- if (hasMenu) {
+ if (hasMenu && (!yosemiteOrLater || bdi.kind == kThemeBevelButton)) {
int mbi = proxy()->pixelMetric(QStyle::PM_MenuButtonIndicator, btn, w);
QRect ir = btn->rect;
int arrowXOffset = 0;
@@ -3973,7 +4031,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter
bool hasIcon = !btn.icon.isNull();
bool hasText = !btn.text.isEmpty();
- if (QSysInfo::QSysInfo::MacintoshVersion > QSysInfo::MV_10_9) {
+ if (!hasMenu && QSysInfo::QSysInfo::MacintoshVersion > QSysInfo::MV_10_9) {
if (tds == kThemeStatePressed
|| (tds == kThemeStateActive
&& ((btn.features & QStyleOptionButton::DefaultButton && !d->autoDefaultButton)
@@ -5325,6 +5383,7 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
// because on Tiger I only "fake" the reverse stuff.
bool reverseHorizontal = (slider->direction == Qt::RightToLeft
&& slider->orientation == Qt::Horizontal);
+
if ((reverseHorizontal
&& slider->activeSubControls == SC_ScrollBarAddLine)
|| (!reverseHorizontal
@@ -5375,6 +5434,9 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
tdi.attributes |= kThemeTrackHideTrack;
}
+ const bool usingYosemiteOrLater = QSysInfo::MacintoshVersion > QSysInfo::MV_10_9;
+ const bool isHorizontal = slider->orientation == Qt::Horizontal;
+
#if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_7
if (cc == CC_ScrollBar && proxy()->styleHint(SH_ScrollBar_Transient, opt, widget)) {
bool wasActive = false;
@@ -5459,8 +5521,6 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
}
}
- const bool isHorizontal = slider->orientation == Qt::Horizontal;
-
CGContextSaveGState(cg);
[NSGraphicsContext saveGraphicsState];
@@ -5545,9 +5605,86 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
{
d->stopAnimation(opt->styleObject);
- HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg,
- kHIThemeOrientationNormal);
+ if (usingYosemiteOrLater && cc == CC_Slider) {
+ // Fix min and max positions. (See also getSliderInfo()
+ // for the slider values adjustments.)
+ // HITheme seems to have forgotten how to render
+ // a slide at those positions, leaving a gap between
+ // the knob and the ends of the track.
+ // We fix this by rendering the track first, and then
+ // the knob on top. However, in order to not clip the
+ // knob, we reduce the the drawing rect for the track.
+ HIRect bounds = tdi.bounds;
+ if (isHorizontal) {
+ tdi.bounds.size.width -= 2;
+ tdi.bounds.origin.x += 1;
+ if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward)
+ tdi.bounds.origin.y -= 2;
+ else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward)
+ tdi.bounds.origin.y += 3;
+ } else {
+ tdi.bounds.size.height -= 2;
+ tdi.bounds.origin.y += 1;
+ if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) // pointing right
+ tdi.bounds.origin.x -= 4;
+ else if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left
+ tdi.bounds.origin.x += 2;
+ }
+
+ // Yosemite demands its blue progress track when no tickmarks are present
+ if (!(slider->subControls & SC_SliderTickmarks)) {
+ QCocoaWidgetKind sliderKind = slider->orientation == Qt::Horizontal ? QCocoaHorizontalSlider : QCocoaVerticalSlider;
+ NSSlider *sl = (NSSlider *)d->cocoaControl(QCocoaWidget(sliderKind, QAquaSizeLarge), 0);
+ sl.minValue = slider->minimum;
+ sl.maxValue = slider->maximum;
+ sl.intValue = slider->sliderValue;
+ sl.enabled = slider->state & QStyle::State_Enabled;
+ d->drawNSViewInRect(sl, opt->rect, p, ^(NSRect rect, CGContextRef ctx) {
+ if (slider->upsideDown) {
+ if (isHorizontal) {
+ CGContextTranslateCTM(ctx, rect.size.width, 0);
+ CGContextScaleCTM(ctx, -1, 1);
+ }
+ } else if (!isHorizontal) {
+ CGContextTranslateCTM(ctx, 0, rect.size.height);
+ CGContextScaleCTM(ctx, 1, -1);
+ }
+ [sl.cell drawBarInside:tdi.bounds flipped:NO];
+ // No need to restore the CTM later, the context has been saved
+ // and will be restored at the end of drawNSViewInRect()
+ });
+ tdi.attributes |= kThemeTrackHideTrack;
+ } else {
+ tdi.attributes &= ~(kThemeTrackShowThumb | kThemeTrackHasFocus);
+ HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg,
+ kHIThemeOrientationNormal);
+ tdi.attributes |= kThemeTrackHideTrack | kThemeTrackShowThumb;
+ }
+
+ tdi.bounds = bounds;
+ }
+
if (cc == CC_Slider && slider->subControls & SC_SliderTickmarks) {
+
+ HIRect bounds;
+ if (usingYosemiteOrLater) {
+ // As part of fixing the min and max positions,
+ // we need to adjust the tickmarks as well
+ bounds = tdi.bounds;
+ if (slider->orientation == Qt::Horizontal) {
+ tdi.bounds.size.width += 2;
+ tdi.bounds.origin.x -= 1;
+ if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward)
+ tdi.bounds.origin.y -= 2;
+ } else {
+ tdi.bounds.size.height += 3;
+ tdi.bounds.origin.y -= 3;
+ tdi.bounds.origin.y += 1;
+ if (tdi.trackInfo.slider.thumbDir == kThemeThumbUpward) // pointing left
+ tdi.bounds.origin.x -= 2;
+ }
+ }
+
if (qt_mac_is_metal(widget)) {
if (tdi.enableState == kThemeTrackInactive)
tdi.enableState = kThemeTrackActive; // Looks more Cocoa-like
@@ -5569,16 +5706,37 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
cg,
kHIThemeOrientationNormal);
tdi.trackInfo.slider.thumbDir = kThemeThumbUpward;
+ if (usingYosemiteOrLater) {
+ if (slider->orientation == Qt::Vertical)
+ tdi.bounds.origin.x -= 2;
+ }
HIThemeDrawTrackTickMarks(&tdi, numMarks,
cg,
kHIThemeOrientationNormal);
+ // Reset to plain thumb to be drawn further down
+ tdi.trackInfo.slider.thumbDir = kThemeThumbPlain;
} else {
HIThemeDrawTrackTickMarks(&tdi, numMarks,
cg,
kHIThemeOrientationNormal);
+ }
+ if (usingYosemiteOrLater)
+ tdi.bounds = bounds;
+ }
+
+ if (usingYosemiteOrLater && cc == CC_Slider) {
+ // Still as part of fixing the min and max positions,
+ // we also adjust the knob position. We can do this
+ // because it's rendered separately from the track.
+ if (slider->orientation == Qt::Vertical) {
+ if (tdi.trackInfo.slider.thumbDir == kThemeThumbDownward) // pointing right
+ tdi.bounds.origin.x -= 2;
}
}
+
+ HIThemeDrawTrack(&tdi, tracking ? 0 : &macRect, cg,
+ kHIThemeOrientationNormal);
}
}
break;
diff --git a/src/widgets/styles/qmacstyle_mac_p_p.h b/src/widgets/styles/qmacstyle_mac_p_p.h
index b6267c43e6d..080f944ef8f 100644
--- a/src/widgets/styles/qmacstyle_mac_p_p.h
+++ b/src/widgets/styles/qmacstyle_mac_p_p.h
@@ -126,12 +126,17 @@ enum QCocoaWidgetKind {
QCocoaCheckBox,
QCocoaComboBox, // Editable QComboBox
QCocoaPopupButton, // Non-editable QComboBox
+ QCocoaPullDownButton, // QPushButton with menu
QCocoaPushButton,
- QCocoaRadioButton
+ QCocoaRadioButton,
+ QCocoaHorizontalSlider,
+ QCocoaVerticalSlider
};
typedef QPair<QCocoaWidgetKind, QAquaWidgetSize> QCocoaWidget;
+typedef void (^QCocoaDrawRectBlock)(NSRect, CGContextRef);
+
#define SIZE(large, small, mini) \
(controlSize == QAquaSizeLarge ? (large) : controlSize == QAquaSizeSmall ? (small) : (mini))
@@ -201,7 +206,7 @@ public:
NSView *cocoaControl(QCocoaWidget widget, QPoint *offset) const;
- void drawNSViewInRect(NSView *view, const QRect &rect, QPainter *p) const;
+ void drawNSViewInRect(NSView *view, const QRect &rect, QPainter *p, QCocoaDrawRectBlock drawRectBlock = nil) const;
void resolveCurrentNSView(QWindow *window);
public:
diff --git a/src/widgets/widgets/qabstractscrollarea.cpp b/src/widgets/widgets/qabstractscrollarea.cpp
index 3b755919986..4cafeafceca 100644
--- a/src/widgets/widgets/qabstractscrollarea.cpp
+++ b/src/widgets/widgets/qabstractscrollarea.cpp
@@ -609,6 +609,9 @@ void QAbstractScrollArea::setViewport(QWidget *widget)
#endif
#endif
d->layoutChildren();
+#ifndef QT_NO_OPENGL
+ QWidgetPrivate::get(d->viewport)->initializeViewportFramebuffer();
+#endif
if (isVisible())
d->viewport->show();
setupViewport(widget);
diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp
index 2fa197b2c84..44e22555dbe 100644
--- a/src/widgets/widgets/qcombobox.cpp
+++ b/src/widgets/widgets/qcombobox.cpp
@@ -2439,7 +2439,7 @@ bool QComboBoxPrivate::showNativePopup()
offset = QPoint(-1, 7);
else if (q->testAttribute(Qt::WA_MacMiniSize))
offset = QPoint(-2, 6);
- menu->showPopup(tlw, tlw->mapFromGlobal(q->mapToGlobal(offset)), currentItem);
+ menu->showPopup(tlw, QRect(tlw->mapFromGlobal(q->mapToGlobal(offset)), QSize()), currentItem);
menu->deleteLater();
Q_FOREACH (QPlatformMenuItem *item, items)
item->deleteLater();
diff --git a/src/widgets/widgets/qmenu.cpp b/src/widgets/widgets/qmenu.cpp
index affea4f9a30..a4c22de15b0 100644
--- a/src/widgets/widgets/qmenu.cpp
+++ b/src/widgets/widgets/qmenu.cpp
@@ -3114,6 +3114,8 @@ static void copyActionToPlatformItem(const QAction *action, QPlatformMenuItem* i
QStyleOption opt;
item->setIconSize(qApp->style()->pixelMetric(QStyle::PM_SmallIconSize, &opt, 0));
}
+ } else {
+ item->setIcon(QIcon());
}
item->setVisible(action->isVisible());
item->setShortcut(action->shortcut());
diff --git a/src/widgets/widgets/qtoolbutton.cpp b/src/widgets/widgets/qtoolbutton.cpp
index 3d3f42605e7..bb3f2d74a8b 100644
--- a/src/widgets/widgets/qtoolbutton.cpp
+++ b/src/widgets/widgets/qtoolbutton.cpp
@@ -636,6 +636,9 @@ void QToolButton::setMenu(QMenu* menu)
{
Q_D(QToolButton);
+ if (d->menuAction == (menu ? menu->menuAction() : 0))
+ return;
+
if (d->menuAction)
removeAction(d->menuAction);
diff --git a/src/xml/sax/qxml.cpp b/src/xml/sax/qxml.cpp
index bedb0ba689f..106bdf2dec9 100644
--- a/src/xml/sax/qxml.cpp
+++ b/src/xml/sax/qxml.cpp
@@ -2948,29 +2948,12 @@ bool QXmlSimpleReader::feature(const QString& name, bool *ok) const
\li If enabled, the original prefixed names
and attributes used for namespace declarations are
reported.
- \row \li \e http://trolltech.com/xml/features/report-whitespace-only-CharData
- \li true
- \li Obsolete, use the following string instead.
- If enabled, CharData that consist of
- only whitespace characters are reported
- using QXmlContentHandler::characters(). If disabled, whitespace is silently
- discarded.
\row \li \e http://qt-project.org/xml/features/report-whitespace-only-CharData
\li true
\li If enabled, CharData that consist of
only whitespace characters are reported
using QXmlContentHandler::characters(). If disabled, whitespace is silently
discarded.
- \row \li \e http://trolltech.com/xml/features/report-start-end-entity
- \li false
- \li Obsolete, use the following string instead.
- If enabled, the parser reports
- QXmlContentHandler::startEntity() and
- QXmlContentHandler::endEntity() events, so character data
- might be reported in chunks.
- If disabled, the parser does not report these events, but
- silently substitutes the entities, and reports the character
- data in one chunk.
\row \li \e http://qt-project.org/xml/features/report-start-end-entity
\li false
\li If enabled, the parser reports