From 6918c0a15ba049d7e0de2302846dfadce4866861 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 3 Sep 2015 19:07:18 -0700 Subject: Add Qt 5.5.1 changelog with updated 5.7 future direction notice We should carry this in all 5.5.x and 5.6.x releases, to make sure everyone gets the message. But for this release, we need to note the changes from what was announced for 5.5.0: Clang 3.2 cannot compile std::atomic properly, so it will not be supported. That means the minimum XCode version we'll require will be 5.1, which fortunately does not raise the minimum OS X version that can compile Qt. See http://llvm.org/bugs/show_bug.cgi?id=12670 for more information. ICC 14.x and 15.x on Windows miscompiles pointer-to-members across DLL boundaries, so signal-slot connections fail. See QTBUG-40281. Change-Id: I42e7ef1a481840699a8dffff1400a4377fcf4589 Reviewed-by: Lars Knoll --- dist/changes-5.5.1 | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 dist/changes-5.5.1 diff --git a/dist/changes-5.5.1 b/dist/changes-5.5.1 new file mode 100644 index 0000000000..23e6c95f44 --- /dev/null +++ b/dist/changes-5.5.1 @@ -0,0 +1,50 @@ +Qt 5.5.1 is a bug-fix release. It maintains both forward and backward +compatibility (source and binary) with Qt 5.5.0. + +For more details, refer to the online documentation included in this +distribution. The documentation is also available online: + + http://doc.qt.io/qt-5.5/ + +The Qt version 5.5 series is binary compatible with the 5.4.x series. +Applications compiled for 5.4 will continue to run with 5.5. + +Some of the changes listed in this file include issue tracking numbers +corresponding to tasks in the Qt Bug Tracker: + + http://bugreports.qt.io/ + +Each of these identifiers can be entered in the bug tracker to obtain more +information about a particular change. + +**************************************************************************** +* Important Behavior Changes * +**************************************************************************** + +**************************************************************************** +* Future Direction Notice * +**************************************************************************** + + - Qt 5.7 will begin requiring certain C++11 features in order to + compile. Due to bugs in the Clang compiler that comes with XCode 5.0, + that version will not be supported, despite what was noted in the Qt + 5.5.0 changelog. + The minimum compiler versions for Qt 5.7 release will be: + * Clang 3.3 (XCode 5.1 contains version 3.4) + * GCC 4.7 + * Intel C++ Composer XE 2013 SP1 (compiler version 14.0) on Linux and OS X + * Intel C++ Composer XE 2016 (compiler version 16.0) on Windows + * Microsoft Visual Studio 2012 (compiler version 17.0) + +**************************************************************************** +* Library * +**************************************************************************** + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + + +**************************************************************************** +* Tools * +**************************************************************************** -- cgit v1.2.3 From 020ddba56e8cf477d3c6c78d00e6137d7cc50355 Mon Sep 17 00:00:00 2001 From: Liang Qi Date: Mon, 14 Sep 2015 09:56:41 +0200 Subject: Revert "Cocoa: correct QDesktopWidget::availableGeometry()" Wrong calculation of flip. This reverts commit 1a5cc2a868969f1b1e9278c4145b7af2fc4b8f69. Task-number: QTBUG-47030 Change-Id: Ide178eb5e027c4ecec1e3952c973fb64987eb7ce Reviewed-by: Jake Petroules --- src/plugins/platforms/cocoa/qcocoaintegration.mm | 12 ++---------- 1 file changed, 2 insertions(+), 10 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 8f84539e04..c8f6dd05db 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -86,17 +86,9 @@ void QCocoaScreen::updateGeometry() NSRect frameRect = [nsScreen frame]; - // Since Mavericks, there is a setting, System Preferences->Mission Control-> - // Displays have separate Spaces. - BOOL spansDisplays = NO; -#if QT_OSX_PLATFORM_SDK_EQUAL_OR_ABOVE(__MAC_10_9) - if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_9) - spansDisplays = [NSScreen screensHaveSeparateSpaces]; -#endif - if (spansDisplays || m_screenIndex == 0) { + if (m_screenIndex == 0) { m_geometry = QRect(frameRect.origin.x, frameRect.origin.y, frameRect.size.width, frameRect.size.height); - // Displays have separate Spaces setting is on or this is the primary screen, - // the one that contains the menubar. Its origin should be + // This is the primary screen, the one that contains the menubar. Its origin should be // (0, 0), and it's the only one whose available geometry differs from its full geometry. NSRect visibleRect = [nsScreen visibleFrame]; m_availableGeometry = QRect(visibleRect.origin.x, -- cgit v1.2.3 From 0de6c52bfe2433eca768a5f6fe9d5f08a545c254 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Fri, 28 Aug 2015 18:20:04 +0200 Subject: Fix QMYSQL plugin database connection setup check Opening a connection to an e.g. inactive server will return true regardless of the server accessibility. This patch aims to fix the current checks done. The first one is an allocation check which should only fail if there's not enough memory but is currently wrote as if the connection failed there. The second check that is "failing" is the connection setup. The return value should either be NULL or the same value provided as first parameter. That is now verified. [ChangeLog][QtSql][QSqlDatabase] Fixed a bug where opening a connection to a MySQL database using the QMYSQL plugin would always return true even if the server was unreachable. This bug could also lead to crashes depending on the platform used. Task-number: QTBUG-47784 Task-number: QTBUG-47452 Change-Id: I91651684b5a342eaa7305473e26d8371b35396c4 Reviewed-by: Andy Shaw --- src/sql/drivers/mysql/qsql_mysql.cpp | 41 +++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 17 deletions(-) diff --git a/src/sql/drivers/mysql/qsql_mysql.cpp b/src/sql/drivers/mysql/qsql_mysql.cpp index d901008e00..8ac7f765e2 100644 --- a/src/sql/drivers/mysql/qsql_mysql.cpp +++ b/src/sql/drivers/mysql/qsql_mysql.cpp @@ -1282,19 +1282,21 @@ bool QMYSQLDriver::open(const QString& db, if (writeTimeout != 0) mysql_options(d->mysql, MYSQL_OPT_WRITE_TIMEOUT, &writeTimeout); #endif - if (mysql_real_connect(d->mysql, - host.isNull() ? static_cast(0) - : host.toLocal8Bit().constData(), - user.isNull() ? static_cast(0) - : user.toLocal8Bit().constData(), - password.isNull() ? static_cast(0) - : password.toLocal8Bit().constData(), - db.isNull() ? static_cast(0) - : db.toLocal8Bit().constData(), - (port > -1) ? port : 0, - unixSocket.isNull() ? static_cast(0) - : unixSocket.toLocal8Bit().constData(), - optionFlags)) { + MYSQL *mysql = mysql_real_connect(d->mysql, + host.isNull() ? static_cast(0) + : host.toLocal8Bit().constData(), + user.isNull() ? static_cast(0) + : user.toLocal8Bit().constData(), + password.isNull() ? static_cast(0) + : password.toLocal8Bit().constData(), + db.isNull() ? static_cast(0) + : db.toLocal8Bit().constData(), + (port > -1) ? port : 0, + unixSocket.isNull() ? static_cast(0) + : unixSocket.toLocal8Bit().constData(), + optionFlags); + + if (mysql == d->mysql) { if (!db.isEmpty() && mysql_select_db(d->mysql, db.toLocal8Bit().constData())) { setLastError(qMakeError(tr("Unable to open database '%1'").arg(db), QSqlError::ConnectionError, d)); mysql_close(d->mysql); @@ -1305,12 +1307,17 @@ bool QMYSQLDriver::open(const QString& db, if (reconnect) mysql_options(d->mysql, MYSQL_OPT_RECONNECT, &reconnect); #endif + } else { + setLastError(qMakeError(tr("Unable to connect"), + QSqlError::ConnectionError, d)); + mysql_close(d->mysql); + d->mysql = NULL; + setOpenError(true); + return false; } } else { - setLastError(qMakeError(tr("Unable to connect"), - QSqlError::ConnectionError, d)); - mysql_close(d->mysql); - d->mysql = NULL; + setLastError(qMakeError(tr("Failed to allocated data"), + QSqlError::UnknownError, d)); setOpenError(true); return false; } -- cgit v1.2.3 From 07d4113f8f94bddf12437ac3205dce1b6d8fab7d Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 15 Sep 2015 16:17:16 +0200 Subject: buildsystem changelog for 5.5.1 Change-Id: I310f9eff657e9730830cd5c302bdfc46fe67febc Reviewed-by: Joerg Bornemann --- dist/changes-5.5.1 | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/dist/changes-5.5.1 b/dist/changes-5.5.1 index 23e6c95f44..3b926bd7f2 100644 --- a/dist/changes-5.5.1 +++ b/dist/changes-5.5.1 @@ -48,3 +48,22 @@ information about a particular change. **************************************************************************** * Tools * **************************************************************************** + +configure & build system +------------------------ + + - [QTBUG-46125] Fixed misuse of target linker features for host tools. + - [QTBUG-46473] QML plugin DLLs now have version information. + +qmake +----- + + - [QTBUG-46824][Darwin] Characters in the bundle identifier which + the App Store considers invalid are now substituted. + - [QTBUG-47065][Unix] Fixed use of CONFIG+=separate_debug_info together + with CONFIG+=unversioned_libname. + - [QTBUG-47450][Xcode] Fixed Info.plist creation in shadow builds. + - [QTBUG-47775][Darwin] Fixed Info.plist creation when bundle name + contains spaces. + - [QTBUG-48110][VS] Fixed VS2015 solution file generation. + - [MSVC][nmake] Fixed use of VS2013 mkspecs from VS2015 shell. -- cgit v1.2.3 From dc716f2dc2df06c40b3709ded81a5b7588f53e7a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Fri, 18 Sep 2015 18:01:50 -0700 Subject: ICC on Windows: Disable ref-qualified member functions in MSVC <= 2013 Like MSVC, ICC on Windows in debug mode always makes calls to dllexported functions instead of inlining them. Since MSVC 2013 doesn't know about ref-qualification of member functions, this creates an incompatibility between DLL creation and DLL use. Task-number: QTBUG-48349 Change-Id: I42e7ef1a481840699a8dffff14053b594810fb42 Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Lars Knoll --- src/corelib/global/qcompilerdetection.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 4828d8596a..9f79b3e70c 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -572,6 +572,9 @@ # if _MSC_VER < 1900 // ICC disables unicode string support when compatibility mode with MSVC 2013 or lower is active # undef Q_COMPILER_UNICODE_STRINGS +// Even though ICC knows about ref-qualified members, MSVC 2013 or lower doesn't, so +// certain member functions (like QString::toUpper) may be missing from the DLLs. +# undef Q_COMPILER_REF_QUALIFIERS // Disable constexpr unless the MS headers have constexpr in all the right places too // (like std::numeric_limits::max()) # undef Q_COMPILER_CONSTEXPR -- cgit v1.2.3 From 113a51b61540b1db74b78d30c04fb979b05f210c Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 20 Sep 2015 21:33:40 -0700 Subject: Update the Qt 5.5.1 changelog for qtbase Change-Id: I42e7ef1a481840699a8dffff1405e4154dd6b5dc Reviewed-by: Lars Knoll --- dist/changes-5.5.1 | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 72 insertions(+), 1 deletion(-) diff --git a/dist/changes-5.5.1 b/dist/changes-5.5.1 index 3b926bd7f2..0dd5d6c594 100644 --- a/dist/changes-5.5.1 +++ b/dist/changes-5.5.1 @@ -21,6 +21,11 @@ information about a particular change. * Important Behavior Changes * **************************************************************************** + - [QTBUG-47316] QDebug output for QStrings changed compared to Qt 5.5.0 to + more closely match the output of previous Qt versions. Like Qt 5.5.0, + QDebug will escape non-printable characters, the backslash and quote + characters, but will no longer escape the printable characters. + **************************************************************************** * Future Direction Notice * **************************************************************************** @@ -40,10 +45,76 @@ information about a particular change. * Library * **************************************************************************** +QtCore +------ + + - Logging framework: + * Fixed a bug that would cause a + "%{time boot}" field in the logging framework's pattern to always + display the same value, instead of the time since boot. + + - QDate/QTime: + * Fixed a minor source-incompatibility between Qt 5.4 and 5.5.0 + involving sets of functions overloaded on QTime and some integer or + QDate and some integer. + + - QDir: + * QDir::relativeFilePath() now returns "." instead of an empty string if + the given path is the same as the directory. + + - QLoggingCategory: + * Fixed behavior of default severity passed to constructor or + Q_LOGGING_CATEGORY with regards to QtInfoMsg, which was previously + treated as being more severe than QtFatalMsg. + + - QTimeZone: + * [QTBUG-47037] Fixed a wrong timezone conversion when the POSIX + timezone rule contains a fractional timezone (e.g. VET4:30). + +QtNetwork +--------- + + - [QTBUG-47048] Fix HTTP issues with "Unknown Error" and "Connection + Closed" + [ChangeLog][QtNetwork][Sockets] Read OS/encrypted read buffers when + connection closed by server. + +QtSql +----- + + - QSqlDatabase: + * [QTBUG-47784][QTBUG-47452] Fixed a bug where opening a connection to a + MySQL database using the QMYSQL plugin would always return true even + if the server was unreachable. This bug could also lead to crashes + depending on the platform used. + +QtWidgets +--------- + + - Important behavior changes: + * [QTBUG-46379] Tooltips on OS X are now transparent for mouse events. + +**************************************************************************** +* Platform Specific Changes * +**************************************************************************** + +Windows +------- + + - Text: + * [QTBUG-46963] Fixed crash in DirectWrite engine when constructing a + QRawFont from raw font data. + **************************************************************************** -* Platform Specific Changes * +* Compiler Specific Changes * **************************************************************************** +GCC +--- + + - Fixed a regression introduced Qt 5.5.0 that generated lots of + compiler warnings in Qt public headers when using the (deprecated) + version 4.5 of GCC. **************************************************************************** * Tools * -- cgit v1.2.3 From 7943d4f77c721da17b6be76cf1045d34654a8cc5 Mon Sep 17 00:00:00 2001 From: Andrew Knight Date: Mon, 28 Sep 2015 22:47:00 +0300 Subject: ANGLE: Fix Windows Store D3D Trim and Level 9 requirements Due to additional validation not covered in previous patches, the Windows Store certification compatibility had regressed. These changes ensure that the required D3D behaviors are met. Change-Id: I0a74f0d2fecaa87d4a9409da3a7a194254609759 Task-number: QTBUG-38481 Reviewed-by: Samuel Nevala Reviewed-by: Maurice Kalinowski Reviewed-by: Jani Heikkinen --- .../src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 19 ++++++- .../angle/src/libGLESv2/entry_points_egl_ext.cpp | 2 + ...indows-Store-D3D-Trim-and-Level-9-require.patch | 63 ++++++++++++++++++++++ src/plugins/platforms/winrt/qwinrtscreen.cpp | 2 +- 4 files changed, 83 insertions(+), 3 deletions(-) create mode 100644 src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp index 5291a3a086..ea5953fee8 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp @@ -293,10 +293,25 @@ Renderer11::Renderer11(egl::Display *display) #if defined(ANGLE_ENABLE_WINDOWS_STORE) if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) #else - if (requestedMajorVersion == 9 && requestedMinorVersion == 3) + if (requestedMajorVersion == 9) #endif { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); + switch (requestedMinorVersion) { +#if defined(ANGLE_ENABLE_WINDOWS_STORE) + case EGL_DONT_CARE: + case 1: + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); + // fall through + case 2: + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); + // fall through +#endif + case 3: + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); + break; + default: + break; + } } EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp index 62f3ca1207..02b663192d 100644 --- a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp +++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp @@ -49,6 +49,8 @@ EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surfa // validate the attribute parameter switch (attribute) { + case EGL_DEVICE_EXT: + break; case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: if (!display->getExtensions().surfaceD3DTexture2DShareHandle) { diff --git a/src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch b/src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch new file mode 100644 index 0000000000..e9677fab68 --- /dev/null +++ b/src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch @@ -0,0 +1,63 @@ +From f6d73de2a8a36becb8a2e0cce84475e91f1f63b4 Mon Sep 17 00:00:00 2001 +From: Andrew Knight +Date: Mon, 28 Sep 2015 22:43:13 +0300 +Subject: [PATCH] ANGLE: Fix Windows Store D3D Trim and Level 9 requirements + +Due to additional validation not covered in previous patches, the Windows +Store certification compatibility had regressed. These changes ensure that +the required D3D behaviors are met. + +Change-Id: I0a74f0d2fecaa87d4a9409da3a7a194254609759 +--- + .../src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 19 +++++++++++++++++-- + .../angle/src/libGLESv2/entry_points_egl_ext.cpp | 2 ++ + 2 files changed, 19 insertions(+), 2 deletions(-) + +diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +index 5291a3a..ea5953f 100644 +--- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp ++++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +@@ -293,10 +293,25 @@ Renderer11::Renderer11(egl::Display *display) + #if defined(ANGLE_ENABLE_WINDOWS_STORE) + if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) + #else +- if (requestedMajorVersion == 9 && requestedMinorVersion == 3) ++ if (requestedMajorVersion == 9) + #endif + { +- mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); ++ switch (requestedMinorVersion) { ++#if defined(ANGLE_ENABLE_WINDOWS_STORE) ++ case EGL_DONT_CARE: ++ case 1: ++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); ++ // fall through ++ case 2: ++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); ++ // fall through ++#endif ++ case 3: ++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); ++ break; ++ default: ++ break; ++ } + } + + EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, +diff --git a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp +index 62f3ca1..02b6631 100644 +--- a/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp ++++ b/src/3rdparty/angle/src/libGLESv2/entry_points_egl_ext.cpp +@@ -49,6 +49,8 @@ EGLBoolean EGLAPIENTRY QuerySurfacePointerANGLE(EGLDisplay dpy, EGLSurface surfa + // validate the attribute parameter + switch (attribute) + { ++ case EGL_DEVICE_EXT: ++ break; + case EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE: + if (!display->getExtensions().surfaceD3DTexture2DShareHandle) + { +-- +2.5.1.windows.1 + diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp index 1d36bb31f6..8962332208 100644 --- a/src/plugins/platforms/winrt/qwinrtscreen.cpp +++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp @@ -1115,7 +1115,7 @@ HRESULT QWinRTScreen::onSuspended(IInspectable *, ISuspendingEventArgs *) #ifndef Q_OS_WINPHONE Q_D(QWinRTScreen); ComPtr d3dDevice; - const EGLBoolean ok = eglQuerySurfacePointerANGLE(d->eglDisplay, EGL_NO_SURFACE, EGL_DEVICE_EXT, (void **)d3dDevice.GetAddressOf()); + const EGLBoolean ok = eglQuerySurfacePointerANGLE(d->eglDisplay, d->eglSurface, EGL_DEVICE_EXT, (void **)d3dDevice.GetAddressOf()); if (ok && d3dDevice) { ComPtr dxgiDevice; if (SUCCEEDED(d3dDevice.As(&dxgiDevice))) -- cgit v1.2.3 From b8e0f7cfc638a71770f44ada828ff2cf6d2ee201 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Thu, 1 Oct 2015 17:41:07 +0300 Subject: Fix the spurious socket notifications on OS X MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Core Foundation Framework forwards notifications about socket activity through a callback function which called from the run loop. Previous implementation sets kCFSocketReadCallBack, kCFSocketWriteCallBack to be automatically re-enabled after they are triggered. With these semantics, an application need not read all available data in response to a read notification: a single recv in response to each read notification is appropriate. If an application issues multiple recv calls in response to a single notification, it can receive spurious notifications. To solve this issue, this patch disables automatically reenabling callback feature. Now, callback gets called exactly once, and is not called again until manually re-enabled by calling CFSocketEnableCallBacks() just before entering to wait for the new events. Task-number: QTBUG-48556 Change-Id: Ia3393c2026230c7b3397cc614758dec1d432535f Reviewed-by: Morten Johan Sørvig --- .../cfsocketnotifier/qcfsocketnotifier.cpp | 37 ++++++++++++++++++---- .../cfsocketnotifier/qcfsocketnotifier_p.h | 6 +++- .../platforms/cocoa/qcocoaeventdispatcher.mm | 11 ++++--- 3 files changed, 42 insertions(+), 12 deletions(-) diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp index 2b5723d827..91f7aeb7d0 100644 --- a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp +++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp @@ -55,11 +55,15 @@ void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CF // notifier is now gone. The upshot is we have to check the notifier // every time. if (callbackType == kCFSocketReadCallBack) { - if (socketInfo->readNotifier) + if (socketInfo->readNotifier && socketInfo->readEnabled) { + socketInfo->readEnabled = false; QGuiApplication::sendEvent(socketInfo->readNotifier, ¬ifierEvent); + } } else if (callbackType == kCFSocketWriteCallBack) { - if (socketInfo->writeNotifier) + if (socketInfo->writeNotifier && socketInfo->writeEnabled) { + socketInfo->writeEnabled = false; QGuiApplication::sendEvent(socketInfo->writeNotifier, ¬ifierEvent); + } } if (cfSocketNotifier->maybeCancelWaitForMoreEvents) @@ -150,8 +154,8 @@ void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier) } CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket); - flags |= kCFSocketAutomaticallyReenableWriteCallBack; //QSocketNotifier stays enabled after a write - flags &= ~kCFSocketCloseOnInvalidate; //QSocketNotifier doesn't close the socket upon destruction/invalidation + // QSocketNotifier doesn't close the socket upon destruction/invalidation + flags &= ~(kCFSocketCloseOnInvalidate | kCFSocketAutomaticallyReenableReadCallBack); CFSocketSetSocketFlags(socketInfo->socket, flags); // Add CFSocket to runloop. @@ -171,15 +175,14 @@ void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier) macSockets.insert(nativeSocket, socketInfo); } - // Increment read/write counters and select enable callbacks if necessary. if (type == QSocketNotifier::Read) { Q_ASSERT(socketInfo->readNotifier == 0); socketInfo->readNotifier = notifier; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack); + socketInfo->readEnabled = false; } else if (type == QSocketNotifier::Write) { Q_ASSERT(socketInfo->writeNotifier == 0); socketInfo->writeNotifier = notifier; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); + socketInfo->writeEnabled = false; } } @@ -212,10 +215,12 @@ void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier) if (type == QSocketNotifier::Read) { Q_ASSERT(notifier == socketInfo->readNotifier); socketInfo->readNotifier = 0; + socketInfo->readEnabled = false; CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); } else if (type == QSocketNotifier::Write) { Q_ASSERT(notifier == socketInfo->writeNotifier); socketInfo->writeNotifier = 0; + socketInfo->writeEnabled = false; CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); } @@ -232,6 +237,24 @@ void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier) } } +void QCFSocketNotifier::enableSocketNotifiers() +{ + // Enable CFSockets in runloop. + for (MacSocketHash::ConstIterator it = macSockets.constBegin(); it != macSockets.constEnd(); ++it) { + MacSocketInfo *socketInfo = (*it); + if (CFSocketIsValid(socketInfo->socket)) { + if (socketInfo->readNotifier && !socketInfo->readEnabled) { + socketInfo->readEnabled = true; + CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack); + } + if (socketInfo->writeNotifier && !socketInfo->writeEnabled) { + socketInfo->writeEnabled = true; + CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); + } + } + } +} + void QCFSocketNotifier::removeSocketNotifiers() { // Remove CFSockets from the runloop. diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h index af8122f753..1d6dcf2885 100644 --- a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h +++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h @@ -53,11 +53,14 @@ QT_BEGIN_NAMESPACE struct MacSocketInfo { - MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0) {} + MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0), + readEnabled(false), writeEnabled(false) {} CFSocketRef socket; CFRunLoopSourceRef runloop; QObject *readNotifier; QObject *writeNotifier; + bool readEnabled; + bool writeEnabled; }; typedef QHash MacSocketHash; @@ -81,6 +84,7 @@ public: void setMaybeCancelWaitForMoreEventsCallback(MaybeCancelWaitForMoreEventsFn callBack); void registerSocketNotifier(QSocketNotifier *notifier); void unregisterSocketNotifier(QSocketNotifier *notifier); + void enableSocketNotifiers(); void removeSocketNotifiers(); MacSocketHash macSockets; diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index 52b2e23345..b443233d15 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -845,10 +845,13 @@ QCocoaEventDispatcher::QCocoaEventDispatcher(QObject *parent) void QCocoaEventDispatcherPrivate::waitingObserverCallback(CFRunLoopObserverRef, CFRunLoopActivity activity, void *info) { - if (activity == kCFRunLoopBeforeWaiting) - emit static_cast(info)->aboutToBlock(); - else - emit static_cast(info)->awake(); + QCocoaEventDispatcher *dispatcher = static_cast(info); + if (activity == kCFRunLoopBeforeWaiting) { + dispatcher->d_func()->cfSocketNotifier.enableSocketNotifiers(); + emit dispatcher->aboutToBlock(); + } else { + emit dispatcher->awake(); + } } void QCocoaEventDispatcherPrivate::processPostedEvents() -- cgit v1.2.3 From 44f323e5007a389c4103bfc6ca577d26078ce92b Mon Sep 17 00:00:00 2001 From: Samuel Nevala Date: Sat, 3 Oct 2015 02:46:15 +0300 Subject: ANGLE: Fix D3D feature level detection. Commit 7943d4f tried to fix this with a switch/case, but the feature levels need to be in descending order so this failed. So, follow the same style used for feature levels 10/11. Change-Id: Ia1c22981bf8b99eb53df13833aba452482398295 Task-number: QTBUG-38481 Task-number: QTBUG-48571 Reviewed-by: Andrew Knight Reviewed-by: Oliver Wolff --- .../src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 26 ++++++------ ...indows-Store-D3D-Trim-and-Level-9-require.patch | 48 ++++++++++------------ 2 files changed, 33 insertions(+), 41 deletions(-) diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp index ea5953fee8..223e2b019b 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp @@ -293,25 +293,23 @@ Renderer11::Renderer11(egl::Display *display) #if defined(ANGLE_ENABLE_WINDOWS_STORE) if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) #else - if (requestedMajorVersion == 9) + if (requestedMajorVersion == 9 && requestedMinorVersion == 3) #endif { - switch (requestedMinorVersion) { + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); + } #if defined(ANGLE_ENABLE_WINDOWS_STORE) - case EGL_DONT_CARE: - case 1: - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); - // fall through - case 2: + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2) + { mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); - // fall through -#endif - case 3: - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); - break; - default: - break; } + if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) + { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); + } +#endif } EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, diff --git a/src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch b/src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch index e9677fab68..705219ed24 100644 --- a/src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch +++ b/src/angle/patches/0008-ANGLE-Fix-Windows-Store-D3D-Trim-and-Level-9-require.patch @@ -1,6 +1,6 @@ -From f6d73de2a8a36becb8a2e0cce84475e91f1f63b4 Mon Sep 17 00:00:00 2001 -From: Andrew Knight -Date: Mon, 28 Sep 2015 22:43:13 +0300 +From 3d696560f987a08d608b29bf3e0f557e96bebc56 Mon Sep 17 00:00:00 2001 +From: Samuel Nevala +Date: Sat, 3 Oct 2015 02:30:26 +0300 Subject: [PATCH] ANGLE: Fix Windows Store D3D Trim and Level 9 requirements Due to additional validation not covered in previous patches, the Windows @@ -9,39 +9,33 @@ the required D3D behaviors are met. Change-Id: I0a74f0d2fecaa87d4a9409da3a7a194254609759 --- - .../src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 19 +++++++++++++++++-- - .../angle/src/libGLESv2/entry_points_egl_ext.cpp | 2 ++ - 2 files changed, 19 insertions(+), 2 deletions(-) + .../angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp | 16 +++++++++++++++- + .../angle/src/libGLESv2/entry_points_egl_ext.cpp | 2 ++ + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp -index 5291a3a..ea5953f 100644 +index 5291a3a..61d9212 100644 --- a/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp +++ b/src/3rdparty/angle/src/libANGLE/renderer/d3d/d3d11/Renderer11.cpp -@@ -293,10 +293,25 @@ Renderer11::Renderer11(egl::Display *display) - #if defined(ANGLE_ENABLE_WINDOWS_STORE) - if (requestedMajorVersion == EGL_DONT_CARE || requestedMajorVersion >= 9) - #else -- if (requestedMajorVersion == 9 && requestedMinorVersion == 3) -+ if (requestedMajorVersion == 9) +@@ -296,7 +296,21 @@ Renderer11::Renderer11(egl::Display *display) + if (requestedMajorVersion == 9 && requestedMinorVersion == 3) #endif { - mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); -+ switch (requestedMinorVersion) { ++ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 3) ++ { ++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); ++ } +#if defined(ANGLE_ENABLE_WINDOWS_STORE) -+ case EGL_DONT_CARE: -+ case 1: -+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); -+ // fall through -+ case 2: ++ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 2) ++ { + mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_2); -+ // fall through -+#endif -+ case 3: -+ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_3); -+ break; -+ default: -+ break; + } ++ if (requestedMinorVersion == EGL_DONT_CARE || requestedMinorVersion >= 1) ++ { ++ mAvailableFeatureLevels.push_back(D3D_FEATURE_LEVEL_9_1); ++ } ++#endif } EGLint requestedDeviceType = attributes.get(EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE, @@ -59,5 +53,5 @@ index 62f3ca1..02b6631 100644 if (!display->getExtensions().surfaceD3DTexture2DShareHandle) { -- -2.5.1.windows.1 +1.9.5.msysgit.1 -- cgit v1.2.3 From da104e7db04a5aeafb99a7b0ef3ab3cdd08da272 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Sat, 3 Oct 2015 17:02:36 +0300 Subject: Revert "Fix the spurious socket notifications on OS X" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This reverts commit b8e0f7cfc638a71770f44ada828ff2cf6d2ee201. Needs a more testing. Change-Id: Iff0b2741922cfa8f16fbc3f4ce0f83869d6cd8b6 Reviewed-by: Alex Trotsenko Reviewed-by: Tor Arne Vestbø --- .../cfsocketnotifier/qcfsocketnotifier.cpp | 37 ++++------------------ .../cfsocketnotifier/qcfsocketnotifier_p.h | 6 +--- .../platforms/cocoa/qcocoaeventdispatcher.mm | 11 +++---- 3 files changed, 12 insertions(+), 42 deletions(-) diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp index 91f7aeb7d0..2b5723d827 100644 --- a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp +++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp @@ -55,15 +55,11 @@ void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CF // notifier is now gone. The upshot is we have to check the notifier // every time. if (callbackType == kCFSocketReadCallBack) { - if (socketInfo->readNotifier && socketInfo->readEnabled) { - socketInfo->readEnabled = false; + if (socketInfo->readNotifier) QGuiApplication::sendEvent(socketInfo->readNotifier, ¬ifierEvent); - } } else if (callbackType == kCFSocketWriteCallBack) { - if (socketInfo->writeNotifier && socketInfo->writeEnabled) { - socketInfo->writeEnabled = false; + if (socketInfo->writeNotifier) QGuiApplication::sendEvent(socketInfo->writeNotifier, ¬ifierEvent); - } } if (cfSocketNotifier->maybeCancelWaitForMoreEvents) @@ -154,8 +150,8 @@ void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier) } CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket); - // QSocketNotifier doesn't close the socket upon destruction/invalidation - flags &= ~(kCFSocketCloseOnInvalidate | kCFSocketAutomaticallyReenableReadCallBack); + flags |= kCFSocketAutomaticallyReenableWriteCallBack; //QSocketNotifier stays enabled after a write + flags &= ~kCFSocketCloseOnInvalidate; //QSocketNotifier doesn't close the socket upon destruction/invalidation CFSocketSetSocketFlags(socketInfo->socket, flags); // Add CFSocket to runloop. @@ -175,14 +171,15 @@ void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier) macSockets.insert(nativeSocket, socketInfo); } + // Increment read/write counters and select enable callbacks if necessary. if (type == QSocketNotifier::Read) { Q_ASSERT(socketInfo->readNotifier == 0); socketInfo->readNotifier = notifier; - socketInfo->readEnabled = false; + CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack); } else if (type == QSocketNotifier::Write) { Q_ASSERT(socketInfo->writeNotifier == 0); socketInfo->writeNotifier = notifier; - socketInfo->writeEnabled = false; + CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); } } @@ -215,12 +212,10 @@ void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier) if (type == QSocketNotifier::Read) { Q_ASSERT(notifier == socketInfo->readNotifier); socketInfo->readNotifier = 0; - socketInfo->readEnabled = false; CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); } else if (type == QSocketNotifier::Write) { Q_ASSERT(notifier == socketInfo->writeNotifier); socketInfo->writeNotifier = 0; - socketInfo->writeEnabled = false; CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); } @@ -237,24 +232,6 @@ void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier) } } -void QCFSocketNotifier::enableSocketNotifiers() -{ - // Enable CFSockets in runloop. - for (MacSocketHash::ConstIterator it = macSockets.constBegin(); it != macSockets.constEnd(); ++it) { - MacSocketInfo *socketInfo = (*it); - if (CFSocketIsValid(socketInfo->socket)) { - if (socketInfo->readNotifier && !socketInfo->readEnabled) { - socketInfo->readEnabled = true; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack); - } - if (socketInfo->writeNotifier && !socketInfo->writeEnabled) { - socketInfo->writeEnabled = true; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); - } - } - } -} - void QCFSocketNotifier::removeSocketNotifiers() { // Remove CFSockets from the runloop. diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h index 1d6dcf2885..af8122f753 100644 --- a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h +++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h @@ -53,14 +53,11 @@ QT_BEGIN_NAMESPACE struct MacSocketInfo { - MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0), - readEnabled(false), writeEnabled(false) {} + MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0) {} CFSocketRef socket; CFRunLoopSourceRef runloop; QObject *readNotifier; QObject *writeNotifier; - bool readEnabled; - bool writeEnabled; }; typedef QHash MacSocketHash; @@ -84,7 +81,6 @@ public: void setMaybeCancelWaitForMoreEventsCallback(MaybeCancelWaitForMoreEventsFn callBack); void registerSocketNotifier(QSocketNotifier *notifier); void unregisterSocketNotifier(QSocketNotifier *notifier); - void enableSocketNotifiers(); void removeSocketNotifiers(); MacSocketHash macSockets; diff --git a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm index b443233d15..52b2e23345 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventdispatcher.mm @@ -845,13 +845,10 @@ QCocoaEventDispatcher::QCocoaEventDispatcher(QObject *parent) void QCocoaEventDispatcherPrivate::waitingObserverCallback(CFRunLoopObserverRef, CFRunLoopActivity activity, void *info) { - QCocoaEventDispatcher *dispatcher = static_cast(info); - if (activity == kCFRunLoopBeforeWaiting) { - dispatcher->d_func()->cfSocketNotifier.enableSocketNotifiers(); - emit dispatcher->aboutToBlock(); - } else { - emit dispatcher->awake(); - } + if (activity == kCFRunLoopBeforeWaiting) + emit static_cast(info)->aboutToBlock(); + else + emit static_cast(info)->awake(); } void QCocoaEventDispatcherPrivate::processPostedEvents() -- cgit v1.2.3 From 6542161d5c698d461a11f0e5ca6cc2a00d33a824 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Wed, 7 Oct 2015 16:49:47 +0300 Subject: Fix spurious socket notifications on OS X and iOS MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Core Foundation Framework forwards notifications about socket activity through a callback function which called from the run loop. The default behavior of Core Foundation is to automatically re-enable the read callback after each notification, and we explicitly enabled the same behavior for the write callback. With this behavior, if the client did multiple recv() calls in response to the first notification in a series of read notifications, the client would still get the QSocketNotifier notifications for the data that was already read. To get rid of these extra notifications, we disable automatically re-enabling the callbacks, and then manually enable them on each run loop pass. Task-number: QTBUG-48556 Change-Id: I0b060222b787f45600be0cb7da85d04aef415e57 Reviewed-by: Tor Arne Vestbø --- .../cfsocketnotifier/qcfsocketnotifier.cpp | 129 +++++++++++++++------ .../cfsocketnotifier/qcfsocketnotifier_p.h | 14 ++- 2 files changed, 105 insertions(+), 38 deletions(-) diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp index 2b5723d827..c58e0ea78d 100644 --- a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp +++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier.cpp @@ -55,11 +55,15 @@ void qt_mac_socket_callback(CFSocketRef s, CFSocketCallBackType callbackType, CF // notifier is now gone. The upshot is we have to check the notifier // every time. if (callbackType == kCFSocketReadCallBack) { - if (socketInfo->readNotifier) + if (socketInfo->readNotifier && socketInfo->readEnabled) { + socketInfo->readEnabled = false; QGuiApplication::sendEvent(socketInfo->readNotifier, ¬ifierEvent); + } } else if (callbackType == kCFSocketWriteCallBack) { - if (socketInfo->writeNotifier) + if (socketInfo->writeNotifier && socketInfo->writeEnabled) { + socketInfo->writeEnabled = false; QGuiApplication::sendEvent(socketInfo->writeNotifier, ¬ifierEvent); + } } if (cfSocketNotifier->maybeCancelWaitForMoreEvents) @@ -88,12 +92,12 @@ void qt_mac_remove_socket_from_runloop(const CFSocketRef socket, CFRunLoopSource CFRunLoopRemoveSource(CFRunLoopGetMain(), runloop, kCFRunLoopCommonModes); CFSocketDisableCallBacks(socket, kCFSocketReadCallBack); CFSocketDisableCallBacks(socket, kCFSocketWriteCallBack); - CFRunLoopSourceInvalidate(runloop); } QCFSocketNotifier::QCFSocketNotifier() -:eventDispatcher(0) -, maybeCancelWaitForMoreEvents(0) + : eventDispatcher(0) + , maybeCancelWaitForMoreEvents(0) + , enableNotifiersObserver(0) { } @@ -150,36 +154,34 @@ void QCFSocketNotifier::registerSocketNotifier(QSocketNotifier *notifier) } CFOptionFlags flags = CFSocketGetSocketFlags(socketInfo->socket); - flags |= kCFSocketAutomaticallyReenableWriteCallBack; //QSocketNotifier stays enabled after a write - flags &= ~kCFSocketCloseOnInvalidate; //QSocketNotifier doesn't close the socket upon destruction/invalidation + // QSocketNotifier doesn't close the socket upon destruction/invalidation + flags &= ~kCFSocketCloseOnInvalidate; + // Expicitly disable automatic re-enable, as we do that manually on each runloop pass + flags &= ~(kCFSocketAutomaticallyReenableWriteCallBack | kCFSocketAutomaticallyReenableReadCallBack); CFSocketSetSocketFlags(socketInfo->socket, flags); - // Add CFSocket to runloop. - if (!(socketInfo->runloop = qt_mac_add_socket_to_runloop(socketInfo->socket))) { - qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to add CFSocket to runloop"); - CFSocketInvalidate(socketInfo->socket); - CFRelease(socketInfo->socket); - return; - } - - // Disable both callback types by default. This must be done after - // we add the CFSocket to the runloop, or else these calls will have - // no effect. - CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); - CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); - macSockets.insert(nativeSocket, socketInfo); } - // Increment read/write counters and select enable callbacks if necessary. if (type == QSocketNotifier::Read) { Q_ASSERT(socketInfo->readNotifier == 0); socketInfo->readNotifier = notifier; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack); + socketInfo->readEnabled = false; } else if (type == QSocketNotifier::Write) { Q_ASSERT(socketInfo->writeNotifier == 0); socketInfo->writeNotifier = notifier; - CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); + socketInfo->writeEnabled = false; + } + + if (!enableNotifiersObserver) { + // Create a run loop observer which enables the socket notifiers on each + // pass of the run loop, before any sources are processed. + CFRunLoopObserverContext context = {}; + context.info = this; + enableNotifiersObserver = CFRunLoopObserverCreate(kCFAllocatorDefault, kCFRunLoopBeforeSources, + true, 0, enableSocketNotifiers, &context); + Q_ASSERT(enableNotifiersObserver); + CFRunLoopAddObserver(CFRunLoopGetMain(), enableNotifiersObserver, kCFRunLoopCommonModes); } } @@ -212,21 +214,18 @@ void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier) if (type == QSocketNotifier::Read) { Q_ASSERT(notifier == socketInfo->readNotifier); socketInfo->readNotifier = 0; + socketInfo->readEnabled = false; CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); } else if (type == QSocketNotifier::Write) { Q_ASSERT(notifier == socketInfo->writeNotifier); socketInfo->writeNotifier = 0; + socketInfo->writeEnabled = false; CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); } // Remove CFSocket from runloop if this was the last QSocketNotifier. if (socketInfo->readNotifier == 0 && socketInfo->writeNotifier == 0) { - if (CFSocketIsValid(socketInfo->socket)) - qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop); - CFRunLoopSourceInvalidate(socketInfo->runloop); - CFRelease(socketInfo->runloop); - CFSocketInvalidate(socketInfo->socket); - CFRelease(socketInfo->socket); + unregisterSocketInfo(socketInfo); delete socketInfo; macSockets.remove(nativeSocket); } @@ -235,14 +234,70 @@ void QCFSocketNotifier::unregisterSocketNotifier(QSocketNotifier *notifier) void QCFSocketNotifier::removeSocketNotifiers() { // Remove CFSockets from the runloop. - for (MacSocketHash::ConstIterator it = macSockets.constBegin(); it != macSockets.constEnd(); ++it) { - MacSocketInfo *socketInfo = (*it); - if (CFSocketIsValid(socketInfo->socket)) { + foreach (MacSocketInfo *socketInfo, macSockets) { + unregisterSocketInfo(socketInfo); + delete socketInfo; + } + + macSockets.clear(); + + destroyRunLoopObserver(); +} + +void QCFSocketNotifier::destroyRunLoopObserver() +{ + if (!enableNotifiersObserver) + return; + + CFRunLoopObserverInvalidate(enableNotifiersObserver); + CFRelease(enableNotifiersObserver); + enableNotifiersObserver = 0; +} + +void QCFSocketNotifier::unregisterSocketInfo(MacSocketInfo *socketInfo) +{ + if (socketInfo->runloop) { + if (CFSocketIsValid(socketInfo->socket)) qt_mac_remove_socket_from_runloop(socketInfo->socket, socketInfo->runloop); - CFRunLoopSourceInvalidate(socketInfo->runloop); - CFRelease(socketInfo->runloop); - CFSocketInvalidate(socketInfo->socket); - CFRelease(socketInfo->socket); + CFRunLoopSourceInvalidate(socketInfo->runloop); + CFRelease(socketInfo->runloop); + } + CFSocketInvalidate(socketInfo->socket); + CFRelease(socketInfo->socket); +} + +void QCFSocketNotifier::enableSocketNotifiers(CFRunLoopObserverRef ref, CFRunLoopActivity activity, void *info) +{ + Q_UNUSED(ref); + Q_UNUSED(activity); + + QCFSocketNotifier *that = static_cast(info); + + foreach (MacSocketInfo *socketInfo, that->macSockets) { + if (!CFSocketIsValid(socketInfo->socket)) + continue; + + if (!socketInfo->runloop) { + // Add CFSocket to runloop. + if (!(socketInfo->runloop = qt_mac_add_socket_to_runloop(socketInfo->socket))) { + qWarning("QEventDispatcherMac::registerSocketNotifier: Failed to add CFSocket to runloop"); + CFSocketInvalidate(socketInfo->socket); + continue; + } + + if (!socketInfo->readNotifier) + CFSocketDisableCallBacks(socketInfo->socket, kCFSocketReadCallBack); + if (!socketInfo->writeNotifier) + CFSocketDisableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); + } + + if (socketInfo->readNotifier && !socketInfo->readEnabled) { + socketInfo->readEnabled = true; + CFSocketEnableCallBacks(socketInfo->socket, kCFSocketReadCallBack); + } + if (socketInfo->writeNotifier && !socketInfo->writeEnabled) { + socketInfo->writeEnabled = true; + CFSocketEnableCallBacks(socketInfo->socket, kCFSocketWriteCallBack); } } } diff --git a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h index af8122f753..9bccc1bf98 100644 --- a/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h +++ b/src/platformsupport/cfsocketnotifier/qcfsocketnotifier_p.h @@ -53,11 +53,14 @@ QT_BEGIN_NAMESPACE struct MacSocketInfo { - MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0) {} + MacSocketInfo() : socket(0), runloop(0), readNotifier(0), writeNotifier(0), + readEnabled(false), writeEnabled(false) {} CFSocketRef socket; CFRunLoopSourceRef runloop; QObject *readNotifier; QObject *writeNotifier; + bool readEnabled; + bool writeEnabled; }; typedef QHash MacSocketHash; @@ -83,9 +86,18 @@ public: void unregisterSocketNotifier(QSocketNotifier *notifier); void removeSocketNotifiers(); +private: + void destroyRunLoopObserver(); + + static void unregisterSocketInfo(MacSocketInfo *socketInfo); + static void enableSocketNotifiers(CFRunLoopObserverRef ref, CFRunLoopActivity activity, void *info); + MacSocketHash macSockets; QAbstractEventDispatcher *eventDispatcher; MaybeCancelWaitForMoreEventsFn maybeCancelWaitForMoreEvents; + CFRunLoopObserverRef enableNotifiersObserver; + + friend void qt_mac_socket_callback(CFSocketRef, CFSocketCallBackType, CFDataRef, const void *, void *); }; QT_END_NAMESPACE -- cgit v1.2.3