diff options
27 files changed, 240 insertions, 81 deletions
@@ -3679,7 +3679,7 @@ Additional options: $XCBY -xcb ............... Compile Xcb support. $EGLFSN -no-eglfs .......... Do not compile EGLFS (EGL Full Screen/Single Surface) support. - $EGLFSY -eglfs ............. Compile EGLFS support (Requires OpenGL ES 2 support). + $EGLFSY -eglfs ............. Compile EGLFS support. $DFBN -no-directfb ....... Do not compile DirectFB support. $DFBY -directfb .......... Compile DirectFB support. @@ -3688,7 +3688,7 @@ Additional options: $LFBY -linuxfb ........... Compile Linux Framebuffer support. $KMSN -no-kms ............ Do not compile KMS support. - $KMSY -kms ............... Compile KMS support (Requires EGL and OpenGL ES 2 support). + $KMSY -kms ............... Compile KMS support (Requires EGL). -qpa <name> ......... Sets the default QPA platform (e.g xcb, cocoa, windows). @@ -4640,11 +4640,6 @@ if [ "$CFG_EGLFS" = "yes" ]; then echo "The EGLFS plugin requires EGL support and cannot be built" exit 101 fi - if [ "$CFG_OPENGL" != "es2" ]; then - echo "The EGLFS plugin requires OpenGL ES 2 support and cannot be built" - exit 101 - fi - CFG_OPENGL="es2" CFG_EGL=yes fi @@ -4653,10 +4648,6 @@ if [ "$CFG_KMS" = "yes" ]; then echo "The KMS plugin requires EGL support and cannot be built" exit 101 fi - if [ "$CFG_OPENGL" != "es2" ]; then - echo "The KMS plugin requires OpenGL ES 2 support and cannot be built" - exit 101 - fi fi # auto-detect SQL-modules support @@ -5492,17 +5483,10 @@ elif [ "$CFG_XKBCOMMON" = "no" ]; then fi # EGL Support -if [ "$CFG_OPENGL" != "es2" ]; then - if [ "$CFG_EGL" = "yes" ] && [ "$CFG_OPENGL" = "desktop" ]; then - echo "EGL support was requested but Qt is being configured for desktop OpenGL." - echo "Either disable EGL support or enable OpenGL ES support." - exit 101 - elif [ "$CFG_EGL" = "yes" ] && [ "$CFG_OPENGL" = "no" ]; then - echo "EGL support was requested but OpenGL ES support is disabled." +if [ "$CFG_EGL" = "yes" ] && [ "$CFG_OPENGL" = "no" ]; then + echo "EGL support was requested but OpenGL support is disabled." echo "Either disable EGL support or enable OpenGL ES support." exit 101 - fi - CFG_EGL=no elif [ "$CFG_EGL" != "no" ]; then if [ -n "$PKG_CONFIG" ] && $PKG_CONFIG --exists egl 2>/dev/null; then QMAKE_INCDIR_EGL=`$PKG_CONFIG --cflags-only-I egl 2>/dev/null | sed -e 's,^-I,,g' -e 's, -I, ,g'` @@ -5525,7 +5509,7 @@ elif [ "$CFG_EGL" != "no" ]; then fi if [ "$CFG_EGLFS" != "no" ]; then - if [ "$CFG_OPENGL" = "es2" ] && [ "$XPLATFORM_QNX" = "no" ]; then + if [ "$XPLATFORM_QNX" = "no" ]; then CFG_EGLFS="$CFG_EGL" else CFG_EGLFS="no" @@ -5533,7 +5517,7 @@ if [ "$CFG_EGLFS" != "no" ]; then fi if [ "$CFG_KMS" = "yes" ]; then - if [ "$CFG_OPENGL" = "es2" ] && [ "$CFG_EGL" = "yes" ]; then + if [ "$CFG_EGL" = "yes" ]; then CFG_KMS="yes" else CFG_KMS="no" @@ -5913,11 +5897,7 @@ else fi if [ "$CFG_OPENGL" = "es2" ]; then - QCONFIG_FLAGS="$QCONFIG_FLAGS QT_OPENGL_ES" -fi - -if [ "$CFG_OPENGL" = "es2" ]; then - QCONFIG_FLAGS="$QCONFIG_FLAGS QT_OPENGL_ES_2" + QCONFIG_FLAGS="$QCONFIG_FLAGS QT_OPENGL_ES QT_OPENGL_ES_2" QT_CONFIG="$QT_CONFIG opengles2" fi diff --git a/qtbase.pro b/qtbase.pro index 8da34c5023..9091fba4e0 100644 --- a/qtbase.pro +++ b/qtbase.pro @@ -179,7 +179,7 @@ write_file($$OUT_PWD/mkspecs/qfeatures.pri, FEATURES_PRI)|error("Aborting.") #mkspecs mkspecs.path = $$[QT_HOST_DATA]/mkspecs mkspecs.files = \ - $$OUT_PWD/mkspecs/qconfig.pri $$OUT_PWD/mkspecs/qmodule.pri $$OUT_PWD/mkspecs/qdevice.pri \ + $$OUT_PWD/mkspecs/qconfig.pri $$OUT_PWD/mkspecs/qmodule.pri $$OUT_PWD/mkspecs/qdevice.pri $$OUT_PWD/mkspecs/qfeatures.pri \ $$files($$PWD/mkspecs/*) mkspecs.files -= $$PWD/mkspecs/modules INSTALLS += mkspecs diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 1629339fd1..c2bb7173ba 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -45,11 +45,11 @@ #include <stddef.h> -#define QT_VERSION_STR "5.2.0" +#define QT_VERSION_STR "5.2.1" /* QT_VERSION is (major << 16) + (minor << 8) + patch. */ -#define QT_VERSION 0x050200 +#define QT_VERSION 0x050201 /* can be used like #if (QT_VERSION >= QT_VERSION_CHECK(4, 4, 0)) */ diff --git a/src/corelib/kernel/qobject.cpp b/src/corelib/kernel/qobject.cpp index c19c3fcbb5..6fb22054cc 100644 --- a/src/corelib/kernel/qobject.cpp +++ b/src/corelib/kernel/qobject.cpp @@ -4140,7 +4140,7 @@ QDebug operator<<(QDebug dbg, const QObject *o) { \macro Q_INVOKABLE \relates QObject - Apply this macro to definitions of member functions to allow them to + Apply this macro to declarations of member functions to allow them to be invoked via the meta-object system. The macro is written before the return type, as shown in the following example: @@ -4157,7 +4157,7 @@ QDebug operator<<(QDebug dbg, const QObject *o) { \macro Q_REVISION \relates QObject - Apply this macro to definitions of member functions to tag them with a + Apply this macro to declarations of member functions to tag them with a revision number in the meta-object system. The macro is written before the return type, as shown in the following example: diff --git a/src/corelib/tools/qlocale_blackberry.cpp b/src/corelib/tools/qlocale_blackberry.cpp index e2dfa6c801..48faa73070 100644 --- a/src/corelib/tools/qlocale_blackberry.cpp +++ b/src/corelib/tools/qlocale_blackberry.cpp @@ -68,17 +68,20 @@ QBBSystemLocaleData::QBBSystemLocaleData() , measurementNotifier(0) , hourNotifier(0) { + // Do not use qWarning to log warnings if qt_safe_open fails to open the pps file + // since the user code may install a message handler that invokes QLocale API again + // (i.e QDate, QDateTime, ...) which will cause a deadlock. if ((measurementFd = qt_safe_open(ppsUomPath, O_RDONLY)) == -1) - qWarning("Failed to open uom pps, errno=%d", errno); + fprintf(stderr, "Failed to open uom pps, errno=%d\n", errno); if ((regionFd = qt_safe_open(ppsRegionLocalePath, O_RDONLY)) == -1) - qWarning("Failed to open region pps, errno=%d", errno); + fprintf(stderr, "Failed to open region pps, errno=%d\n", errno); if ((languageFd = qt_safe_open(ppsLanguageLocalePath, O_RDONLY)) == -1) - qWarning("Failed to open language pps, errno=%d", errno); + fprintf(stderr, "Failed to open language pps, errno=%d\n", errno); if ((hourFd = qt_safe_open(ppsHourFormatPath, O_RDONLY)) == -1) - qWarning("Failed to open hour format pps, errno=%d", errno); + fprintf(stderr, "Failed to open hour format pps, errno=%d\n", errno); // we cannot call this directly, because by the time this constructor is // called, the event dispatcher has not yet been created, causing the @@ -186,8 +189,12 @@ QByteArray QBBSystemLocaleData::readPpsValue(const char *ppsObject, int ppsFd) char buffer[ppsBufferSize]; int bytes = qt_safe_read(ppsFd, buffer, ppsBufferSize - 1); + // This method is called in the ctor(), so do not use qWarning to log warnings + // if qt_safe_read fails to read the pps file + // since the user code may install a message handler that invokes QLocale API again + // (i.e QDate, QDateTime, ...) which will cause a deadlock. if (bytes == -1) { - qWarning("Failed to read Locale pps, errno=%d", errno); + fprintf(stderr, "Failed to read pps object:%s, errno=%d\n", ppsObject, errno); return result; } // ensure data is null terminated diff --git a/src/plugins/platforms/cocoa/qcocoahelpers.mm b/src/plugins/platforms/cocoa/qcocoahelpers.mm index 197a2058af..4a5696b35e 100644 --- a/src/plugins/platforms/cocoa/qcocoahelpers.mm +++ b/src/plugins/platforms/cocoa/qcocoahelpers.mm @@ -599,7 +599,17 @@ NSRect qt_mac_flipRect(const QRect &rect, QWindow *window) { QPlatformScreen *onScreen = QPlatformScreen::platformScreenForWindow(window); int flippedY = onScreen->geometry().height() - (rect.y() + rect.height()); - + QList<QScreen *> screens = QGuiApplication::screens(); + if (screens.size() > 1) { + int height = 0; + foreach (QScreen *scr, screens) + height = qMax(height, scr->size().height()); + int difference = height - onScreen->geometry().height(); + if (difference > 0) + flippedY += difference; + else + flippedY -= difference; + } // In case of automatic positioning, try to put as much of the window onscreen as possible. if (window->isTopLevel() && qt_window_private(const_cast<QWindow*>(window))->positionAutomatic && flippedY < 0) flippedY = onScreen->geometry().height() - onScreen->availableGeometry().height() - onScreen->availableGeometry().y(); diff --git a/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp b/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp index 9de5960fdb..03531916cf 100644 --- a/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp +++ b/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp @@ -139,6 +139,7 @@ void QEglFSBackingStore::resize(const QSize &size, const QRegion &staticContents m_window->create(); rootWin->screen()->rootContext()->makeCurrent(rootWin->window()); + initializeOpenGLFunctions(); if (m_texture) glDeleteTextures(1, &m_texture); diff --git a/src/plugins/platforms/eglfs/qeglfsbackingstore.h b/src/plugins/platforms/eglfs/qeglfsbackingstore.h index 535428aac1..9af856e8e7 100644 --- a/src/plugins/platforms/eglfs/qeglfsbackingstore.h +++ b/src/plugins/platforms/eglfs/qeglfsbackingstore.h @@ -43,6 +43,7 @@ #define QEGLFSBACKINGSTORE_H #include <qpa/qplatformbackingstore.h> +#include <QtGui/QOpenGLFunctions> #include <QImage> #include <QRegion> @@ -52,7 +53,7 @@ QT_BEGIN_NAMESPACE class QOpenGLPaintDevice; class QEglFSWindow; -class QEglFSBackingStore : public QPlatformBackingStore +class QEglFSBackingStore : public QPlatformBackingStore, public QOpenGLFunctions { public: QEglFSBackingStore(QWindow *window); diff --git a/src/plugins/platforms/eglfs/qeglfscompositor.cpp b/src/plugins/platforms/eglfs/qeglfscompositor.cpp index 9db43a57a1..845bb5b3b5 100644 --- a/src/plugins/platforms/eglfs/qeglfscompositor.cpp +++ b/src/plugins/platforms/eglfs/qeglfscompositor.cpp @@ -53,7 +53,8 @@ static QEglFSCompositor *compositor = 0; QEglFSCompositor::QEglFSCompositor() : m_screen(0), - m_program(0) + m_program(0), + m_initialized(false) { Q_ASSERT(!compositor); m_updateTimer.setSingleShot(true); @@ -86,6 +87,10 @@ void QEglFSCompositor::renderAll() Q_ASSERT(context); context->makeCurrent(rootWin->window()); + if (!m_initialized) { + initializeOpenGLFunctions(); + m_initialized = true; + } ensureProgram(); m_program->bind(); diff --git a/src/plugins/platforms/eglfs/qeglfscompositor.h b/src/plugins/platforms/eglfs/qeglfscompositor.h index ade2e06031..0d5daafa2c 100644 --- a/src/plugins/platforms/eglfs/qeglfscompositor.h +++ b/src/plugins/platforms/eglfs/qeglfscompositor.h @@ -42,7 +42,8 @@ #ifndef QEGLFSCOMPOSITOR_H #define QEGLFSCOMPOSITOR_H -#include <QTimer> +#include <QtCore/QTimer> +#include <QtGui/QOpenGLFunctions> QT_BEGIN_NAMESPACE @@ -50,7 +51,7 @@ class QEglFSScreen; class QEglFSWindow; class QOpenGLShaderProgram; -class QEglFSCompositor : public QObject +class QEglFSCompositor : public QObject, public QOpenGLFunctions { Q_OBJECT @@ -76,6 +77,7 @@ private: int m_vertexCoordEntry; int m_textureCoordEntry; int m_isRasterEntry; + bool m_initialized; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfscursor.cpp b/src/plugins/platforms/eglfs/qeglfscursor.cpp index c00e86de35..0066426769 100644 --- a/src/plugins/platforms/eglfs/qeglfscursor.cpp +++ b/src/plugins/platforms/eglfs/qeglfscursor.cpp @@ -79,7 +79,7 @@ void QEglFSCursor::resetResources() m_cursorAtlas.texture = 0; } -static GLuint createShader(GLenum shaderType, const char *program) +GLuint QEglFSCursor::createShader(GLenum shaderType, const char *program) { GLuint shader = glCreateShader(shaderType); glShaderSource(shader, 1 /* count */, &program, NULL /* lengths */); @@ -98,7 +98,7 @@ static GLuint createShader(GLenum shaderType, const char *program) return 0; } -static GLuint createProgram(GLuint vshader, GLuint fshader) +GLuint QEglFSCursor::createProgram(GLuint vshader, GLuint fshader) { GLuint program = glCreateProgram(); glAttachShader(program, vshader); @@ -286,6 +286,7 @@ void QEglFSCursor::draw(const QRectF &r) { if (!m_program) { // one time initialization + initializeOpenGLFunctions(); createShaderPrograms(); if (!m_cursorAtlas.texture) { diff --git a/src/plugins/platforms/eglfs/qeglfscursor.h b/src/plugins/platforms/eglfs/qeglfscursor.h index 51a34e041d..71ff73b8f3 100644 --- a/src/plugins/platforms/eglfs/qeglfscursor.h +++ b/src/plugins/platforms/eglfs/qeglfscursor.h @@ -43,15 +43,15 @@ #define QEGLFSCURSOR_H #include <qpa/qplatformcursor.h> +#include <QtGui/QOpenGLFunctions> #include "qeglfsscreen.h" -#include <GLES2/gl2.h> QT_BEGIN_NAMESPACE class QOpenGLShaderProgram; class QEglFSScreen; -class QEglFSCursor : public QPlatformCursor +class QEglFSCursor : public QPlatformCursor, public QOpenGLFunctions { public: QEglFSCursor(QEglFSScreen *screen); @@ -78,6 +78,9 @@ protected: void draw(const QRectF &rect); void update(const QRegion ®ion); + GLuint createShader(GLenum shaderType, const char *program); + GLuint createProgram(GLuint vshader, GLuint fshader); + QEglFSScreen *m_screen; // current cursor information diff --git a/src/plugins/platforms/kms/qkmsbackingstore.cpp b/src/plugins/platforms/kms/qkmsbackingstore.cpp index 29395f3b4f..fa4ef847cd 100644 --- a/src/plugins/platforms/kms/qkmsbackingstore.cpp +++ b/src/plugins/platforms/kms/qkmsbackingstore.cpp @@ -52,6 +52,7 @@ QKmsBackingStore::QKmsBackingStore(QWindow *window) , m_context(new QOpenGLContext) , m_texture(0) , m_program(0) + , m_initialized(false) { m_context->setFormat(window->requestedFormat()); m_context->setScreen(window->screen()); @@ -85,6 +86,11 @@ void QKmsBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoin m_context->makeCurrent(window); + if (!m_initialized) { + initializeOpenGLFunctions(); + m_initialized = true; + } + if (!m_program) { static const char *textureVertexProgram = "attribute highp vec2 vertexCoordEntry;\n" diff --git a/src/plugins/platforms/kms/qkmsbackingstore.h b/src/plugins/platforms/kms/qkmsbackingstore.h index 34ea49a346..c5f6c81d18 100644 --- a/src/plugins/platforms/kms/qkmsbackingstore.h +++ b/src/plugins/platforms/kms/qkmsbackingstore.h @@ -43,6 +43,7 @@ #define QBACKINGSTORE_KMS_H #include <qpa/qplatformbackingstore.h> +#include <QtGui/QOpenGLFunctions> #include <QImage> QT_BEGIN_NAMESPACE @@ -50,7 +51,7 @@ QT_BEGIN_NAMESPACE class QOpenGLContext; class QOpenGLShaderProgram; -class QKmsBackingStore : public QPlatformBackingStore +class QKmsBackingStore : public QPlatformBackingStore, public QOpenGLFunctions { public: QKmsBackingStore(QWindow *window); @@ -69,6 +70,7 @@ private: uint m_texture; QOpenGLShaderProgram *m_program; QRegion m_dirty; + bool m_initialized; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmsscreen.h b/src/plugins/platforms/kms/qkmsscreen.h index a90d6fa051..f0c49ad11c 100644 --- a/src/plugins/platforms/kms/qkmsscreen.h +++ b/src/plugins/platforms/kms/qkmsscreen.h @@ -55,8 +55,7 @@ extern "C" { #include <EGL/egl.h> #include <EGL/eglext.h> -#include <GLES2/gl2.h> -#include <GLES2/gl2ext.h> +#include <QtGui/qopengl.h> #include <qpa/qplatformscreen.h> diff --git a/src/plugins/platforms/qnx/qqnxglcontext.h b/src/plugins/platforms/qnx/qqnxglcontext.h index ff57861498..2b12657da9 100644 --- a/src/plugins/platforms/qnx/qqnxglcontext.h +++ b/src/plugins/platforms/qnx/qqnxglcontext.h @@ -75,6 +75,8 @@ public: static EGLDisplay getEglDisplay(); EGLConfig getEglConfig() const { return m_eglConfig;} + EGLContext getEglContext() const { return m_eglContext; } + private: //Can be static because different displays returne the same handle static EGLDisplay ms_eglDisplay; diff --git a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp index 8958a5c1e2..6e7fc35a82 100644 --- a/src/plugins/platforms/qnx/qqnxnativeinterface.cpp +++ b/src/plugins/platforms/qnx/qqnxnativeinterface.cpp @@ -41,9 +41,11 @@ #include "qqnxnativeinterface.h" +#include "qqnxglcontext.h" #include "qqnxscreen.h" #include "qqnxwindow.h" +#include <QtGui/QOpenGLContext> #include <QtGui/QScreen> #include <QtGui/QWindow> @@ -71,6 +73,14 @@ void *QQnxNativeInterface::nativeResourceForScreen(const QByteArray &resource, Q return 0; } +void *QQnxNativeInterface::nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context) +{ + if (resource == "eglcontext" && context) + return static_cast<QQnxGLContext*>(context->handle())->getEglContext(); + + return 0; +} + void QQnxNativeInterface::setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value) { if (name == QStringLiteral("mmRendererWindowName")) { diff --git a/src/plugins/platforms/qnx/qqnxnativeinterface.h b/src/plugins/platforms/qnx/qqnxnativeinterface.h index b61f6a56cc..dfd386214e 100644 --- a/src/plugins/platforms/qnx/qqnxnativeinterface.h +++ b/src/plugins/platforms/qnx/qqnxnativeinterface.h @@ -51,6 +51,7 @@ class QQnxNativeInterface : public QPlatformNativeInterface public: void *nativeResourceForWindow(const QByteArray &resource, QWindow *window); void *nativeResourceForScreen(const QByteArray &resource, QScreen *screen); + void *nativeResourceForContext(const QByteArray &resource, QOpenGLContext *context); void setWindowProperty(QPlatformWindow *window, const QString &name, const QVariant &value); }; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index d2fb481824..58047124a1 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -1500,6 +1500,8 @@ void QWindowsWindow::handleWindowStateChange(Qt::WindowState state) handleHidden(); QWindowSystemInterface::flushWindowSystemEvents(); // Tell QQuickWindow to stop rendering now. break; + case Qt::WindowMaximized: + case Qt::WindowFullScreen: case Qt::WindowNoState: { // QTBUG-17548: We send expose events when receiving WM_Paint, but for // layered windows and transient children, we won't receive any WM_Paint. diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index dd404d044d..e2c6932992 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -154,7 +154,7 @@ enum QX11EmbedMessageType { XEMBED_ACTIVATE_ACCELERATOR = 14 }; -const long XEMBED_VERSION = 0; +const quint32 XEMBED_VERSION = 0; // Returns \c true if we should set WM_TRANSIENT_FOR on \a w static inline bool isTransient(const QWindow *w) @@ -403,7 +403,7 @@ void QXcbWindow::create() } // set the PID to let the WM kill the application if unresponsive - long pid = getpid(); + quint32 pid = getpid(); Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::_NET_WM_PID), XCB_ATOM_CARDINAL, 32, 1, &pid)); @@ -422,7 +422,7 @@ void QXcbWindow::create() 1, &leader)); /* Add XEMBED info; this operation doesn't initiate the embedding. */ - long data[] = { XEMBED_VERSION, XEMBED_MAPPED }; + quint32 data[] = { XEMBED_VERSION, XEMBED_MAPPED }; Q_XCB_CALL(xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, atom(QXcbAtom::_XEMBED_INFO), atom(QXcbAtom::_XEMBED_INFO), @@ -1824,7 +1824,7 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev xcb_get_property_reply(xcb_connection(), get_cookie, NULL); if (reply && reply->format == 32 && reply->type == wmStateAtom) { - const long *data = (const long *)xcb_get_property_value(reply); + const quint32 *data = (const quint32 *)xcb_get_property_value(reply); if (reply->length != 0 && XCB_WM_STATE_ICONIC == data[0]) newState = Qt::WindowMinimized; } @@ -1995,8 +1995,8 @@ bool QXcbWindow::startSystemResize(const QPoint &pos, Qt::Corner corner) } // Sends an XEmbed message. -void QXcbWindow::sendXEmbedMessage(xcb_window_t window, long message, - long detail, long data1, long data2) +void QXcbWindow::sendXEmbedMessage(xcb_window_t window, quint32 message, + quint32 detail, quint32 data1, quint32 data2) { xcb_client_message_event_t event; diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 5601a115e9..45d44b213f 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -169,8 +169,8 @@ private: void updateDoesNotAcceptFocus(bool doesNotAcceptFocus); QRect windowToWmGeometry(QRect r) const; - void sendXEmbedMessage(xcb_window_t window, long message, - long detail = 0, long data1 = 0, long data2 = 0); + void sendXEmbedMessage(xcb_window_t window, quint32 message, + quint32 detail = 0, quint32 data1 = 0, quint32 data2 = 0); void handleXEmbedMessage(const xcb_client_message_event_t *event); void create(); diff --git a/src/widgets/kernel/qapplication.cpp b/src/widgets/kernel/qapplication.cpp index 4e3ecf144a..9056ffe461 100644 --- a/src/widgets/kernel/qapplication.cpp +++ b/src/widgets/kernel/qapplication.cpp @@ -3761,6 +3761,16 @@ void QApplicationPrivate::giveFocusAccordingToFocusPolicy(QWidget *widget, QEven } if (focusWidget->isWindow()) break; + + // find out whether this widget (or its proxy) already has focus + QWidget *f = focusWidget; + if (focusWidget->d_func()->extra && focusWidget->d_func()->extra->focus_proxy) + f = focusWidget->d_func()->extra->focus_proxy; + // if it has, stop here. + // otherwise a click on the focused widget would remove its focus if ClickFocus isn't set + if (f->hasFocus()) + break; + localPos += focusWidget->pos(); focusWidget = focusWidget->parentWidget(); } diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index e977ab3d6f..2e96247873 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -251,7 +251,9 @@ bool QWidgetWindow::event(QEvent *event) case QEvent::Show: case QEvent::Hide: return QWindow::event(event); - + case QEvent::WindowBlocked: + qt_button_down = 0; + break; default: break; } diff --git a/src/widgets/kernel/qwindowcontainer.cpp b/src/widgets/kernel/qwindowcontainer.cpp index 6914f64f8e..7482f1587a 100644 --- a/src/widgets/kernel/qwindowcontainer.cpp +++ b/src/widgets/kernel/qwindowcontainer.cpp @@ -222,6 +222,11 @@ void QWindowContainer::focusWindowChanged(QWindow *focusWindow) { Q_D(QWindowContainer); d->oldFocusWindow = focusWindow; + if (focusWindow == d->window) { + QWidget *widget = QApplication::focusWidget(); + if (widget) + widget->clearFocus(); + } } /*! diff --git a/tests/auto/testlib/selftests/tst_selftests.cpp b/tests/auto/testlib/selftests/tst_selftests.cpp index b737f823c8..e332f01861 100644 --- a/tests/auto/testlib/selftests/tst_selftests.cpp +++ b/tests/auto/testlib/selftests/tst_selftests.cpp @@ -63,7 +63,7 @@ private slots: void cleanup(); private: - void doRunSubTest(QString const& subdir, QStringList const& loggers, QStringList const& arguments); + void doRunSubTest(QString const& subdir, QStringList const& loggers, QStringList const& arguments, bool crashes); QString logName(const QString &logger) const; QList<LoggerSet> allLoggerSets() const; @@ -324,6 +324,7 @@ void tst_Selftests::runSubTest_data() QTest::addColumn<QString>("subdir"); QTest::addColumn<QStringList>("loggers"); QTest::addColumn<QStringList>("arguments"); + QTest::addColumn<bool>("crashes"); QStringList tests = QStringList() // << "alive" // timer dependent @@ -479,11 +480,14 @@ void tst_Selftests::runSubTest_data() continue; } } - + const bool crashes = subtest == QLatin1String("assert") || subtest == QLatin1String("exceptionthrow") + || subtest == QLatin1String("fetchbogus") || subtest == QLatin1String("crashedterminate") + || subtest == QLatin1String("crashes") || subtest == QLatin1String("silent"); QTest::newRow(qPrintable(QString("%1 %2").arg(subtest).arg(loggerSet.name))) << subtest << loggers << arguments + << crashes ; } } @@ -491,30 +495,41 @@ void tst_Selftests::runSubTest_data() #ifndef QT_NO_PROCESS -static void insertEnvironmentVariable(QString const& name, QProcessEnvironment &result) -{ - const QProcessEnvironment systemEnvironment = QProcessEnvironment::systemEnvironment(); - const QString value = systemEnvironment.value(name); - if (!value.isEmpty()) - result.insert(name, value); -} - -static inline QProcessEnvironment processEnvironment() +static QProcessEnvironment processEnvironment() { - QProcessEnvironment result; - insertEnvironmentVariable(QStringLiteral("PATH"), result); - // Preserve DISPLAY for X11 as some tests use Qt GUI. -#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC) - insertEnvironmentVariable(QStringLiteral("DISPLAY"), result); -#endif - insertEnvironmentVariable(QStringLiteral("QT_QPA_PLATFORM"), result); + static QProcessEnvironment result; + if (result.isEmpty()) { + const QProcessEnvironment systemEnvironment = QProcessEnvironment::systemEnvironment(); + foreach (const QString &key, systemEnvironment.keys()) { + const bool useVariable = key == QLatin1String("PATH") || key == QLatin1String("QT_QPA_PLATFORM") +#ifdef Q_OS_UNIX + || key == QLatin1String("HOME") || key == QLatin1String("USER") // Required for X11 on openSUSE +# ifndef Q_OS_MAC + || key == QLatin1String("DISPLAY") || key == QLatin1String("XAUTHLOCALHOSTNAME") + || key.startsWith(QLatin1String("XDG_")) +# endif // !Q_OS_MAC +#endif // Q_OS_UNIX #ifdef __COVERAGESCANNER__ - insertEnvironmentVariable(QStringLiteral("QT_TESTCOCOON_ACTIVE"), result); + || key == QLatin1String("QT_TESTCOCOON_ACTIVE") #endif + ; + if (useVariable) + result.insert(key, systemEnvironment.value(key)); + } + } return result; } -void tst_Selftests::doRunSubTest(QString const& subdir, QStringList const& loggers, QStringList const& arguments) +static inline QByteArray msgProcessError(const QString &binary, const QStringList &args, + const QProcessEnvironment &e, const QString &what) +{ + QString result; + QTextStream(&result) <<"Error running " << binary << ' ' << args.join(' ') + << " with environment " << e.toStringList().join(' ') << ": " << what; + return result.toLocal8Bit(); +} + +void tst_Selftests::doRunSubTest(QString const& subdir, QStringList const& loggers, QStringList const& arguments, bool crashes) { #if defined(__GNUC__) && defined(__i386) && defined(Q_OS_LINUX) if (arguments.contains("-callgrind")) { @@ -532,8 +547,14 @@ void tst_Selftests::doRunSubTest(QString const& subdir, QStringList const& logge proc.setProcessEnvironment(environment); const QString path = subdir + QLatin1Char('/') + subdir; proc.start(path, arguments); - QVERIFY2(proc.waitForStarted(), qPrintable(QString::fromLatin1("Cannot start '%1': %2").arg(path, proc.errorString()))); - QVERIFY2(proc.waitForFinished(), qPrintable(proc.errorString())); + QVERIFY2(proc.waitForStarted(), msgProcessError(path, arguments, environment, QStringLiteral("Cannot start: ") + proc.errorString())); + QVERIFY2(proc.waitForFinished(), msgProcessError(path, arguments, environment, QStringLiteral("Timed out: ") + proc.errorString())); + if (!crashes) { + QVERIFY2(proc.exitStatus() == QProcess::NormalExit, + msgProcessError(path, arguments, environment, + QStringLiteral("Crashed: ") + proc.errorString() + + QStringLiteral(": ") + QString::fromLocal8Bit(proc.readAllStandardError()))); + } QList<QByteArray> actualOutputs; for (int i = 0; i < loggers.count(); ++i) { @@ -700,8 +721,9 @@ void tst_Selftests::runSubTest() QFETCH(QString, subdir); QFETCH(QStringList, loggers); QFETCH(QStringList, arguments); + QFETCH(bool, crashes); - doRunSubTest(subdir, loggers, arguments); + doRunSubTest(subdir, loggers, arguments, crashes); #endif // !QT_NO_PROCESS } diff --git a/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp b/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp index 68502f0d8d..060fa51293 100644 --- a/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp +++ b/tests/auto/widgets/dialogs/qprogressdialog/tst_qprogressdialog.cpp @@ -57,6 +57,8 @@ public: virtual ~tst_QProgressDialog(); private slots: + void autoShow_data(); + void autoShow(); void getSetCheck(); void task198202(); void QTBUG_31046(); @@ -70,6 +72,34 @@ tst_QProgressDialog::~tst_QProgressDialog() { } +void tst_QProgressDialog::autoShow_data() +{ + QTest::addColumn<int>("min"); + QTest::addColumn<int>("max"); + QTest::addColumn<int>("delay"); + QTest::addColumn<bool>("expectedAutoShow"); + + QTest::newRow("50_to_100_long") << 50 << 100 << 100 << true; // 50*100ms = 5s + QTest::newRow("50_to_100_short") << 50 << 1 << 100 << false; // 50*1ms = 50ms + + QTest::newRow("0_to_100_long") << 0 << 100 << 100 << true; // 100*100ms = 10s + QTest::newRow("0_to_10_short") << 0 << 10 << 100 << false; // 10*100ms = 1s +} + +void tst_QProgressDialog::autoShow() +{ + QFETCH(int, min); + QFETCH(int, max); + QFETCH(int, delay); + QFETCH(bool, expectedAutoShow); + + QProgressDialog dlg("", "", min, max); + dlg.setValue(0); + QThread::msleep(delay); + dlg.setValue(min+1); + QCOMPARE(dlg.isVisible(), expectedAutoShow); +} + // Testing get/set functions void tst_QProgressDialog::getSetCheck() { diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index 8d75298673..091927abe4 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -153,6 +153,7 @@ private slots: void focusChanged(); void focusOut(); + void focusMouseClick(); void execAfterExit(); @@ -1771,6 +1772,63 @@ void tst_QApplication::focusOut() QTest::qWait(2000); } +class SpontaneousEvent +{ + Q_GADGET + QDOC_PROPERTY(bool accepted READ isAccepted WRITE setAccepted) + Q_ENUMS(Type) +public: + enum Type { + Void + }; + + virtual ~SpontaneousEvent() {} + + QEventPrivate *d; + ushort t; + + ushort posted : 1; + ushort spont : 1; +}; + +void tst_QApplication::focusMouseClick() +{ + int argc = 1; + QApplication app(argc, &argv0); + + QWidget w; + w.setFocusPolicy(Qt::StrongFocus); + QWidget w2(&w); + w2.setFocusPolicy(Qt::TabFocus); + w.show(); + w.setFocus(); + QTRY_COMPARE(QApplication::focusWidget(), &w); + + // front most widget has Qt::TabFocus, parent widget accepts clicks as well + // now send a mouse button press event and check what happens with the focus + // it should be given to the parent widget + QMouseEvent ev(QEvent::MouseButtonPress, QPointF(), Qt::LeftButton, Qt::LeftButton, Qt::NoModifier); + reinterpret_cast<SpontaneousEvent *>(&ev)->spont = 1; + QVERIFY(ev.spontaneous()); + qApp->notify(&w2, &ev); + QCOMPARE(QApplication::focusWidget(), &w); + + // then we give the inner widget strong focus -> it should get focus + w2.setFocusPolicy(Qt::StrongFocus); + reinterpret_cast<SpontaneousEvent *>(&ev)->spont = 1; + QVERIFY(ev.spontaneous()); + qApp->notify(&w2, &ev); + QTRY_COMPARE(QApplication::focusWidget(), &w2); + + // now back to tab focus and click again (it already had focus) -> focus should stay + // (focus was revoked as of QTBUG-34042) + w2.setFocusPolicy(Qt::TabFocus); + reinterpret_cast<SpontaneousEvent *>(&ev)->spont = 1; + QVERIFY(ev.spontaneous()); + qApp->notify(&w2, &ev); + QCOMPARE(QApplication::focusWidget(), &w2); +} + void tst_QApplication::execAfterExit() { int argc = 1; |