summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dist/changes-5.11.1144
-rw-r--r--mkspecs/macx-xcode/WorkspaceSettings.xcsettings2
-rw-r--r--qmake/generators/mac/pbuilder_pbx.cpp2
-rw-r--r--src/corelib/Qt5CoreMacros.cmake51
-rw-r--r--src/corelib/global/qsystemdetection.h79
-rw-r--r--src/corelib/kernel/kernel.pri2
-rw-r--r--src/corelib/kernel/qcore_mac_objc.mm41
-rw-r--r--src/corelib/kernel/qcore_mac_p.h11
-rw-r--r--src/gui/kernel/qguiapplication.cpp14
-rw-r--r--src/plugins/platforms/cocoa/qnswindowdelegate.mm35
-rw-r--r--src/plugins/platforms/ios/kernel.pro2
-rw-r--r--src/plugins/platforms/ios/qiosapplicationstate.mm4
-rw-r--r--src/plugins/platforms/ios/qiosfiledialog.mm4
-rw-r--r--src/plugins/platforms/ios/qiosglobal.mm14
-rw-r--r--src/plugins/platforms/ios/qiosinputcontext.mm9
-rw-r--r--src/plugins/platforms/ios/qiosintegration.mm2
-rw-r--r--src/plugins/platforms/ios/qiosmessagedialog.mm4
-rw-r--r--src/plugins/platforms/ios/qiosscreen.mm33
-rw-r--r--src/plugins/platforms/ios/qiosservices.mm25
-rw-r--r--src/plugins/platforms/ios/qiostextinputoverlay.mm8
-rw-r--r--src/plugins/platforms/ios/qiostheme.mm3
-rw-r--r--src/plugins/platforms/ios/qiosviewcontroller.mm10
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.cpp107
-rw-r--r--src/plugins/platforms/xcb/qxcbbackingstore.h3
-rw-r--r--src/plugins/platforms/xcb/qxcbconnection.cpp40
-rw-r--r--src/plugins/platforms/xcb/qxcbscreen.cpp7
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm31
-rw-r--r--src/widgets/graphicsview/qgraphicsitem.cpp2
-rw-r--r--src/widgets/itemviews/qheaderview.cpp2
-rw-r--r--src/widgets/kernel/qwidget.cpp3
-rw-r--r--tests/auto/cmake/CMakeLists.txt1
-rw-r--r--tests/auto/cmake/test_use_modules_function/CMakeLists.txt18
-rw-r--r--tests/auto/cmake/test_use_modules_function/three.cpp45
-rw-r--r--tests/auto/cmake/test_use_modules_function/two.cpp43
-rw-r--r--tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp65
35 files changed, 660 insertions, 206 deletions
diff --git a/dist/changes-5.11.1 b/dist/changes-5.11.1
new file mode 100644
index 0000000000..ed219df454
--- /dev/null
+++ b/dist/changes-5.11.1
@@ -0,0 +1,144 @@
+Qt 5.11.1 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.11.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/index.html
+
+The Qt version 5.11 series is binary compatible with the 5.10.x series.
+Applications compiled for 5.10 will continue to run with 5.11.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://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 *
+****************************************************************************
+
+ - [QTBUG-68619] In Qt 5.11.0, support for selecting a platform plugin
+ based on the XDG_SESSION_TYPE environment variable was added. On
+ gnome-shell, however, bugs—in both Qt and gnome-shell—made many
+ widget applications almost unusable. So until those bugs are fixed
+ XDG_SESSION_TYPE=wayland is now ignored on gnome-shell.
+
+****************************************************************************
+* Library *
+****************************************************************************
+
+QtCore
+------
+
+ - Item Models:
+ * [QTBUG-18001] Fixed a bug that made selecting or deselecting a column if
+ some flags are applied to certain items.
+ * [QTBUG-44962][QTBUG-67948][QTBUG-68427] Fixed issues with the replacing
+ of the source model in QSortFilterProxyModel that could lead to empty
+ views or failed assertions.
+
+ - QJsonDocument
+ * [QTBUG-61969] Fixed a number of bugs in the parsing of binary data
+ (QJson::fromRawData) that could lead to crashes or out-of-bounds access.
+
+ - QLocale:
+ * On Unix, when using LANGUAGE would lose information about script or
+ country, without changing language, use the locale implied by LC_ALL,
+ LC_MESSAGES or LANG.
+
+ - QPointF/QRectF:
+ * [QTBUG-60359][QTBUG-62161] Fixed an issue that led to inconsistent
+ comparison results for the different edges of a rectangle.
+
+ - QProcess:
+ * [QTBUG-68472] On Unix, the QProcess SIGCHLD handler now restores errno
+ on exit.
+ * [QTBUG-67744] QProcess now properly reports an error state if it failed
+ to create the communication pipes.
+
+ - QSharedPointer:
+ * [QTBUG-68300] Fixed a problem that made create() on a type with const
+ qualification fail to compile.
+
+QtNetwork
+---------
+
+ - QNetworkCookieJar:
+ * [QTBUG-52040] Cookies will no longer be rejected when the domain
+ matches a TLD. However (to avoid problems with TLDs), such cookies are
+ only accepted, or sent, when the host name matches exactly.
+
+QtWidgets
+---------
+
+ - [QTBUG-48325] Sending a key press event with sendEvent() now sends a
+ ShortCutOverride event first to the widget to trigger any shortcuts set
+ first.
+ - [QTBUG-67533] QOpenGLWidget/QQuickWidget is now respecting AlwaysStackOnTop.
+ - [QTBUG-60404] Fixed crash in QMacPanGestureRecognizer.
+ - [QTBUG-67836] Fixed input method commits that end with newline.
+ - [QTBUG-33855] Fixed issue with fonts in QHeaderViews
+ - [QTBUG-56457] Fixed margin issue related to sections in QHeaderView.
+
+****************************************************************************
+* Platform-specific Changes *
+****************************************************************************
+
+Android
+-------
+
+ - [QTBUG-68344] QTemporaryFile does not try to use O_TMPFILE any more,
+ to work around outdated sandbox restrictions of linkat(). This also fixes
+ use of QSettings and QFile::copy().
+
+Linux
+-----
+
+ - [QTBUG-68586] Fixed a bug that caused QFileSystemWatcher to print a warning
+ if the file being watched did not exist. The class is documented to return
+ the list of files that it could not watch.
+
+macOS
+-----
+
+ - [QTBUG-60676] Fixed a bug in using QFileSystemWatcher to watch different
+ file paths that shared a common prefix.
+
+Windows
+-------
+
+ - [QTBUG-68514] Reverted a change that caused static binaries compiled
+ with Visual Studio 2015 to crash on start-up. Note that this does not
+ apply to Visual Studio 2017 static binaries, even though the crash stack
+ traces are very similar: with 2017, the problem is compiler regression
+ and requires updating to version 15.8 for the fix.
+
+****************************************************************************
+* Tools *
+****************************************************************************
+
+configure & build system
+------------------------
+
+ - [QTBUG-68478] Fixed parallel build of examples in some modules.
+
+qmake
+-----
+
+ - [QTBUG-37417][CMake] Fixed missing include paths in private modules.
+ - [QTBUG-47325] Fixed crash when $QMAKEFEATURES contains empty paths
+ (e.g., due to a trailing colon).
+ - [QTBUG-52474][Xcode] Fixed sources being excluded from Time Machine
+ backups.
+ - [QTBUG-66462][Darwin] Fixed overriding QMAKE_TARGET_BUNDLE_PREFIX in
+ project files.
+ - [QTBUG-68705][Xcode] Fixed build directory location of app bundles.
+ - [Xcode] Fixed compatibility with Xcode 10 by opting out from the new
+ build system.
+ - [Darwin] Fixed .prl file lookup for suffixed frameworks.
+ - Fixed look-up of relative files from extra compilers' .depend_command
+ in shadow builds.
diff --git a/mkspecs/macx-xcode/WorkspaceSettings.xcsettings b/mkspecs/macx-xcode/WorkspaceSettings.xcsettings
index 08de0be8d3..a3f43a8b38 100644
--- a/mkspecs/macx-xcode/WorkspaceSettings.xcsettings
+++ b/mkspecs/macx-xcode/WorkspaceSettings.xcsettings
@@ -2,6 +2,8 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
+ <key>BuildSystemType</key>
+ <string>Original</string>
<key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
<false/>
</dict>
diff --git a/qmake/generators/mac/pbuilder_pbx.cpp b/qmake/generators/mac/pbuilder_pbx.cpp
index 18b62c5135..80891e682f 100644
--- a/qmake/generators/mac/pbuilder_pbx.cpp
+++ b/qmake/generators/mac/pbuilder_pbx.cpp
@@ -1613,7 +1613,7 @@ ProjectBuilderMakefileGenerator::writeMakeParts(QTextStream &t)
// The configuration build dir however is not treated as excluded,
// so we can safely point it to the root output dir.
t << "\t\t\t\t" << writeSettings("CONFIGURATION_BUILD_DIR",
- Option::output_dir + Option::dir_sep + "$(CONFIGURATION)") << ";\n";
+ Option::output_dir + Option::dir_sep + "$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)") << ";\n";
if (!project->isEmpty("DESTDIR")) {
ProString dir = project->first("DESTDIR");
diff --git a/src/corelib/Qt5CoreMacros.cmake b/src/corelib/Qt5CoreMacros.cmake
index 1627de4002..819b48f973 100644
--- a/src/corelib/Qt5CoreMacros.cmake
+++ b/src/corelib/Qt5CoreMacros.cmake
@@ -294,3 +294,54 @@ function(QT5_ADD_RESOURCES outfiles )
endfunction()
set(_Qt5_COMPONENT_PATH "${CMAKE_CURRENT_LIST_DIR}/..")
+
+if (NOT CMAKE_VERSION VERSION_LESS 2.8.9)
+ macro(qt5_use_modules _target _link_type)
+ if(NOT CMAKE_MINIMUM_REQUIRED_VERSION VERSION_LESS 2.8.11)
+ if(CMAKE_WARN_DEPRECATED)
+ set(messageType WARNING)
+ endif()
+ if(CMAKE_ERROR_DEPRECATED)
+ set(messageType FATAL_ERROR)
+ endif()
+ if(messageType)
+ message(${messageType} "The qt5_use_modules macro is obsolete. Use target_link_libraries with IMPORTED targets instead.")
+ endif()
+ endif()
+
+ if (NOT TARGET ${_target})
+ message(FATAL_ERROR "The first argument to qt5_use_modules must be an existing target.")
+ endif()
+ if ("${_link_type}" STREQUAL "LINK_PUBLIC" OR "${_link_type}" STREQUAL "LINK_PRIVATE" )
+ set(_qt5_modules ${ARGN})
+ set(_qt5_link_type ${_link_type})
+ else()
+ set(_qt5_modules ${_link_type} ${ARGN})
+ endif()
+
+ if ("${_qt5_modules}" STREQUAL "")
+ message(FATAL_ERROR "qt5_use_modules requires at least one Qt module to use.")
+ endif()
+
+ foreach(_module ${_qt5_modules})
+ if (NOT Qt5${_module}_FOUND)
+ find_package(Qt5${_module} PATHS "${_Qt5_COMPONENT_PATH}" NO_DEFAULT_PATH)
+ if (NOT Qt5${_module}_FOUND)
+ message(FATAL_ERROR "Can not use \"${_module}\" module which has not yet been found.")
+ endif()
+ endif()
+ target_link_libraries(${_target} ${_qt5_link_type} ${Qt5${_module}_LIBRARIES})
+ set_property(TARGET ${_target} APPEND PROPERTY INCLUDE_DIRECTORIES ${Qt5${_module}_INCLUDE_DIRS})
+ set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS ${Qt5${_module}_COMPILE_DEFINITIONS})
+ set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELEASE QT_NO_DEBUG)
+ set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_RELWITHDEBINFO QT_NO_DEBUG)
+ set_property(TARGET ${_target} APPEND PROPERTY COMPILE_DEFINITIONS_MINSIZEREL QT_NO_DEBUG)
+ if (Qt5_POSITION_INDEPENDENT_CODE
+ AND (CMAKE_VERSION VERSION_LESS 2.8.12
+ AND (NOT CMAKE_CXX_COMPILER_ID STREQUAL "GNU"
+ OR CMAKE_CXX_COMPILER_VERSION VERSION_LESS 5.0)))
+ set_property(TARGET ${_target} PROPERTY POSITION_INDEPENDENT_CODE ${Qt5_POSITION_INDEPENDENT_CODE})
+ endif()
+ endforeach()
+ endmacro()
+endif()
diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h
index ff0e03108b..cacb95b674 100644
--- a/src/corelib/global/qsystemdetection.h
+++ b/src/corelib/global/qsystemdetection.h
@@ -216,18 +216,6 @@
# // Numerical checks are preferred to named checks, but to be safe
# // we define the missing version names in case Qt uses them.
#
-# if !defined(__MAC_10_7)
-# define __MAC_10_7 1070
-# endif
-# if !defined(__MAC_10_8)
-# define __MAC_10_8 1080
-# endif
-# if !defined(__MAC_10_9)
-# define __MAC_10_9 1090
-# endif
-# if !defined(__MAC_10_10)
-# define __MAC_10_10 101000
-# endif
# if !defined(__MAC_10_11)
# define __MAC_10_11 101100
# endif
@@ -237,17 +225,8 @@
# if !defined(__MAC_10_13)
# define __MAC_10_13 101300
# endif
-# if !defined(MAC_OS_X_VERSION_10_7)
-# define MAC_OS_X_VERSION_10_7 1070
-# endif
-# if !defined(MAC_OS_X_VERSION_10_8)
-# define MAC_OS_X_VERSION_10_8 1080
-# endif
-# if !defined(MAC_OS_X_VERSION_10_9)
-# define MAC_OS_X_VERSION_10_9 1090
-# endif
-# if !defined(MAC_OS_X_VERSION_10_10)
-# define MAC_OS_X_VERSION_10_10 101000
+# if !defined(__MAC_10_14)
+# define __MAC_10_14 101400
# endif
# if !defined(MAC_OS_X_VERSION_10_11)
# define MAC_OS_X_VERSION_10_11 101100
@@ -258,55 +237,10 @@
# if !defined(MAC_OS_X_VERSION_10_13)
# define MAC_OS_X_VERSION_10_13 101300
# endif
-#
-# if !defined(__IPHONE_4_3)
-# define __IPHONE_4_3 40300
-# endif
-# if !defined(__IPHONE_5_0)
-# define __IPHONE_5_0 50000
-# endif
-# if !defined(__IPHONE_5_1)
-# define __IPHONE_5_1 50100
-# endif
-# if !defined(__IPHONE_6_0)
-# define __IPHONE_6_0 60000
-# endif
-# if !defined(__IPHONE_6_1)
-# define __IPHONE_6_1 60100
-# endif
-# if !defined(__IPHONE_7_0)
-# define __IPHONE_7_0 70000
-# endif
-# if !defined(__IPHONE_7_1)
-# define __IPHONE_7_1 70100
-# endif
-# if !defined(__IPHONE_8_0)
-# define __IPHONE_8_0 80000
-# endif
-# if !defined(__IPHONE_8_1)
-# define __IPHONE_8_1 80100
-# endif
-# if !defined(__IPHONE_8_2)
-# define __IPHONE_8_2 80200
-# endif
-# if !defined(__IPHONE_8_3)
-# define __IPHONE_8_3 80300
-# endif
-# if !defined(__IPHONE_8_4)
-# define __IPHONE_8_4 80400
-# endif
-# if !defined(__IPHONE_9_0)
-# define __IPHONE_9_0 90000
-# endif
-# if !defined(__IPHONE_9_1)
-# define __IPHONE_9_1 90100
-# endif
-# if !defined(__IPHONE_9_2)
-# define __IPHONE_9_2 90200
-# endif
-# if !defined(__IPHONE_9_3)
-# define __IPHONE_9_3 90300
+# if !defined(MAC_OS_X_VERSION_10_14)
+# define MAC_OS_X_VERSION_10_14 101400
# endif
+#
# if !defined(__IPHONE_10_0)
# define __IPHONE_10_0 100000
# endif
@@ -322,6 +256,9 @@
# if !defined(__IPHONE_11_0)
# define __IPHONE_11_0 110000
# endif
+# if !defined(__IPHONE_12_0)
+# define __IPHONE_12_0 120000
+# endif
#endif
#ifdef __LSB_VERSION__
diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri
index ca8bd30698..c528b16f9c 100644
--- a/src/corelib/kernel/kernel.pri
+++ b/src/corelib/kernel/kernel.pri
@@ -120,7 +120,7 @@ mac {
LIBS_PRIVATE += -framework Foundation
- osx: LIBS_PRIVATE += -framework CoreServices -framework AppKit
+ osx: LIBS_PRIVATE += -framework CoreServices -framework AppKit -framework Security
ios|tvos {
# We need UIKit for UIApplication in qeventdispatcher_cf.mm
diff --git a/src/corelib/kernel/qcore_mac_objc.mm b/src/corelib/kernel/qcore_mac_objc.mm
index c29c4dfc14..6b11e90a4e 100644
--- a/src/corelib/kernel/qcore_mac_objc.mm
+++ b/src/corelib/kernel/qcore_mac_objc.mm
@@ -44,6 +44,10 @@
#include <AppKit/NSText.h>
#endif
+#if defined(QT_PLATFORM_UIKIT)
+#include <UIKit/UIKit.h>
+#endif
+
#include <qdebug.h>
QT_BEGIN_NAMESPACE
@@ -189,6 +193,43 @@ AppleApplication *qt_apple_sharedApplication()
}
#endif
+#if defined(Q_OS_MACOS) && !defined(QT_BOOTSTRAPPED)
+bool qt_apple_isSandboxed()
+{
+ static bool isSandboxed = []() {
+ QCFType<SecStaticCodeRef> staticCode = nullptr;
+ NSURL *bundleUrl = [[NSBundle mainBundle] bundleURL];
+ if (SecStaticCodeCreateWithPath((__bridge CFURLRef)bundleUrl,
+ kSecCSDefaultFlags, &staticCode) != errSecSuccess)
+ return false;
+
+ QCFType<SecRequirementRef> sandboxRequirement;
+ if (SecRequirementCreateWithString(CFSTR("entitlement[\"com.apple.security.app-sandbox\"] exists"),
+ kSecCSDefaultFlags, &sandboxRequirement) != errSecSuccess)
+ return false;
+
+ if (SecStaticCodeCheckValidityWithErrors(staticCode,
+ kSecCSBasicValidateOnly, sandboxRequirement, nullptr) != errSecSuccess)
+ return false;
+
+ return true;
+ }();
+ return isSandboxed;
+}
+
+QT_END_NAMESPACE
+@implementation NSObject (QtSandboxHelpers)
+- (id)qt_valueForPrivateKey:(NSString *)key
+{
+ if (qt_apple_isSandboxed())
+ return nil;
+
+ return [self valueForKey:key];
+}
+@end
+QT_BEGIN_NAMESPACE
+#endif
+
#ifdef Q_OS_MACOS
/*
Ensure that Objective-C objects auto-released in main(), directly or indirectly,
diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h
index 9bd2e31bc9..af939abaac 100644
--- a/src/corelib/kernel/qcore_mac_p.h
+++ b/src/corelib/kernel/qcore_mac_p.h
@@ -160,6 +160,17 @@ QDebug operator<<(QDebug debug, const QMacAutoReleasePool *pool);
Q_CORE_EXPORT void qt_apple_check_os_version();
Q_CORE_EXPORT bool qt_apple_isApplicationExtension();
+#if defined(Q_OS_MACOS) && !defined(QT_BOOTSTRAPPED)
+Q_CORE_EXPORT bool qt_apple_isSandboxed();
+# ifdef __OBJC__
+QT_END_NAMESPACE
+@interface NSObject (QtSandboxHelpers)
+- (id)qt_valueForPrivateKey:(NSString *)key;
+@end
+QT_BEGIN_NAMESPACE
+# endif
+#endif
+
#if !defined(QT_BOOTSTRAPPED) && !defined(Q_OS_WATCHOS)
QT_END_NAMESPACE
# if defined(Q_OS_MACOS)
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index c73dac42d6..2ef689b5b9 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1297,10 +1297,18 @@ void QGuiApplicationPrivate::createPlatformIntegration()
#if defined(Q_OS_UNIX) && !defined(Q_OS_DARWIN)
QByteArray sessionType = qgetenv("XDG_SESSION_TYPE");
if (!sessionType.isEmpty()) {
- if (sessionType == QByteArrayLiteral("x11") && !platformName.contains(QByteArrayLiteral("xcb")))
+ if (sessionType == QByteArrayLiteral("x11") && !platformName.contains(QByteArrayLiteral("xcb"))) {
platformName = QByteArrayLiteral("xcb");
- else if (sessionType == QByteArrayLiteral("wayland") && !platformName.contains(QByteArrayLiteral("wayland")))
- platformName = QByteArrayLiteral("wayland");
+ } else if (sessionType == QByteArrayLiteral("wayland") && !platformName.contains(QByteArrayLiteral("wayland"))) {
+ QByteArray currentDesktop = qgetenv("XDG_CURRENT_DESKTOP").toLower();
+ QByteArray sessionDesktop = qgetenv("XDG_SESSION_DESKTOP").toLower();
+ if (currentDesktop.contains("gnome") || sessionDesktop.contains("gnome")) {
+ qInfo() << "Warning: Ignoring XDG_SESSION_TYPE=wayland on Gnome."
+ << "Use QT_QPA_PLATFORM=wayland to run on Wayland anyway.";
+ } else {
+ platformName = QByteArrayLiteral("wayland");
+ }
+ }
}
#ifdef QT_QPA_DEFAULT_PLATFORM_NAME
// Add it as fallback in case XDG_SESSION_TYPE is something wrong
diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.mm b/src/plugins/platforms/cocoa/qnswindowdelegate.mm
index 15c141448d..057a4c2943 100644
--- a/src/plugins/platforms/cocoa/qnswindowdelegate.mm
+++ b/src/plugins/platforms/cocoa/qnswindowdelegate.mm
@@ -69,25 +69,38 @@ static QRegExp whitespaceRegex = QRegExp(QStringLiteral("\\s*"));
/*!
Overridden to ensure that the zoomed state always results in a maximized
window, which would otherwise not be the case for borderless windows.
+
+ We also keep the window on the same screen as before; something AppKit
+ sometimes fails to do using its built in logic.
*/
- (NSRect)windowWillUseStandardFrame:(NSWindow *)window defaultFrame:(NSRect)proposedFrame
{
Q_UNUSED(proposedFrame);
Q_ASSERT(window == m_cocoaWindow->nativeWindow());
-
- // We compute the maximized state based on the maximum size, and
- // the current position of the window. This may result in the window
- // geometry falling outside of the current screen's available geometry,
- // e.g. when there is not maximize size set, but this is okey, AppKit
- // will then shift and possibly clip the geometry for us.
const QWindow *w = m_cocoaWindow->window();
- QRect maximizedRect = QRect(w->framePosition(), w->maximumSize());
- // QWindow::maximumSize() refers to the client size,
- // but AppKit expects the full frame size.
- maximizedRect.adjust(0, 0, 0, w->frameMargins().top());
+ // maximumSize() refers to the client size, but AppKit expects the full frame size
+ QSizeF maximumSize = w->maximumSize() + QSize(0, w->frameMargins().top());
+
+ // The window should never be larger than the current screen geometry
+ const QRectF screenGeometry = m_cocoaWindow->screen()->geometry();
+ maximumSize = maximumSize.boundedTo(screenGeometry.size());
+
+ // Use the current frame position for the initial maximized frame,
+ // so that the window stays put and just expand, in case its maximum
+ // size is within the screen bounds.
+ QRectF maximizedFrame = QRectF(w->framePosition(), maximumSize);
+
+ // But constrain the frame to the screen bounds in case the frame
+ // extends beyond the screen bounds as a result of starting out
+ // with the current frame position.
+ maximizedFrame.translate(QPoint(
+ qMax(screenGeometry.left() - maximizedFrame.left(), 0.0) +
+ qMin(screenGeometry.right() - maximizedFrame.right(), 0.0),
+ qMax(screenGeometry.top() - maximizedFrame.top(), 0.0) +
+ qMin(screenGeometry.bottom() - maximizedFrame.bottom(), 0.0)));
- return QCocoaScreen::mapToNative(maximizedRect);
+ return QCocoaScreen::mapToNative(maximizedFrame);
}
- (BOOL)window:(NSWindow *)window shouldPopUpDocumentPathMenu:(NSMenu *)menu
diff --git a/src/plugins/platforms/ios/kernel.pro b/src/plugins/platforms/ios/kernel.pro
index 6eb9f2c534..71257d09f7 100644
--- a/src/plugins/platforms/ios/kernel.pro
+++ b/src/plugins/platforms/ios/kernel.pro
@@ -5,8 +5,6 @@ TARGET = qios
# application's main() when the plugin is a shared library.
qtConfig(shared): CONFIG += static
-CONFIG += no_app_extension_api_only
-
QT += \
core-private gui-private \
clipboard_support-private fontdatabase_support-private graphics_support-private
diff --git a/src/plugins/platforms/ios/qiosapplicationstate.mm b/src/plugins/platforms/ios/qiosapplicationstate.mm
index cc76d198f5..bf4e9cc900 100644
--- a/src/plugins/platforms/ios/qiosapplicationstate.mm
+++ b/src/plugins/platforms/ios/qiosapplicationstate.mm
@@ -86,7 +86,7 @@ static void qRegisterApplicationStateNotifications()
QLatin1String("Extension loaded, assuming state is active"));
} else {
// Initialize correct startup state, which may not be the Qt default (inactive)
- UIApplicationState startupState = [UIApplication sharedApplication].applicationState;
+ UIApplicationState startupState = qt_apple_sharedApplication().applicationState;
QIOSApplicationState::handleApplicationStateChanged(startupState, QLatin1String("Application loaded"));
}
}
@@ -95,7 +95,7 @@ Q_CONSTRUCTOR_FUNCTION(qRegisterApplicationStateNotifications)
QIOSApplicationState::QIOSApplicationState()
{
if (!qt_apple_isApplicationExtension()) {
- UIApplicationState startupState = [UIApplication sharedApplication].applicationState;
+ UIApplicationState startupState = qt_apple_sharedApplication().applicationState;
QIOSApplicationState::handleApplicationStateChanged(startupState, QLatin1String("Application launched"));
}
}
diff --git a/src/plugins/platforms/ios/qiosfiledialog.mm b/src/plugins/platforms/ios/qiosfiledialog.mm
index 5987bc1540..e8a3f5b30e 100644
--- a/src/plugins/platforms/ios/qiosfiledialog.mm
+++ b/src/plugins/platforms/ios/qiosfiledialog.mm
@@ -43,6 +43,8 @@
#include <QtGui/qwindow.h>
#include <QDebug>
+#include <QtCore/private/qcore_mac_p.h>
+
#include "qiosfiledialog.h"
#include "qiosintegration.h"
#include "qiosoptionalplugininterface.h"
@@ -94,7 +96,7 @@ bool QIOSFileDialog::showImagePickerDialog(QWindow *parent)
}
UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window
- : [UIApplication sharedApplication].keyWindow;
+ : qt_apple_sharedApplication().keyWindow;
[window.rootViewController presentViewController:m_viewController animated:YES completion:nil];
return true;
diff --git a/src/plugins/platforms/ios/qiosglobal.mm b/src/plugins/platforms/ios/qiosglobal.mm
index f27b2242df..a523d1be45 100644
--- a/src/plugins/platforms/ios/qiosglobal.mm
+++ b/src/plugins/platforms/ios/qiosglobal.mm
@@ -42,6 +42,8 @@
#include "qiosviewcontroller.h"
#include "qiosscreen.h"
+#include <QtCore/private/qcore_mac_p.h>
+
QT_BEGIN_NAMESPACE
Q_LOGGING_CATEGORY(lcQpaApplication, "qt.qpa.application");
@@ -50,13 +52,16 @@ Q_LOGGING_CATEGORY(lcQpaWindow, "qt.qpa.window");
bool isQtApplication()
{
+ if (qt_apple_isApplicationExtension())
+ return false;
+
// Returns \c true if the plugin is in full control of the whole application. This means
// that we control the application delegate and the top view controller, and can take
// actions that impacts all parts of the application. The opposite means that we are
// embedded inside a native iOS application, and should be more focused on playing along
// with native UIControls, and less inclined to change structures that lies outside the
// scope of our QWindows/UIViews.
- static bool isQt = ([[UIApplication sharedApplication].delegate isKindOfClass:[QIOSApplicationDelegate class]]);
+ static bool isQt = ([qt_apple_sharedApplication().delegate isKindOfClass:[QIOSApplicationDelegate class]]);
return isQt;
}
@@ -152,8 +157,13 @@ QT_END_NAMESPACE
+ (id)currentFirstResponder
{
+ if (qt_apple_isApplicationExtension()) {
+ qWarning() << "can't get first responder in application extensions!";
+ return nil;
+ }
+
QtFirstResponderEvent *event = [[[QtFirstResponderEvent alloc] init] autorelease];
- [[UIApplication sharedApplication] sendAction:@selector(qt_findFirstResponder:event:) to:nil from:nil forEvent:event];
+ [qt_apple_sharedApplication() sendAction:@selector(qt_findFirstResponder:event:) to:nil from:nil forEvent:event];
return event.firstResponder;
}
diff --git a/src/plugins/platforms/ios/qiosinputcontext.mm b/src/plugins/platforms/ios/qiosinputcontext.mm
index 050c592aca..493c283ec1 100644
--- a/src/plugins/platforms/ios/qiosinputcontext.mm
+++ b/src/plugins/platforms/ios/qiosinputcontext.mm
@@ -49,6 +49,8 @@
#include "qioswindow.h"
#include "quiview.h"
+#include <QtCore/private/qcore_mac_p.h>
+
#include <QGuiApplication>
#include <QtGui/private/qwindow_p.h>
@@ -536,6 +538,11 @@ void QIOSInputContext::scroll(int y)
if (!rootView)
return;
+ if (qt_apple_isApplicationExtension()) {
+ qWarning() << "can't scroll root view in application extension";
+ return;
+ }
+
CATransform3D translationTransform = CATransform3DMakeTranslation(0.0, -y, 0.0);
if (CATransform3DEqualToTransform(translationTransform, rootView.layer.sublayerTransform))
return;
@@ -574,7 +581,7 @@ void QIOSInputContext::scroll(int y)
// Raise all known windows to above the status-bar if we're scrolling the screen,
// while keeping the relative window level between the windows the same.
- NSArray *applicationWindows = [[UIApplication sharedApplication] windows];
+ NSArray *applicationWindows = [qt_apple_sharedApplication() windows];
static QHash<UIWindow *, UIWindowLevel> originalWindowLevels;
for (UIWindow *window in applicationWindows) {
if (keyboardScrollIsActive && !originalWindowLevels.contains(window))
diff --git a/src/plugins/platforms/ios/qiosintegration.mm b/src/plugins/platforms/ios/qiosintegration.mm
index b8ce49aaca..ed2bfbc0d8 100644
--- a/src/plugins/platforms/ios/qiosintegration.mm
+++ b/src/plugins/platforms/ios/qiosintegration.mm
@@ -86,7 +86,7 @@ QIOSIntegration::QIOSIntegration()
, m_accessibility(0)
, m_optionalPlugins(new QFactoryLoader(QIosOptionalPluginInterface_iid, QLatin1String("/platforms/darwin")))
{
- if (Q_UNLIKELY(![UIApplication sharedApplication])) {
+ if (Q_UNLIKELY(!qt_apple_isApplicationExtension() && !qt_apple_sharedApplication())) {
qFatal("Error: You are creating QApplication before calling UIApplicationMain.\n" \
"If you are writing a native iOS application, and only want to use Qt for\n" \
"parts of the application, a good place to create QApplication is from within\n" \
diff --git a/src/plugins/platforms/ios/qiosmessagedialog.mm b/src/plugins/platforms/ios/qiosmessagedialog.mm
index 9d05b792c2..a7de9b473a 100644
--- a/src/plugins/platforms/ios/qiosmessagedialog.mm
+++ b/src/plugins/platforms/ios/qiosmessagedialog.mm
@@ -43,6 +43,8 @@
#include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformtheme.h>
+#include <QtCore/private/qcore_mac_p.h>
+
#include "qiosglobal.h"
#include "quiview.h"
#include "qiosmessagedialog.h"
@@ -126,7 +128,7 @@ bool QIOSMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality win
[m_alertController addAction:createAction(NoButton)];
}
- UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window : [UIApplication sharedApplication].keyWindow;
+ UIWindow *window = parent ? reinterpret_cast<UIView *>(parent->winId()).window : qt_apple_sharedApplication().keyWindow;
[window.rootViewController presentViewController:m_alertController animated:YES completion:nil];
return true;
}
diff --git a/src/plugins/platforms/ios/qiosscreen.mm b/src/plugins/platforms/ios/qiosscreen.mm
index c394592d76..f367d1e75e 100644
--- a/src/plugins/platforms/ios/qiosscreen.mm
+++ b/src/plugins/platforms/ios/qiosscreen.mm
@@ -46,6 +46,8 @@
#include "qiosviewcontroller.h"
#include "quiview.h"
+#include <QtCore/private/qcore_mac_p.h>
+
#include <QtGui/private/qwindow_p.h>
#include <private/qcoregraphics_p.h>
@@ -271,17 +273,19 @@ QIOSScreen::QIOSScreen(UIScreen *screen)
m_physicalDpi = 96;
}
- for (UIWindow *existingWindow in [[UIApplication sharedApplication] windows]) {
- if (existingWindow.screen == m_uiScreen) {
- m_uiWindow = [m_uiWindow retain];
- break;
+ if (!qt_apple_isApplicationExtension()) {
+ for (UIWindow *existingWindow in qt_apple_sharedApplication().windows) {
+ if (existingWindow.screen == m_uiScreen) {
+ m_uiWindow = [m_uiWindow retain];
+ break;
+ }
}
- }
- if (!m_uiWindow) {
- // Create a window and associated view-controller that we can use
- m_uiWindow = [[QUIWindow alloc] initWithFrame:[m_uiScreen bounds]];
- m_uiWindow.rootViewController = [[[QIOSViewController alloc] initWithQIOSScreen:this] autorelease];
+ if (!m_uiWindow) {
+ // Create a window and associated view-controller that we can use
+ m_uiWindow = [[QUIWindow alloc] initWithFrame:[m_uiScreen bounds]];
+ m_uiWindow.rootViewController = [[[QIOSViewController alloc] initWithQIOSScreen:this] autorelease];
+ }
}
updateProperties();
@@ -327,17 +331,20 @@ void QIOSScreen::updateProperties()
#ifndef Q_OS_TVOS
if (m_uiScreen == [UIScreen mainScreen]) {
- Qt::ScreenOrientation statusBarOrientation = toQtScreenOrientation(UIDeviceOrientation([UIApplication sharedApplication].statusBarOrientation));
-
QIOSViewController *qtViewController = [m_uiWindow.rootViewController isKindOfClass:[QIOSViewController class]] ?
static_cast<QIOSViewController *>(m_uiWindow.rootViewController) : nil;
if (qtViewController.lockedOrientation) {
+ Q_ASSERT(!qt_apple_isApplicationExtension());
+
// Setting the statusbar orientation (content orientation) on will affect the screen geometry,
// which is not what we want. We want to reflect the screen geometry based on the locked orientation,
// and adjust the available geometry based on the repositioned status bar for the current status
// bar orientation.
+ Qt::ScreenOrientation statusBarOrientation = toQtScreenOrientation(
+ UIDeviceOrientation(qt_apple_sharedApplication().statusBarOrientation));
+
Qt::ScreenOrientation lockedOrientation = toQtScreenOrientation(UIDeviceOrientation(qtViewController.lockedOrientation));
QTransform transform = transformBetween(lockedOrientation, statusBarOrientation, m_geometry).inverted();
@@ -487,8 +494,8 @@ Qt::ScreenOrientation QIOSScreen::orientation() const
// the orientation the application was started up in (which may not match
// the physical orientation of the device, but typically does unless the
// application has been locked to a subset of the available orientations).
- if (deviceOrientation == UIDeviceOrientationUnknown)
- deviceOrientation = UIDeviceOrientation([UIApplication sharedApplication].statusBarOrientation);
+ if (deviceOrientation == UIDeviceOrientationUnknown && !qt_apple_isApplicationExtension())
+ deviceOrientation = UIDeviceOrientation(qt_apple_sharedApplication().statusBarOrientation);
// If the device reports face up or face down orientations, we can't map
// them to Qt orientations, so we pretend we're in the same orientation
diff --git a/src/plugins/platforms/ios/qiosservices.mm b/src/plugins/platforms/ios/qiosservices.mm
index 3c44e1d7d6..7222bf6793 100644
--- a/src/plugins/platforms/ios/qiosservices.mm
+++ b/src/plugins/platforms/ios/qiosservices.mm
@@ -40,6 +40,9 @@
#include "qiosservices.h"
#include <QtCore/qurl.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/private/qcore_mac_p.h>
+
#include <QtGui/qdesktopservices.h>
#import <UIKit/UIApplication.h>
@@ -48,6 +51,11 @@ QT_BEGIN_NAMESPACE
bool QIOSServices::openUrl(const QUrl &url)
{
+ if (qt_apple_isApplicationExtension()) {
+ qWarning() << "openUrl not implement for application extensions yet";
+ return false;
+ }
+
if (url == m_handlingUrl)
return false;
@@ -55,12 +63,25 @@ bool QIOSServices::openUrl(const QUrl &url)
return openDocument(url);
NSURL *nsUrl = url.toNSURL();
- UIApplication *application = [UIApplication sharedApplication];
+ UIApplication *application = qt_apple_sharedApplication();
if (![application canOpenURL:nsUrl])
return false;
- [application openURL:nsUrl options:@{} completionHandler:nil];
+ static SEL openUrlSelector = @selector(openURL:options:completionHandler:);
+ NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
+ [UIApplication instanceMethodSignatureForSelector:openUrlSelector]];
+ invocation.target = application;
+ invocation.selector = openUrlSelector;
+
+ static auto kEmptyDictionary = @{};
+ // Indices 0 and 1 are self and _cmd
+ [invocation setArgument:&nsUrl atIndex:2];
+ [invocation setArgument:&kEmptyDictionary atIndex:3];
+ // Fourth argument is nil, so left unset
+
+ [invocation invoke];
+
return true;
}
diff --git a/src/plugins/platforms/ios/qiostextinputoverlay.mm b/src/plugins/platforms/ios/qiostextinputoverlay.mm
index fe3c29d037..87c282e24a 100644
--- a/src/plugins/platforms/ios/qiostextinputoverlay.mm
+++ b/src/plugins/platforms/ios/qiostextinputoverlay.mm
@@ -46,6 +46,7 @@
#include <QtGui/private/qinputmethod_p.h>
#include <QtCore/private/qobject_p.h>
+#include <QtCore/private/qcore_mac_p.h>
#include "qiosglobal.h"
#include "qiostextinputoverlay.h"
@@ -475,7 +476,7 @@ static void executeBlockWithoutAnimation(Block block)
if (enabled) {
_focusView = [reinterpret_cast<UIView *>(qApp->focusWindow()->winId()) retain];
- _desktopView = [[UIApplication sharedApplication].keyWindow.rootViewController.view retain];
+ _desktopView = [qt_apple_sharedApplication().keyWindow.rootViewController.view retain];
Q_ASSERT(_focusView && _desktopView && _desktopView.superview);
[_desktopView addGestureRecognizer:self];
} else {
@@ -991,6 +992,11 @@ QIOSTextInputOverlay::QIOSTextInputOverlay()
, m_selectionRecognizer(nullptr)
, m_openMenuOnTapRecognizer(nullptr)
{
+ if (qt_apple_isApplicationExtension()) {
+ qWarning() << "text input overlays disabled in application extensions";
+ return;
+ }
+
connect(qApp, &QGuiApplication::focusObjectChanged, this, &QIOSTextInputOverlay::updateFocusObject);
}
diff --git a/src/plugins/platforms/ios/qiostheme.mm b/src/plugins/platforms/ios/qiostheme.mm
index 91980d3f35..5534264a60 100644
--- a/src/plugins/platforms/ios/qiostheme.mm
+++ b/src/plugins/platforms/ios/qiostheme.mm
@@ -41,6 +41,7 @@
#include <QtCore/QStringList>
#include <QtCore/QVariant>
+#include <QtCore/private/qcore_mac_p.h>
#include <QtGui/QFont>
@@ -103,7 +104,7 @@ bool QIOSTheme::usePlatformNativeDialog(QPlatformTheme::DialogType type) const
switch (type) {
case FileDialog:
case MessageDialog:
- return true;
+ return !qt_apple_isApplicationExtension();
default:
return false;
}
diff --git a/src/plugins/platforms/ios/qiosviewcontroller.mm b/src/plugins/platforms/ios/qiosviewcontroller.mm
index d7db6ba856..aa909d6f63 100644
--- a/src/plugins/platforms/ios/qiosviewcontroller.mm
+++ b/src/plugins/platforms/ios/qiosviewcontroller.mm
@@ -41,6 +41,7 @@
#import "qiosviewcontroller.h"
#include <QtCore/qscopedvaluerollback.h>
+#include <QtCore/private/qcore_mac_p.h>
#include <QtGui/QGuiApplication>
#include <QtGui/QWindow>
@@ -307,15 +308,17 @@
{
[super viewDidLoad];
+ Q_ASSERT(!qt_apple_isApplicationExtension());
+
#ifndef Q_OS_TVOS
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(willChangeStatusBarFrame:)
name:UIApplicationWillChangeStatusBarFrameNotification
- object:[UIApplication sharedApplication]];
+ object:qt_apple_sharedApplication()];
[center addObserver:self selector:@selector(didChangeStatusBarOrientation:)
name:UIApplicationDidChangeStatusBarOrientationNotification
- object:[UIApplication sharedApplication]];
+ object:qt_apple_sharedApplication()];
#endif
}
@@ -455,7 +458,6 @@
focusWindow = qt_window_private(focusWindow)->topLevelWindow();
#ifndef Q_OS_TVOS
- UIApplication *uiApplication = [UIApplication sharedApplication];
// -------------- Status bar style and visbility ---------------
@@ -479,6 +481,8 @@
// -------------- Content orientation ---------------
+ UIApplication *uiApplication = qt_apple_sharedApplication();
+
static BOOL kAnimateContentOrientationChanges = YES;
Qt::ScreenOrientation contentOrientation = focusWindow->contentOrientation();
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
index 8cfcc49f9a..b81cb8efa1 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp
@@ -95,6 +95,9 @@ public:
void put(xcb_drawable_t dst, const QRegion &region, const QPoint &offset);
void preparePaint(const QRegion &region);
+ static bool createSystemVShmSegment(QXcbConnection *c, size_t segmentSize = 1,
+ xcb_shm_segment_info_t *shm_info = nullptr);
+
private:
void createShmSegment(size_t segmentSize);
void destroyShmSegment(size_t segmentSize);
@@ -325,15 +328,16 @@ void QXcbBackingStoreImage::createShmSegment(size_t segmentSize)
#ifdef XCB_USE_SHM_FD
if (connection()->hasShmFd()) {
if (Q_UNLIKELY(segmentSize > std::numeric_limits<uint32_t>::max())) {
- qWarning("QXcbShmImage: xcb_shm_create_segment() can't be called for size %zu, maximum allowed size is %u",
- segmentSize, std::numeric_limits<uint32_t>::max());
+ qCWarning(lcQpaXcb, "xcb_shm_create_segment() can't be called for size %zu, maximum"
+ "allowed size is %u", segmentSize, std::numeric_limits<uint32_t>::max());
return;
}
+
const auto seg = xcb_generate_id(xcb_connection());
auto reply = Q_XCB_REPLY(xcb_shm_create_segment,
xcb_connection(), seg, segmentSize, false);
if (!reply) {
- qWarning("QXcbShmImage: xcb_shm_create_segment() failed for size %zu", segmentSize);
+ qCWarning(lcQpaXcb, "xcb_shm_create_segment() failed for size %zu", segmentSize);
return;
}
@@ -342,13 +346,13 @@ void QXcbBackingStoreImage::createShmSegment(size_t segmentSize)
for (int i = 0; i < reply->nfd; i++)
close(fds[i]);
- qWarning("QXcbShmImage: failed to get file descriptor for shm segment of size %zu", segmentSize);
+ qCWarning(lcQpaXcb, "failed to get file descriptor for shm segment of size %zu", segmentSize);
return;
}
void *addr = mmap(nullptr, segmentSize, PROT_READ|PROT_WRITE, MAP_SHARED, fds[0], 0);
if (addr == MAP_FAILED) {
- qWarning("QXcbShmImage: failed to mmap segment from X server (%d: %s) for size %zu",
+ qCWarning(lcQpaXcb, "failed to mmap segment from X server (%d: %s) for size %zu",
errno, strerror(errno), segmentSize);
close(fds[0]);
xcb_shm_detach(xcb_connection(), seg);
@@ -358,47 +362,54 @@ void QXcbBackingStoreImage::createShmSegment(size_t segmentSize)
close(fds[0]);
m_shm_info.shmseg = seg;
m_shm_info.shmaddr = static_cast<quint8 *>(addr);
-
m_segmentSize = segmentSize;
} else
#endif
{
- const int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600);
- if (id == -1) {
- qWarning("QXcbShmImage: shmget() failed (%d: %s) for size %zu",
- errno, strerror(errno), segmentSize);
- return;
- }
-
- void *addr = shmat(id, 0, 0);
- if (addr == (void *)-1) {
- qWarning("QXcbShmImage: shmat() failed (%d: %s) for id %d",
- errno, strerror(errno), id);
- return;
- }
-
- if (shmctl(id, IPC_RMID, 0) == -1)
- qWarning("QXcbBackingStore: Error while marking the shared memory segment to be destroyed");
+ if (createSystemVShmSegment(connection(), segmentSize, &m_shm_info))
+ m_segmentSize = segmentSize;
+ }
+}
- const auto seg = xcb_generate_id(xcb_connection());
- auto cookie = xcb_shm_attach_checked(xcb_connection(), seg, id, false);
- auto *error = xcb_request_check(xcb_connection(), cookie);
- if (error) {
- connection()->printXcbError("QXcbShmImage: xcb_shm_attach() failed with error", error);
- free(error);
- if (shmdt(addr) == -1) {
- qWarning("QXcbShmImage: shmdt() failed (%d: %s) for %p",
- errno, strerror(errno), addr);
- }
- return;
- }
+bool QXcbBackingStoreImage::createSystemVShmSegment(QXcbConnection *c, size_t segmentSize,
+ xcb_shm_segment_info_t *shmInfo)
+{
+ const int id = shmget(IPC_PRIVATE, segmentSize, IPC_CREAT | 0600);
+ if (id == -1) {
+ qCWarning(lcQpaXcb, "shmget() failed (%d: %s) for size %zu", errno, strerror(errno), segmentSize);
+ return false;
+ }
- m_shm_info.shmseg = seg;
- m_shm_info.shmid = id; // unused
- m_shm_info.shmaddr = static_cast<quint8 *>(addr);
+ void *addr = shmat(id, 0, 0);
+ if (addr == (void *)-1) {
+ qCWarning(lcQpaXcb, "shmat() failed (%d: %s) for id %d", errno, strerror(errno), id);
+ return false;
+ }
- m_segmentSize = segmentSize;
+ if (shmctl(id, IPC_RMID, 0) == -1)
+ qCWarning(lcQpaXcb, "Error while marking the shared memory segment to be destroyed");
+
+ const auto seg = xcb_generate_id(c->xcb_connection());
+ auto cookie = xcb_shm_attach_checked(c->xcb_connection(), seg, id, false);
+ auto *error = xcb_request_check(c->xcb_connection(), cookie);
+ if (error) {
+ c->printXcbError("xcb_shm_attach() failed with error", error);
+ free(error);
+ if (shmdt(addr) == -1)
+ qCWarning(lcQpaXcb, "shmdt() failed (%d: %s) for %p", errno, strerror(errno), addr);
+ return false;
+ } else if (!shmInfo) { // this was a test run, free the allocated test segment
+ xcb_shm_detach(c->xcb_connection(), seg);
+ auto shmaddr = static_cast<quint8 *>(addr);
+ if (shmdt(shmaddr) == -1)
+ qCWarning(lcQpaXcb, "shmdt() failed (%d: %s) for %p", errno, strerror(errno), shmaddr);
+ }
+ if (shmInfo) {
+ shmInfo->shmseg = seg;
+ shmInfo->shmid = id; // unused
+ shmInfo->shmaddr = static_cast<quint8 *>(addr);
}
+ return true;
}
void QXcbBackingStoreImage::destroyShmSegment(size_t segmentSize)
@@ -409,21 +420,21 @@ void QXcbBackingStoreImage::destroyShmSegment(size_t segmentSize)
auto cookie = xcb_shm_detach_checked(xcb_connection(), m_shm_info.shmseg);
xcb_generic_error_t *error = xcb_request_check(xcb_connection(), cookie);
if (error)
- connection()->printXcbError("QXcbShmImage: xcb_shm_detach() failed with error", error);
+ connection()->printXcbError("xcb_shm_detach() failed with error", error);
m_shm_info.shmseg = 0;
#ifdef XCB_USE_SHM_FD
if (connection()->hasShmFd()) {
if (munmap(m_shm_info.shmaddr, segmentSize) == -1) {
- qWarning("QXcbShmImage: munmap() failed (%d: %s) for %p with size %zu",
- errno, strerror(errno), m_shm_info.shmaddr, segmentSize);
+ qCWarning(lcQpaXcb, "munmap() failed (%d: %s) for %p with size %zu",
+ errno, strerror(errno), m_shm_info.shmaddr, segmentSize);
}
} else
#endif
{
if (shmdt(m_shm_info.shmaddr) == -1) {
- qWarning("QXcbShmImage: shmdt() failed (%d: %s) for %p",
- errno, strerror(errno), m_shm_info.shmaddr);
+ qCWarning(lcQpaXcb, "shmdt() failed (%d: %s) for %p",
+ errno, strerror(errno), m_shm_info.shmaddr);
}
m_shm_info.shmid = 0; // unused
}
@@ -718,6 +729,12 @@ void QXcbBackingStoreImage::preparePaint(const QRegion &region)
m_pendingFlush |= region;
}
+bool QXcbBackingStore::createSystemVShmSegment(QXcbConnection *c, size_t segmentSize, void *shmInfo)
+{
+ auto info = reinterpret_cast<xcb_shm_segment_info_t *>(shmInfo);
+ return QXcbBackingStoreImage::createSystemVShmSegment(c, segmentSize, info);
+}
+
QXcbBackingStore::QXcbBackingStore(QWindow *window)
: QPlatformBackingStore(window)
{
@@ -757,7 +774,7 @@ void QXcbBackingStore::beginPaint(const QRegion &region)
void QXcbBackingStore::endPaint()
{
if (Q_UNLIKELY(m_paintRegions.isEmpty())) {
- qWarning("%s: paint regions empty!", Q_FUNC_INFO);
+ qCWarning(lcQpaXcb, "%s: paint regions empty!", Q_FUNC_INFO);
return;
}
@@ -811,7 +828,7 @@ void QXcbBackingStore::flush(QWindow *window, const QRegion &region, const QPoin
QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle());
if (!platformWindow) {
- qWarning("QXcbBackingStore::flush: QWindow has no platform window (QTBUG-32681)");
+ qCWarning(lcQpaXcb, "%s QWindow has no platform window, see QTBUG-32681", Q_FUNC_INFO);
return;
}
diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.h b/src/plugins/platforms/xcb/qxcbbackingstore.h
index 747626c213..734de1f7d7 100644
--- a/src/plugins/platforms/xcb/qxcbbackingstore.h
+++ b/src/plugins/platforms/xcb/qxcbbackingstore.h
@@ -74,6 +74,9 @@ public:
void beginPaint(const QRegion &) override;
void endPaint() override;
+ static bool createSystemVShmSegment(QXcbConnection *c, size_t segmentSize = 1,
+ void *shmInfo = nullptr);
+
private:
QXcbBackingStoreImage *m_image = nullptr;
QStack<QRegion> m_paintRegions;
diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp
index 879d31f29a..5fd1fc6a47 100644
--- a/src/plugins/platforms/xcb/qxcbconnection.cpp
+++ b/src/plugins/platforms/xcb/qxcbconnection.cpp
@@ -55,6 +55,7 @@
#include "qxcbsystemtraytracker.h"
#include "qxcbglintegrationfactory.h"
#include "qxcbglintegration.h"
+#include "qxcbbackingstore.h"
#include <QSocketNotifier>
#include <QAbstractEventDispatcher>
@@ -585,7 +586,8 @@ QXcbConnection::QXcbConnection(QXcbNativeInterface *nativeInterface, bool canGra
initializeAllAtoms();
- initializeShm();
+ if (!qEnvironmentVariableIsSet("QT_XCB_NO_MITSHM"))
+ initializeShm();
if (!qEnvironmentVariableIsSet("QT_XCB_NO_XRANDR"))
initializeXRandr();
if (!has_randr_extension)
@@ -973,7 +975,7 @@ void QXcbConnection::printXcbError(const char *message, xcb_generic_error_t *err
uint clamped_error_code = qMin<uint>(error->error_code, (sizeof(xcb_errors) / sizeof(xcb_errors[0])) - 1);
uint clamped_major_code = qMin<uint>(error->major_code, (sizeof(xcb_protocol_request_codes) / sizeof(xcb_protocol_request_codes[0])) - 1);
- qWarning("%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
+ qCWarning(lcQpaXcb, "%s: %d (%s), sequence: %d, resource id: %d, major code: %d (%s), minor code: %d",
message,
int(error->error_code), xcb_errors[clamped_error_code],
int(error->sequence), int(error->resource_id),
@@ -1683,12 +1685,14 @@ bool QXcbConnection::compressEvent(xcb_generic_event_t *event, int currentIndex,
if (!hasXInput2())
return false;
- // compress XI_Motion, but not from tablet devices
+ // compress XI_Motion
if (isXIType(event, m_xiOpCode, XI_Motion)) {
#if QT_CONFIG(tabletevent)
xXIDeviceEvent *xdev = reinterpret_cast<xXIDeviceEvent *>(event);
+ // Xlib's XI2 events need memmove, see xi2PrepareXIGenericDeviceEvent()
+ auto sourceId = *reinterpret_cast<uint16_t *>(reinterpret_cast<char *>(&xdev->sourceid) + 4);
if (!QCoreApplication::testAttribute(Qt::AA_CompressTabletEvents) &&
- const_cast<QXcbConnection *>(this)->tabletDataForDevice(xdev->sourceid))
+ const_cast<QXcbConnection *>(this)->tabletDataForDevice(sourceId))
return false;
#endif // QT_CONFIG(tabletevent)
for (int j = nextIndex; j < eventqueue->size(); ++j) {
@@ -2101,20 +2105,34 @@ void QXcbConnection::initializeShm()
{
const xcb_query_extension_reply_t *reply = xcb_get_extension_data(m_connection, &xcb_shm_id);
if (!reply || !reply->present) {
- qWarning("QXcbConnection: MIT-SHM extension is not present on the X server.");
+ qCDebug(lcQpaXcb, "MIT-SHM extension is not present on the X server");
return;
}
-
has_shm = true;
auto shm_query = Q_XCB_REPLY(xcb_shm_query_version, m_connection);
- if (!shm_query) {
- qWarning("QXcbConnection: Failed to request MIT-SHM version");
- return;
+ if (shm_query) {
+ has_shm_fd = (shm_query->major_version == 1 && shm_query->minor_version >= 2) ||
+ shm_query->major_version > 1;
+ } else {
+ qCWarning(lcQpaXcb, "QXcbConnection: Failed to request MIT-SHM version");
}
- has_shm_fd = (shm_query->major_version == 1 && shm_query->minor_version >= 2) ||
- shm_query->major_version > 1;
+ qCDebug(lcQpaXcb) << "Has MIT-SHM :" << has_shm;
+ qCDebug(lcQpaXcb) << "Has MIT-SHM FD :" << has_shm_fd;
+
+ // Temporary disable warnings (unless running in debug mode).
+ auto logging = const_cast<QLoggingCategory*>(&lcQpaXcb());
+ bool wasEnabled = logging->isEnabled(QtMsgType::QtWarningMsg);
+ if (!logging->isEnabled(QtMsgType::QtDebugMsg))
+ logging->setEnabled(QtMsgType::QtWarningMsg, false);
+ if (!QXcbBackingStore::createSystemVShmSegment(this)) {
+ qCDebug(lcQpaXcb, "failed to create System V shared memory segment (remote "
+ "X11 connection?), disabling SHM");
+ has_shm = has_shm_fd = false;
+ }
+ if (wasEnabled)
+ logging->setEnabled(QtMsgType::QtWarningMsg, true);
}
void QXcbConnection::initializeXFixes()
diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp
index e1bd8eb752..df458e85d7 100644
--- a/src/plugins/platforms/xcb/qxcbscreen.cpp
+++ b/src/plugins/platforms/xcb/qxcbscreen.cpp
@@ -750,12 +750,7 @@ void QXcbScreen::updateGeometry(const QRect &geometry, uint8_t rotation)
m_sizeMillimeters = sizeInMillimeters(geometry.size(), virtualDpi());
qreal dpi = geometry.width() / physicalSize().width() * qreal(25.4);
- qreal rawFactor = dpi/96;
- int roundedFactor = qFloor(rawFactor);
- // Round up for .8 and higher. This favors "small UI" over "large UI".
- if (rawFactor - roundedFactor >= 0.8)
- roundedFactor = qCeil(rawFactor);
- m_pixelDensity = qMax(1, roundedFactor);
+ m_pixelDensity = qMax(1, qRound(dpi/96));
m_geometry = geometry;
m_availableGeometry = geometry & m_virtualDesktop->workArea();
QWindowSystemInterface::handleScreenGeometryChange(QPlatformScreen::screen(), m_geometry, m_availableGeometry);
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index 5999163c91..2d212bfe3b 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -248,24 +248,6 @@ QT_NAMESPACE_ALIAS_OBJC_CLASS(QVerticalSplitView);
}
@end
-#if !QT_CONFIG(appstore_compliant)
-
-// This API was requested to Apple in rdar #36197888.
-// We know it's safe to use up to macOS 10.13.3.
-// See drawComplexControl(CC_ComboBox) for its usage.
-
-@interface NSComboBoxCell (QtButtonCell)
-@property (readonly) NSButtonCell *qt_buttonCell;
-@end
-
-@implementation NSComboBoxCell (QtButtonCell)
-- (NSButtonCell *)qt_buttonCell {
- return self->_buttonCell;
-}
-@end
-
-#endif
-
QT_BEGIN_NAMESPACE
// The following constants are used for adjusting the size
@@ -5215,11 +5197,14 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
auto *cb = static_cast<NSComboBox *>(cc);
const auto frameRect = cw.adjustedControlFrame(combo->rect);
cb.frame = frameRect.toCGRect();
-#if !QT_CONFIG(appstore_compliant)
- static_cast<NSComboBoxCell *>(cc.cell).qt_buttonCell.highlighted = isPressed;
-#else
- // TODO Render to pixmap and darken the button manually
-#endif
+
+ // This API was requested to Apple in rdar #36197888. We know it's safe to use up to macOS 10.13.3
+ if (NSButtonCell *cell = static_cast<NSButtonCell *>([cc.cell qt_valueForPrivateKey:@"_buttonCell"])) {
+ cell.highlighted = isPressed;
+ } else {
+ // TODO Render to pixmap and darken the button manually
+ }
+
d->drawNSViewInRect(cb, frameRect, p, ^(CGContextRef __unused ctx, const CGRect &r) {
// FIXME This is usually drawn in the control's superview, but we wouldn't get inactive look in this case
[cb.cell drawWithFrame:r inView:cb];
diff --git a/src/widgets/graphicsview/qgraphicsitem.cpp b/src/widgets/graphicsview/qgraphicsitem.cpp
index cef1d1b6da..fdf21fb499 100644
--- a/src/widgets/graphicsview/qgraphicsitem.cpp
+++ b/src/widgets/graphicsview/qgraphicsitem.cpp
@@ -1579,6 +1579,7 @@ QGraphicsItem::~QGraphicsItem()
QObjectPrivate *p = QObjectPrivate::get(o);
p->wasDeleted = true;
if (p->declarativeData) {
+ p->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
if (static_cast<QAbstractDeclarativeDataImpl*>(p->declarativeData)->ownedByQml1) {
if (QAbstractDeclarativeData::destroyed_qml1)
QAbstractDeclarativeData::destroyed_qml1(p->declarativeData, o);
@@ -1587,6 +1588,7 @@ QGraphicsItem::~QGraphicsItem()
QAbstractDeclarativeData::destroyed(p->declarativeData, o);
}
p->declarativeData = 0;
+ p->wasDeleted = false;
}
}
diff --git a/src/widgets/itemviews/qheaderview.cpp b/src/widgets/itemviews/qheaderview.cpp
index 00e9ff7400..9a8206de45 100644
--- a/src/widgets/itemviews/qheaderview.cpp
+++ b/src/widgets/itemviews/qheaderview.cpp
@@ -2725,7 +2725,7 @@ void QHeaderView::mouseMoveEvent(QMouseEvent *e)
statusTip = d->model->headerData(logical, d->orientation, Qt::StatusTipRole).toString();
if (d->shouldClearStatusTip || !statusTip.isEmpty()) {
QStatusTipEvent tip(statusTip);
- QCoreApplication::sendEvent(d->parent, &tip);
+ QCoreApplication::sendEvent(d->parent ? d->parent : this, &tip);
d->shouldClearStatusTip = !statusTip.isEmpty();
}
#endif // !QT_NO_STATUSTIP
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 41f9d69c12..5f1f6d880a 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -1677,8 +1677,8 @@ QWidget::~QWidget()
}
}
- d->wasDeleted = true;
if (d->declarativeData) {
+ d->wasDeleted = true; // needed, so that destroying the declarative data does the right thing
if (static_cast<QAbstractDeclarativeDataImpl*>(d->declarativeData)->ownedByQml1) {
if (QAbstractDeclarativeData::destroyed_qml1)
QAbstractDeclarativeData::destroyed_qml1(d->declarativeData, this);
@@ -1687,6 +1687,7 @@ QWidget::~QWidget()
QAbstractDeclarativeData::destroyed(d->declarativeData, this);
}
d->declarativeData = 0; // don't activate again in ~QObject
+ d->wasDeleted = false;
}
d->blockSig = blocked;
diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt
index f1d8657091..ec75ec7caf 100644
--- a/tests/auto/cmake/CMakeLists.txt
+++ b/tests/auto/cmake/CMakeLists.txt
@@ -47,6 +47,7 @@ find_package(Qt5Core REQUIRED)
include("${_Qt5CTestMacros}")
+expect_pass(test_use_modules_function)
expect_pass(test_umbrella_config)
expect_pass(test_wrap_cpp_and_resources)
if (NOT NO_WIDGETS)
diff --git a/tests/auto/cmake/test_use_modules_function/CMakeLists.txt b/tests/auto/cmake/test_use_modules_function/CMakeLists.txt
new file mode 100644
index 0000000000..be05c75054
--- /dev/null
+++ b/tests/auto/cmake/test_use_modules_function/CMakeLists.txt
@@ -0,0 +1,18 @@
+
+cmake_minimum_required(VERSION 2.8)
+
+project(test_use_modules_function)
+
+set(CMAKE_AUTOMOC ON)
+
+set(CMAKE_INCLUDE_CURRENT_DIR ON)
+
+add_executable(two two.cpp)
+add_executable(three three.cpp)
+
+find_package(Qt5Core)
+
+set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${Qt5Core_EXECUTABLE_COMPILE_FLAGS}")
+
+qt5_use_modules(two Test)
+qt5_use_modules(three Gui Test)
diff --git a/tests/auto/cmake/test_use_modules_function/three.cpp b/tests/auto/cmake/test_use_modules_function/three.cpp
new file mode 100644
index 0000000000..507cc8479d
--- /dev/null
+++ b/tests/auto/cmake/test_use_modules_function/three.cpp
@@ -0,0 +1,45 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest>
+#include <QWindow>
+
+class Three : public QObject
+{
+ Q_OBJECT
+public:
+ Three(QObject *parent = 0)
+ {
+ QWindow *w = new QWindow;
+ w->show();
+ }
+};
+
+QTEST_MAIN(Three)
+
+#include "three.moc"
diff --git a/tests/auto/cmake/test_use_modules_function/two.cpp b/tests/auto/cmake/test_use_modules_function/two.cpp
new file mode 100644
index 0000000000..44eb7fe96e
--- /dev/null
+++ b/tests/auto/cmake/test_use_modules_function/two.cpp
@@ -0,0 +1,43 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Stephen Kelly <stephen.kelly@kdab.com>
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QtTest>
+
+class Two : public QObject
+{
+ Q_OBJECT
+public:
+ Two(QObject *parent = 0)
+ {
+
+ }
+};
+
+QTEST_MAIN(Two)
+
+#include "two.moc"
diff --git a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
index fd83228c8b..0dd98cf61c 100644
--- a/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
+++ b/tests/auto/widgets/itemviews/qheaderview/tst_qheaderview.cpp
@@ -43,6 +43,7 @@
#include <qtreewidget.h>
#include <qdebug.h>
#include <qscreen.h>
+#include <qdesktopwidget.h>
typedef QList<int> IntList;
@@ -243,7 +244,7 @@ private slots:
void testMinMaxSectionSize_data();
void testMinMaxSectionSize();
void sizeHintCrash();
-
+ void statusTips();
protected:
void setupTestData(bool use_reset_model = false);
void additionalInit();
@@ -269,7 +270,19 @@ public:
int rowCount(const QModelIndex&) const { return rows; }
int columnCount(const QModelIndex&) const { return cols; }
bool isEditable(const QModelIndex &) const { return true; }
-
+ QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const
+ {
+ if (section < 0 || (role != Qt::DisplayRole && role != Qt::StatusTipRole))
+ return QVariant();
+ const int row = (orientation == Qt::Vertical ? section : 0);
+ const int col = (orientation == Qt::Horizontal ? section : 0);
+ if (orientation == Qt::Vertical && row >= rows)
+ return QVariant();
+ if (orientation == Qt::Horizontal && col >= cols)
+ return QVariant();
+ return QLatin1Char('[') + QString::number(row) + QLatin1Char(',')
+ + QString::number(col) + QLatin1String(",0] -- Header");
+ }
QVariant data(const QModelIndex &idx, int) const
{
if (idx.row() < 0 || idx.column() < 0 || idx.column() >= cols || idx.row() >= rows) {
@@ -3325,6 +3338,54 @@ void tst_QHeaderView::testMinMaxSectionSize()
QTRY_COMPARE(header.sectionSize(0), defaultSectionSize);
}
+class StatusTipHeaderView : public QHeaderView
+{
+public:
+ StatusTipHeaderView(Qt::Orientation orientation = Qt::Horizontal, QWidget *parent = 0) :
+ QHeaderView(orientation, parent), gotStatusTipEvent(false) {}
+ bool gotStatusTipEvent;
+ QString statusTipText;
+protected:
+ bool event(QEvent *e)
+ {
+ if (e->type() == QEvent::StatusTip) {
+ gotStatusTipEvent = true;
+ statusTipText = static_cast<QStatusTipEvent *>(e)->tip();
+ }
+ return QHeaderView::event(e);
+ }
+};
+
+void tst_QHeaderView::statusTips()
+{
+ StatusTipHeaderView headerView;
+ QtTestModel model;
+ model.rows = model.cols = 5;
+ headerView.setModel(&model);
+ headerView.viewport()->setMouseTracking(true);
+ headerView.setGeometry(QRect(QPoint(QApplication::desktop()->geometry().center() - QPoint(250, 250)),
+ QSize(500, 500)));
+ headerView.show();
+ qApp->setActiveWindow(&headerView);
+ QVERIFY(QTest::qWaitForWindowActive(&headerView));
+
+ // Ensure it is moved away first and then moved to the relevant section
+ QTest::mouseMove(QApplication::desktop(),
+ headerView.rect().bottomLeft() + QPoint(20, 20));
+ QPoint centerPoint = QRect(headerView.sectionPosition(0), headerView.y(),
+ headerView.sectionSize(0), headerView.height()).center();
+ QTest::mouseMove(headerView.windowHandle(), centerPoint);
+ QTRY_VERIFY(headerView.gotStatusTipEvent);
+ QCOMPARE(headerView.statusTipText, QLatin1String("[0,0,0] -- Header"));
+
+ headerView.gotStatusTipEvent = false;
+ headerView.statusTipText.clear();
+ centerPoint = QRect(headerView.sectionPosition(1), headerView.y(),
+ headerView.sectionSize(1), headerView.height()).center();
+ QTest::mouseMove(headerView.windowHandle(), centerPoint);
+ QTRY_VERIFY(headerView.gotStatusTipEvent);
+ QCOMPARE(headerView.statusTipText, QLatin1String("[0,1,0] -- Header"));
+}
QTEST_MAIN(tst_QHeaderView)
#include "tst_qheaderview.moc"