Merge "Merge remote-tracking branch 'origin/release' into stable" into refs/staging/stable
This commit is contained in:
commit
16501e32eb
19
configure
vendored
19
configure
vendored
@ -616,7 +616,7 @@ CFG_EGL=auto
|
||||
CFG_EGL_X=auto
|
||||
CFG_FONTCONFIG=auto
|
||||
CFG_FREETYPE=auto
|
||||
CFG_HARFBUZZ=no
|
||||
CFG_HARFBUZZ=auto
|
||||
CFG_SQL_AVAILABLE=
|
||||
QT_ALL_BUILD_PARTS=" libs tools examples tests "
|
||||
QT_DEFAULT_BUILD_PARTS="libs tools examples"
|
||||
@ -781,8 +781,6 @@ QT_LIBS_GLIB=
|
||||
|
||||
# default qpa platform
|
||||
QT_QPA_DEFAULT_PLATFORM=
|
||||
# default print support plugin
|
||||
QT_PRINTSUPPORT_DEFAULT_PLUGIN=
|
||||
|
||||
# Android vars
|
||||
CFG_DEFAULT_ANDROID_NDK_ROOT=$ANDROID_NDK_ROOT
|
||||
@ -3126,7 +3124,7 @@ if [ "$XPLATFORM_IOS" = "yes" ]; then
|
||||
CFG_PKGCONFIG="no"
|
||||
CFG_NOBUILD_PARTS="$CFG_NOBUILD_PARTS examples"
|
||||
CFG_SHARED="no" # iOS builds should be static to be able to submit to the App Store
|
||||
CFG_SKIP_MODULES="$CFG_SKIP_MODULES qtconnectivity qtdoc qtmacextras qtserialport qttools qtwebkit qtwebkit-examples"
|
||||
CFG_SKIP_MODULES="$CFG_SKIP_MODULES qtconnectivity qtdoc qtmacextras qtserialport qtwebkit qtwebkit-examples"
|
||||
|
||||
# If the user passes -sdk on the command line we build a SDK-specific Qt build.
|
||||
# Otherwise we build a joined simulator and device build, which is the default.
|
||||
@ -5206,15 +5204,6 @@ if [ -z "$QT_QPA_DEFAULT_PLATFORM" ]; then
|
||||
fi
|
||||
fi
|
||||
|
||||
# Determine print support plugin belonging to the default QPA platform
|
||||
if [ "$QT_QPA_DEFAULT_PLATFORM" = "cocoa" ]; then
|
||||
QT_PRINTSUPPORT_DEFAULT_PLUGIN=cocoaprintersupport
|
||||
elif [ "$QT_QPA_DEFAULT_PLATFORM" = "windows" ]; then
|
||||
QT_PRINTSUPPORT_DEFAULT_PLUGIN=windowsprintersupport
|
||||
elif [ "$QT_QPA_DEFAULT_PLATFORM" = "xcb" ]; then
|
||||
QT_PRINTSUPPORT_DEFAULT_PLUGIN=cupsprintersupport
|
||||
fi
|
||||
|
||||
if [ -n "$QMAKE_CFLAGS_XCB" ] || [ -n "$QMAKE_LIBS_XCB" ]; then
|
||||
QMakeVar set QMAKE_CFLAGS_XCB "$QMAKE_CFLAGS_XCB"
|
||||
QMakeVar set QMAKE_LIBS_XCB "$QMAKE_LIBS_XCB"
|
||||
@ -5258,8 +5247,8 @@ if [ "$CFG_FREETYPE" = "auto" ]; then
|
||||
fi
|
||||
|
||||
# harfbuzz support
|
||||
[ "$XPLATFORM_MINGW" = "yes" ] && [ "$CFG_HARFBUZZ" = "auto" ] && CFG_HARFBUZZ=no
|
||||
[ "$XPLATFORM_MAC" = "yes" ] && [ "$CFG_HARFBUZZ" = "auto" ] && CFG_HARFBUZZ=yes
|
||||
[ "$CFG_HARFBUZZ" = "auto" ] && CFG_HARFBUZZ=no # disable auto-detection on non-Mac for now
|
||||
if [ "$CFG_HARFBUZZ" = "auto" ]; then
|
||||
if compileTest unix/harfbuzz "HarfBuzz"; then
|
||||
CFG_HARFBUZZ=system
|
||||
@ -6174,7 +6163,6 @@ EOF
|
||||
fi
|
||||
|
||||
echo "#define QT_QPA_DEFAULT_PLATFORM_NAME \"$QT_QPA_DEFAULT_PLATFORM\"" >>"$outpath/src/corelib/global/qconfig.h.new"
|
||||
echo "#define QT_QPA_DEFAULT_PRINTSUPPORTPLUGIN_NAME \"QT_PRINTSUPPORT_DEFAULT_PLUGIN\"" >>"$outpath/src/corelib/global/qconfig.h.new"
|
||||
|
||||
# avoid unecessary rebuilds by copying only if qconfig.h has changed
|
||||
if cmp -s "$outpath/src/corelib/global/qconfig.h" "$outpath/src/corelib/global/qconfig.h.new"; then
|
||||
@ -6244,7 +6232,6 @@ EOF
|
||||
|
||||
if [ "$CFG_SHARED" = "no" ]; then
|
||||
echo "QT_DEFAULT_QPA_PLUGIN = q$QT_QPA_DEFAULT_PLATFORM" >> "$QTCONFIG.tmp"
|
||||
echo "QT_DEFAULT_PRINTSUPPORTPLUGIN = $QT_PRINTSUPPORT_DEFAULT_PLUGIN" >> "$QTCONFIG.tmp"
|
||||
echo >> "$QTCONFIG.tmp"
|
||||
fi
|
||||
|
||||
|
@ -19,6 +19,7 @@ defines += Q_QDOC \
|
||||
Q_COMPILER_RVALUE_REFS
|
||||
|
||||
Cpp.ignoretokens += \
|
||||
ENGINIOCLIENT_EXPORT \
|
||||
PHONON_EXPORT \
|
||||
Q_AUTOTEST_EXPORT \
|
||||
Q_BLUETOOTH_EXPORT \
|
||||
|
@ -204,8 +204,6 @@ contains(QT_CONFIG, static) {
|
||||
else: \
|
||||
QTPLUGIN += $$QT_DEFAULT_QPA_PLUGIN
|
||||
}
|
||||
needs_printsupport_plugin: \
|
||||
QTPLUGIN += $$QT_DEFAULT_PRINTSUPPORTPLUGIN
|
||||
import_plugins:!isEmpty(QTPLUGIN) {
|
||||
IMPORT_FILE_CONT = \
|
||||
"// This file is autogenerated by qmake. It imports static plugin classes for" \
|
||||
|
@ -488,7 +488,7 @@ bool Option::postProcessProject(QMakeProject *project)
|
||||
|
||||
Option::dir_sep = project->dirSep().toQString();
|
||||
|
||||
if (Option::output_dir.startsWith(project->buildRoot()))
|
||||
if (!project->buildRoot().isEmpty() && Option::output_dir.startsWith(project->buildRoot()))
|
||||
Option::mkfile::cachefile_depth =
|
||||
Option::output_dir.mid(project->buildRoot().length()).count('/');
|
||||
|
||||
|
@ -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.
|
||||
|
@ -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;
|
||||
|
||||
|
3
src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
vendored
3
src/3rdparty/harfbuzz-ng/harfbuzz-ng.pro
vendored
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 += ..
|
||||
|
||||
|
@ -842,21 +842,28 @@
|
||||
#endif /* Q_CC_MSVC */
|
||||
|
||||
#ifdef __cplusplus
|
||||
# if defined(Q_OS_QNX)
|
||||
# include <utility>
|
||||
# if defined(Q_OS_QNX)
|
||||
# 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
|
||||
// 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
|
||||
#endif // Q_OS_QNX
|
||||
#endif
|
||||
|
||||
/*
|
||||
* C++11 keywords and expressions
|
||||
|
@ -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}
|
||||
*/
|
||||
|
||||
/*!
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -417,6 +417,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.
|
||||
*/
|
||||
|
@ -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,22 +689,52 @@ 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))
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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*)));
|
||||
|
@ -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;
|
||||
|
@ -2011,12 +2011,6 @@ void QOpenGLFunctions::initializeOpenGLFunctions()
|
||||
This convenience function will do nothing on OpenGL ES 1.x systems.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\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");
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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,25 +328,22 @@ 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;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static qint64 nativeWrite(T *socket, const char *data, qint64 len)
|
||||
{
|
||||
ComPtr<IOutputStream> stream;
|
||||
HRESULT hr = socket->get_OutputStream(&stream);
|
||||
if (FAILED(hr))
|
||||
return -1;
|
||||
ComPtr<ByteArrayBuffer> buffer = Make<ByteArrayBuffer>(data, len);
|
||||
ComPtr<IAsyncOperationWithProgress<UINT32, UINT32>> op;
|
||||
hr = stream->WriteAsync(buffer.Get(), &op);
|
||||
if (FAILED(hr))
|
||||
return -1;
|
||||
UINT32 bytesWritten;
|
||||
while ((hr = op->GetResults(&bytesWritten)) == E_ILLEGAL_METHOD_CALL)
|
||||
QCoreApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
return bytesWritten;
|
||||
QMutexLocker mutexLocker(&d->readMutex);
|
||||
return d->readBytes.read(data, maxlen);
|
||||
}
|
||||
|
||||
qint64 QNativeSocketEngine::write(const char *data, qint64 len)
|
||||
{
|
||||
Q_D(QNativeSocketEngine);
|
||||
qint64 bytesWritten = -1;
|
||||
HRESULT hr = E_FAIL;
|
||||
ComPtr<IOutputStream> stream;
|
||||
if (d->socketType == QAbstractSocket::TcpSocket)
|
||||
bytesWritten = nativeWrite(d->tcp, data, len);
|
||||
hr = d->tcp->get_OutputStream(&stream);
|
||||
else if (d->socketType == QAbstractSocket::UdpSocket)
|
||||
bytesWritten = nativeWrite(d->udp, data, len);
|
||||
if (bytesWritten != -1 && d->notifyOnWrite)
|
||||
writeNotification();
|
||||
return bytesWritten;
|
||||
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)) {
|
||||
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;
|
||||
hr = op->GetResults(&bytesWritten);
|
||||
if (FAILED(hr)) {
|
||||
qErrnoWarning(hr, "Failed to get written socket length.");
|
||||
return -1;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
HRESULT QNativeSocketEnginePrivate::interruptEventDispatcher(IAsyncAction *, AsyncStatus)
|
||||
{
|
||||
if (QThread *thread = QThread::currentThread()) {
|
||||
if (QAbstractEventDispatcher *dispatcher = thread->eventDispatcher())
|
||||
dispatcher->interrupt();
|
||||
}
|
||||
emit q->connectionReady();
|
||||
emit q->readReady();
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncOperationWithProgress<IBuffer *, UINT32> *asyncInfo, AsyncStatus)
|
||||
HRESULT QNativeSocketEnginePrivate::handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus)
|
||||
{
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
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;
|
||||
if (len > 0 && q->isReadNotificationEnabled()) {
|
||||
q->readNotification();
|
||||
}
|
||||
|
||||
// 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);
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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();
|
||||
|
@ -680,7 +680,11 @@ 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;
|
||||
// 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]) {
|
||||
|
@ -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];
|
||||
}
|
||||
|
||||
|
@ -1040,7 +1040,11 @@ QWindowsFontDatabase::~QWindowsFontDatabase()
|
||||
|
||||
QFontEngineMulti *QWindowsFontDatabase::fontEngineMulti(QFontEngine *fontEngine, QChar::Script 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,7 +1623,6 @@ 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));
|
||||
|
||||
qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
|
||||
|
@ -477,7 +477,6 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString &family, QF
|
||||
}
|
||||
#endif
|
||||
|
||||
if (script == QChar::Script_Common || script == QChar::Script_Han)
|
||||
result.append(QWindowsFontDatabase::extraTryFontsForFamily(family));
|
||||
|
||||
qCDebug(lcQpaFonts) << __FUNCTION__ << family << style << styleHint
|
||||
|
@ -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);
|
||||
}
|
||||
args->put_Handled(backPress.isAccepted() || backRelease.isAccepted());
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -454,6 +454,10 @@ public:
|
||||
|
||||
QXcbSystemTrayTracker *systemTrayTracker();
|
||||
|
||||
#ifdef XCB_USE_XINPUT2
|
||||
void handleEnterEvent(const xcb_enter_notify_event_t *);
|
||||
#endif
|
||||
|
||||
private slots:
|
||||
void processXcbEvents();
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -21,4 +21,4 @@ HEADERS += \
|
||||
|
||||
OTHER_FILES += windows.json
|
||||
|
||||
LIBS += -lwinspool -lcomdlg32
|
||||
LIBS += -lwinspool -lcomdlg32 -lgdi32 -luser32
|
||||
|
@ -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()))
|
||||
|
@ -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 = \
|
||||
|
@ -335,6 +335,15 @@ QApplicationPrivate::~QApplicationPrivate()
|
||||
See setColorSpec() for full details.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QApplication::setGraphicsSystem(const QString &)
|
||||
\obsolete
|
||||
|
||||
This call has no effect.
|
||||
|
||||
Use the QPA framework instead.
|
||||
*/
|
||||
|
||||
/*!
|
||||
\fn QWidget *QApplication::topLevelAt(const QPoint &point)
|
||||
|
||||
|
@ -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
|
||||
|
@ -309,9 +309,6 @@ void tst_QTextLayout::simpleBoundingRect()
|
||||
|
||||
void tst_QTextLayout::threeLineBoundingRect()
|
||||
{
|
||||
#if defined(Q_OS_MAC)
|
||||
QSKIP("QTestFontEngine on the mac does not support logclusters at the moment");
|
||||
#endif
|
||||
/* stricter check. break text into three lines */
|
||||
|
||||
QString firstWord("hello");
|
||||
@ -430,9 +427,6 @@ void tst_QTextLayout::forcedBreaks()
|
||||
|
||||
void tst_QTextLayout::breakAny()
|
||||
{
|
||||
#if defined(Q_OS_MAC)
|
||||
QSKIP("QTestFontEngine on the mac does not support logclusters at the moment");
|
||||
#endif
|
||||
QString text = "ABCD";
|
||||
|
||||
QTextLayout layout(text, testFont);
|
||||
@ -473,9 +467,6 @@ void tst_QTextLayout::breakAny()
|
||||
|
||||
void tst_QTextLayout::noWrap()
|
||||
{
|
||||
#if defined(Q_OS_MAC)
|
||||
QSKIP("QTestFontEngine on the mac does not support logclusters at the moment");
|
||||
#endif
|
||||
QString text = "AB CD";
|
||||
|
||||
QTextLayout layout(text, testFont);
|
||||
@ -1048,9 +1039,6 @@ void tst_QTextLayout::charWordStopOnLineSeparator()
|
||||
|
||||
void tst_QTextLayout::xToCursorAtEndOfLine()
|
||||
{
|
||||
#if defined(Q_OS_MAC)
|
||||
QSKIP("QTestFontEngine on the mac does not support logclusters at the moment");
|
||||
#endif
|
||||
QString text = "FirstLine SecondLine";
|
||||
text.replace('\n', QChar::LineSeparator);
|
||||
|
||||
@ -1112,9 +1100,6 @@ void tst_QTextLayout::graphemeBoundaryForSurrogatePairs()
|
||||
|
||||
void tst_QTextLayout::tabStops()
|
||||
{
|
||||
#if defined(Q_OS_MAC)
|
||||
QSKIP("QTestFontEngine on the mac does not support logclusters at the moment");
|
||||
#endif
|
||||
QString txt("Hello there\tworld");
|
||||
QTextLayout layout(txt, testFont);
|
||||
layout.beginLayout();
|
||||
@ -1931,13 +1916,16 @@ void tst_QTextLayout::textWithSurrogates_qtbug15679()
|
||||
void tst_QTextLayout::textWidthWithStackedTextEngine()
|
||||
{
|
||||
QString text = QString::fromUtf8("คลิก ถัดไป เพื่อดำเนินการต่อ");
|
||||
|
||||
QTextLayout layout(text);
|
||||
layout.setCacheEnabled(true);
|
||||
layout.beginLayout();
|
||||
QTextLine line = layout.createLine();
|
||||
layout.endLayout();
|
||||
QFontMetricsF fm(layout.font());
|
||||
QCOMPARE(line.naturalTextWidth(), fm.width(text));
|
||||
|
||||
QStackTextEngine layout2(text, layout.font());
|
||||
|
||||
QVERIFY(layout2.width(0, text.size()).toReal() >= line.naturalTextWidth());
|
||||
}
|
||||
|
||||
void tst_QTextLayout::textWidthWithLineSeparator()
|
||||
@ -1958,27 +1946,24 @@ void tst_QTextLayout::textWidthWithLineSeparator()
|
||||
|
||||
void tst_QTextLayout::cursorInLigatureWithMultipleLines()
|
||||
{
|
||||
#if !defined(Q_OS_MAC)
|
||||
QSKIP("This test can only be run on Mac");
|
||||
#endif
|
||||
QTextLayout layout("first line finish", QFont("Times", 20));
|
||||
layout.setCacheEnabled(true);
|
||||
layout.beginLayout();
|
||||
QTextLine line = layout.createLine();
|
||||
line.setLineWidth(70);
|
||||
line = layout.createLine();
|
||||
line.setNumColumns(10);
|
||||
QTextLine line2 = layout.createLine();
|
||||
layout.endLayout();
|
||||
|
||||
// The second line will be "finish", with "fi" as a ligature
|
||||
QEXPECT_FAIL("", "QTBUG-26403", Abort);
|
||||
QVERIFY(line.cursorToX(0) != line.cursorToX(1));
|
||||
// The second line will be "finish"
|
||||
QCOMPARE(layout.text().mid(line2.textStart(), line2.textLength()), QString::fromLatin1("finish"));
|
||||
|
||||
QVERIFY(line.cursorToX(1) != line.cursorToX(0));
|
||||
QCOMPARE(line2.cursorToX(line2.textStart()), line.cursorToX(0));
|
||||
QCOMPARE(line2.cursorToX(line2.textStart() + 1), line.cursorToX(1));
|
||||
}
|
||||
|
||||
void tst_QTextLayout::xToCursorForLigatures()
|
||||
{
|
||||
#if !defined(Q_OS_MAC)
|
||||
QSKIP("This test can only be run on Mac");
|
||||
#endif
|
||||
QTextLayout layout("fi", QFont("Times", 20));
|
||||
layout.setCacheEnabled(true);
|
||||
layout.beginLayout();
|
||||
@ -2001,9 +1986,6 @@ void tst_QTextLayout::xToCursorForLigatures()
|
||||
|
||||
void tst_QTextLayout::cursorInNonStopChars()
|
||||
{
|
||||
#if defined(Q_OS_MAC)
|
||||
QSKIP("This test can not be run on Mac");
|
||||
#endif
|
||||
QTextLayout layout(QString::fromUtf8("\xE0\xA4\xA4\xE0\xA5\x8D\xE0\xA4\xA8"));
|
||||
layout.setCacheEnabled(true);
|
||||
layout.beginLayout();
|
||||
|
@ -1105,6 +1105,9 @@ void tst_QTextScriptEngine::mirroredChars()
|
||||
|
||||
void tst_QTextScriptEngine::controlInSyllable_qtbug14204()
|
||||
{
|
||||
#ifdef Q_OS_MAC
|
||||
QSKIP("Result differs for HarfBuzz-NG, skip test.");
|
||||
#endif
|
||||
QFontDatabase db;
|
||||
if (!db.families().contains(QStringLiteral("Aparajita")))
|
||||
QSKIP("couldn't find 'Aparajita' font");
|
||||
@ -1143,6 +1146,10 @@ void tst_QTextScriptEngine::combiningMarks_qtbug15675_data()
|
||||
QTest::addColumn<QFont>("font");
|
||||
QTest::addColumn<QString>("string");
|
||||
|
||||
#ifdef Q_OS_MAC
|
||||
QSKIP("Result differs for HarfBuzz-NG, skip test.");
|
||||
#endif
|
||||
|
||||
bool hasTests = false;
|
||||
|
||||
QStringList families;
|
||||
@ -1251,36 +1258,37 @@ void tst_QTextScriptEngine::thaiWithZWJ()
|
||||
QTextLayout layout(s, font);
|
||||
QTextEngine *e = layout.engine();
|
||||
e->itemize();
|
||||
QCOMPARE(e->layoutData->items.size(), 11);
|
||||
QCOMPARE(e->layoutData->items.size(), 3);
|
||||
|
||||
for (int item = 0; item < e->layoutData->items.size(); ++item)
|
||||
e->shape(item);
|
||||
|
||||
QCOMPARE(e->layoutData->items[0].num_glyphs, ushort(7)); // Thai: The ZWJ and ZWNJ characters are inherited, so should be part of the thai script
|
||||
QCOMPARE(e->layoutData->items[1].num_glyphs, ushort(1)); // Common: The smart quotes cannot be handled by thai, so should be a separate item
|
||||
QCOMPARE(e->layoutData->items[2].num_glyphs, ushort(1)); // Thai: Thai character
|
||||
QCOMPARE(e->layoutData->items[3].num_glyphs, ushort(1)); // Common: Ellipsis
|
||||
QCOMPARE(e->layoutData->items[4].num_glyphs, ushort(1)); // Thai: Thai character
|
||||
QCOMPARE(e->layoutData->items[5].num_glyphs, ushort(1)); // Common: Smart quote
|
||||
QCOMPARE(e->layoutData->items[6].num_glyphs, ushort(1)); // Thai: Thai character
|
||||
QCOMPARE(e->layoutData->items[7].num_glyphs, ushort(1)); // Common: \xA0 = non-breaking space. Could be useful to have in thai, but not currently implemented
|
||||
QCOMPARE(e->layoutData->items[8].num_glyphs, ushort(1)); // Thai: Thai character
|
||||
QCOMPARE(e->layoutData->items[9].num_glyphs, ushort(1)); // Japanese: Kanji for tree
|
||||
QCOMPARE(e->layoutData->items[10].num_glyphs, ushort(2)); // Thai: Thai character followed by superscript "a" which is of inherited type
|
||||
QCOMPARE(e->layoutData->items[0].num_glyphs, ushort(15)); // Thai: The ZWJ and ZWNJ characters are inherited, so should be part of the thai script
|
||||
QCOMPARE(e->layoutData->items[1].num_glyphs, ushort(1)); // Han: Kanji for tree
|
||||
QCOMPARE(e->layoutData->items[2].num_glyphs, ushort(2)); // Thai: Thai character followed by superscript "a" which is of inherited type
|
||||
|
||||
//A quick sanity check - check all the characters are individual clusters
|
||||
unsigned short *logClusters = e->layoutData->logClustersPtr;
|
||||
for (int i = 0; i < 7; i++)
|
||||
for (int i = 0; i <= 14; i++)
|
||||
QCOMPARE(logClusters[i], ushort(i));
|
||||
for (int i = 0; i < 10; i++)
|
||||
QCOMPARE(logClusters[i+7], ushort(0));
|
||||
QCOMPARE(logClusters[15], ushort(0));
|
||||
QCOMPARE(logClusters[16], ushort(0));
|
||||
#ifndef Q_OS_MAC
|
||||
// ### Result differs for HarfBuzz-NG
|
||||
QCOMPARE(logClusters[17], ushort(1));
|
||||
#endif
|
||||
|
||||
// A thai implementation could either remove the ZWJ and ZWNJ characters, or hide them.
|
||||
// The current implementation hides them, so we test for that.
|
||||
// The only characters that we should be hiding are the ZWJ and ZWNJ characters in position 1 and 3.
|
||||
const QGlyphLayout glyphLayout = e->layoutData->glyphLayout;
|
||||
for (int i = 0; i < 18; i++) {
|
||||
#ifdef Q_OS_MAC
|
||||
// ### Result differs for HarfBuzz-NG
|
||||
if (i == 17)
|
||||
QCOMPARE(glyphLayout.advances[i].toInt(), 0);
|
||||
else
|
||||
#endif
|
||||
if (i == 1 || i == 3)
|
||||
QCOMPARE(glyphLayout.advances[i].toInt(), 0);
|
||||
else
|
||||
|
@ -679,7 +679,8 @@ void tst_QTabBar::tabBarClicked()
|
||||
QCOMPARE(doubleClickSpy.count(), 0);
|
||||
|
||||
QTest::mouseDClick(&tabBar, button, 0, tabPos);
|
||||
QCOMPARE(clickSpy.count(), 0);
|
||||
QCOMPARE(clickSpy.count(), 1);
|
||||
QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), 0);
|
||||
QCOMPARE(doubleClickSpy.count(), 1);
|
||||
QCOMPARE(doubleClickSpy.takeFirst().takeFirst().toInt(), 0);
|
||||
|
||||
@ -691,7 +692,8 @@ void tst_QTabBar::tabBarClicked()
|
||||
QCOMPARE(doubleClickSpy.count(), 0);
|
||||
|
||||
QTest::mouseDClick(&tabBar, button, 0, barPos);
|
||||
QCOMPARE(clickSpy.count(), 0);
|
||||
QCOMPARE(clickSpy.count(), 1);
|
||||
QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), -1);
|
||||
QCOMPARE(doubleClickSpy.count(), 1);
|
||||
QCOMPARE(doubleClickSpy.takeFirst().takeFirst().toInt(), -1);
|
||||
|
||||
|
@ -690,7 +690,8 @@ void tst_QTabWidget::tabBarClicked()
|
||||
QCOMPARE(doubleClickSpy.count(), 0);
|
||||
|
||||
QTest::mouseDClick(&tabBar, button, 0, tabPos);
|
||||
QCOMPARE(clickSpy.count(), 0);
|
||||
QCOMPARE(clickSpy.count(), 1);
|
||||
QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), 0);
|
||||
QCOMPARE(doubleClickSpy.count(), 1);
|
||||
QCOMPARE(doubleClickSpy.takeFirst().takeFirst().toInt(), 0);
|
||||
|
||||
@ -702,7 +703,8 @@ void tst_QTabWidget::tabBarClicked()
|
||||
QCOMPARE(doubleClickSpy.count(), 0);
|
||||
|
||||
QTest::mouseDClick(&tabBar, button, 0, barPos);
|
||||
QCOMPARE(clickSpy.count(), 0);
|
||||
QCOMPARE(clickSpy.count(), 1);
|
||||
QCOMPARE(clickSpy.takeFirst().takeFirst().toInt(), -1);
|
||||
QCOMPARE(doubleClickSpy.count(), 1);
|
||||
QCOMPARE(doubleClickSpy.takeFirst().takeFirst().toInt(), -1);
|
||||
|
||||
|
@ -3398,10 +3398,8 @@ void Configure::generateQConfigPri()
|
||||
if (!dictionary["QT_NAMESPACE"].isEmpty())
|
||||
configStream << "#namespaces" << endl << "QT_NAMESPACE = " << dictionary["QT_NAMESPACE"] << endl;
|
||||
|
||||
if (dictionary[ "SHARED" ] == "no") {
|
||||
configStream << "QT_DEFAULT_QPA_PLUGIN = q" << qpaPlatformName() << endl
|
||||
<< "QT_DEFAULT_PRINTSUPPORTPLUGIN = " << qpaPrintSupportPluginName() << endl;
|
||||
}
|
||||
if (dictionary[ "SHARED" ] == "no")
|
||||
configStream << "QT_DEFAULT_QPA_PLUGIN = q" << qpaPlatformName() << endl;
|
||||
|
||||
if (!configStream.flush())
|
||||
dictionary[ "DONE" ] = "error";
|
||||
@ -3574,8 +3572,7 @@ void Configure::generateConfigfiles()
|
||||
for (int i = 0; i < qconfigList.count(); ++i)
|
||||
tmpStream << addDefine(qconfigList.at(i));
|
||||
|
||||
tmpStream << "#define QT_QPA_DEFAULT_PLATFORM_NAME \"" << qpaPlatformName() << "\"" << endl
|
||||
<< "#define QT_QPA_DEFAULT_PRINTSUPPORTPLUGIN_NAME \"" << qpaPrintSupportPluginName() << "\"" << endl;
|
||||
tmpStream<<"#define QT_QPA_DEFAULT_PLATFORM_NAME \"" << qpaPlatformName() << "\""<<endl;
|
||||
|
||||
if (!tmpStream.flush())
|
||||
dictionary[ "DONE" ] = "error";
|
||||
@ -4475,11 +4472,6 @@ QString Configure::qpaPlatformName() const
|
||||
}
|
||||
}
|
||||
|
||||
QString Configure::qpaPrintSupportPluginName() const
|
||||
{
|
||||
return platform() == WINDOWS ? QStringLiteral("windowsprintersupport") : QString();
|
||||
}
|
||||
|
||||
int Configure::platform() const
|
||||
{
|
||||
const QString qMakeSpec = dictionary.value("QMAKESPEC");
|
||||
|
@ -100,7 +100,6 @@ public:
|
||||
int platform() const;
|
||||
QString platformName() const;
|
||||
QString qpaPlatformName() const;
|
||||
QString qpaPrintSupportPluginName() const;
|
||||
|
||||
private:
|
||||
bool checkAngleAvailability(QString *errorMessage = 0) const;
|
||||
|
Loading…
Reference in New Issue
Block a user