diff options
Diffstat (limited to 'src/plugins/platforms')
61 files changed, 1935 insertions, 449 deletions
diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro index 2ae39dd16c..f149a6775b 100644 --- a/src/plugins/platforms/cocoa/cocoa.pro +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -36,6 +36,7 @@ OBJECTIVE_SOURCES += main.mm \ qpaintengine_mac.mm \ qprintengine_mac.mm \ qcocoaprintersupport.mm \ + qcocoaservices.mm \ HEADERS += qcocoaintegration.h \ qcocoatheme.h \ @@ -69,6 +70,7 @@ HEADERS += qcocoaintegration.h \ qpaintengine_mac_p.h \ qprintengine_mac_p.h \ qcocoaprintersupport.h \ + qcocoaservices.h \ FORMS += $$PWD/../../../widgets/dialogs/qfiledialog.ui RESOURCES += qcocoaresources.qrc diff --git a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm index fd4d6605a9..405cacee01 100644 --- a/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoacolordialoghelper.mm @@ -395,6 +395,8 @@ void QCocoaColorDialogHelper::hide_sys() QCocoaColorDialogHelper::DialogCode QCocoaColorDialogHelper::dialogResultCode_sys() { + if (!mDelegate) + return QPlatformDialogHelper::Rejected; QT_MANGLE_NAMESPACE(QNSColorPanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSColorPanelDelegate) *>(mDelegate); return [delegate dialogResultCode]; } @@ -429,6 +431,8 @@ void QCocoaColorDialogHelper::setCurrentColor_sys(const QColor &color) QColor QCocoaColorDialogHelper::currentColor_sys() const { + if (!mDelegate) + return QColor(); return reinterpret_cast<QT_MANGLE_NAMESPACE(QNSColorPanelDelegate) *>(mDelegate)->mQtColor; } diff --git a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm index d05a0156b1..1e89270775 100644 --- a/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm +++ b/src/plugins/platforms/cocoa/qcocoafontdialoghelper.mm @@ -414,6 +414,8 @@ void QCocoaFontDialogHelper::hide_sys() QCocoaFontDialogHelper::DialogCode QCocoaFontDialogHelper::dialogResultCode_sys() { + if (!mDelegate) + return QPlatformDialogHelper::Rejected; QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *delegate = static_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate); return [delegate dialogResultCode]; } @@ -448,6 +450,8 @@ void QCocoaFontDialogHelper::setCurrentFont_sys(const QFont &font) QFont QCocoaFontDialogHelper::currentFont_sys() const { + if (!mDelegate) + return QFont(); return reinterpret_cast<QT_MANGLE_NAMESPACE(QNSFontPanelDelegate) *>(mDelegate)->mQtFont; } diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index fb3ee3290e..a001b6234a 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -48,6 +48,7 @@ #include "qcocoacursor.h" #include "qcocoaclipboard.h" #include "qcocoadrag.h" +#include "qcocoaservices.h" #include <QtCore/QScopedPointer> #include <QtGui/QPlatformIntegration> @@ -99,6 +100,7 @@ public: QStringList themeNames() const; QPlatformTheme *createPlatformTheme(const QString &name) const; + QPlatformServices *services() const; private: @@ -111,6 +113,8 @@ private: QList<QCocoaScreen *> mScreens; QCocoaClipboard *mCocoaClipboard; QScopedPointer<QCocoaDrag> mCocoaDrag; + QScopedPointer<QPlatformNativeInterface> mNativeInterface; + QScopedPointer<QCocoaServices> mServices; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index f91351ad46..0b87773dee 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -99,6 +99,8 @@ QCocoaIntegration::QCocoaIntegration() , mAccessibility(new QPlatformAccessibility) , mCocoaClipboard(new QCocoaClipboard) , mCocoaDrag(new QCocoaDrag) + , mNativeInterface(new QCocoaNativeInterface) + , mServices(new QCocoaServices) { QCocoaAutoReleasePool pool; @@ -204,7 +206,7 @@ QPlatformFontDatabase *QCocoaIntegration::fontDatabase() const QPlatformNativeInterface *QCocoaIntegration::nativeInterface() const { - return new QCocoaNativeInterface(); + return mNativeInterface.data(); } QPlatformInputContext *QCocoaIntegration::inputContext() const @@ -239,4 +241,9 @@ QPlatformTheme *QCocoaIntegration::createPlatformTheme(const QString &name) cons return QPlatformIntegration::createPlatformTheme(name); } +QPlatformServices *QCocoaIntegration::services() const +{ + return mServices.data(); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.h b/src/plugins/platforms/cocoa/qcocoamenuloader.h index 128792410b..b0d61fa541 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuloader.h +++ b/src/plugins/platforms/cocoa/qcocoamenuloader.h @@ -88,6 +88,7 @@ - (IBAction)qtDispatcherToQAction:(id)sender; - (void)qtUpdateMenubar; - (void)orderFrontCharacterPalette:(id)sender; +- (BOOL)validateMenuItem:(NSMenuItem*)menuItem; @end void qt_mac_loadMenuNib(QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader); diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm index 4993937b91..2fdc28de1e 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm @@ -310,4 +310,16 @@ void qt_mac_loadMenuNib(QT_MANGLE_NAMESPACE(QCocoaMenuLoader) *qtMenuLoader) { [NSApp orderFrontCharacterPalette:sender]; } + +- (BOOL)validateMenuItem:(NSMenuItem*)menuItem +{ + if ([menuItem action] == @selector(hide:) + || [menuItem action] == @selector(hideOtherApplications:) + || [menuItem action] == @selector(unhideAllApplications:)) { + return [NSApp validateMenuItem:menuItem]; + } else { + return [menuItem isEnabled]; + } +} + @end diff --git a/src/plugins/platforms/cocoa/qcocoaservices.h b/src/plugins/platforms/cocoa/qcocoaservices.h new file mode 100644 index 0000000000..022c39dc57 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaservices.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCOCOADESKTOPSERVICES_H +#define QCOCOADESKTOPSERVICES_H + +#include <QtGui/qplatformservices_qpa.h> + +QT_BEGIN_NAMESPACE + +class QCocoaServices : public QPlatformServices +{ +public: + bool openUrl(const QUrl &url); + bool openDocument(const QUrl &url); +}; + +QT_END_NAMESPACE + +#endif // QCOCOADESKTOPSERVICES_H diff --git a/src/plugins/platforms/cocoa/qcocoaservices.mm b/src/plugins/platforms/cocoa/qcocoaservices.mm new file mode 100644 index 0000000000..60bd62eef8 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaservices.mm @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcocoaservices.h" + +#include "qt_mac_p.h" + +#include <AppKit/NSWorkspace.h> +#include <Foundation/NSURL.h> + +#include <QtCore/QUrl> + +QT_BEGIN_NAMESPACE + +bool QCocoaServices::openUrl(const QUrl &url) +{ + const QString scheme = url.scheme(); + if (scheme.isEmpty()) + return openDocument(url); + return [[NSWorkspace sharedWorkspace] openURL:[NSURL URLWithString:QT_PREPEND_NAMESPACE(QCFString::toNSString)(url.toString())]]; +} + +bool QCocoaServices::openDocument(const QUrl &url) +{ + if (!url.isValid()) + return false; + + return [[NSWorkspace sharedWorkspace] openFile:QT_PREPEND_NAMESPACE(QCFString::toNSString)(url.toLocalFile())]; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qt_menu.nib/keyedobjects.nib b/src/plugins/platforms/cocoa/qt_menu.nib/keyedobjects.nib Binary files differindex 3edb0ed2eb..67207ca628 100644 --- a/src/plugins/platforms/cocoa/qt_menu.nib/keyedobjects.nib +++ b/src/plugins/platforms/cocoa/qt_menu.nib/keyedobjects.nib diff --git a/src/plugins/platforms/directfb/directfb.pro b/src/plugins/platforms/directfb/directfb.pro index ae47ec397b..5dfddeb225 100644 --- a/src/plugins/platforms/directfb/directfb.pro +++ b/src/plugins/platforms/directfb/directfb.pro @@ -4,15 +4,8 @@ DESTDIR = $$QT.gui.plugins/platforms QT += core-private gui-private platformsupport-private -isEmpty(DIRECTFB_LIBS) { - DIRECTFB_LIBS = -ldirectfb -lfusion -ldirect -lpthread -} -isEmpty(DIRECTFB_INCLUDEPATH) { - DIRECTFB_INCLUDEPATH = /usr/include/directfb -} - -INCLUDEPATH += $$DIRECTFB_INCLUDEPATH -LIBS += $$DIRECTFB_LIBS +LIBS += $$QMAKE_LIBS_DIRECTFB +QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_DIRECTFB SOURCES = main.cpp \ qdirectfbintegration.cpp \ @@ -30,15 +23,27 @@ HEADERS = qdirectfbintegration.h \ qdirectfbinput.h \ qdirectfbcursor.h \ qdirectfbwindow.h \ - qdirectfbscreen.h + qdirectfbscreen.h \ + qdirectfbeglhooks.h # ### port the GL context -directfbegl: { +directfb_egl { HEADERS += qdirectfb_egl.h SOURCES += qdirectfb_egl.cpp DEFINES += DIRECTFB_GL_EGL } +!isEmpty(DIRECTFB_PLATFORM_HOOKS_SOURCES) { + HEADERS += $$DIRECTFB_PLATFORM_HOOKS_HEADERS + SOURCES += $$DIRECTFB_PLATFORM_HOOKS_SOURCES + DEFINES += DIRECTFB_PLATFORM_HOOKS + LIBS += $$DIRECTFB_PLATFORM_HOOKS_LIBS + QMAKE_LIBDIR += $$DIRECTFB_PLATFORM_HOOKS_LIBDIR + INCLUDEPATH += $$DIRECTFB_PLATFORM_HOOKS_INCLUDEPATH +} else { + SOURCES += qdirectfbeglhooks_stub.cpp +} + CONFIG += qpa/genericunixfontdatabase target.path += $$[QT_INSTALL_PLUGINS]/platforms diff --git a/src/plugins/platforms/directfb/qdirectfb_egl.cpp b/src/plugins/platforms/directfb/qdirectfb_egl.cpp index ee0cbbae95..ac9142c0f4 100644 --- a/src/plugins/platforms/directfb/qdirectfb_egl.cpp +++ b/src/plugins/platforms/directfb/qdirectfb_egl.cpp @@ -42,6 +42,7 @@ #include "qdirectfb_egl.h" #include "qdirectfbwindow.h" #include "qdirectfbscreen.h" +#include "qdirectfbeglhooks.h" #include <QtGui/QOpenGLContext> #include <QtGui/QPlatformOpenGLContext> @@ -54,6 +55,13 @@ QT_BEGIN_NAMESPACE +#ifdef DIRECTFB_PLATFORM_HOOKS +extern QDirectFBEGLHooks platform_hook; +static QDirectFBEGLHooks *hooks = &platform_hook; +#else +static QDirectFBEGLHooks *hooks = 0; +#endif + /** * This provides OpenGL ES 2.0 integration with DirectFB. It assumes that * one can adapt a DirectFBSurface as a EGLSurface. It might need some vendor @@ -137,12 +145,14 @@ void QDirectFbScreenEGL::initializeEGL() void QDirectFbScreenEGL::platformInit() { - // Place vendor init code here. + if (hooks) + hooks->platformInit(); } void QDirectFbScreenEGL::platformDestroy() { - // Place vendor finalize code here. + if (hooks) + hooks->platformDestroy(); } QDirectFbWindowEGL::QDirectFbWindowEGL(QWindow *tlw, QDirectFbInput *input) @@ -209,4 +219,12 @@ void QDirectFbIntegrationEGL::initializeScreen() screenAdded(m_primaryScreen.data()); } +bool QDirectFbIntegrationEGL::hasCapability(QPlatformIntegration::Capability cap) const +{ + // We assume that devices will have more and not less capabilities + if (hooks && hooks->hasCapability(cap)) + return true; + return QDirectFbIntegration::hasCapability(cap); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/directfb/qdirectfb_egl.h b/src/plugins/platforms/directfb/qdirectfb_egl.h index 88f7e60e99..7781b17831 100644 --- a/src/plugins/platforms/directfb/qdirectfb_egl.h +++ b/src/plugins/platforms/directfb/qdirectfb_egl.h @@ -53,6 +53,8 @@ public: QPlatformWindow *createPlatformWindow(QWindow *window) const; QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const; + bool hasCapability(QPlatformIntegration::Capability cap) const; + protected: void initializeScreen(); }; diff --git a/src/plugins/platforms/eglfs/qeglfs_hooks.h b/src/plugins/platforms/directfb/qdirectfbeglhooks.h index a30af9409f..d0711b62dd 100644 --- a/src/plugins/platforms/eglfs/qeglfs_hooks.h +++ b/src/plugins/platforms/directfb/qdirectfbeglhooks.h @@ -39,21 +39,17 @@ ** ****************************************************************************/ -#ifndef QEGLFS_HOOKS_H -#define QEGLFS_HOOKS_H +#ifndef QDIRECTFBEGL_HOOKS_H +#define QDIRECTFBEGL_HOOKS_H #include "qplatformintegration_qpa.h" -#include <EGL/egl.h> QT_BEGIN_NAMESPACE -struct QEglFSHooks { +struct QDirectFBEGLHooks { void platformInit(); void platformDestroy(); - EGLNativeDisplayType platformDisplay() const; - QSize screenSize() const; - EGLNativeWindowType createNativeWindow(const QSize &size); - void destroyNativeWindow(EGLNativeWindowType window); + bool hasCapability(QPlatformIntegration::Capability) const; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/directfb/qdirectfbeglhooks_stub.cpp b/src/plugins/platforms/directfb/qdirectfbeglhooks_stub.cpp new file mode 100644 index 0000000000..753a9d4372 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbeglhooks_stub.cpp @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdirectfbeglhooks.h" + +/** + * This file is compiled in case there is no platform specific hook. On an + * optimizing compiler these functions should never be called. + */ + +void QDirectFBEGLHooks::platformInit() +{ +} + +void QDirectFBEGLHooks::platformDestroy() +{ +} + +bool QDirectFBEGLHooks::hasCapability(QPlatformIntegration::Capability) const +{ + return false; +} + diff --git a/src/plugins/platforms/eglfs/eglfs.pro b/src/plugins/platforms/eglfs/eglfs.pro index 89d56efc82..421bbd5561 100644 --- a/src/plugins/platforms/eglfs/eglfs.pro +++ b/src/plugins/platforms/eglfs/eglfs.pro @@ -12,17 +12,22 @@ DESTDIR = $$QT.gui.plugins/platforms #Avoid X11 header collision DEFINES += MESA_EGL_NO_X11_HEADERS +#To test the hooks on x11 (xlib), comment the above define too +#EGLFS_PLATFORM_HOOKS_SOURCES += qeglfshooks_x11.cpp +#LIBS += -lX11 + SOURCES = main.cpp \ qeglfsintegration.cpp \ qeglfswindow.cpp \ qeglfsbackingstore.cpp \ - qeglfsscreen.cpp + qeglfsscreen.cpp \ + qeglfshooks_stub.cpp HEADERS = qeglfsintegration.h \ qeglfswindow.h \ qeglfsbackingstore.h \ qeglfsscreen.h \ - qeglfs_hooks.h + qeglfshooks.h QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF diff --git a/src/plugins/platforms/eglfs/qeglfshooks.h b/src/plugins/platforms/eglfs/qeglfshooks.h new file mode 100644 index 0000000000..a56c80261b --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfshooks.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QEGLFSHOOKS_H +#define QEGLFSHOOKS_H + +#include "qplatformintegration_qpa.h" +#include <EGL/egl.h> + +QT_BEGIN_NAMESPACE + +class QEglFSHooks +{ +public: + virtual void platformInit(); + virtual void platformDestroy(); + virtual EGLNativeDisplayType platformDisplay() const; + virtual QSize screenSize() const; + virtual EGLNativeWindowType createNativeWindow(const QSize &size); + virtual void destroyNativeWindow(EGLNativeWindowType window); + virtual bool hasCapability(QPlatformIntegration::Capability cap) const; +}; + +#ifdef EGLFS_PLATFORM_HOOKS +extern QEglFSHooks *platformHooks; +static QEglFSHooks *hooks = platformHooks; +#else +extern QEglFSHooks stubHooks; +static QEglFSHooks *hooks = &stubHooks; +#endif + +QT_END_NAMESPACE + +#endif // QEGLFSHOOKS_H diff --git a/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp new file mode 100644 index 0000000000..7cc3527a0c --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfshooks_stub.cpp @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the qmake spec of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qeglfshooks.h" + +void QEglFSHooks::platformInit() +{ +} + +void QEglFSHooks::platformDestroy() +{ +} + +EGLNativeDisplayType QEglFSHooks::platformDisplay() const +{ + return EGL_DEFAULT_DISPLAY; +} + +QSize QEglFSHooks::screenSize() const +{ + return QSize(); +} + +EGLNativeWindowType QEglFSHooks::createNativeWindow(const QSize &size) +{ + Q_UNUSED(size); + return 0; +} + +void QEglFSHooks::destroyNativeWindow(EGLNativeWindowType window) +{ + Q_UNUSED(window); +} + +bool QEglFSHooks::hasCapability(QPlatformIntegration::Capability cap) const +{ + Q_UNUSED(cap); + return false; +} + +#ifndef EGLFS_PLATFORM_HOOKS +QEglFSHooks stubHooks; +#endif diff --git a/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp b/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp new file mode 100644 index 0000000000..cb788c52f2 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfshooks_x11.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the qmake spec of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qeglfshooks.h" + +#include <X11/Xlib.h> + +class QEglFSX11Hooks : public QEglFSHooks +{ +public: + virtual void platformInit(); + virtual void platformDestroy(); + virtual EGLNativeDisplayType platformDisplay() const; + virtual QSize screenSize() const; + virtual EGLNativeWindowType createNativeWindow(const QSize &size); + virtual void destroyNativeWindow(EGLNativeWindowType window); + virtual bool hasCapability(QPlatformIntegration::Capability cap) const; +}; + +static Display *display = 0; + +void QEglFSX11Hooks::platformInit() +{ + display = XOpenDisplay(NULL); + if (!display) + qFatal("Could not open display"); +} + +void QEglFSX11Hooks::platformDestroy() +{ + XCloseDisplay(display); +} + +EGLNativeDisplayType QEglFSX11Hooks::platformDisplay() const +{ + return display; +} + +QSize QEglFSX11Hooks::screenSize() const +{ + QList<QByteArray> env = qgetenv("EGLFS_X11_SIZE").split('x'); + if (env.length() != 2) + return QSize(640, 480); + return QSize(env.at(0).toInt(), env.at(1).toInt()); +} + +EGLNativeWindowType QEglFSX11Hooks::createNativeWindow(const QSize &size) +{ + Window root = DefaultRootWindow(display); + XSetWindowAttributes swa; + memset(&swa, 0, sizeof(swa)); + Window win = XCreateWindow(display, root, 0, 0, size.width(), size.height(), 0, CopyFromParent, + InputOutput, CopyFromParent, CWEventMask, &swa); + XMapWindow(display, win); + XStoreName(display, win, "EGLFS"); + return win; +} + +void QEglFSX11Hooks::destroyNativeWindow(EGLNativeWindowType window) +{ + XDestroyWindow(display, window); +} + +bool QEglFSX11Hooks::hasCapability(QPlatformIntegration::Capability cap) const +{ + Q_UNUSED(cap); + return false; +} + +static QEglFSX11Hooks eglFSX11Hooks; +QEglFSHooks *platformHooks = &eglFSX11Hooks; + diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index d9214f87fe..9b7d9246f9 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -43,7 +43,7 @@ #include "qeglfswindow.h" #include "qeglfsbackingstore.h" -#include "qeglfs_hooks.h" +#include "qeglfshooks.h" #include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h> #include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h> @@ -74,6 +74,10 @@ QEglFSIntegration::~QEglFSIntegration() bool QEglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) const { + // We assume that devices will have more and not less capabilities + if (hooks && hooks->hasCapability(cap)) + return true; + switch (cap) { case ThreadedPixmaps: return true; case OpenGL: return true; diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp index c7e983b0fb..ea939a9821 100644 --- a/src/plugins/platforms/eglfs/qeglfsscreen.cpp +++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp @@ -41,7 +41,7 @@ #include "qeglfsscreen.h" #include "qeglfswindow.h" -#include "qeglfs_hooks.h" +#include "qeglfshooks.h" #include <QtPlatformSupport/private/qeglconvenience_p.h> #include <QtPlatformSupport/private/qeglplatformcontext_p.h> @@ -53,13 +53,6 @@ QT_BEGIN_NAMESPACE -#ifdef EGLFS_PLATFORM_HOOKS -extern QEglFSHooks platform_hooks; -static QEglFSHooks *hooks = &platform_hooks; -#else -static QEglFSHooks *hooks = 0; -#endif - // #define QEGL_EXTRA_DEBUG #ifdef QEGL_EXTRA_DEBUG diff --git a/src/plugins/platforms/kms/kms.json b/src/plugins/platforms/kms/kms.json new file mode 100644 index 0000000000..be662226ae --- /dev/null +++ b/src/plugins/platforms/kms/kms.json @@ -0,0 +1,3 @@ +{ + "Keys": [ "kms" ] +} diff --git a/src/plugins/platforms/kms/kms.pro b/src/plugins/platforms/kms/kms.pro index 73a3fa0418..f97973b1a1 100644 --- a/src/plugins/platforms/kms/kms.pro +++ b/src/plugins/platforms/kms/kms.pro @@ -1,13 +1,14 @@ TARGET = qkms - load(qt_plugin) -QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms -QT = core-private gui-private platformsupport-private opengl-private +QT += core-private gui-private platformsupport-private opengl-private +DESTDIR = $$QT.gui.plugins/platforms + +DEFINES += MESA_EGL_NO_X11_HEADERS -CONFIG += link_pkgconfig qpa/genericunixfontdatabase +CONFIG += link_pkgconfig egl qpa/genericunixfontdatabase -PKGCONFIG += libdrm egl gbm glesv2 +PKGCONFIG += libdrm libudev egl gbm glesv2 SOURCES = main.cpp \ qkmsintegration.cpp \ @@ -17,7 +18,11 @@ SOURCES = main.cpp \ qkmscursor.cpp \ qkmsdevice.cpp \ qkmsbuffermanager.cpp \ - qkmsbackingstore.cpp + qkmsbackingstore.cpp \ + qkmsnativeinterface.cpp \ + qkmsudevlistener.cpp \ + qkmsudevhandler.cpp \ + qkmsudevdrmhandler.cpp HEADERS = qkmsintegration.h \ qkmsscreen.h \ qkmscontext.h \ @@ -25,18 +30,14 @@ HEADERS = qkmsintegration.h \ qkmscursor.h \ qkmsdevice.h \ qkmsbuffermanager.h \ - qkmsbackingstore.h + qkmsbackingstore.h \ + qkmsnativeinterface.h \ + qkmsudevlistener.h \ + qkmsudevhandler.h \ + qkmsudevdrmhandler.h target.path += $$[QT_INSTALL_PLUGINS]/platforms INSTALLS += target - - - - - - - - - - +OTHER_FILES += \ + kms.json diff --git a/src/plugins/platforms/kms/main.cpp b/src/plugins/platforms/kms/main.cpp index d79d0d240f..422fc5fba6 100644 --- a/src/plugins/platforms/kms/main.cpp +++ b/src/plugins/platforms/kms/main.cpp @@ -46,6 +46,8 @@ QT_BEGIN_NAMESPACE class QKmsIntegrationPlugin : public QPlatformIntegrationPlugin { + Q_OBJECT + Q_PLUGIN_METADATA(IID "org.qt-project.Qt.QPlatformIntegrationFactoryInterface" FILE "kms.json") public: QStringList keys() const; QPlatformIntegration *create(const QString&, const QStringList&); @@ -67,6 +69,6 @@ QPlatformIntegration *QKmsIntegrationPlugin::create(const QString& system, const return 0; } -Q_EXPORT_PLUGIN2(kms, QKmsIntegrationPlugin) - QT_END_NAMESPACE + +#include "main.moc" diff --git a/src/plugins/platforms/kms/qkmsbuffermanager.cpp b/src/plugins/platforms/kms/qkmsbuffermanager.cpp index 5c231e6beb..05da957af0 100644 --- a/src/plugins/platforms/kms/qkmsbuffermanager.cpp +++ b/src/plugins/platforms/kms/qkmsbuffermanager.cpp @@ -121,6 +121,8 @@ void QKmsBufferManager::setupBuffersForMode(const drmModeModeInfo &mode, int num GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, this->renderTargetBuffer()); + + eglMakeCurrent(m_screen->device()->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); } void QKmsBufferManager::clearBuffers() diff --git a/src/plugins/platforms/kms/qkmscontext.cpp b/src/plugins/platforms/kms/qkmscontext.cpp index 66829bc73a..4ae5325ca7 100644 --- a/src/plugins/platforms/kms/qkmscontext.cpp +++ b/src/plugins/platforms/kms/qkmscontext.cpp @@ -110,4 +110,11 @@ QSurfaceFormat QKmsContext::format() const return QSurfaceFormat(); } +GLuint QKmsContext::defaultFramebufferObject(QPlatformSurface *surface) const +{ + QPlatformWindow *window = static_cast<QPlatformWindow *>(surface); + QKmsScreen *screen = static_cast<QKmsScreen *> (QPlatformScreen::platformScreenForWindow(window->window())); + return screen->framebufferObject(); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmscontext.h b/src/plugins/platforms/kms/qkmscontext.h index 57f3a1a8e5..6378780f34 100644 --- a/src/plugins/platforms/kms/qkmscontext.h +++ b/src/plugins/platforms/kms/qkmscontext.h @@ -65,6 +65,8 @@ public: EGLContext eglContext() const; + GLuint defaultFramebufferObject(QPlatformSurface *surface) const; + private: QKmsDevice *m_device; diff --git a/src/plugins/platforms/kms/qkmsintegration.cpp b/src/plugins/platforms/kms/qkmsintegration.cpp index c495ca26f9..0405330617 100644 --- a/src/plugins/platforms/kms/qkmsintegration.cpp +++ b/src/plugins/platforms/kms/qkmsintegration.cpp @@ -45,6 +45,9 @@ #include "qkmswindow.h" #include "qkmsbackingstore.h" #include "qkmscontext.h" +#include "qkmsnativeinterface.h" +#include "qkmsudevlistener.h" +#include "qkmsudevdrmhandler.h" #include <QtPlatformSupport/private/qgenericunixprintersupport_p.h> #include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h> @@ -58,14 +61,14 @@ QT_BEGIN_NAMESPACE QKmsIntegration::QKmsIntegration() : QPlatformIntegration(), m_fontDatabase(new QGenericUnixFontDatabase()), - m_eventDispatcher(createUnixEventDispatcher()) + m_eventDispatcher(createUnixEventDispatcher()), + m_nativeInterface(new QKmsNativeInterface), + m_udevListener(new QKmsUdevListener) { QGuiApplicationPrivate::instance()->setEventDispatcher(m_eventDispatcher); setenv("EGL_PLATFORM", "drm",1); - QStringList drmDevices = findDrmDevices(); - foreach (QString path, drmDevices) { - m_devices.append(new QKmsDevice(path, this)); - } + m_drmHandler = new QKmsUdevDRMHandler(this); + m_udevListener->addHandler(m_drmHandler); } QKmsIntegration::~QKmsIntegration() @@ -77,6 +80,14 @@ QKmsIntegration::~QKmsIntegration() delete screen; } delete m_fontDatabase; + delete m_udevListener; +} + +QObject *QKmsIntegration::createDevice(const char *path) +{ + QKmsDevice *device = new QKmsDevice(path, this); + m_devices.append(device); + return device; } bool QKmsIntegration::hasCapability(QPlatformIntegration::Capability cap) const @@ -110,14 +121,6 @@ QPlatformFontDatabase *QKmsIntegration::fontDatabase() const return m_fontDatabase; } -QStringList QKmsIntegration::findDrmDevices() -{ - //Return a list addresses of DRM supported devices - //Hardcoded now, but could use udev to return a list - //of multiple devices. - return QStringList(QString::fromLatin1("/dev/dri/card0")); -} - void QKmsIntegration::addScreen(QKmsScreen *screen) { m_screens.append(screen); @@ -129,4 +132,9 @@ QAbstractEventDispatcher *QKmsIntegration::guiThreadEventDispatcher() const return m_eventDispatcher; } +QPlatformNativeInterface *QKmsIntegration::nativeInterface() const +{ + return m_nativeInterface; +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmsintegration.h b/src/plugins/platforms/kms/qkmsintegration.h index 5724471295..03fc5080a6 100644 --- a/src/plugins/platforms/kms/qkmsintegration.h +++ b/src/plugins/platforms/kms/qkmsintegration.h @@ -43,11 +43,14 @@ #define QPLATFORMINTEGRATION_KMS_H #include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformNativeInterface> QT_BEGIN_NAMESPACE class QKmsScreen; class QKmsDevice; +class QKmsUdevListener; +class QKmsUdevDRMHandler; class QKmsIntegration : public QPlatformIntegration { @@ -64,7 +67,10 @@ public: QPlatformFontDatabase *fontDatabase() const; QAbstractEventDispatcher *guiThreadEventDispatcher() const; + QPlatformNativeInterface *nativeInterface() const; + void addScreen(QKmsScreen *screen); + QObject *createDevice(const char *); private: QStringList findDrmDevices(); @@ -73,6 +79,9 @@ private: QList<QKmsDevice *> m_devices; QPlatformFontDatabase *m_fontDatabase; QAbstractEventDispatcher *m_eventDispatcher; + QPlatformNativeInterface *m_nativeInterface; + QKmsUdevListener *m_udevListener; + QKmsUdevDRMHandler *m_drmHandler; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmsnativeinterface.cpp b/src/plugins/platforms/kms/qkmsnativeinterface.cpp new file mode 100644 index 0000000000..8e026b2503 --- /dev/null +++ b/src/plugins/platforms/kms/qkmsnativeinterface.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <private/qguiapplication_p.h> +#include "qkmsnativeinterface.h" +#include "qkmsdevice.h" + +#include "qscreen.h" + +class QKmsResourceMap : public QMap<QByteArray, QKmsNativeInterface::ResourceType> +{ +public: + QKmsResourceMap() + :QMap<QByteArray, QKmsNativeInterface::ResourceType>() + { + insert("egldisplay", QKmsNativeInterface::EglDisplay); + insert("eglcontext", QKmsNativeInterface::EglContext); + } +}; + +Q_GLOBAL_STATIC(QKmsResourceMap, qKmsResourceMap) + +void *QKmsNativeInterface::nativeResourceForWindow(const QByteArray &resourceString, QWindow *window) +{ + QByteArray lowerCaseResource = resourceString.toLower(); + ResourceType resource = qKmsResourceMap()->value(lowerCaseResource); + void *result = 0; + switch (resource) { + case EglDisplay: + result = eglDisplayForWindow(window); + break; + case EglContext: + result = eglContextForWindow(window); + break; + default: + result = 0; + } + return result; +} + +void *QKmsNativeInterface::eglDisplayForWindow(QWindow *window) +{ + QKmsScreen *screen = qPlatformScreenForWindow(window); + if (!screen) + return 0; + QKmsDevice *device = screen->device(); + if (!device) + return 0; + return device->eglDisplay(); +} + +void *QKmsNativeInterface::eglContextForWindow(QWindow *window) +{ + QKmsScreen *screen = qPlatformScreenForWindow(window); + if (!screen) + return 0; + QKmsDevice *device = screen->device(); + if (!device) + return 0; + return device->eglContext(); +} + +QKmsScreen *QKmsNativeInterface::qPlatformScreenForWindow(QWindow *window) +{ + QScreen *screen = window ? window->screen() : QGuiApplication::primaryScreen(); + return static_cast<QKmsScreen *>(screen->handle()); +} diff --git a/src/plugins/platforms/kms/qkmsnativeinterface.h b/src/plugins/platforms/kms/qkmsnativeinterface.h new file mode 100644 index 0000000000..77a9573250 --- /dev/null +++ b/src/plugins/platforms/kms/qkmsnativeinterface.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QKMSNATIVEINTERFACE_H +#define QKMSNATIVEINTERFACE_H + +#include "qkmsscreen.h" + +#include <QtGui/QPlatformNativeInterface> + +class QKmsNativeInterface : public QPlatformNativeInterface +{ +public: + enum ResourceType { + EglDisplay, + EglContext + }; + + void *nativeResourceForWindow(const QByteArray &resourceString, QWindow *window); + + void *eglDisplayForWindow(QWindow *window); + void *eglContextForWindow(QWindow *window); + +private: + static QKmsScreen *qPlatformScreenForWindow(QWindow *window); +}; + + +#endif // QKMSNATIVEINTERFACE_H diff --git a/src/plugins/platforms/kms/qkmsudevdrmhandler.cpp b/src/plugins/platforms/kms/qkmsudevdrmhandler.cpp new file mode 100644 index 0000000000..0f59de4cef --- /dev/null +++ b/src/plugins/platforms/kms/qkmsudevdrmhandler.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtCore/QRegExp> + +#include <qkmsintegration.h> +#include <qkmsudevdrmhandler.h> + +QT_BEGIN_NAMESPACE + +QKmsUdevDRMHandler::QKmsUdevDRMHandler(QKmsIntegration *integration) + : m_integration(integration) +{ +} + +QObject *QKmsUdevDRMHandler::create(struct udev_device *device) +{ + if (strcmp(udev_device_get_subsystem(device), "drm")) + return 0; + + QRegExp regexp("^card\\d+$"); + if (!regexp.exactMatch(udev_device_get_sysname(device))) + return 0; + + return m_integration->createDevice(udev_device_get_devnode(device)); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmsudevdrmhandler.h b/src/plugins/platforms/kms/qkmsudevdrmhandler.h new file mode 100644 index 0000000000..d627fec1c6 --- /dev/null +++ b/src/plugins/platforms/kms/qkmsudevdrmhandler.h @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QKMSUDEVDRMHANDLER_H +#define QKMSUDEVDRMHANDLER_H + +#include <QObject> + +#include <qkmsudevhandler.h> + +QT_BEGIN_NAMESPACE + +class QKmsIntegration; + +class QKmsUdevDRMHandler : public QKmsUdevHandler +{ +public: + QKmsUdevDRMHandler(QKmsIntegration *integration); + + QObject *create(struct udev_device *device); + +private: + QKmsIntegration *m_integration; +}; + +QT_END_NAMESPACE + +#endif // QKMSUDEVDRMHANDLER_H diff --git a/src/plugins/platforms/kms/qkmsudevhandler.cpp b/src/plugins/platforms/kms/qkmsudevhandler.cpp new file mode 100644 index 0000000000..c0ec4c4ba1 --- /dev/null +++ b/src/plugins/platforms/kms/qkmsudevhandler.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qkmsudevhandler.h> + +QT_BEGIN_NAMESPACE + +QKmsUdevHandler::QKmsUdevHandler(QObject *parent) + : QObject(parent) +{ +} + +QKmsUdevHandler::~QKmsUdevHandler() +{ +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmsudevhandler.h b/src/plugins/platforms/kms/qkmsudevhandler.h new file mode 100644 index 0000000000..4870809927 --- /dev/null +++ b/src/plugins/platforms/kms/qkmsudevhandler.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QKMSUDEVHANDLER_H +#define QKMSUDEVHANDLER_H + +#include <QObject> + +#include <libudev.h> + +QT_BEGIN_NAMESPACE + +class QKmsUdevHandler : public QObject +{ + Q_OBJECT + +public: + QKmsUdevHandler(QObject *parent = 0); + virtual ~QKmsUdevHandler(); + + virtual QObject *create(struct udev_device *) = 0; +}; + +QT_END_NAMESPACE + +#endif // QKMSUDEVHANDLER_H diff --git a/src/plugins/platforms/kms/qkmsudevlistener.cpp b/src/plugins/platforms/kms/qkmsudevlistener.cpp new file mode 100644 index 0000000000..c0a933b57b --- /dev/null +++ b/src/plugins/platforms/kms/qkmsudevlistener.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <qkmsudevlistener.h> + +QT_BEGIN_NAMESPACE + +QKmsUdevListener::QKmsUdevListener(QObject *parent) + : QObject(parent) +{ + m_udev = udev_new(); +} + +QKmsUdevListener::~QKmsUdevListener() +{ + udev_unref(m_udev); +} + +void QKmsUdevListener::addHandler(QKmsUdevHandler *handler) +{ + m_handlers.removeAll((QKmsUdevHandler *) 0); + m_handlers.removeAll(handler); + m_handlers.prepend(handler); + + scan(); +} + +bool QKmsUdevListener::create(struct udev_device *device) +{ + foreach (QKmsUdevHandler *handler, m_handlers) { + if (!handler) + continue; + + QObject *obj = handler->create(device); + if (obj) { + m_devices[udev_device_get_syspath(device)] = obj; + return true; + } + } + + return false; +} + +void QKmsUdevListener::scan() +{ + struct udev_enumerate *e; + struct udev_list_entry *entry; + + e = udev_enumerate_new(m_udev); + udev_enumerate_scan_devices(e); + udev_list_entry_foreach(entry, udev_enumerate_get_list_entry(e)) { + const char *path = udev_list_entry_get_name(entry); + if (m_devices.contains(path)) + continue; + + struct udev_device *device = udev_device_new_from_syspath(m_udev, path); + create(device); + udev_device_unref(device); + } + udev_enumerate_unref(e); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/kms/qkmsudevlistener.h b/src/plugins/platforms/kms/qkmsudevlistener.h new file mode 100644 index 0000000000..3d87cfe662 --- /dev/null +++ b/src/plugins/platforms/kms/qkmsudevlistener.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QKMSUDEVLISTENER_H +#define QKMSUDEVLISTENER_H + +#include <QObject> +#include <QMap> +#include <QList> +#include <QPointer> +#include <QString> + +#include <qkmsudevhandler.h> + +#include <libudev.h> + +QT_BEGIN_NAMESPACE + +class QKmsUdevListener : public QObject +{ + Q_OBJECT + +public: + QKmsUdevListener(QObject *parent = 0); + ~QKmsUdevListener(); + + void addHandler(QKmsUdevHandler *); + +private: + QList<QPointer<QKmsUdevHandler> > m_handlers; + QMap<QString, QPointer<QObject> > m_devices; + struct udev *m_udev; + + void scan(); + bool create(struct udev_device *); +}; + +QT_END_NAMESPACE + +#endif // QKMSUDEVLISTENER_H diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index 442390f6a6..51de06f910 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -6,9 +6,7 @@ contains(QT_CONFIG, xcb) { SUBDIRS += xcb } -mac { - SUBDIRS += cocoa -} +mac:contains(QT_CONFIG, coreservices): SUBDIRS += cocoa win32: SUBDIRS += windows @@ -19,3 +17,7 @@ qnx { contains(QT_CONFIG, eglfs) { SUBDIRS += eglfs } + +contains(QT_CONFIG, directfb) { + SUBDIRS += directfb +} diff --git a/src/plugins/platforms/qnx/qnx.pro b/src/plugins/platforms/qnx/qnx.pro index bdc8c38614..82c3b201c9 100644 --- a/src/plugins/platforms/qnx/qnx.pro +++ b/src/plugins/platforms/qnx/qnx.pro @@ -17,6 +17,7 @@ QT += opengl opengl-private platformsupport platformsupport-private widgets-priv #DEFINES += QQNXINPUTCONTEXT_IMF_EVENT_DEBUG #DEFINES += QQNXINTEGRATION_DEBUG #DEFINES += QQNXNAVIGATOREVENTHANDLER_DEBUG +#DEFINES += QQNXNAVIGATOREVENTNOTIFIER_DEBUG #DEFINES += QQNXRASTERBACKINGSTORE_DEBUG #DEFINES += QQNXROOTWINDOW_DEBUG #DEFINES += QQNXSCREEN_DEBUG @@ -31,6 +32,7 @@ SOURCES = main.cpp \ qqnxglbackingstore.cpp \ qqnxintegration.cpp \ qqnxnavigatoreventhandler.cpp \ + qqnxnavigatoreventnotifier.cpp \ qqnxscreen.cpp \ qqnxwindow.cpp \ qqnxrasterbackingstore.cpp \ @@ -46,6 +48,7 @@ HEADERS = qqnxbuffer.h \ qqnxkeytranslator.h \ qqnxintegration.h \ qqnxnavigatoreventhandler.h \ + qqnxnavigatoreventnotifier.h \ qqnxglcontext.h \ qqnxglbackingstore.h \ qqnxscreen.h \ diff --git a/src/plugins/platforms/qnx/qqnxintegration.cpp b/src/plugins/platforms/qnx/qqnxintegration.cpp index f12073e367..b4112999b6 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.cpp +++ b/src/plugins/platforms/qnx/qqnxintegration.cpp @@ -45,6 +45,7 @@ #include "qqnxglcontext.h" #include "qqnxnativeinterface.h" #include "qqnxnavigatoreventhandler.h" +#include "qqnxnavigatoreventnotifier.h" #include "qqnxrasterbackingstore.h" #include "qqnxscreen.h" #include "qqnxscreeneventhandler.h" @@ -80,7 +81,8 @@ QMutex QQnxIntegration::ms_windowMapperMutex; QQnxIntegration::QQnxIntegration() : QPlatformIntegration() , m_eventThread(0) - , m_navigatorEventHandler(0) + , m_navigatorEventHandler(new QQnxNavigatorEventHandler()) + , m_navigatorEventNotifier(0) , m_virtualKeyboard(0) , m_inputContext(0) , m_fontDatabase(new QGenericUnixFontDatabase()) @@ -103,12 +105,12 @@ QQnxIntegration::QQnxIntegration() qFatal("QQnx: failed to connect to composition manager, errno=%d", errno); } - // Create/start navigator event handler - m_navigatorEventHandler = new QQnxNavigatorEventHandler; + // Create/start navigator event notifier + m_navigatorEventNotifier = new QQnxNavigatorEventNotifier(m_navigatorEventHandler); // delay invocation of start() to the time the event loop is up and running // needed to have the QThread internals of the main thread properly initialized - QMetaObject::invokeMethod(m_navigatorEventHandler, "start", Qt::QueuedConnection); + QMetaObject::invokeMethod(m_navigatorEventNotifier, "start", Qt::QueuedConnection); // Create displays for all possible screens (which may not be attached) createDisplays(); @@ -160,12 +162,12 @@ QQnxIntegration::~QQnxIntegration() delete m_clipboard; #endif - // Stop/destroy event thread - delete m_eventThread; - - // Stop/destroy navigator thread + // Stop/destroy navigator event notifier + delete m_navigatorEventNotifier; delete m_navigatorEventHandler; + // Stop/destroy event thread + delete m_eventThread; delete m_screenEventHandler; // Destroy all displays diff --git a/src/plugins/platforms/qnx/qqnxintegration.h b/src/plugins/platforms/qnx/qqnxintegration.h index f29baf1323..801bd7b6e5 100644 --- a/src/plugins/platforms/qnx/qqnxintegration.h +++ b/src/plugins/platforms/qnx/qqnxintegration.h @@ -54,6 +54,7 @@ class QQnxEventThread; class QQnxInputContext; class QQnxNativeInterface; class QQnxNavigatorEventHandler; +class QQnxNavigatorEventNotifier; class QQnxAbstractVirtualKeyboard; class QQnxWindow; class QQnxServices; @@ -112,6 +113,7 @@ private: screen_context_t m_screenContext; QQnxEventThread *m_eventThread; QQnxNavigatorEventHandler *m_navigatorEventHandler; + QQnxNavigatorEventNotifier *m_navigatorEventNotifier; QQnxAbstractVirtualKeyboard *m_virtualKeyboard; QQnxInputContext *m_inputContext; QPlatformFontDatabase *m_fontDatabase; diff --git a/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.cpp b/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.cpp index 9527a57ca3..72227c6089 100644 --- a/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.cpp +++ b/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.cpp @@ -1,6 +1,6 @@ /*************************************************************************** ** -** Copyright (C) 2011 - 2012 Research In Motion +** Copyright (C) 2012 Research In Motion ** Contact: http://www.qt-project.org/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -41,216 +41,58 @@ #include "qqnxnavigatoreventhandler.h" -#include <QtGui/QGuiApplication> -#include <QtGui/QWindow> -#include <QtGui/QWindowSystemInterface> +#include <QDebug> +#include <QGuiApplication> +#include <QWindowSystemInterface> -#include <QtCore/QByteArray> -#include <QtCore/QDebug> -#include <QtCore/QList> -#include <QtCore/QSocketNotifier> -#include <QtCore/private/qcore_unix_p.h> - -#include <errno.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> - -static const char *navigatorControlPath = "/pps/services/navigator/control"; -static const int ppsBufferSize = 4096; +QT_BEGIN_NAMESPACE QQnxNavigatorEventHandler::QQnxNavigatorEventHandler(QObject *parent) - : QObject(parent), - m_fd(-1), - m_readNotifier(0) -{ -} - -QQnxNavigatorEventHandler::~QQnxNavigatorEventHandler() + : QObject(parent) { - delete m_readNotifier; - - // close connection to navigator - if (m_fd != -1) - close(m_fd); - -#if defined(QQNXNAVIGATOREVENTHANDLER_DEBUG) - qDebug() << "QQNX: navigator event handler stopped"; -#endif } -void QQnxNavigatorEventHandler::start() +bool QQnxNavigatorEventHandler::handleOrientationCheck(int angle) { + // reply to navigator that (any) orientation is acceptable #if defined(QQNXNAVIGATOREVENTHANDLER_DEBUG) - qDebug() << "QQNX: navigator event handler started"; + qDebug() << Q_FUNC_INFO << "angle=" << angle; #endif - // open connection to navigator - errno = 0; - m_fd = open(navigatorControlPath, O_RDWR); - if (m_fd == -1) { - qWarning("QQNX: failed to open navigator pps, errno=%d", errno); - return; - } - - m_readNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read); - connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(readData())); + // TODO: check if top window flags prohibit orientation change + return true; } -void QQnxNavigatorEventHandler::parsePPS(const QByteArray &ppsData, QByteArray &msg, QByteArray &dat, QByteArray &id) +void QQnxNavigatorEventHandler::handleOrientationChange(int angle) { + // update screen geometry and reply to navigator that we're ready #if defined(QQNXNAVIGATOREVENTHANDLER_DEBUG) - qDebug() << "PPS: data=" << ppsData; -#endif - - // tokenize pps data into lines - QList<QByteArray> lines = ppsData.split('\n'); - - // validate pps object - if (lines.size() == 0 || lines.at(0) != "@control") { - qFatal("QQNX: unrecognized pps object, data=%s", ppsData.constData()); - } - - // parse pps object attributes and extract values - for (int i = 1; i < lines.size(); i++) { - - // tokenize current attribute - const QByteArray &attr = lines.at(i); - -#if defined(QQNXNAVIGATOREVENTHANDLER_DEBUG) - qDebug() << "PPS: attr=" << attr; -#endif - - int firstColon = attr.indexOf(':'); - if (firstColon == -1) { - // abort - malformed attribute - continue; - } - - int secondColon = attr.indexOf(':', firstColon + 1); - if (secondColon == -1) { - // abort - malformed attribute - continue; - } - - QByteArray key = attr.left(firstColon); - QByteArray value = attr.mid(secondColon + 1); - -#if defined(QQNXNAVIGATOREVENTHANDLER_DEBUG) - qDebug() << "PPS: key=" << key; - qDebug() << "PPS: val=" << value; + qDebug() << Q_FUNC_INFO << "angle=" << angle; #endif - // save attribute value - if (key == "msg") { - msg = value; - } else if (key == "dat") { - dat = value; - } else if (key == "id") { - id = value; - } else { - qFatal("QQNX: unrecognized pps attribute, attr=%s", key.constData()); - } - } + emit rotationChanged(angle); } -void QQnxNavigatorEventHandler::replyPPS(const QByteArray &res, const QByteArray &id, const QByteArray &dat) +void QQnxNavigatorEventHandler::handleSwipeDown() { - // construct pps message - QByteArray ppsData = "res::"; - ppsData += res; - ppsData += "\nid::"; - ppsData += id; - if (!dat.isEmpty()) { - ppsData += "\ndat::"; - ppsData += dat; - } - ppsData += "\n"; - + // simulate menu key press #if defined(QQNXNAVIGATOREVENTHANDLER_DEBUG) - qDebug() << "PPS reply=" << ppsData; + qDebug() << Q_FUNC_INFO; #endif - // send pps message to navigator - errno = 0; - int bytes = write(m_fd, ppsData.constData(), ppsData.size()); - if (bytes == -1) { - qFatal("QQNX: failed to write navigator pps, errno=%d", errno); - } + QWindow *w = QGuiApplication::focusWindow(); + QWindowSystemInterface::handleKeyEvent(w, QEvent::KeyPress, Qt::Key_Menu, Qt::NoModifier); + QWindowSystemInterface::handleKeyEvent(w, QEvent::KeyRelease, Qt::Key_Menu, Qt::NoModifier); } -void QQnxNavigatorEventHandler::handleMessage(const QByteArray &msg, const QByteArray &dat, const QByteArray &id) +void QQnxNavigatorEventHandler::handleExit() { + // shutdown everything #if defined(QQNXNAVIGATOREVENTHANDLER_DEBUG) - qDebug() << "PPS: msg=" << msg << ", dat=" << dat << ", id=" << id; + qDebug() << Q_FUNC_INFO; #endif - // check message type - if (msg == "orientationCheck") { - - // reply to navigator that (any) orientation is acceptable -#if defined(QQNXNAVIGATOREVENTHANDLER_DEBUG) - qDebug() << "PPS: orientation check, o=" << dat; -#endif - replyPPS(msg, id, "true"); - - } else if (msg == "orientation") { - - // update screen geometry and reply to navigator that we're ready -#if defined(QQNXNAVIGATOREVENTHANDLER_DEBUG) - qDebug() << "PPS: orientation, o=" << dat; -#endif - Q_EMIT rotationChanged(dat.toInt()); - replyPPS(msg, id, ""); - - } else if (msg == "SWIPE_DOWN") { - - // simulate menu key press -#if defined(QQNXNAVIGATOREVENTHANDLER_DEBUG) - qDebug() << "PPS: menu"; -#endif - QWindow *w = QGuiApplication::focusWindow(); - QWindowSystemInterface::handleKeyEvent(w, QEvent::KeyPress, Qt::Key_Menu, Qt::NoModifier); - QWindowSystemInterface::handleKeyEvent(w, QEvent::KeyRelease, Qt::Key_Menu, Qt::NoModifier); - - } else if (msg == "exit") { - - // shutdown everything -#if defined(QQNXNAVIGATOREVENTHANDLER_DEBUG) - qDebug() << "PPS: exit"; -#endif - QCoreApplication::quit(); - } + QCoreApplication::quit(); } -void QQnxNavigatorEventHandler::readData() -{ -#if defined(QQNXNAVIGATOREVENTHANDLER_DEBUG) - qDebug() << "QQNX: reading navigator data"; -#endif - // allocate buffer for pps data - char buffer[ppsBufferSize]; - - // attempt to read pps data - errno = 0; - int bytes = qt_safe_read(m_fd, buffer, ppsBufferSize - 1); - if (bytes == -1) { - qFatal("QQNX: failed to read navigator pps, errno=%d", errno); - } - - // check if pps data was received - if (bytes > 0) { - - // ensure data is null terminated - buffer[bytes] = '\0'; - - // process received message - QByteArray ppsData(buffer); - QByteArray msg; - QByteArray dat; - QByteArray id; - parsePPS(ppsData, msg, dat, id); - handleMessage(msg, dat, id); - } -} +QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.h b/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.h index 8084eba1d9..58a1ac8cb3 100644 --- a/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.h +++ b/src/plugins/platforms/qnx/qqnxnavigatoreventhandler.h @@ -1,6 +1,6 @@ /*************************************************************************** ** -** Copyright (C) 2011 - 2012 Research In Motion +** Copyright (C) 2012 Research In Motion ** Contact: http://www.qt-project.org/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -46,31 +46,19 @@ QT_BEGIN_NAMESPACE -class QSocketNotifier; - class QQnxNavigatorEventHandler : public QObject { Q_OBJECT public: explicit QQnxNavigatorEventHandler(QObject *parent = 0); - ~QQnxNavigatorEventHandler(); + + bool handleOrientationCheck(int angle); + void handleOrientationChange(int angle); + void handleSwipeDown(); + void handleExit(); Q_SIGNALS: void rotationChanged(int angle); - -public Q_SLOTS: - void start(); - -private Q_SLOTS: - void readData(); - -private: - void parsePPS(const QByteArray &ppsData, QByteArray &msg, QByteArray &dat, QByteArray &id); - void replyPPS(const QByteArray &res, const QByteArray &id, const QByteArray &dat); - void handleMessage(const QByteArray &msg, const QByteArray &dat, const QByteArray &id); - - int m_fd; - QSocketNotifier *m_readNotifier; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxnavigatoreventnotifier.cpp b/src/plugins/platforms/qnx/qqnxnavigatoreventnotifier.cpp new file mode 100644 index 0000000000..d5220c936e --- /dev/null +++ b/src/plugins/platforms/qnx/qqnxnavigatoreventnotifier.cpp @@ -0,0 +1,233 @@ +/*************************************************************************** +** +** Copyright (C) 2011 - 2012 Research In Motion +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qqnxnavigatoreventnotifier.h" + +#include "qqnxnavigatoreventhandler.h" + +#include <QtCore/QByteArray> +#include <QtCore/QDebug> +#include <QtCore/QList> +#include <QtCore/QSocketNotifier> +#include <QtCore/private/qcore_unix_p.h> + +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <sys/types.h> +#include <sys/stat.h> + +static const char *navigatorControlPath = "/pps/services/navigator/control"; +static const int ppsBufferSize = 4096; + +QT_BEGIN_NAMESPACE + +QQnxNavigatorEventNotifier::QQnxNavigatorEventNotifier(QQnxNavigatorEventHandler *eventHandler, QObject *parent) + : QObject(parent), + m_fd(-1), + m_readNotifier(0), + m_eventHandler(eventHandler) +{ +} + +QQnxNavigatorEventNotifier::~QQnxNavigatorEventNotifier() +{ + delete m_readNotifier; + + // close connection to navigator + if (m_fd != -1) + close(m_fd); + +#if defined(QQNXNAVIGATOREVENTNOTIFIER_DEBUG) + qDebug() << "QQNX: navigator event notifier stopped"; +#endif +} + +void QQnxNavigatorEventNotifier::start() +{ +#if defined(QQNXNAVIGATOREVENTNOTIFIER_DEBUG) + qDebug() << "QQNX: navigator event notifier started"; +#endif + + // open connection to navigator + errno = 0; + m_fd = open(navigatorControlPath, O_RDWR); + if (m_fd == -1) { + qWarning("QQNX: failed to open navigator pps, errno=%d", errno); + return; + } + + m_readNotifier = new QSocketNotifier(m_fd, QSocketNotifier::Read); + connect(m_readNotifier, SIGNAL(activated(int)), this, SLOT(readData())); +} + +void QQnxNavigatorEventNotifier::parsePPS(const QByteArray &ppsData, QByteArray &msg, QByteArray &dat, QByteArray &id) +{ +#if defined(QQNXNAVIGATOREVENTNOTIFIER_DEBUG) + qDebug() << "PPS: data=" << ppsData; +#endif + + // tokenize pps data into lines + QList<QByteArray> lines = ppsData.split('\n'); + + // validate pps object + if (lines.size() == 0 || lines.at(0) != "@control") + qFatal("QQNX: unrecognized pps object, data=%s", ppsData.constData()); + + // parse pps object attributes and extract values + for (int i = 1; i < lines.size(); ++i) { + + // tokenize current attribute + const QByteArray &attr = lines.at(i); + +#if defined(QQNXNAVIGATOREVENTNOTIFIER_DEBUG) + qDebug() << "PPS: attr=" << attr; +#endif + + int firstColon = attr.indexOf(':'); + if (firstColon == -1) { + // abort - malformed attribute + continue; + } + + int secondColon = attr.indexOf(':', firstColon + 1); + if (secondColon == -1) { + // abort - malformed attribute + continue; + } + + QByteArray key = attr.left(firstColon); + QByteArray value = attr.mid(secondColon + 1); + +#if defined(QQNXNAVIGATOREVENTNOTIFIER_DEBUG) + qDebug() << "PPS: key=" << key; + qDebug() << "PPS: val=" << value; +#endif + + // save attribute value + if (key == "msg") + msg = value; + else if (key == "dat") + dat = value; + else if (key == "id") + id = value; + else + qFatal("QQNX: unrecognized pps attribute, attr=%s", key.constData()); + } +} + +void QQnxNavigatorEventNotifier::replyPPS(const QByteArray &res, const QByteArray &id, const QByteArray &dat) +{ + // construct pps message + QByteArray ppsData = "res::"; + ppsData += res; + ppsData += "\nid::"; + ppsData += id; + if (!dat.isEmpty()) { + ppsData += "\ndat::"; + ppsData += dat; + } + ppsData += "\n"; + +#if defined(QQNXNAVIGATOREVENTNOTIFIER_DEBUG) + qDebug() << "PPS reply=" << ppsData; +#endif + + // send pps message to navigator + errno = 0; + int bytes = write(m_fd, ppsData.constData(), ppsData.size()); + if (bytes == -1) + qFatal("QQNX: failed to write navigator pps, errno=%d", errno); +} + +void QQnxNavigatorEventNotifier::handleMessage(const QByteArray &msg, const QByteArray &dat, const QByteArray &id) +{ +#if defined(QQNXNAVIGATOREVENTNOTIFIER_DEBUG) + qDebug() << "PPS: msg=" << msg << ", dat=" << dat << ", id=" << id; +#endif + + // check message type + if (msg == "orientationCheck") { + const bool response = m_eventHandler->handleOrientationCheck(dat.toInt()); + + // reply to navigator that (any) orientation is acceptable + replyPPS(msg, id, response ? "true" : "false"); + } else if (msg == "orientation") { + m_eventHandler->handleOrientationChange(dat.toInt()); + replyPPS(msg, id, ""); + } else if (msg == "SWIPE_DOWN") { + m_eventHandler->handleSwipeDown(); + } else if (msg == "exit") { + m_eventHandler->handleExit(); + } +} + +void QQnxNavigatorEventNotifier::readData() +{ +#if defined(QQNXNAVIGATOREVENTNOTIFIER_DEBUG) + qDebug() << "QQNX: reading navigator data"; +#endif + // allocate buffer for pps data + char buffer[ppsBufferSize]; + + // attempt to read pps data + errno = 0; + int bytes = qt_safe_read(m_fd, buffer, ppsBufferSize - 1); + if (bytes == -1) + qFatal("QQNX: failed to read navigator pps, errno=%d", errno); + + // check if pps data was received + if (bytes > 0) { + + // ensure data is null terminated + buffer[bytes] = '\0'; + + // process received message + QByteArray ppsData(buffer); + QByteArray msg; + QByteArray dat; + QByteArray id; + parsePPS(ppsData, msg, dat, id); + handleMessage(msg, dat, id); + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/qnx/qqnxnavigatoreventnotifier.h b/src/plugins/platforms/qnx/qqnxnavigatoreventnotifier.h new file mode 100644 index 0000000000..bdf1220b56 --- /dev/null +++ b/src/plugins/platforms/qnx/qqnxnavigatoreventnotifier.h @@ -0,0 +1,77 @@ +/*************************************************************************** +** +** Copyright (C) 2011 - 2012 Research In Motion +** Contact: http://www.qt-project.org/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** GNU Lesser General Public License Usage +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this +** file. Please review the following information to ensure the GNU Lesser +** General Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU General +** Public License version 3.0 as published by the Free Software Foundation +** and appearing in the file LICENSE.GPL included in the packaging of this +** file. Please review the following information to ensure the GNU General +** Public License version 3.0 requirements will be met: +** http://www.gnu.org/copyleft/gpl.html. +** +** Other Usage +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QQNXNAVIGATOREVENTNOTIFIER_H +#define QQNXNAVIGATOREVENTNOTIFIER_H + +#include <QObject> + +QT_BEGIN_NAMESPACE + +class QQnxNavigatorEventHandler; +class QSocketNotifier; + +class QQnxNavigatorEventNotifier : public QObject +{ + Q_OBJECT +public: + explicit QQnxNavigatorEventNotifier(QQnxNavigatorEventHandler *eventHandler, QObject *parent = 0); + ~QQnxNavigatorEventNotifier(); + +public Q_SLOTS: + void start(); + +private Q_SLOTS: + void readData(); + +private: + void parsePPS(const QByteArray &ppsData, QByteArray &msg, QByteArray &dat, QByteArray &id); + void replyPPS(const QByteArray &res, const QByteArray &id, const QByteArray &dat); + void handleMessage(const QByteArray &msg, const QByteArray &dat, const QByteArray &id); + + int m_fd; + QSocketNotifier *m_readNotifier; + QQnxNavigatorEventHandler *m_eventHandler; +}; + +QT_END_NAMESPACE + +#endif // QQNXNAVIGATOREVENTNOTIFIER_H diff --git a/src/plugins/platforms/windows/accessible/accessible.pri b/src/plugins/platforms/windows/accessible/accessible.pri index 3069c2dda3..1a409cb87e 100644 --- a/src/plugins/platforms/windows/accessible/accessible.pri +++ b/src/plugins/platforms/windows/accessible/accessible.pri @@ -8,7 +8,7 @@ HEADERS += \ $$PWD/qwindowsaccessibility.h \ $$PWD/comutils.h -!*g++: { +!win32-g++*: { SOURCES += $$PWD/iaccessible2.cpp HEADERS += $$PWD/iaccessible2.h include(../../../../3rdparty/iaccessible2/iaccessible2.pri) diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.cpp b/src/plugins/platforms/windows/accessible/iaccessible2.cpp index be680e7d48..ddab3cb0f2 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.cpp +++ b/src/plugins/platforms/windows/accessible/iaccessible2.cpp @@ -114,6 +114,68 @@ HRESULT STDMETHODCALLTYPE AccessibleApplication::get_toolkitVersion(/* [retval][ } +/**************************************************************\ + * AccessibleRelation * + **************************************************************/ +AccessibleRelation::AccessibleRelation(const QList<QAccessibleInterface *> &targets, + QAccessible::Relation relation) + : m_targets(targets), m_relation(relation), m_ref(1) +{ + Q_ASSERT(m_targets.count()); +} + +/* IUnknown */ +HRESULT STDMETHODCALLTYPE AccessibleRelation::QueryInterface(REFIID id, LPVOID *iface) +{ + *iface = 0; + if (id == IID_IUnknown) + *iface = (IUnknown*)this; + + if (*iface) { + AddRef(); + return S_OK; + } + + return E_NOINTERFACE; +} + +ULONG STDMETHODCALLTYPE AccessibleRelation::AddRef() +{ + return ++m_ref; +} + +ULONG STDMETHODCALLTYPE AccessibleRelation::Release() +{ + if (!--m_ref) { + delete this; + return 0; + } + return m_ref; +} + +/* IAccessibleRelation */ +HRESULT STDMETHODCALLTYPE AccessibleRelation::get_relationType( + /* [retval][out] */ BSTR *relationType) +{ + *relationType = relationToBSTR(m_relation); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleRelation::get_localizedRelationType( + /* [retval][out] */ BSTR *localizedRelationType) +{ + // Who ever needs this??? + *localizedRelationType = relationToBSTR(m_relation); + return S_OK; +} + +HRESULT STDMETHODCALLTYPE AccessibleRelation::get_nTargets( + /* [retval][out] */ long *nTargets) +{ + // ### always one target + *nTargets = m_targets.count(); + return S_OK; +} /*! \internal @@ -140,7 +202,7 @@ HRESULT STDMETHODCALLTYPE AccessibleRelation::get_target( (see "Special Consideration when using Arrays", in Accessible2.idl) */ HRESULT STDMETHODCALLTYPE AccessibleRelation::get_targets( - /* [in] */ long maxTargets, // Hmmm, ignore ??? + /* [in] */ long maxTargets, /* [length_is][size_is][out] */ IUnknown **targets, /* [retval][out] */ long *nTargets) { @@ -215,6 +277,10 @@ HRESULT STDMETHODCALLTYPE QWindowsIA2Accessible::QueryInterface(REFIID id, LPVOI return hr; } + +/* Note that IUnknown is inherited from several interfaces. Therefore we must reimplement all its + functions in the concrete class to avoid ambiguity. +*/ ULONG STDMETHODCALLTYPE QWindowsIA2Accessible::AddRef() { return QWindowsMsaaAccessible::AddRef(); diff --git a/src/plugins/platforms/windows/accessible/iaccessible2.h b/src/plugins/platforms/windows/accessible/iaccessible2.h index 9b8a1ad3a6..0f9d3b3c41 100644 --- a/src/plugins/platforms/windows/accessible/iaccessible2.h +++ b/src/plugins/platforms/windows/accessible/iaccessible2.h @@ -298,83 +298,27 @@ private: /**************************************************************\ - * IAccessibleRelation * + * AccessibleRelation * **************************************************************/ -struct AccessibleRelation : public IAccessibleRelation +class AccessibleRelation : public IAccessibleRelation { +public: AccessibleRelation(const QList<QAccessibleInterface *> &targets, - QAccessible::Relation relation) - : m_targets(targets), m_relation(relation), m_ref(1) - { - Q_ASSERT(m_targets.count()); - } + QAccessible::Relation relation); + virtual ~AccessibleRelation() {} /* IUnknown */ - HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface) - { - *iface = 0; - if (id == IID_IUnknown) - *iface = (IUnknown*)this; - - if (*iface) { - AddRef(); - return S_OK; - } - - return E_NOINTERFACE; - } - - ULONG STDMETHODCALLTYPE AddRef() - { - return ++m_ref; - } - - ULONG STDMETHODCALLTYPE Release() - { - if (!--m_ref) { - delete this; - return 0; - } - return m_ref; - } + HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface); + ULONG STDMETHODCALLTYPE AddRef(); + ULONG STDMETHODCALLTYPE Release(); /* IAccessibleRelation */ - HRESULT STDMETHODCALLTYPE get_relationType( - /* [retval][out] */ BSTR *relationType) - { - *relationType = relationToBSTR(m_relation); - return S_OK; - } - - HRESULT STDMETHODCALLTYPE get_localizedRelationType( - /* [retval][out] */ BSTR *localizedRelationType) - { - // Who ever needs this??? - *localizedRelationType = relationToBSTR(m_relation); - return S_OK; - } - - HRESULT STDMETHODCALLTYPE get_nTargets( - /* [retval][out] */ long *nTargets) - { - // ### always one target - *nTargets = m_targets.count(); - return S_OK; - } - + HRESULT STDMETHODCALLTYPE get_relationType(BSTR *relationType); + HRESULT STDMETHODCALLTYPE get_localizedRelationType(BSTR *localizedRelationType); + HRESULT STDMETHODCALLTYPE get_nTargets(long *nTargets); HRESULT STDMETHODCALLTYPE get_target(long targetIndex, IUnknown **target); - - - /*! - \internal - Client allocates and deallocates \a targets array - (see "Special Consideration when using Arrays", in Accessible2.idl) - */ - HRESULT STDMETHODCALLTYPE get_targets( - /* [in] */ long maxTargets, // Hmmm, ignore ??? - /* [length_is][size_is][out] */ IUnknown **targets, - /* [retval][out] */ long *nTargets); + HRESULT STDMETHODCALLTYPE get_targets(long maxTargets, IUnknown **targets, long *nTargets); private: static BSTR relationToBSTR(QAccessible::Relation relation) diff --git a/src/plugins/platforms/windows/qwindowscontext.cpp b/src/plugins/platforms/windows/qwindowscontext.cpp index 17420d271d..c5b1dcce9f 100644 --- a/src/plugins/platforms/windows/qwindowscontext.cpp +++ b/src/plugins/platforms/windows/qwindowscontext.cpp @@ -54,6 +54,7 @@ #include <QtGui/QWindow> #include <QtGui/QWindowSystemInterface> #include <QtGui/QPlatformNativeInterface> +#include <QtGui/QGuiApplication> #include <QtCore/QSet> #include <QtCore/QHash> @@ -276,7 +277,7 @@ QWindowsContext::QWindowsContext() : # pragma warning( disable : 4996 ) #endif m_instance = this; - if (const char *v = getenv("QT_LIGHTHOUSE_WINDOWS_VERBOSE")) { + if (const char *v = getenv("QT_QPA_VERBOSE")) { QWindowsContext::verboseIntegration = componentVerbose(v, "integration"); QWindowsContext::verboseWindows = componentVerbose(v, "windows"); QWindowsContext::verboseEvents = componentVerbose(v, "events"); @@ -791,6 +792,11 @@ bool QWindowsContext::windowsProc(HWND hwnd, UINT message, if (QWindowsTheme *theme = QWindowsTheme::instance()) theme->windowsThemeChanged(platformWindow->window()); return true; + case QtWindows::ActivateWindowEvent: + if (platformWindow->testFlag(QWindowsWindow::BlockedByModal)) + if (const QWindow *modalWindow = QGuiApplication::modalWindow()) + QWindowsWindow::baseWindowOf(modalWindow)->alertWindow(); + break; default: break; } diff --git a/src/plugins/platforms/windows/qwindowscursor.cpp b/src/plugins/platforms/windows/qwindowscursor.cpp index 337ba9ab27..ebcf1172db 100644 --- a/src/plugins/platforms/windows/qwindowscursor.cpp +++ b/src/plugins/platforms/windows/qwindowscursor.cpp @@ -369,8 +369,6 @@ QPoint QWindowsCursor::mousePosition() { POINT p; GetCursorPos(&p); - if (QWindowsContext::verboseWindows) - qDebug("%s %ld,%ld", __FUNCTION__, p.x, p.y); return QPoint(p.x, p.y); } diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index 9621846284..a6bde74103 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -116,6 +116,7 @@ typedef struct _COMDLG_FILTERSPEC #define FOS_DEFAULTNOMINIMODE 0x20000000 #define FOS_FORCEPREVIEWPANEON 0x40000000 +#if !defined(__MINGW64_VERSION_MAJOR) || (__MINGW64_VERSION_MAJOR < 2) typedef int GETPROPERTYSTOREFLAGS; #define GPS_DEFAULT 0x00000000 #define GPS_HANDLERPROPERTIESONLY 0x00000001 @@ -126,6 +127,7 @@ typedef int GETPROPERTYSTOREFLAGS; #define GPS_DELAYCREATION 0x00000020 #define GPS_BESTEFFORT 0x00000040 #define GPS_MASK_VALID 0x0000007F +#endif typedef int (QT_WIN_CALLBACK* BFFCALLBACK)(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData); // message from browser @@ -288,7 +290,9 @@ DECLARE_INTERFACE_(IFileOpenDialog, IFileDialog) STDMETHOD(GetSelectedItems)(THIS_ IShellItemArray **ppsai) PURE; }; +#if !defined(__MINGW64_VERSION_MAJOR) || (__MINGW64_VERSION_MAJOR < 2) typedef IUnknown IPropertyStore; +#endif typedef IUnknown IFileOperationProgressSink; DECLARE_INTERFACE_(IFileSaveDialog, IFileDialog) diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp index c1c25dd686..979b2a028b 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.cpp @@ -698,6 +698,32 @@ QStringList QWindowsFontDatabase::fallbacksForFamily(const QString family, const QStringList result = QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script); if (!result.isEmpty()) return result; + + switch (styleHint) { + case QFont::Times: + result << QString::fromLatin1("Times New Roman"); + break; + case QFont::Courier: + result << QString::fromLatin1("Courier New"); + break; + case QFont::Monospace: + result << QString::fromLatin1("Courier New"); + break; + case QFont::Cursive: + result << QString::fromLatin1("Comic Sans MS"); + break; + case QFont::Fantasy: + result << QString::fromLatin1("Impact"); + break; + case QFont::Decorative: + result << QString::fromLatin1("Old English"); + break; + case QFont::Helvetica: + case QFont::System: + default: + result << QString::fromLatin1("Arial"); + } + if (QWindowsContext::verboseFonts) qDebug() << __FUNCTION__ << family << style << styleHint << script << result << m_families.size(); @@ -874,6 +900,11 @@ QString QWindowsFontDatabase::fontDir() const return result; } +bool QWindowsFontDatabase::fontsAlwaysScalable() const +{ + return true; +} + HFONT QWindowsFontDatabase::systemFont() { static const HFONT stock_sysfont = (HFONT)GetStockObject(SYSTEM_FONT); diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase.h b/src/plugins/platforms/windows/qwindowsfontdatabase.h index 2fa615253e..3921992775 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase.h @@ -86,6 +86,8 @@ public: virtual QString fontDir() const; virtual QFont defaultFont() const { return systemDefaultFont(); } + virtual bool fontsAlwaysScalable() const; + static QFont systemDefaultFont(); static QFontEngine *createEngine(int script, const QFontDef &request, diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp index e84f0c7630..246b5b3710 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.cpp @@ -422,6 +422,31 @@ QStringList QWindowsFontDatabaseFT::fallbacksForFamily(const QString family, con QStringList result = QPlatformFontDatabase::fallbacksForFamily(family, style, styleHint, script); if (!result.isEmpty()) return result; + + switch (styleHint) { + case QFont::Times: + result << QString::fromLatin1("Times New Roman"); + break; + case QFont::Courier: + result << QString::fromLatin1("Courier New"); + break; + case QFont::Monospace: + result << QString::fromLatin1("Courier New"); + break; + case QFont::Cursive: + result << QString::fromLatin1("Comic Sans MS"); + break; + case QFont::Fantasy: + result << QString::fromLatin1("Impact"); + break; + case QFont::Decorative: + result << QString::fromLatin1("Old English"); + break; + case QFont::Helvetica: + case QFont::System: + default: + result << QString::fromLatin1("Arial"); + } if (QWindowsContext::verboseFonts) qDebug() << __FUNCTION__ << family << style << styleHint << script << result << m_families; diff --git a/src/plugins/platforms/windows/qwindowsfontengine.cpp b/src/plugins/platforms/windows/qwindowsfontengine.cpp index 007f6d597a..94072622eb 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.cpp +++ b/src/plugins/platforms/windows/qwindowsfontengine.cpp @@ -179,14 +179,14 @@ void QWindowsFontEngine::getCMap() } } - +// ### Qt 5.1: replace with QStringIterator inline unsigned int getChar(const QChar *str, int &i, const int len) { - unsigned int uc = str[i].unicode(); - if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { + uint uc = str[i].unicode(); + if (QChar::isHighSurrogate(uc) && i < len-1) { uint low = str[i+1].unicode(); - if (low >= 0xdc00 && low < 0xe000) { - uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; + if (QChar::isLowSurrogate(low)) { + uc = QChar::surrogateToUcs4(uc, low); ++i; } } @@ -402,7 +402,7 @@ void QWindowsFontEngine::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::Shape if (!ttf) { QChar ch[2] = { ushort(glyph), 0 }; int chrLen = 1; - if (glyph > 0xffff) { + if (QChar::requiresSurrogates(glyph)) { ch[0] = QChar::highSurrogate(glyph); ch[1] = QChar::lowSurrogate(glyph); ++chrLen; diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index c8906bd3c9..4dbb2cf65b 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -295,13 +295,14 @@ QFixed QWindowsFontEngineDirectWrite::emSquareSize() const return QFontEngine::emSquareSize(); } +// ### Qt 5.1: replace with QStringIterator inline unsigned int getChar(const QChar *str, int &i, const int len) { - unsigned int uc = str[i].unicode(); - if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { + uint uc = str[i].unicode(); + if (QChar::isHighSurrogate(uc) && i < len-1) { uint low = str[i+1].unicode(); - if (low >= 0xdc00 && low < 0xe000) { - uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; + if (QChar::isLowSurrogate(low)) { + uc = QChar::surrogateToUcs4(uc, low); ++i; } } diff --git a/src/plugins/platforms/windows/qwindowsintegration.cpp b/src/plugins/platforms/windows/qwindowsintegration.cpp index 47d6a2f11a..d8d04fc1b6 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.cpp +++ b/src/plugins/platforms/windows/qwindowsintegration.cpp @@ -228,8 +228,6 @@ bool QWindowsIntegration::hasCapability(QPlatformIntegration::Capability cap) co QPlatformPixmap *QWindowsIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const { - if (QWindowsContext::verboseIntegration) - qDebug() << __FUNCTION__ << type; return new QRasterPlatformPixmap(type); } @@ -279,17 +277,44 @@ QPlatformOpenGLContext return 0; } +/* Workaround for QTBUG-24205: In 'Auto', pick the FreeType engine for + * QML2 applications. */ + +enum FontDatabaseOption { + FontDatabaseAuto, + FontDatabaseFreeType, + FontDatabaseNative +}; + +static inline FontDatabaseOption fontDatabaseOption(const QObject &nativeInterface) +{ + const QVariant argumentV = nativeInterface.property("fontengine"); + if (argumentV.isValid()) { + const QString argument = argumentV.toString(); + if (argument == QLatin1String("freetype")) + return FontDatabaseFreeType; + if (argument == QLatin1String("native")) + return FontDatabaseNative; + } + return FontDatabaseAuto; +} + QPlatformFontDatabase *QWindowsIntegration::fontDatabase() const { if (!d->m_fontDatabase) { -#ifndef QT_NO_FREETYPE - const QVariant argument = d->m_nativeInterface.property("fontengine"); - if (argument.isValid() && argument.toString() == QLatin1String("freetype")) - d->m_fontDatabase = new QWindowsFontDatabaseFT(); - else - d->m_fontDatabase = new QWindowsFontDatabase(); -#else +#ifdef QT_NO_FREETYPE d->m_fontDatabase = new QWindowsFontDatabase(); +#else + FontDatabaseOption option = fontDatabaseOption(d->m_nativeInterface); + if (option == FontDatabaseAuto) { + option = QCoreApplication::applicationName() == QStringLiteral("QtQmlViewer") ? + FontDatabaseFreeType : FontDatabaseNative; + } + if (option == FontDatabaseFreeType) { + d->m_fontDatabase = new QWindowsFontDatabaseFT; + } else { + d->m_fontDatabase = new QWindowsFontDatabase; + } #endif } return d->m_fontDatabase; diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp index 6ff854805c..38a44e2b5a 100644 --- a/src/plugins/platforms/windows/qwindowswindow.cpp +++ b/src/plugins/platforms/windows/qwindowswindow.cpp @@ -704,8 +704,11 @@ void QWindowsWindow::setVisible(bool visible) if (m_data.hwnd) { if (visible) { show_sys(); + QWindowSystemInterface::handleSynchronousExposeEvent(window(), + QRect(QPoint(), geometry().size())); } else { hide_sys(); + QWindowSystemInterface::handleSynchronousExposeEvent(window(), QRegion()); } } } @@ -1191,6 +1194,22 @@ void QWindowsWindow::lower() SetWindowPos(m_data.hwnd, HWND_BOTTOM, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); } +void QWindowsWindow::windowEvent(QEvent *event) +{ + switch (event->type()) { + case QEvent::WindowBlocked: // Blocked by another modal window. + setEnabled(false); + setFlag(BlockedByModal); + break; + case QEvent::WindowUnblocked: + setEnabled(true); + clearFlag(BlockedByModal); + break; + default: + break; + } +} + void QWindowsWindow::propagateSizeHints() { if (QWindowsContext::verboseWindows) @@ -1351,6 +1370,50 @@ QWindowsWindow *QWindowsWindow::childAt(const QPoint &clientPoint, unsigned cwex return 0; } +void QWindowsWindow::alertWindow(int durationMs) +{ + DWORD timeOutMs = GetCaretBlinkTime(); + if (!timeOutMs || timeOutMs == INFINITE) + timeOutMs = 250; + + FLASHWINFO info; + info.cbSize = sizeof(info); + info.hwnd = m_data.hwnd; + info.dwFlags = FLASHW_TRAY; + info.dwTimeout = timeOutMs; + info.uCount = durationMs == 0 ? 10 : durationMs / timeOutMs; + FlashWindowEx(&info); +} + +void QWindowsWindow::stopAlertWindow() +{ + FLASHWINFO info; + info.cbSize = sizeof(info); + info.hwnd = m_data.hwnd; + info.dwFlags = FLASHW_STOP; + info.dwTimeout = 0; + info.uCount = 0; + FlashWindowEx(&info); +} + +bool QWindowsWindow::isEnabled() const +{ + return (style() & WS_DISABLED) == 0; +} + +void QWindowsWindow::setEnabled(bool enabled) +{ + const unsigned oldStyle = style(); + unsigned newStyle = oldStyle; + if (enabled) { + newStyle &= ~WS_DISABLED; + } else { + newStyle |= WS_DISABLED; + } + if (newStyle != oldStyle) + setStyle(newStyle); +} + QByteArray QWindowsWindow::debugWindowFlags(Qt::WindowFlags wf) { const int iwf = int(wf); diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index e3336d1c3a..badc229718 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -100,7 +100,8 @@ public: FrameDirty = 0x4, //! Frame outdated by setStyle, recalculate in next query. OpenGLSurface = 0x10, OpenGLDoubleBuffered = 0x20, - OpenGlPixelFormatInitialized = 0x40 + OpenGlPixelFormatInitialized = 0x40, + BlockedByModal = 0x80 }; struct WindowData @@ -137,6 +138,8 @@ public: virtual void raise(); virtual void lower(); + void windowEvent(QEvent *event); + virtual void propagateSizeHints(); virtual QMargins frameMargins() const; @@ -189,6 +192,12 @@ public: inline void setFlag(unsigned f) const { m_flags |= f; } inline void clearFlag(unsigned f) const { m_flags &= ~f; } + void setEnabled(bool enabled); + bool isEnabled() const; + + void alertWindow(int durationMs = 0); + void stopAlertWindow(); + private: inline void show_sys() const; inline void hide_sys() const; diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index f328c2f2f8..6996c87f3f 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -149,6 +149,7 @@ QXcbWindow::QXcbWindow(QWindow *window) #if defined(XCB_USE_EGL) , m_eglSurface(0) #endif + , m_lastWindowStateEvent(-1) { m_screen = static_cast<QXcbScreen *>(window->screen()->handle()); @@ -638,29 +639,9 @@ static void setMotifWmHints(QXcbConnection *c, xcb_window_t window, const QtMoti } } -void QXcbWindow::printNetWmState(const QVector<xcb_atom_t> &state) +QXcbWindow::NetWmStates QXcbWindow::netWmStates() { - printf("_NET_WM_STATE (%d): ", state.size()); - for (int i = 0; i < state.size(); ++i) { -#define CHECK_WM_STATE(state_atom) \ - if (state.at(i) == atom(QXcbAtom::state_atom))\ - printf(#state_atom " "); - CHECK_WM_STATE(_NET_WM_STATE_ABOVE) - CHECK_WM_STATE(_NET_WM_STATE_BELOW) - CHECK_WM_STATE(_NET_WM_STATE_FULLSCREEN) - CHECK_WM_STATE(_NET_WM_STATE_MAXIMIZED_HORZ) - CHECK_WM_STATE(_NET_WM_STATE_MAXIMIZED_VERT) - CHECK_WM_STATE(_NET_WM_STATE_MODAL) - CHECK_WM_STATE(_NET_WM_STATE_STAYS_ON_TOP) - CHECK_WM_STATE(_NET_WM_STATE_DEMANDS_ATTENTION) -#undef CHECK_WM_STATE - } - printf("\n"); -} - -QVector<xcb_atom_t> QXcbWindow::getNetWmState() -{ - QVector<xcb_atom_t> result; + NetWmStates result(0); xcb_get_property_cookie_t get_cookie = xcb_get_property_unchecked(xcb_connection(), 0, m_window, atom(QXcbAtom::_NET_WM_STATE), @@ -670,15 +651,24 @@ QVector<xcb_atom_t> QXcbWindow::getNetWmState() xcb_get_property_reply(xcb_connection(), get_cookie, NULL); if (reply && reply->format == 32 && reply->type == XCB_ATOM_ATOM) { - result.resize(reply->length); - - memcpy(result.data(), xcb_get_property_value(reply), reply->length * sizeof(xcb_atom_t)); - -#ifdef NET_WM_STATE_DEBUG - printf("getting net wm state (%x)\n", m_window); - printNetWmState(result); -#endif - + const xcb_atom_t *states = static_cast<const xcb_atom_t *>(xcb_get_property_value(reply)); + const xcb_atom_t *statesEnd = states + reply->length; + if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_ABOVE))) + result |= NetWmStateAbove; + if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_BELOW))) + result |= NetWmStateBelow; + if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN))) + result |= NetWmStateFullScreen; + if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ))) + result |= NetWmStateMaximizedHorz; + if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT))) + result |= NetWmStateMaximizedVert; + if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_MODAL))) + result |= NetWmStateModal; + if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP))) + result |= NetWmStateStaysOnTop; + if (statesEnd != qFind(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION))) + result |= NetWmStateDemandsAttention; free(reply); } else { #ifdef NET_WM_STATE_DEBUG @@ -689,8 +679,26 @@ QVector<xcb_atom_t> QXcbWindow::getNetWmState() return result; } -void QXcbWindow::setNetWmState(const QVector<xcb_atom_t> &atoms) +void QXcbWindow::setNetWmStates(NetWmStates states) { + QVector<xcb_atom_t> atoms; + if (states & NetWmStateAbove) + atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE)); + if (states & NetWmStateBelow) + atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_BELOW)); + if (states & NetWmStateFullScreen) + atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)); + if (states & NetWmStateMaximizedHorz) + atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)); + if (states & NetWmStateMaximizedVert) + atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT)); + if (states & NetWmStateModal) + atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_MODAL)); + if (states & NetWmStateStaysOnTop) + atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP)); + if (states & NetWmStateDemandsAttention) + atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)); + if (atoms.isEmpty()) { Q_XCB_CALL(xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_NET_WM_STATE))); } else { @@ -701,7 +709,6 @@ void QXcbWindow::setNetWmState(const QVector<xcb_atom_t> &atoms) xcb_flush(xcb_connection()); } - Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags) { Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask)); @@ -968,30 +975,28 @@ void QXcbWindow::updateMotifWmHintsBeforeMap() void QXcbWindow::updateNetWmStateBeforeMap() { - QVector<xcb_atom_t> netWmState; + NetWmStates states(0); - Qt::WindowFlags flags = window()->windowFlags(); + const Qt::WindowFlags flags = window()->windowFlags(); if (flags & Qt::WindowStaysOnTopHint) { - netWmState.append(atom(QXcbAtom::_NET_WM_STATE_ABOVE)); - netWmState.append(atom(QXcbAtom::_NET_WM_STATE_STAYS_ON_TOP)); + states |= NetWmStateAbove; + states |= NetWmStateStaysOnTop; } else if (flags & Qt::WindowStaysOnBottomHint) { - netWmState.append(atom(QXcbAtom::_NET_WM_STATE_BELOW)); + states |= NetWmStateBelow; } - if (window()->windowState() & Qt::WindowFullScreen) { - netWmState.append(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)); - } + if (window()->windowState() & Qt::WindowFullScreen) + states |= NetWmStateFullScreen; if (window()->windowState() & Qt::WindowMaximized) { - netWmState.append(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)); - netWmState.append(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT)); + states |= NetWmStateMaximizedHorz; + states |= NetWmStateMaximizedVert; } - if (window()->windowModality() != Qt::NonModal) { - netWmState.append(atom(QXcbAtom::_NET_WM_STATE_MODAL)); - } + if (window()->windowModality() != Qt::NonModal) + states |= NetWmStateModal; - setNetWmState(netWmState); + setNetWmStates(states); } void QXcbWindow::updateNetWmUserTime(xcb_timestamp_t timestamp) @@ -1469,41 +1474,42 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev { connection()->setTime(event->time); - bool propertyDeleted = event->state == XCB_PROPERTY_DELETE; + const bool propertyDeleted = event->state == XCB_PROPERTY_DELETE; + const xcb_atom_t netWmStateAtom = atom(QXcbAtom::_NET_WM_STATE); + const xcb_atom_t wmStateAtom = atom(QXcbAtom::WM_STATE); - if (event->atom == atom(QXcbAtom::_NET_WM_STATE) || event->atom == atom(QXcbAtom::WM_STATE)) { + if (event->atom == netWmStateAtom || event->atom == wmStateAtom) { if (propertyDeleted) return; - xcb_get_property_cookie_t get_cookie = - xcb_get_property(xcb_connection(), 0, m_window, atom(QXcbAtom::WM_STATE), - XCB_ATOM_ANY, 0, 1024); + Qt::WindowState newState = Qt::WindowNoState; + if (event->atom == wmStateAtom) { // WM_STATE: Quick check for 'Minimize'. + const xcb_get_property_cookie_t get_cookie = + xcb_get_property(xcb_connection(), 0, m_window, wmStateAtom, + XCB_ATOM_ANY, 0, 1024); - xcb_get_property_reply_t *reply = - xcb_get_property_reply(xcb_connection(), get_cookie, NULL); + xcb_get_property_reply_t *reply = + xcb_get_property_reply(xcb_connection(), get_cookie, NULL); - xcb_atom_t wm_state = XCB_WM_STATE_WITHDRAWN; - if (reply && reply->format == 32 && reply->type == atom(QXcbAtom::WM_STATE)) { - if (reply->length != 0) - wm_state = ((long *)xcb_get_property_value(reply))[0]; - free(reply); + if (reply && reply->format == 32 && reply->type == wmStateAtom) { + const long *data = (const long *)xcb_get_property_value(reply); + if (reply->length != 0 && XCB_WM_STATE_ICONIC == data[0]) + newState = Qt::WindowMinimized; + free(reply); + } + } // WM_STATE: Quick check for 'Minimize'. + if (newState != Qt::WindowMinimized) { // Something else changed, get _NET_WM_STATE. + const NetWmStates states = netWmStates(); + if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert)) + newState = Qt::WindowMaximized; + else if (states & NetWmStateFullScreen) + newState = Qt::WindowFullScreen; + } + // Send Window state, compress events in case other flags (modality, etc) are changed. + if (m_lastWindowStateEvent != newState) { + QWindowSystemInterface::handleWindowStateChanged(window(), newState); + m_lastWindowStateEvent = newState; } - - QVector<xcb_atom_t> netWmState = getNetWmState(); - - bool maximized = netWmState.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)) - && netWmState.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_VERT)); - bool fullscreen = netWmState.contains(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)); - - Qt::WindowState state = Qt::WindowNoState; - if (wm_state == XCB_WM_STATE_ICONIC) - state = Qt::WindowMinimized; - else if (maximized) - state = Qt::WindowMaximized; - else if (fullscreen) - state = Qt::WindowFullScreen; - - QWindowSystemInterface::handleWindowStateChanged(window(), state); } } diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 37e0bdb8d3..c8999de83d 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -59,6 +59,19 @@ class QXcbEGLSurface; class QXcbWindow : public QXcbObject, public QPlatformWindow { public: + enum NetWmState { + NetWmStateAbove = 0x1, + NetWmStateBelow = 0x2, + NetWmStateFullScreen = 0x4, + NetWmStateMaximizedHorz = 0x8, + NetWmStateMaximizedVert = 0x10, + NetWmStateModal = 0x20, + NetWmStateStaysOnTop = 0x40, + NetWmStateDemandsAttention = 0x80 + }; + + Q_DECLARE_FLAGS(NetWmStates, NetWmState) + QXcbWindow(QWindow *window); ~QXcbWindow(); @@ -123,9 +136,8 @@ public: private: void changeNetWmState(bool set, xcb_atom_t one, xcb_atom_t two = 0); - QVector<xcb_atom_t> getNetWmState(); - void setNetWmState(const QVector<xcb_atom_t> &atoms); - void printNetWmState(const QVector<xcb_atom_t> &state); + NetWmStates netWmStates(); + void setNetWmStates(NetWmStates); void setNetWmWindowFlags(Qt::WindowFlags flags); void setMotifWindowFlags(Qt::WindowFlags flags); @@ -173,6 +185,7 @@ private: QRegion m_exposeRegion; xcb_visualid_t m_visualId; + int m_lastWindowStateEvent; }; QT_END_NAMESPACE |