Merge "Merge remote-tracking branch 'origin/release' into stable" into refs/staging/stable

This commit is contained in:
Jani Heikkinen 2014-04-25 09:38:39 +02:00 committed by The Qt Project
commit 16501e32eb
48 changed files with 696 additions and 353 deletions

19
configure vendored
View File

@ -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

View File

@ -19,6 +19,7 @@ defines += Q_QDOC \
Q_COMPILER_RVALUE_REFS
Cpp.ignoretokens += \
ENGINIOCLIENT_EXPORT \
PHONON_EXPORT \
Q_AUTOTEST_EXPORT \
Q_BLUETOOTH_EXPORT \

View File

@ -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" \

View File

@ -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('/');

View File

@ -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.

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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 += ..

View File

@ -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

View File

@ -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}
*/
/*!

View File

@ -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,

View File

@ -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

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -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.
*/

View File

@ -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;
}

View File

@ -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*)));

View File

@ -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;

View File

@ -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");

View File

@ -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

View File

@ -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:

View File

@ -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;
}

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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();

View File

@ -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]) {

View File

@ -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];
}

View File

@ -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

View File

@ -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

View File

@ -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;
}

View File

@ -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;
}

View File

@ -454,6 +454,10 @@ public:
QXcbSystemTrayTracker *systemTrayTracker();
#ifdef XCB_USE_XINPUT2
void handleEnterEvent(const xcb_enter_notify_event_t *);
#endif
private slots:
void processXcbEvents();

View File

@ -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

View File

@ -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

View File

@ -21,4 +21,4 @@ HEADERS += \
OTHER_FILES += windows.json
LIBS += -lwinspool -lcomdlg32
LIBS += -lwinspool -lcomdlg32 -lgdi32 -luser32

View File

@ -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()))

View File

@ -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 = \

View File

@ -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)

View File

@ -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

View File

@ -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();

View File

@ -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

View File

@ -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);

View File

@ -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);

View File

@ -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");

View File

@ -100,7 +100,6 @@ public:
int platform() const;
QString platformName() const;
QString qpaPlatformName() const;
QString qpaPrintSupportPluginName() const;
private:
bool checkAngleAvailability(QString *errorMessage = 0) const;