summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJani Heikkinen <jani.heikkinen@digia.com>2014-04-23 12:42:48 +0300
committerJani Heikkinen <jani.heikkinen@digia.com>2014-04-23 12:42:48 +0300
commit54c1e5ed220570034a784bf4c616e177697e4d28 (patch)
tree2bac29aabf5380db0cb1f5176525417ac483fd81 /src
parent207598fd8e69be34e8ba2c9db7720cb6003ea114 (diff)
parentb0d996aed19570da73e9bdc166a38bbb14f4b859 (diff)
Merge remote-tracking branch 'origin/release' into stable
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp47
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h15
-rw-r--r--src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro3
-rw-r--r--src/angle/patches/0016-ANGLE-WinRT-Call-Trim-when-application-suspends.patch118
-rw-r--r--src/corelib/doc/qtcore.qdocconf2
-rw-r--r--src/corelib/global/qcompilerdetection.h23
-rw-r--r--src/corelib/kernel/qobject.cpp13
-rw-r--r--src/corelib/kernel/qtranslator.cpp6
-rw-r--r--src/corelib/thread/qthread_win.cpp21
-rw-r--r--src/corelib/tools/qchar.h3
-rw-r--r--src/corelib/tools/qstring.h3
-rw-r--r--src/corelib/tools/qtimezone.cpp7
-rw-r--r--src/corelib/tools/qunicodetools.cpp38
-rw-r--r--src/gui/kernel/qguiapplication.cpp12
-rw-r--r--src/gui/kernel/qopenglcontext.cpp10
-rw-r--r--src/gui/opengl/qopenglfunctions.cpp25
-rw-r--r--src/gui/opengl/qopenglfunctions.h24
-rw-r--r--src/gui/text/qtextengine.cpp19
-rw-r--r--src/network/socket/qnativesocketengine_winrt.cpp319
-rw-r--r--src/network/socket/qnativesocketengine_winrt_p.h18
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.cpp16
-rw-r--r--src/plugins/platforms/android/qandroidinputcontext.h2
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.h3
-rw-r--r--src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm25
-rw-r--r--src/plugins/platforms/cocoa/qnsview.mm6
-rw-r--r--src/plugins/platforms/ios/quiview_textinput.mm2
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase.cpp9
-rw-r--r--src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp3
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp10
-rw-r--r--src/plugins/platforms/xcb/qglxintegration.cpp28
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.h4
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection_xi2.cpp29
-rw-r--r--src/plugins/platforms/xcb/qxcbwindow.cpp3
-rw-r--r--src/plugins/printsupport/windows/windows.pro2
-rw-r--r--src/printsupport/dialogs/qprintdialog_mac.mm16
-rw-r--r--src/printsupport/printsupport.pro1
-rw-r--r--src/widgets/kernel/qapplication.cpp9
-rw-r--r--src/widgets/kernel/qwidget.cpp4
38 files changed, 635 insertions, 263 deletions
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp
index 2de477b3bc..e70727c65e 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp
@@ -40,6 +40,13 @@
#include "libEGL/Display.h"
+#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE)
+# include <dxgi1_3.h>
+# include <wrl.h>
+# include <windows.applicationmodel.core.h>
+typedef ABI::Windows::Foundation::IEventHandler<ABI::Windows::ApplicationModel::SuspendingEventArgs *> SuspendEventHandler;
+#endif
+
#ifdef _DEBUG
// this flag enables suppressing some spurious warnings that pop up in certain WebGL samples
// and conformance tests. to enable all warnings, remove this define.
@@ -426,9 +433,49 @@ EGLint Renderer11::initialize()
}
}
+#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE)
+ // Monitor when the application suspends so that Trim() can be called
+ Microsoft::WRL::ComPtr<ABI::Windows::ApplicationModel::Core::ICoreApplication> application;
+ result = RoGetActivationFactory(Microsoft::WRL::Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
+ IID_PPV_ARGS(&application));
+ if (FAILED(result))
+ {
+ ERR("Error obtaining CoreApplication: 0x%08X", result);
+ return EGL_NOT_INITIALIZED;
+ }
+
+ EventRegistrationToken cookie;
+ result = application->add_Suspending(Microsoft::WRL::Callback<SuspendEventHandler>(this, &Renderer11::onSuspend).Get(), &cookie);
+ if (FAILED(result))
+ {
+ ERR("Error setting suspend callback: 0x%08X", result);
+ return EGL_NOT_INITIALIZED;
+ }
+#endif
+
return EGL_SUCCESS;
}
+#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE)
+HRESULT Renderer11::onSuspend(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *)
+{
+ if (!mDevice)
+ return S_OK;
+
+ Microsoft::WRL::ComPtr<IDXGIDevice3> dxgiDevice;
+ HRESULT result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice));
+ if (FAILED(result))
+ {
+ ERR("Error obtaining DXGIDevice3 on suspend: 0x%08X", result);
+ return S_OK;
+ }
+
+ dxgiDevice->Trim();
+
+ return S_OK;
+}
+#endif
+
// do any one-time device initialization
// NOTE: this is also needed after a device lost/reset
// to reset the scene status and ensure the default states are reset.
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h
index a8a722c56c..773fc26db1 100644
--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h
@@ -18,6 +18,17 @@
#include "libGLESv2/renderer/d3d11/InputLayoutCache.h"
#include "libGLESv2/renderer/RenderTarget.h"
+#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE)
+struct IInspectable;
+namespace ABI {
+ namespace Windows {
+ namespace ApplicationModel {
+ struct ISuspendingEventArgs;
+ }
+ }
+}
+#endif
+
namespace gl
{
class Renderbuffer;
@@ -202,6 +213,10 @@ class Renderer11 : public Renderer
RenderTarget *drawRenderTarget, bool wholeBufferCopy);
ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource);
+#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE)
+ HRESULT onSuspend(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *);
+#endif
+
HMODULE mD3d11Module;
HMODULE mDxgiModule;
diff --git a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
index 7d997d7d8b..d505c30aa6 100644
--- a/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
+++ b/src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
@@ -7,6 +7,9 @@ CONFIG += \
exceptions_off rtti_off
CONFIG -= qt
+contains(QT_CONFIG, debug_and_release):CONFIG += debug_and_release
+contains(QT_CONFIG, build_all):CONFIG += build_all
+
DESTDIR = $$QT_BUILD_TREE/lib
DEFINES += HAVE_CONFIG_H
diff --git a/src/angle/patches/0016-ANGLE-WinRT-Call-Trim-when-application-suspends.patch b/src/angle/patches/0016-ANGLE-WinRT-Call-Trim-when-application-suspends.patch
new file mode 100644
index 0000000000..bf2a1ad363
--- /dev/null
+++ b/src/angle/patches/0016-ANGLE-WinRT-Call-Trim-when-application-suspends.patch
@@ -0,0 +1,118 @@
+From 158b7642c53843ed954fa667ff23b8746f95f8eb Mon Sep 17 00:00:00 2001
+From: Andrew Knight <andrew.knight@digia.com>
+Date: Tue, 22 Apr 2014 09:13:57 +0300
+Subject: [PATCH] ANGLE WinRT: Call Trim() when application suspends
+
+This is required by Windows Store Apps to pass certification.
+
+Task-number: QTBUG-38481
+Change-Id: I6dc00431ee5f6c7d4c64111ccc38f46483d3b9a8
+---
+ .../src/libGLESv2/renderer/d3d11/Renderer11.cpp | 47 ++++++++++++++++++++++
+ .../src/libGLESv2/renderer/d3d11/Renderer11.h | 15 +++++++
+ 2 files changed, 62 insertions(+)
+
+diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp
+index 2de477b..e70727c 100644
+--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp
++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.cpp
+@@ -40,6 +40,13 @@
+
+ #include "libEGL/Display.h"
+
++#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE)
++# include <dxgi1_3.h>
++# include <wrl.h>
++# include <windows.applicationmodel.core.h>
++typedef ABI::Windows::Foundation::IEventHandler<ABI::Windows::ApplicationModel::SuspendingEventArgs *> SuspendEventHandler;
++#endif
++
+ #ifdef _DEBUG
+ // this flag enables suppressing some spurious warnings that pop up in certain WebGL samples
+ // and conformance tests. to enable all warnings, remove this define.
+@@ -426,9 +433,49 @@ EGLint Renderer11::initialize()
+ }
+ }
+
++#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE)
++ // Monitor when the application suspends so that Trim() can be called
++ Microsoft::WRL::ComPtr<ABI::Windows::ApplicationModel::Core::ICoreApplication> application;
++ result = RoGetActivationFactory(Microsoft::WRL::Wrappers::HString::MakeReference(RuntimeClass_Windows_ApplicationModel_Core_CoreApplication).Get(),
++ IID_PPV_ARGS(&application));
++ if (FAILED(result))
++ {
++ ERR("Error obtaining CoreApplication: 0x%08X", result);
++ return EGL_NOT_INITIALIZED;
++ }
++
++ EventRegistrationToken cookie;
++ result = application->add_Suspending(Microsoft::WRL::Callback<SuspendEventHandler>(this, &Renderer11::onSuspend).Get(), &cookie);
++ if (FAILED(result))
++ {
++ ERR("Error setting suspend callback: 0x%08X", result);
++ return EGL_NOT_INITIALIZED;
++ }
++#endif
++
+ return EGL_SUCCESS;
+ }
+
++#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE)
++HRESULT Renderer11::onSuspend(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *)
++{
++ if (!mDevice)
++ return S_OK;
++
++ Microsoft::WRL::ComPtr<IDXGIDevice3> dxgiDevice;
++ HRESULT result = mDevice->QueryInterface(IID_PPV_ARGS(&dxgiDevice));
++ if (FAILED(result))
++ {
++ ERR("Error obtaining DXGIDevice3 on suspend: 0x%08X", result);
++ return S_OK;
++ }
++
++ dxgiDevice->Trim();
++
++ return S_OK;
++}
++#endif
++
+ // do any one-time device initialization
+ // NOTE: this is also needed after a device lost/reset
+ // to reset the scene status and ensure the default states are reset.
+diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h
+index a8a722c..773fc26 100644
+--- a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h
++++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/Renderer11.h
+@@ -18,6 +18,17 @@
+ #include "libGLESv2/renderer/d3d11/InputLayoutCache.h"
+ #include "libGLESv2/renderer/RenderTarget.h"
+
++#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE)
++struct IInspectable;
++namespace ABI {
++ namespace Windows {
++ namespace ApplicationModel {
++ struct ISuspendingEventArgs;
++ }
++ }
++}
++#endif
++
+ namespace gl
+ {
+ class Renderbuffer;
+@@ -202,6 +213,10 @@ class Renderer11 : public Renderer
+ RenderTarget *drawRenderTarget, bool wholeBufferCopy);
+ ID3D11Texture2D *resolveMultisampledTexture(ID3D11Texture2D *source, unsigned int subresource);
+
++#if defined(ANGLE_OS_WINRT) && !defined(ANGLE_OS_WINPHONE)
++ HRESULT onSuspend(IInspectable *, ABI::Windows::ApplicationModel::ISuspendingEventArgs *);
++#endif
++
+ HMODULE mD3d11Module;
+ HMODULE mDxgiModule;
+
+--
+1.9.0.msysgit.0
+
diff --git a/src/corelib/doc/qtcore.qdocconf b/src/corelib/doc/qtcore.qdocconf
index 18342d0138..c8eb15a7f7 100644
--- a/src/corelib/doc/qtcore.qdocconf
+++ b/src/corelib/doc/qtcore.qdocconf
@@ -26,7 +26,7 @@ qhp.QtCore.subprojects.classes.sortPages = true
tagfile = ../../../doc/qtcore/qtcore.tags
-depends += qtgui qtwidgets qtnetwork qtdoc qtmacextras qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake
+depends += activeqt qtdbus qtgui qtwidgets qtnetwork qtdoc qtmacextras qtqml qtquick qtlinguist qtdesigner qtconcurrent qtxml qmake
headerdirs += ..
diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h
index 950647004a..dd880d8ede 100644
--- a/src/corelib/global/qcompilerdetection.h
+++ b/src/corelib/global/qcompilerdetection.h
@@ -842,21 +842,28 @@
#endif /* Q_CC_MSVC */
#ifdef __cplusplus
+# include <utility>
# if defined(Q_OS_QNX)
-# include <utility>
# if defined(_YVALS) || defined(_LIBCPP_VER)
// QNX: libcpp (Dinkumware-based) doesn't have the <initializer_list>
// header, so the feature is useless, even if the compiler supports
// it. Disable.
-# ifdef Q_COMPILER_INITIALIZER_LISTS
-# undef Q_COMPILER_INITIALIZER_LISTS
-# endif
-# ifdef Q_COMPILER_RVALUE_REFS
-# undef Q_COMPILER_RVALUE_REFS
-# endif
+# undef Q_COMPILER_INITIALIZER_LISTS
+// That libcpp doesn't have std::move either, so disable everything
+// related to rvalue refs.
+# undef Q_COMPILER_RVALUE_REFS
+# undef Q_COMPILER_REF_QUALIFIERS
# endif
+# endif // Q_OS_QNX
+# if (defined(Q_CC_CLANG) || defined(Q_CC_INTEL)) && defined(Q_OS_MAC) && defined(__GNUC_LIBSTD__) \
+ && ((__GNUC_LIBSTD__-0) * 100 + __GNUC_LIBSTD_MINOR__-0 <= 402)
+// Mac OS X: Apple has not updated libstdc++ since 2007, which means it does not have
+// <initializer_list> or std::move. Let's disable these features
+# undef Q_COMPILER_INITIALIZER_LISTS
+# undef Q_COMPILER_RVALUE_REFS
+# undef Q_COMPILER_REF_QUALIFIERS
# endif
-#endif // Q_OS_QNX
+#endif
/*
* C++11 keywords and expressions
diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp
index 01bedb4a3a..0a504657a3 100644
--- a/src/corelib/kernel/qobject.cpp
+++ b/src/corelib/kernel/qobject.cpp
@@ -4063,18 +4063,21 @@ QDebug operator<<(QDebug dbg, const QObject *o) {
\macro Q_CLASSINFO(Name, Value)
\relates QObject
- This macro associates extra information to the class, which is
- available using QObject::metaObject(). Except for the ActiveQt
- extension, Qt doesn't use this information.
+ This macro associates extra information to the class, which is available
+ using QObject::metaObject(). Qt makes only limited use of this feature, in
+ the \l{Active Qt}, \l{Qt D-Bus} and \l{Qt QML} modules.
- The extra information takes the form of a \a Name string and a \a
- Value literal string.
+ The extra information takes the form of a \a Name string and a \a Value
+ literal string.
Example:
\snippet code/src_corelib_kernel_qobject.cpp 35
\sa QMetaObject::classInfo()
+ \sa QAxFactory
+ \sa {Using Qt D-Bus Adaptors}
+ \sa {Extending QML - Default Property Example}
*/
/*!
diff --git a/src/corelib/kernel/qtranslator.cpp b/src/corelib/kernel/qtranslator.cpp
index 843a6edce1..94c77302dd 100644
--- a/src/corelib/kernel/qtranslator.cpp
+++ b/src/corelib/kernel/qtranslator.cpp
@@ -465,6 +465,12 @@ QTranslator::~QTranslator()
\li \c /opt/foolib/foo.qm
\li \c /opt/foolib/foo
\endlist
+
+ Usually, it is better to use the QTranslator::load(const QLocale &,
+ const QString &, const QString &, const QString &, const QString &)
+ function instead, because it uses \l{QLocale::uiLanguages()} and not simply
+ the locale name, which refers to the formatting of dates and numbers and not
+ necessarily the UI language.
*/
bool QTranslator::load(const QString & filename, const QString & directory,
diff --git a/src/corelib/thread/qthread_win.cpp b/src/corelib/thread/qthread_win.cpp
index a12636778e..bdc3463b9f 100644
--- a/src/corelib/thread/qthread_win.cpp
+++ b/src/corelib/thread/qthread_win.cpp
@@ -63,6 +63,7 @@
#include <qt_windows.h>
#ifdef Q_OS_WINRT
+#include <qelapsedtimer.h>
#include <thread>
#endif
@@ -680,21 +681,11 @@ bool QThread::wait(unsigned long time)
break;
}
#else // !Q_OS_WINRT
- if (d->handle->joinable()) {
- HANDLE handle = d->handle->native_handle();
- switch (WaitForSingleObjectEx(handle, time, FALSE)) {
- case WAIT_OBJECT_0:
- ret = true;
- d->handle->join();
- break;
- case WAIT_FAILED:
- qErrnoWarning("QThread::wait: WaitForSingleObjectEx() failed");
- break;
- case WAIT_ABANDONED:
- case WAIT_TIMEOUT:
- default:
- break;
- }
+ if (!d->finished) {
+ QElapsedTimer timer;
+ timer.start();
+ while (timer.elapsed() < time && !d->finished)
+ yieldCurrentThread();
}
#endif // Q_OS_WINRT
diff --git a/src/corelib/tools/qchar.h b/src/corelib/tools/qchar.h
index 266effb66a..1955758fca 100644
--- a/src/corelib/tools/qchar.h
+++ b/src/corelib/tools/qchar.h
@@ -358,6 +358,9 @@ public:
case QChar::Joining_Causing: return QChar::Center;
case QChar::Joining_Dual: return QChar::Dual;
case QChar::Joining_Right: return QChar::Right;
+ case QChar::Joining_None:
+ case QChar::Joining_Left:
+ case QChar::Joining_Transparent:
default: return QChar::OtherJoining;
}
}
diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h
index 2d9a42957e..359d0c49e5 100644
--- a/src/corelib/tools/qstring.h
+++ b/src/corelib/tools/qstring.h
@@ -954,6 +954,9 @@ public:
case QChar::Joining_Causing: return QChar::Center;
case QChar::Joining_Dual: return QChar::Dual;
case QChar::Joining_Right: return QChar::Right;
+ case QChar::Joining_None:
+ case QChar::Joining_Left:
+ case QChar::Joining_Transparent:
default: return QChar::OtherJoining;
}
}
diff --git a/src/corelib/tools/qtimezone.cpp b/src/corelib/tools/qtimezone.cpp
index b30caf4289..e17ff2b249 100644
--- a/src/corelib/tools/qtimezone.cpp
+++ b/src/corelib/tools/qtimezone.cpp
@@ -418,6 +418,13 @@ QTimeZone::~QTimeZone()
}
/*!
+ \fn QTimeZone::swap(QTimeZone &other)
+
+ Swaps this time zone instance with \a other. This function is very
+ fast and never fails.
+*/
+
+/*!
Assignment operator, assign \a other to this.
*/
diff --git a/src/corelib/tools/qunicodetools.cpp b/src/corelib/tools/qunicodetools.cpp
index fac795051a..fc36d07a4a 100644
--- a/src/corelib/tools/qunicodetools.cpp
+++ b/src/corelib/tools/qunicodetools.cpp
@@ -667,7 +667,7 @@ Q_CORE_EXPORT void initCharAttributes(const ushort *string, int length,
// ----------------------------------------------------------------------------
//
-// The Unicode script property. See http://www.unicode.org/reports/tr24/ (some very old version)
+// The Unicode script property. See http://www.unicode.org/reports/tr24/tr24-21.html
//
// ----------------------------------------------------------------------------
@@ -689,15 +689,36 @@ Q_CORE_EXPORT void initScripts(const ushort *string, int length, uchar *scripts)
const QUnicodeTables::Properties *prop = QUnicodeTables::properties(ucs4);
- if (Q_LIKELY(prop->script == script || prop->script == QChar::Script_Inherited))
+ if (Q_LIKELY(prop->script == script || prop->script <= QChar::Script_Inherited))
continue;
// Never break between a combining mark (gc= Mc, Mn or Me) and its base character.
// Thus, a combining mark — whatever its script property value is — should inherit
// the script property value of its base character.
static const int test = (FLAG(QChar::Mark_NonSpacing) | FLAG(QChar::Mark_SpacingCombining) | FLAG(QChar::Mark_Enclosing));
- if (Q_UNLIKELY(FLAG(prop->category) & test))
- continue;
+ if (Q_UNLIKELY(FLAG(prop->category) & test)) {
+ // In cases where the base character itself has the Common script property value,
+ // and it is followed by one or more combining marks with a specific script property value,
+ // it may be even better for processing to let the base acquire the script property value
+ // from the first mark. This approach can be generalized by treating all the characters
+ // of a combining character sequence as having the script property value
+ // of the first non-Inherited, non-Common character in the sequence if there is one,
+ // and otherwise treating all the characters as having the Common script property value.
+ if (Q_LIKELY(script > QChar::Script_Common || prop->script <= QChar::Script_Common))
+ continue;
+
+ script = QChar::Script(prop->script);
+ }
+
+ if (Q_LIKELY(script != QChar::Script_Common)) {
+ // override preceding Common-s
+ while (sor > 0 && scripts[sor - 1] == QChar::Script_Common)
+ --sor;
+ } else {
+ // see if we are inheriting preceding run
+ if (sor > 0)
+ script = scripts[sor - 1];
+ }
while (sor < eor)
scripts[sor++] = script;
@@ -705,6 +726,15 @@ Q_CORE_EXPORT void initScripts(const ushort *string, int length, uchar *scripts)
script = prop->script;
}
eor = length;
+ if (Q_LIKELY(script != QChar::Script_Common)) {
+ // override preceding Common-s
+ while (sor > 0 && scripts[sor - 1] == QChar::Script_Common)
+ --sor;
+ } else {
+ // see if we are inheriting preceding run
+ if (sor > 0)
+ script = scripts[sor - 1];
+ }
while (sor < eor)
scripts[sor++] = script;
}
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index bdedc9d75f..ab71fe9081 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1872,7 +1872,11 @@ void QGuiApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate
return;
if (previous) {
- QFocusEvent focusOut(QEvent::FocusOut, e->reason);
+ Qt::FocusReason r = e->reason;
+ if ((r == Qt::OtherFocusReason || r == Qt::ActiveWindowFocusReason) &&
+ newFocus && (newFocus->flags() & Qt::Popup) == Qt::Popup)
+ r = Qt::PopupFocusReason;
+ QFocusEvent focusOut(QEvent::FocusOut, r);
QCoreApplication::sendSpontaneousEvent(previous, &focusOut);
QObject::disconnect(previous, SIGNAL(focusObjectChanged(QObject*)),
qApp, SLOT(_q_updateFocusObject(QObject*)));
@@ -1881,7 +1885,11 @@ void QGuiApplicationPrivate::processActivatedEvent(QWindowSystemInterfacePrivate
}
if (QGuiApplicationPrivate::focus_window) {
- QFocusEvent focusIn(QEvent::FocusIn, e->reason);
+ Qt::FocusReason r = e->reason;
+ if ((r == Qt::OtherFocusReason || r == Qt::ActiveWindowFocusReason) &&
+ previous && (previous->flags() & Qt::Popup) == Qt::Popup)
+ r = Qt::PopupFocusReason;
+ QFocusEvent focusIn(QEvent::FocusIn, r);
QCoreApplication::sendSpontaneousEvent(QGuiApplicationPrivate::focus_window, &focusIn);
QObject::connect(QGuiApplicationPrivate::focus_window, SIGNAL(focusObjectChanged(QObject*)),
qApp, SLOT(_q_updateFocusObject(QObject*)));
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 7382d63a06..dbca05037b 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -61,6 +61,10 @@
#include <QDebug>
+#ifndef QT_OPENGL_ES_2
+#include <QOpenGLFunctions_1_0>
+#endif
+
QT_BEGIN_NAMESPACE
class QOpenGLVersionProfilePrivate
@@ -366,7 +370,9 @@ int QOpenGLContextPrivate::maxTextureSize()
GLint size;
GLint next = 64;
funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
+ QOpenGLFunctions_1_0 *gl1funcs = q->versionFunctions<QOpenGLFunctions_1_0>();
+ gl1funcs->initializeOpenGLFunctions();
+ gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &size);
if (size == 0) {
return max_texture_size;
}
@@ -377,7 +383,7 @@ int QOpenGLContextPrivate::maxTextureSize()
if (next > max_texture_size)
break;
funcs->glTexImage2D(proxy, 0, GL_RGBA, next, next, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
- funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
+ gl1funcs->glGetTexLevelParameteriv(proxy, 0, GL_TEXTURE_WIDTH, &next);
} while (next > size);
max_texture_size = size;
diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp
index eb2c98e1f5..af536fa927 100644
--- a/src/gui/opengl/qopenglfunctions.cpp
+++ b/src/gui/opengl/qopenglfunctions.cpp
@@ -2012,12 +2012,6 @@ void QOpenGLFunctions::initializeOpenGLFunctions()
*/
/*!
- \fn void QOpenGLFunctions::glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
-
- \internal
-*/
-
-/*!
\fn bool QOpenGLFunctions::isInitialized(const QOpenGLFunctionsPrivate *d)
\internal
*/
@@ -3174,15 +3168,7 @@ static void QOPENGLF_APIENTRY qopenglfResolveGetBufferSubData(GLenum target, qop
(target, offset, size, data);
}
-#ifndef QT_OPENGL_ES_2
-// Desktop only
-
-static void QOPENGLF_APIENTRY qopenglfResolveGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
-{
- RESOLVE_FUNC_VOID(0, GetTexLevelParameteriv)(target, level, pname, params);
-}
-
-#ifndef QT_OPENGL_DYNAMIC
+#if !defined(QT_OPENGL_ES_2) && !defined(QT_OPENGL_DYNAMIC)
// Special translation functions for ES-specific calls on desktop GL
static void QOPENGLF_APIENTRY qopenglfTranslateClearDepthf(GLclampf depth)
@@ -3194,10 +3180,7 @@ static void QOPENGLF_APIENTRY qopenglfTranslateDepthRangef(GLclampf zNear, GLcla
{
::glDepthRange(zNear, zFar);
}
-
-#endif // QT_OPENGL_DYNAMIC
-
-#endif // QT_OPENGL_ES2
+#endif // !ES && !DYNAMIC
QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
{
@@ -3256,8 +3239,6 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
TexParameteriv = qopenglfResolveTexParameteriv;
TexSubImage2D = qopenglfResolveTexSubImage2D;
Viewport = qopenglfResolveViewport;
-
- GetTexLevelParameteriv = qopenglfResolveGetTexLevelParameteriv;
} else {
#ifndef QT_OPENGL_DYNAMIC
// Use the functions directly. This requires linking QtGui to an OpenGL implementation.
@@ -3308,8 +3289,6 @@ QOpenGLFunctionsPrivate::QOpenGLFunctionsPrivate(QOpenGLContext *)
TexParameteriv = ::glTexParameteriv;
TexSubImage2D = ::glTexSubImage2D;
Viewport = ::glViewport;
-
- GetTexLevelParameteriv = ::glGetTexLevelParameteriv;
#else // QT_OPENGL_DYNAMIC
// This should not happen.
qFatal("QOpenGLFunctions: Dynamic OpenGL builds do not support platforms with insufficient function resolving capabilities");
diff --git a/src/gui/opengl/qopenglfunctions.h b/src/gui/opengl/qopenglfunctions.h
index 03c12200d5..de1de39db2 100644
--- a/src/gui/opengl/qopenglfunctions.h
+++ b/src/gui/opengl/qopenglfunctions.h
@@ -407,9 +407,6 @@ public:
void glVertexAttrib4fv(GLuint indx, const GLfloat* values);
void glVertexAttribPointer(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr);
- // OpenGL1, not GLES2
- void glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params);
-
protected:
QOpenGLFunctionsPrivate *d_ptr;
static bool isInitialized(const QOpenGLFunctionsPrivate *d) { return d != 0; }
@@ -565,9 +562,6 @@ struct QOpenGLFunctionsPrivate
void (QOPENGLF_APIENTRYP VertexAttrib4fv)(GLuint indx, const GLfloat* values);
void (QOPENGLF_APIENTRYP VertexAttribPointer)(GLuint indx, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const void* ptr);
- // OpenGL1 only, not GLES2
- void (QOPENGLF_APIENTRYP GetTexLevelParameteriv)(GLenum target, GLint level, GLenum pname, GLint *params);
-
// Special non-ES OpenGL variants, not to be called directly
void (QOPENGLF_APIENTRYP ClearDepth)(GLdouble depth);
void (QOPENGLF_APIENTRYP DepthRange)(GLdouble zNear, GLdouble zFar);
@@ -2154,24 +2148,6 @@ inline void QOpenGLFunctions::glVertexAttribPointer(GLuint indx, GLint size, GLe
Q_OPENGL_FUNCTIONS_DEBUG
}
-// OpenGL1, not GLES2
-
-inline void QOpenGLFunctions::glGetTexLevelParameteriv(GLenum target, GLint level, GLenum pname, GLint *params)
-{
-#ifdef QT_OPENGL_ES_2
- Q_UNUSED(target);
- Q_UNUSED(level);
- Q_UNUSED(pname);
- Q_UNUSED(params);
- // Cannot get here.
- qFatal("QOpenGLFunctions: glGetTexLevelParameteriv not available with OpenGL ES");
-#else
- Q_ASSERT(QOpenGLFunctions::isInitialized(d_ptr));
- d_ptr->GetTexLevelParameteriv(target, level, pname, params);
-#endif
- Q_OPENGL_FUNCTIONS_DEBUG
-}
-
QT_END_NAMESPACE
#endif // QT_NO_OPENGL
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index 35950c709b..34788dc4dc 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -122,20 +122,9 @@ private:
return;
const int end = start + length;
for (int i = start + 1; i < end; ++i) {
- // According to the unicode spec we should be treating characters in the Common script
- // (punctuation, spaces, etc) as being the same script as the surrounding text for the
- // purpose of splitting up text. This is important because, for example, a fullstop
- // (0x2E) can be used to indicate an abbreviation and so must be treated as part of a
- // word. Thus it must be passed along with the word in languages that have to calculate
- // word breaks. For example the thai word "ครม." has no word breaks but the word "ครม"
- // does.
- // Unfortuntely because we split up the strings for both wordwrapping and for setting
- // the font and because Japanese and Chinese are also aliases of the script "Common",
- // doing this would break too many things. So instead we only pass the full stop
- // along, and nothing else.
if (m_analysis[i].bidiLevel == m_analysis[start].bidiLevel
&& m_analysis[i].flags == m_analysis[start].flags
- && (m_analysis[i].script == m_analysis[start].script || m_string[i] == QLatin1Char('.'))
+ && m_analysis[i].script == m_analysis[start].script
&& m_analysis[i].flags < QScriptAnalysis::SpaceTabOrObject
&& i - start < MaxItemLength)
continue;
@@ -1515,26 +1504,22 @@ void QTextEngine::itemize() const
while (uc < e) {
switch (*uc) {
case QChar::ObjectReplacementCharacter:
- analysis->script = QChar::Script_Common;
analysis->flags = QScriptAnalysis::Object;
break;
case QChar::LineSeparator:
if (analysis->bidiLevel % 2)
--analysis->bidiLevel;
- analysis->script = QChar::Script_Common;
analysis->flags = QScriptAnalysis::LineOrParagraphSeparator;
if (option.flags() & QTextOption::ShowLineAndParagraphSeparators)
*const_cast<ushort*>(uc) = 0x21B5; // visual line separator
break;
case QChar::Tabulation:
- analysis->script = QChar::Script_Common;
analysis->flags = QScriptAnalysis::Tab;
analysis->bidiLevel = control.baseLevel();
break;
case QChar::Space:
case QChar::Nbsp:
if (option.flags() & QTextOption::ShowTabsAndSpaces) {
- analysis->script = QChar::Script_Common;
analysis->flags = QScriptAnalysis::Space;
analysis->bidiLevel = control.baseLevel();
break;
@@ -1556,8 +1541,10 @@ void QTextEngine::itemize() const
#ifdef QT_ENABLE_HARFBUZZ_NG
analysis = scriptAnalysis.data();
if (useHarfbuzzNG) {
+ // ### pretend HB-old behavior for now
for (int i = 0; i < length; ++i) {
switch (analysis[i].script) {
+ case QChar::Script_Latin:
case QChar::Script_Han:
case QChar::Script_Hiragana:
case QChar::Script_Katakana:
diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp
index 4b2d1c372e..db1d3dc96b 100644
--- a/src/network/socket/qnativesocketengine_winrt.cpp
+++ b/src/network/socket/qnativesocketengine_winrt.cpp
@@ -74,6 +74,7 @@ typedef ITypedEventHandler<StreamSocketListener *, StreamSocketListenerConnectio
typedef ITypedEventHandler<DatagramSocket *, DatagramSocketMessageReceivedEventArgs *> DatagramReceivedHandler;
typedef IAsyncOperationWithProgressCompletedHandler<IBuffer *, UINT32> SocketReadCompletedHandler;
typedef IAsyncOperationWithProgressCompletedHandler<UINT32, UINT32> SocketWriteCompletedHandler;
+typedef IAsyncOperationWithProgress<IBuffer *, UINT32> IAsyncBufferOperation;
QT_BEGIN_NAMESPACE
@@ -130,6 +131,8 @@ QString qt_QStringFromHSTRING(HSTRING string)
return QString::fromWCharArray(rawString, length);
}
+#define READ_BUFFER_SIZE 8192
+
class ByteArrayBuffer : public Microsoft::WRL::RuntimeClass<RuntimeClassFlags<WinRtClassicComMix>,
IBuffer, Windows::Storage::Streams::IBufferByteAccess>
{
@@ -167,16 +170,6 @@ public:
return S_OK;
}
- QNativeSocketEngine *engine() const
- {
- return m_engine;
- }
-
- void setEngine(QNativeSocketEngine *engine)
- {
- m_engine = engine;
- }
-
ComPtr<IInputStream> inputStream() const
{
return m_stream;
@@ -190,13 +183,33 @@ public:
private:
QByteArray m_bytes;
UINT32 m_length;
- QPointer<QNativeSocketEngine> m_engine;
ComPtr<IInputStream> m_stream;
};
+template <typename T>
+static AsyncStatus opStatus(const ComPtr<T> &op)
+{
+ ComPtr<IAsyncInfo> info;
+ HRESULT hr = op.As(&info);
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to cast op to IAsyncInfo.");
+ return Error;
+ }
+ AsyncStatus status;
+ hr = info->get_Status(&status);
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to get AsyncStatus.");
+ return Error;
+ }
+ return status;
+}
+
QNativeSocketEngine::QNativeSocketEngine(QObject *parent)
: QAbstractSocketEngine(*new QNativeSocketEnginePrivate(), parent)
{
+ connect(this, SIGNAL(connectionReady()), SLOT(connectionNotification()), Qt::QueuedConnection);
+ connect(this, SIGNAL(readReady()), SLOT(readNotification()), Qt::QueuedConnection);
+ connect(this, SIGNAL(writeReady()), SLOT(writeNotification()), Qt::QueuedConnection);
}
QNativeSocketEngine::~QNativeSocketEngine()
@@ -230,7 +243,7 @@ bool QNativeSocketEngine::initialize(qintptr socketDescriptor, QAbstractSocket::
// Currently, only TCP sockets are initialized this way.
SocketHandler *handler = gSocketHandler();
- d->tcp = handler->pendingTcpSockets.value(socketDescriptor, Q_NULLPTR);
+ d->tcp = handler->pendingTcpSockets.take(socketDescriptor);
d->socketType = QAbstractSocket::TcpSocket;
if (!d->tcp || !d->fetchConnectionParameters())
@@ -271,23 +284,33 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
return false;
}
+ ComPtr<IAsyncAction> op;
const QString portString = QString::number(port);
HStringReference portReference(reinterpret_cast<LPCWSTR>(portString.utf16()));
- ComPtr<IAsyncAction> action;
HRESULT hr = E_FAIL;
if (d->socketType == QAbstractSocket::TcpSocket)
- hr = d->tcp->ConnectAsync(remoteHost.Get(), portReference.Get(), &action);
+ hr = d->tcp->ConnectAsync(remoteHost.Get(), portReference.Get(), &op);
else if (d->socketType == QAbstractSocket::UdpSocket)
- hr = d->udp->ConnectAsync(remoteHost.Get(), portReference.Get(), &action);
+ hr = d->udp->ConnectAsync(remoteHost.Get(), portReference.Get(), &op);
if (FAILED(hr)) {
qWarning("QNativeSocketEnginePrivate::nativeConnect:: Could not obtain connect action");
return false;
}
- action->put_Completed(Callback<IAsyncActionCompletedHandler>(&QNativeSocketEnginePrivate::interruptEventDispatcher).Get());
- hr = action->GetResults();
- while ((hr = action->GetResults()) == E_ILLEGAL_METHOD_CALL)
- QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents | QEventLoop::WaitForMoreEvents);
+ hr = op->put_Completed(Callback<IAsyncActionCompletedHandler>(
+ d, &QNativeSocketEnginePrivate::handleConnectToHost).Get());
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Unable to set host connection callback.");
+ return false;
+ }
+ d->socketState = QAbstractSocket::ConnectingState;
+ while (opStatus(op) == Started)
+ d->eventLoop.processEvents();
+
+ AsyncStatus status = opStatus(op);
+ if (status == Error || status == Canceled)
+ return false;
+
if (hr == 0x8007274c) { // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
d->setError(QAbstractSocket::NetworkError, d->ConnectionTimeOutErrorString);
d->socketState = QAbstractSocket::UnconnectedState;
@@ -305,24 +328,21 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port)
}
if (d->socketType == QAbstractSocket::TcpSocket) {
- UINT32 capacity;
- hr = d->inputBuffer->get_Capacity(&capacity);
- if (FAILED(hr))
- return false;
IInputStream *stream;
hr = d->tcp->get_InputStream(&stream);
if (FAILED(hr))
return false;
- ByteArrayBuffer *buffer = static_cast<ByteArrayBuffer *>(d->inputBuffer.Get());
- buffer->setEngine(this);
+ ByteArrayBuffer *buffer = static_cast<ByteArrayBuffer *>(d->readBuffer.Get());
buffer->setInputStream(stream);
- ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> op;
- hr = stream->ReadAsync(buffer, capacity, InputStreamOptions_Partial, &op);
+ ComPtr<IAsyncBufferOperation> op;
+ hr = stream->ReadAsync(buffer, READ_BUFFER_SIZE, InputStreamOptions_Partial, &op);
if (FAILED(hr))
return false;
- hr = op->put_Completed(Callback<SocketReadCompletedHandler>(&QNativeSocketEnginePrivate::handleReadyRead).Get());
- if (FAILED(hr))
+ hr = op->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get());
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to set socket read callback.");
return false;
+ }
}
d->socketState = QAbstractSocket::ConnectedState;
return true;
@@ -358,21 +378,35 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port)
d->tcpListener->add_ConnectionReceived(Callback<ClientConnectedHandler>(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), &token);
hr = d->tcpListener->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op);
if (FAILED(hr)) {
- qWarning("Unable to bind"); // ### Set error message
+ qErrnoWarning(hr, "Unable to bind socket."); // ### Set error message
return false;
}
} else if (d->socketType == QAbstractSocket::UdpSocket) {
hr = d->udp->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op);
if (FAILED(hr)) {
- qWarning("unable to bind"); // ### Set error message
+ qErrnoWarning(hr, "Unable to bind socket."); // ### Set error message
+ return false;
+ }
+ hr = op->put_Completed(Callback<IAsyncActionCompletedHandler>(d, &QNativeSocketEnginePrivate::handleBindCompleted).Get());
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Unable to set bind callback.");
return false;
}
}
if (op) {
- // Wait for connection to enter bound state - TODO: timeout, check result
- while ((hr = op->GetResults()) == E_ILLEGAL_METHOD_CALL)
- QCoreApplication::processEvents();
+ while (opStatus(op) == Started)
+ d->eventLoop.processEvents();
+
+ AsyncStatus status = opStatus(op);
+ if (status == Error || status == Canceled)
+ return false;
+
+ hr = op->GetResults();
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to bind socket");
+ return false;
+ }
d->socketState = QAbstractSocket::BoundState;
d->fetchConnectionParameters();
@@ -410,17 +444,22 @@ int QNativeSocketEngine::accept()
if (d->socketType == QAbstractSocket::TcpSocket) {
IStreamSocket *socket = d->pendingConnections.takeFirst();
- UINT32 capacity;
- d->inputBuffer->get_Capacity(&capacity);
IInputStream *stream;
socket->get_InputStream(&stream);
// TODO: delete buffer and stream on socket close
- ByteArrayBuffer *buffer = static_cast<ByteArrayBuffer *>(d->inputBuffer.Get());
- buffer->setEngine(this);
+ ByteArrayBuffer *buffer = static_cast<ByteArrayBuffer *>(d->readBuffer.Get());
buffer->setInputStream(stream);
- ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> op;
- stream->ReadAsync(buffer, capacity, InputStreamOptions_Partial, &op);
- op->put_Completed(Callback<SocketReadCompletedHandler>(&QNativeSocketEnginePrivate::handleReadyRead).Get());
+ ComPtr<IAsyncBufferOperation> op;
+ HRESULT hr = stream->ReadAsync(buffer, READ_BUFFER_SIZE, InputStreamOptions_Partial, &op);
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Faild to read from the socket buffer.");
+ return -1;
+ }
+ hr = op->put_Completed(Callback<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get());
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to set socket read callback.");
+ return -1;
+ }
d->currentConnections.append(socket);
SocketHandler *handler = gSocketHandler();
@@ -445,7 +484,6 @@ void QNativeSocketEngine::close()
d->closingDown = true;
socket->Close();
socket->Release();
- closeNotification();
d->socketDescriptor = -1;
}
d->socketDescriptor = -1;
@@ -493,13 +531,7 @@ qint64 QNativeSocketEngine::bytesAvailable() const
if (d->socketType != QAbstractSocket::TcpSocket)
return -1;
- if (d->inputBuffer) {
- UINT32 len;
- d->inputBuffer->get_Length(&len);
- return len;
- }
-
- return -1;
+ return d->readBytes.size() - d->readBytes.pos();
}
qint64 QNativeSocketEngine::read(char *data, qint64 maxlen)
@@ -508,54 +540,56 @@ qint64 QNativeSocketEngine::read(char *data, qint64 maxlen)
if (d->socketType != QAbstractSocket::TcpSocket)
return -1;
- ComPtr<IDataReaderStatics> dataReaderStatics;
- GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_DataReader).Get(), &dataReaderStatics);
- ComPtr<IDataReader> reader;
-
- dataReaderStatics->FromBuffer(d->inputBuffer.Get(), &reader);
-
- UINT32 bufferCapacity;
- d->inputBuffer->get_Capacity(&bufferCapacity);
- qint64 lengthToRead = maxlen < bufferCapacity ? maxlen : bufferCapacity;
-
- UINT32 bufferLength;
- d->inputBuffer->get_Length(&bufferLength);
-
- lengthToRead = bufferLength < lengthToRead ? bufferLength : lengthToRead;
- reader->ReadBytes(lengthToRead, (unsigned char*)data);
- return lengthToRead;
+ QMutexLocker mutexLocker(&d->readMutex);
+ return d->readBytes.read(data, maxlen);
}
-template <typename T>
-static qint64 nativeWrite(T *socket, const char *data, qint64 len)
+qint64 QNativeSocketEngine::write(const char *data, qint64 len)
{
+ Q_D(QNativeSocketEngine);
+ HRESULT hr = E_FAIL;
ComPtr<IOutputStream> stream;
- HRESULT hr = socket->get_OutputStream(&stream);
- if (FAILED(hr))
+ if (d->socketType == QAbstractSocket::TcpSocket)
+ hr = d->tcp->get_OutputStream(&stream);
+ else if (d->socketType == QAbstractSocket::UdpSocket)
+ hr = d->udp->get_OutputStream(&stream);
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to get output stream to socket.");
return -1;
+ }
+
ComPtr<ByteArrayBuffer> buffer = Make<ByteArrayBuffer>(data, len);
ComPtr<IAsyncOperationWithProgress<UINT32, UINT32>> op;
hr = stream->WriteAsync(buffer.Get(), &op);
- if (FAILED(hr))
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to write to socket.");
+ return -1;
+ }
+ hr = op->put_Completed(Callback<IAsyncOperationWithProgressCompletedHandler<UINT32, UINT32>>(
+ d, &QNativeSocketEnginePrivate::handleWriteCompleted).Get());
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to set socket write callback.");
return -1;
+ }
+
+ while (opStatus(op) == Started)
+ d->eventLoop.processEvents();
+
+ AsyncStatus status = opStatus(op);
+ if (status == Error || status == Canceled)
+ return -1;
+
UINT32 bytesWritten;
- while ((hr = op->GetResults(&bytesWritten)) == E_ILLEGAL_METHOD_CALL)
- QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
- return bytesWritten;
-}
+ hr = op->GetResults(&bytesWritten);
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to get written socket length.");
+ return -1;
+ }
-qint64 QNativeSocketEngine::write(const char *data, qint64 len)
-{
- Q_D(QNativeSocketEngine);
- qint64 bytesWritten = -1;
- if (d->socketType == QAbstractSocket::TcpSocket)
- bytesWritten = nativeWrite(d->tcp, data, len);
- else if (d->socketType == QAbstractSocket::UdpSocket)
- bytesWritten = nativeWrite(d->udp, data, len);
- if (bytesWritten != -1 && d->notifyOnWrite)
- writeNotification();
- return bytesWritten;
+ if (bytesWritten && d->notifyOnWrite)
+ emit writeReady();
+ return bytesWritten;
}
qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QHostAddress *addr, quint16 *port)
@@ -698,7 +732,7 @@ bool QNativeSocketEngine::setOption(QAbstractSocketEngine::SocketOption option,
bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut)
{
- Q_D(const QNativeSocketEngine);
+ Q_D(QNativeSocketEngine);
Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForRead(), false);
Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForRead(),
QAbstractSocket::UnconnectedState, false);
@@ -714,14 +748,12 @@ bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut)
return true;
// If we are a client, we are ready to read if our buffer has data
- UINT32 length;
- if (FAILED(d->inputBuffer->get_Length(&length)))
- return false;
- if (length)
+ QMutexLocker locker(&d->readMutex);
+ if (!d->readBytes.atEnd())
return true;
// Nothing to do, wait for more events
- QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents|QEventLoop::WaitForMoreEvents);
+ d->eventLoop.processEvents();
}
d->setError(QAbstractSocket::SocketTimeoutError,
@@ -832,8 +864,8 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate()
, closingDown(false)
, socketDescriptor(-1)
{
- ComPtr<ByteArrayBuffer> buffer = Make<ByteArrayBuffer>(8192);
- inputBuffer = buffer;
+ ComPtr<ByteArrayBuffer> buffer = Make<ByteArrayBuffer>(READ_BUFFER_SIZE);
+ readBuffer = buffer;
}
QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate()
@@ -1119,6 +1151,11 @@ bool QNativeSocketEnginePrivate::fetchConnectionParameters()
return true;
}
+HRESULT QNativeSocketEnginePrivate::handleBindCompleted(IAsyncAction *, AsyncStatus)
+{
+ return S_OK;
+}
+
HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener *listener, IStreamSocketListenerConnectionReceivedEventArgs *args)
{
Q_Q(QNativeSocketEngine);
@@ -1126,47 +1163,91 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener
IStreamSocket *socket;
args->get_Socket(&socket);
pendingConnections.append(socket);
- q->connectionNotification();
- q->readNotification();
- return interruptEventDispatcher(0, Completed);
+ emit q->connectionReady();
+ emit q->readReady();
+ return S_OK;
}
-HRESULT QNativeSocketEnginePrivate::interruptEventDispatcher(IAsyncAction *, AsyncStatus)
+HRESULT QNativeSocketEnginePrivate::handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus)
{
- if (QThread *thread = QThread::currentThread()) {
- if (QAbstractEventDispatcher *dispatcher = thread->eventDispatcher())
- dispatcher->interrupt();
- }
return S_OK;
}
-HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncOperationWithProgress<IBuffer *, UINT32> *asyncInfo, AsyncStatus)
+HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status)
{
+ Q_Q(QNativeSocketEngine);
+ if (wasDeleted || isDeletingChildren)
+ return S_OK;
+
+ if (status == Error || status == Canceled)
+ return S_OK;
+
ByteArrayBuffer *buffer = 0;
HRESULT hr = asyncInfo->GetResults((IBuffer **)&buffer);
- if (FAILED(hr))
- return hr;
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to get ready read results.");
+ return S_OK;
+ }
UINT32 len;
buffer->get_Length(&len);
- QNativeSocketEngine *q = buffer->engine();
- if (!q)
+ if (!len) {
+ if (q->isReadNotificationEnabled())
+ emit q->readReady();
+ return S_OK;
+ }
+
+ byte *data;
+ buffer->Buffer(&data);
+
+ readMutex.lock();
+ if (readBytes.atEnd()) // Everything has been read; the buffer is safe to reset
+ readBytes.close();
+ if (!readBytes.isOpen())
+ readBytes.open(QBuffer::ReadWrite|QBuffer::Truncate);
+ qint64 readPos = readBytes.pos();
+ readBytes.seek(readBytes.size());
+ Q_ASSERT(readBytes.atEnd());
+ readBytes.write(reinterpret_cast<const char*>(data), qint64(len));
+ readBytes.seek(readPos);
+ readMutex.unlock();
+
+ if (q->isReadNotificationEnabled())
+ emit q->readReady();
+
+ ComPtr<IAsyncBufferOperation> op;
+ hr = buffer->inputStream()->ReadAsync(buffer, READ_BUFFER_SIZE, InputStreamOptions_Partial, &op);
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Could not read into socket stream buffer.");
return S_OK;
- if (len > 0 && q->isReadNotificationEnabled()) {
- q->readNotification();
}
+ hr = op->put_Completed(Callback<SocketReadCompletedHandler>(this, &QNativeSocketEnginePrivate::handleReadyRead).Get());
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to set socket read callback.");
+ return S_OK;
+ }
+ return S_OK;
+}
- // Continue reading ### TODO: read into offset!!!
- UINT32 capacity;
- buffer->get_Capacity(&capacity);
- ComPtr<IAsyncOperationWithProgress<IBuffer *, UINT32>> op;
- if (SUCCEEDED(buffer->inputStream()->ReadAsync(buffer, capacity, InputStreamOptions_Partial, &op))) {
- if (q)
- return op->put_Completed(Callback<SocketReadCompletedHandler>(&QNativeSocketEnginePrivate::handleReadyRead).Get());
- else
- return op->put_Completed(nullptr);
+HRESULT QNativeSocketEnginePrivate::handleWriteCompleted(IAsyncOperationWithProgress<UINT32, UINT32> *op, AsyncStatus status)
+{
+ if (status == Error) {
+ ComPtr<IAsyncInfo> info;
+ HRESULT hr = op->QueryInterface(IID_PPV_ARGS(&info));
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to cast operation.");
+ return S_OK;
+ }
+ HRESULT errorCode;
+ hr = info->get_ErrorCode(&errorCode);
+ if (FAILED(hr)) {
+ qErrnoWarning(hr, "Failed to get error code.");
+ return S_OK;
+ }
+ qErrnoWarning(errorCode, "A socket error occurred.");
+ return S_OK;
}
- return E_FAIL;
+ return S_OK;
}
HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, IDatagramSocketMessageReceivedEventArgs *args)
@@ -1174,7 +1255,7 @@ HRESULT QNativeSocketEnginePrivate::handleNewDatagram(IDatagramSocket *socket, I
Q_Q(QNativeSocketEngine);
Q_ASSERT(udp == socket);
pendingDatagrams.append(args);
- q->readNotification();
+ emit q->readReady();
return S_OK;
}
diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h
index b5be5fa830..ec2e1b3ad4 100644
--- a/src/network/socket/qnativesocketengine_winrt_p.h
+++ b/src/network/socket/qnativesocketengine_winrt_p.h
@@ -52,6 +52,8 @@
//
// We mean it.
//
+#include <QtCore/QEventLoop>
+#include <QtCore/QBuffer>
#include "QtNetwork/qhostaddress.h"
#include "private/qabstractsocketengine_p.h"
#include <wrl.h>
@@ -127,6 +129,11 @@ public:
bool isExceptionNotificationEnabled() const;
void setExceptionNotificationEnabled(bool enable);
+signals:
+ void connectionReady();
+ void readReady();
+ void writeReady();
+
private:
Q_DECLARE_PRIVATE(QNativeSocketEngine)
Q_DISABLE_COPY(QNativeSocketEngine)
@@ -191,17 +198,22 @@ private:
ABI::Windows::Networking::Sockets::IDatagramSocket *udp;
};
Microsoft::WRL::ComPtr<ABI::Windows::Networking::Sockets::IStreamSocketListener> tcpListener;
- Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IBuffer> inputBuffer;
+ Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IBuffer> readBuffer;
+ QBuffer readBytes;
+ QMutex readMutex;
QList<ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *> pendingDatagrams;
QList<ABI::Windows::Networking::Sockets::IStreamSocket *> pendingConnections;
QList<ABI::Windows::Networking::Sockets::IStreamSocket *> currentConnections;
+ QEventLoop eventLoop;
+ HRESULT handleBindCompleted(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
HRESULT handleNewDatagram(ABI::Windows::Networking::Sockets::IDatagramSocket *socket,
ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args);
HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener,
ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args);
- static HRESULT interruptEventDispatcher(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
- static HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32> *asyncInfo, ABI::Windows::Foundation::AsyncStatus);
+ HRESULT handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus);
+ HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress<ABI::Windows::Storage::Streams::IBuffer *, UINT32> *asyncInfo, ABI::Windows::Foundation::AsyncStatus);
+ HRESULT handleWriteCompleted(ABI::Windows::Foundation::IAsyncOperationWithProgress<UINT32, UINT32> *, ABI::Windows::Foundation::AsyncStatus);
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/android/qandroidinputcontext.cpp b/src/plugins/platforms/android/qandroidinputcontext.cpp
index 3324d9ba49..02fda19d76 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.cpp
+++ b/src/plugins/platforms/android/qandroidinputcontext.cpp
@@ -338,7 +338,7 @@ static JNINativeMethod methods[] = {
QAndroidInputContext::QAndroidInputContext()
- : QPlatformInputContext(), m_blockUpdateSelection(false), m_batchEditNestingLevel(0)
+ : QPlatformInputContext(), m_blockUpdateSelection(false), m_batchEditNestingLevel(0), m_focusObject(0)
{
QtAndroid::AttachedJNIEnv env;
if (!env.jniEnv)
@@ -532,6 +532,18 @@ void QAndroidInputContext::clear()
m_extractedText.clear();
}
+
+void QAndroidInputContext::setFocusObject(QObject *object)
+{
+ if (object != m_focusObject) {
+ m_focusObject = object;
+ if (!m_composingText.isEmpty())
+ finishComposingText();
+ reset();
+ }
+ QPlatformInputContext::setFocusObject(object);
+}
+
void QAndroidInputContext::sendEvent(QObject *receiver, QInputMethodEvent *event)
{
QCoreApplication::sendEvent(receiver, event);
@@ -678,7 +690,7 @@ QString QAndroidInputContext::getTextBeforeCursor(jint length, jint /*flags*/)
{
QVariant textBefore = queryFocusObjectThreadSafe(Qt::ImTextBeforeCursor, QVariant(length));
if (textBefore.isValid()) {
- return textBefore.toString().left(length) + m_composingText;
+ return textBefore.toString().right(length) + m_composingText;
}
//compatibility code for old controls that do not implement the new API
diff --git a/src/plugins/platforms/android/qandroidinputcontext.h b/src/plugins/platforms/android/qandroidinputcontext.h
index f7b29a855f..3ce141ae15 100644
--- a/src/plugins/platforms/android/qandroidinputcontext.h
+++ b/src/plugins/platforms/android/qandroidinputcontext.h
@@ -95,6 +95,7 @@ public:
bool isComposing() const;
void clear();
+ void setFocusObject(QObject *object);
//---------------//
jboolean beginBatchEdit();
@@ -136,6 +137,7 @@ private:
QMetaObject::Connection m_updateCursorPosConnection;
bool m_blockUpdateSelection;
int m_batchEditNestingLevel;
+ QObject *m_focusObject;
};
QT_END_NAMESPACE
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
index 0274ed8201..de6c6585e9 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.h
@@ -134,6 +134,8 @@ public:
void interrupt();
void flush();
+ bool event(QEvent *);
+
friend void qt_mac_maybeCancelWaitForMoreEventsForwarder(QAbstractEventDispatcher *eventDispatcher);
};
@@ -163,7 +165,6 @@ public:
// The following variables help organizing modal sessions:
QStack<QCocoaModalSessionInfo> cocoaModalSessionStack;
bool currentExecIsNSAppRun;
- bool modalSessionOnNSAppRun;
bool nsAppRunCalledByQt;
bool cleanupModalSessionsNeeded;
uint processEventsCalled;
diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
index 495a54cac4..e0ce9f9648 100644
--- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
+++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm
@@ -734,13 +734,25 @@ void QCocoaEventDispatcherPrivate::beginModalSession(QWindow *window)
updateChildrenWorksWhenModal();
currentModalSessionCached = 0;
if (currentExecIsNSAppRun) {
- modalSessionOnNSAppRun = true;
- q->wakeUp();
+ QEvent *e = new QEvent(QEvent::User);
+ qApp->postEvent(q, e, Qt::HighEventPriority);
} else {
q->interrupt();
}
}
+bool QCocoaEventDispatcher::event(QEvent *e)
+{
+ Q_D(QCocoaEventDispatcher);
+
+ if (e->type() == QEvent::User) {
+ d->q_func()->processEvents(QEventLoop::DialogExec | QEventLoop::EventLoopExec | QEventLoop::WaitForMoreEvents);
+ return true;
+ }
+
+ return QObject::event(e);
+}
+
void QCocoaEventDispatcherPrivate::endModalSession(QWindow *window)
{
Q_Q(QCocoaEventDispatcher);
@@ -777,7 +789,6 @@ QCocoaEventDispatcherPrivate::QCocoaEventDispatcherPrivate()
runLoopTimerRef(0),
blockSendPostedEvents(false),
currentExecIsNSAppRun(false),
- modalSessionOnNSAppRun(false),
nsAppRunCalledByQt(false),
cleanupModalSessionsNeeded(false),
processEventsCalled(0),
@@ -908,14 +919,6 @@ void QCocoaEventDispatcherPrivate::postedEventsSourceCallback(void *info)
// processEvents() was called "manually," ignore this source for now
d->maybeCancelWaitForMoreEvents();
return;
- } else if (d->modalSessionOnNSAppRun) {
- // We're about to spawn the 1st modal session on top of the main runloop.
- // Instead of calling processPostedEvents(), which would need us stop
- // NSApp, we just re-enter processEvents(). This is equivalent to calling
- // QDialog::exec() except that it's done in a non-blocking way.
- d->modalSessionOnNSAppRun = false;
- d->q_func()->processEvents(QEventLoop::DialogExec | QEventLoop::EventLoopExec | QEventLoop::WaitForMoreEvents);
- return;
}
d->processPostedEvents();
d->maybeCancelWaitForMoreEvents();
diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm
index e2572d607a..5d20764c87 100644
--- a/src/plugins/platforms/cocoa/qnsview.mm
+++ b/src/plugins/platforms/cocoa/qnsview.mm
@@ -680,8 +680,12 @@ static NSString *_q_NSWindowDidChangeOcclusionStateNotification = nil;
if (m_platformWindow->m_activePopupWindow) {
QWindowSystemInterface::handleCloseEvent(m_platformWindow->m_activePopupWindow);
QWindowSystemInterface::flushWindowSystemEvents();
+ Qt::WindowType type = m_platformWindow->m_activePopupWindow->type();
m_platformWindow->m_activePopupWindow = 0;
- return;
+ // Consume the mouse event when closing the popup, except for tool tips
+ // were it's expected that the event is processed normally.
+ if (type != Qt::ToolTip)
+ return;
}
if ([self hasMarkedText]) {
NSInputManager* inputManager = [NSInputManager currentInputManager];
diff --git a/src/plugins/platforms/ios/quiview_textinput.mm b/src/plugins/platforms/ios/quiview_textinput.mm
index 28fb23d57b..3f6c6d1256 100644
--- a/src/plugins/platforms/ios/quiview_textinput.mm
+++ b/src/plugins/platforms/ios/quiview_textinput.mm
@@ -473,6 +473,8 @@ Q_GLOBAL_STATIC(StaticVariables, staticVariables);
QCoreApplication::sendEvent(focusObject, &e);
QFont qfont = qvariant_cast<QFont>(e.value(Qt::ImFont));
UIFont *uifont = [UIFont fontWithName:qfont.family().toNSString() size:qfont.pointSize()];
+ if (!uifont)
+ return [NSDictionary dictionary];
return [NSDictionary dictionaryWithObject:uifont forKey:UITextInputTextFontKey];
}
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
index 1432dfdcd9..940d75614c 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp
@@ -1040,7 +1040,11 @@ QWindowsFontDatabase::~QWindowsFontDatabase()
QFontEngineMulti *QWindowsFontDatabase::fontEngineMulti(QFontEngine *fontEngine, QChar::Script script)
{
- return new QWindowsMultiFontEngine(fontEngine, script);
+ if (script == QChar::Script_Common)
+ return new QWindowsMultiFontEngine(fontEngine, script);
+ // ### as long as fallbacksForFamily() does not take script parameter into account,
+ // prefer QFontEngineMultiQPA's loadEngine() implementation for complex scripts
+ return QPlatformFontDatabase::fontEngineMulti(fontEngine, script);
}
QFontEngine * QWindowsFontDatabase::fontEngine(const QFontDef &fontDef, void *handle)
@@ -1619,8 +1623,7 @@ QStringList QWindowsFontDatabase::fallbacksForFamily(const QString &family, QFon
result << QString::fromLatin1("Arial");
}
- if (script == QChar::Script_Common || script == QChar::Script_Han)
- result.append(QWindowsFontDatabase::extraTryFontsForFamily(family));
+ result.append(QWindowsFontDatabase::extraTryFontsForFamily(family));
qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
<< script << result << m_families.size();
diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
index 51961014d9..734f645e65 100644
--- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
+++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp
@@ -477,8 +477,7 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF
}
#endif
- if (script == QChar::Script_Common || script == QChar::Script_Han)
- result.append(QWindowsFontDatabase::extraTryFontsForFamily(family));
+ result.append(QWindowsFontDatabase::extraTryFontsForFamily(family));
qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
<< script << result << m_families;
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index 2e38f81499..583441f396 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -1020,7 +1020,9 @@ HRESULT QWinRTScreen::onOrientationChanged(IInspectable *)
HRESULT QWinRTScreen::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args)
{
QKeyEvent backPress(QEvent::KeyPress, Qt::Key_Back, Qt::NoModifier);
+ QKeyEvent backRelease(QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier);
backPress.setAccepted(false);
+ backRelease.setAccepted(false);
QObject *receiver = m_visibleWindows.isEmpty()
? static_cast<QObject *>(QGuiApplication::instance())
@@ -1028,12 +1030,8 @@ HRESULT QWinRTScreen::onBackButtonPressed(IInspectable *, IBackPressedEventArgs
// If the event is ignored, the app will suspend
QGuiApplication::sendEvent(receiver, &backPress);
- if (backPress.isAccepted()) {
- args->put_Handled(true);
- // If the app accepts the event, send the release for symmetry
- QKeyEvent backRelease(QEvent::KeyRelease, Qt::Key_Back, Qt::NoModifier);
- QGuiApplication::sendEvent(receiver, &backRelease);
- }
+ QGuiApplication::sendEvent(receiver, &backRelease);
+ args->put_Handled(backPress.isAccepted() || backRelease.isAccepted());
return S_OK;
}
diff --git a/src/plugins/platforms/xcb/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp
index c183deb3b8..f78d3bcc4e 100644
--- a/src/plugins/platforms/xcb/qglxintegration.cpp
+++ b/src/plugins/platforms/xcb/qglxintegration.cpp
@@ -449,12 +449,32 @@ bool QGLXContext::m_supportsThreading = true;
// binary search.
static const char *qglx_threadedgl_blacklist_renderer[] = {
"Chromium", // QTBUG-32225 (initialization fails)
- "Mesa DRI Intel(R) Sandybridge Mobile", // QTBUG-34492 (flickering in fullscreen)
0
};
+// This disables threaded rendering on anything using mesa, e.g.
+// - nvidia/nouveau
+// - amd/gallium
+// - intel
+// - some software opengl implementations
+//
+// The client glx vendor string is used to identify those setups as that seems to show the least
+// variance between the bad configurations. It's always "Mesa Project and SGI". There are some
+// configurations which don't use mesa and which can do threaded rendering (amd and nvidia chips
+// with their own proprietary drivers).
+//
+// This, of course, is very broad and disables threaded rendering on a lot of devices which would
+// be able to use it. However, the bugs listed below don't follow any easily recognizable pattern
+// and we should rather be safe.
+//
+// http://cgit.freedesktop.org/xcb/libxcb/commit/?id=be0fe56c3bcad5124dcc6c47a2fad01acd16f71a will
+// fix some of the issues. Basically, the proprietary drivers seem to have a way of working around
+// a fundamental flaw with multithreaded access to xcb, but mesa doesn't. The blacklist should be
+// reevaluated once that patch is released in some version of xcb.
static const char *qglx_threadedgl_blacklist_vendor[] = {
- "nouveau", // QTCREATORBUG-10875 (crash in creator)
+ "Mesa Project and SGI", // QTCREATORBUG-10875 (crash in creator)
+ // QTBUG-34492 (flickering in fullscreen)
+ // QTBUG-38221
0
};
@@ -502,9 +522,9 @@ void QGLXContext::queryDummyContext()
}
}
- if (const char *vendor = (const char *) glGetString(GL_VENDOR)) {
+ if (glxvendor) {
for (int i = 0; qglx_threadedgl_blacklist_vendor[i]; ++i) {
- if (strstr(vendor, qglx_threadedgl_blacklist_vendor[i]) != 0) {
+ if (strstr(glxvendor, qglx_threadedgl_blacklist_vendor[i]) != 0) {
m_supportsThreading = false;
break;
}
diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h
index a994c51c7d..13a0280baf 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.h
+++ b/src/plugins/platforms/xcb/qxcbconnection.h
@@ -454,6 +454,10 @@ public:
QXcbSystemTrayTracker *systemTrayTracker();
+#ifdef XCB_USE_XINPUT2
+ void handleEnterEvent(const xcb_enter_notify_event_t *);
+#endif
+
private slots:
void processXcbEvents();
diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
index d80b49ccbb..d7b3c75aee 100644
--- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp
@@ -524,6 +524,35 @@ void QXcbConnection::xi2HandleEvent(xcb_ge_event_t *event)
}
}
+void QXcbConnection::handleEnterEvent(const xcb_enter_notify_event_t *)
+{
+#ifdef XCB_USE_XINPUT21
+ QHash<int, ScrollingDevice>::iterator it = m_scrollingDevices.begin();
+ const QHash<int, ScrollingDevice>::iterator end = m_scrollingDevices.end();
+ while (it != end) {
+ ScrollingDevice& scrollingDevice = it.value();
+ int nrDevices = 0;
+ XIDeviceInfo* xiDeviceInfo = XIQueryDevice(static_cast<Display *>(m_xlib_display), scrollingDevice.deviceId, &nrDevices);
+ if (nrDevices <= 0) {
+ it = m_scrollingDevices.erase(it);
+ continue;
+ }
+ for (int c = 0; c < xiDeviceInfo->num_classes; ++c) {
+ if (xiDeviceInfo->classes[c]->type == XIValuatorClass) {
+ XIValuatorClassInfo *vci = reinterpret_cast<XIValuatorClassInfo *>(xiDeviceInfo->classes[c]);
+ const int valuatorAtom = qatom(vci->label);
+ if (valuatorAtom == QXcbAtom::RelHorizScroll || valuatorAtom == QXcbAtom::RelHorizWheel)
+ scrollingDevice.lastScrollPosition.setX(vci->value);
+ else if (valuatorAtom == QXcbAtom::RelVertScroll || valuatorAtom == QXcbAtom::RelVertWheel)
+ scrollingDevice.lastScrollPosition.setY(vci->value);
+ }
+ }
+ XIFreeDeviceInfo(xiDeviceInfo);
+ ++it;
+ }
+#endif
+}
+
void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollingDevice)
{
#ifdef XCB_USE_XINPUT21
diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp
index dbffd577c1..fb9c03b66d 100644
--- a/src/plugins/platforms/xcb/qxcbwindow.cpp
+++ b/src/plugins/platforms/xcb/qxcbwindow.cpp
@@ -1844,6 +1844,9 @@ public:
void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *event)
{
connection()->setTime(event->time);
+#ifdef XCB_USE_XINPUT2
+ connection()->handleEnterEvent(event);
+#endif
if ((event->mode != XCB_NOTIFY_MODE_NORMAL && event->mode != XCB_NOTIFY_MODE_UNGRAB)
|| event->detail == XCB_NOTIFY_DETAIL_VIRTUAL
diff --git a/src/plugins/printsupport/windows/windows.pro b/src/plugins/printsupport/windows/windows.pro
index 364e19e68e..3366262ef0 100644
--- a/src/plugins/printsupport/windows/windows.pro
+++ b/src/plugins/printsupport/windows/windows.pro
@@ -21,4 +21,4 @@ HEADERS += \
OTHER_FILES += windows.json
-LIBS += -lwinspool -lcomdlg32
+LIBS += -lwinspool -lcomdlg32 -lgdi32 -luser32
diff --git a/src/printsupport/dialogs/qprintdialog_mac.mm b/src/printsupport/dialogs/qprintdialog_mac.mm
index 9ff7c4766a..ef3e88be39 100644
--- a/src/printsupport/dialogs/qprintdialog_mac.mm
+++ b/src/printsupport/dialogs/qprintdialog_mac.mm
@@ -143,11 +143,11 @@ QT_USE_NAMESPACE
CFURLGetFileSystemRepresentation(file, true, localFile, sizeof(localFile));
printer->setOutputFileName(QString::fromUtf8(reinterpret_cast<const char *>(localFile)));
} else {
- // Keep output format.
- QPrinter::OutputFormat format;
- format = printer->outputFormat();
- printer->setOutputFileName(QString());
- printer->setOutputFormat(format);
+ PMPrinter macPrinter;
+ PMSessionGetCurrentPrinter(session, &macPrinter);
+ QString printerId = QString::fromCFString(PMPrinterGetID(macPrinter));
+ if (printer->printerName() != printerId)
+ printer->setPrinterName(printerId);
}
}
@@ -160,13 +160,13 @@ QT_USE_NAMESPACE
PMOrientation orientation;
PMGetOrientation(pageFormat, &orientation);
QPageSize pageSize;
- QCFString key;
+ CFStringRef key;
double width = 0;
double height = 0;
// If the PPD name is empty then is custom, for some reason PMPaperIsCustom doesn't work here
PMPaperGetPPDPaperName(paper, &key);
if (PMPaperGetWidth(paper, &width) == noErr && PMPaperGetHeight(paper, &height) == noErr) {
- QString ppdKey = key;
+ QString ppdKey = QString::fromCFString(key);
if (ppdKey.isEmpty()) {
// Is using a custom page size as defined in the Print Dialog custom settings using mm or inches.
// We can't ask PMPaper what those units actually are, we can only get the point size which may return
@@ -185,7 +185,7 @@ QT_USE_NAMESPACE
pageSize = QPageSize(QSizeF(w / 100.0, h / 100.0), QPageSize::Inch);
}
} else {
- pageSize = QPlatformPrintDevice::createPageSize(key, QSize(width, height), QString());
+ pageSize = QPlatformPrintDevice::createPageSize(ppdKey, QSize(width, height), QString());
}
}
if (pageSize.isValid() && !pageSize.isEquivalentTo(printer->pageLayout().pageSize()))
diff --git a/src/printsupport/printsupport.pro b/src/printsupport/printsupport.pro
index b32ba91c07..6dd3eaab3c 100644
--- a/src/printsupport/printsupport.pro
+++ b/src/printsupport/printsupport.pro
@@ -1,7 +1,6 @@
TARGET = QtPrintSupport
QT = core-private gui-private widgets-private
-MODULE_CONFIG = needs_printsupport_plugin
DEFINES += QT_NO_USING_NAMESPACE
MODULE_PLUGIN_TYPES = \
diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp
index ed376fe923..d90e2f5163 100644
--- a/src/widgets/kernel/qapplication.cpp
+++ b/src/widgets/kernel/qapplication.cpp
@@ -336,6 +336,15 @@ QApplicationPrivate::~QApplicationPrivate()
*/
/*!
+ \fn QApplication::setGraphicsSystem(const QString &)
+ \obsolete
+
+ This call has no effect.
+
+ Use the QPA framework instead.
+*/
+
+/*!
\fn QWidget *QApplication::topLevelAt(const QPoint &point)
Returns the top-level widget at the given \a point; returns 0 if
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 7eecd3d84d..f79eaf197d 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -8525,6 +8525,8 @@ void QWidget::mouseReleaseEvent(QMouseEvent *event)
This event handler, for event \a event, can be reimplemented in a
subclass to receive mouse double click events for the widget.
+ The default implementation calls mousePressEvent().
+
\note The widget will also receive mouse press and mouse release
events in addition to the double click event. It is up to the
developer to ensure that the application interprets these events
@@ -8536,7 +8538,7 @@ void QWidget::mouseReleaseEvent(QMouseEvent *event)
void QWidget::mouseDoubleClickEvent(QMouseEvent *event)
{
- event->ignore();
+ mousePressEvent(event);
}
#ifndef QT_NO_WHEELEVENT