diff options
Diffstat (limited to 'src/plugins/platforms')
150 files changed, 15474 insertions, 2048 deletions
diff --git a/src/plugins/platforms/cocoa/main.mm b/src/plugins/platforms/cocoa/main.mm index 8be8883..da7af3f 100644 --- a/src/plugins/platforms/cocoa/main.mm +++ b/src/plugins/platforms/cocoa/main.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h index 47b94d1..6e41e9a 100644 --- a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h +++ b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm index 9a18fe2..35750cd 100644 --- a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm +++ b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/cocoa/qcocoaeventloopintegration.h b/src/plugins/platforms/cocoa/qcocoaeventloopintegration.h index 87998e3..81e272e 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventloopintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaeventloopintegration.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/cocoa/qcocoaeventloopintegration.mm b/src/plugins/platforms/cocoa/qcocoaeventloopintegration.mm index 844751c..885916e 100644 --- a/src/plugins/platforms/cocoa/qcocoaeventloopintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaeventloopintegration.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h index e7ecf2a..2a04e8c 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.h +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -75,6 +75,7 @@ public: QCocoaIntegration(); ~QCocoaIntegration(); + bool hasCapability(QPlatformIntegration::Capability cap) const; QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const; QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm index 28e894c..7c4319c 100644 --- a/src/plugins/platforms/cocoa/qcocoaintegration.mm +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -94,9 +94,19 @@ QCocoaIntegration::~QCocoaIntegration() delete mPool; } +bool QCocoaIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: return true; + default: return QPlatformIntegration::hasCapability(cap); + } +} + + + QPixmapData *QCocoaIntegration::createPixmapData(QPixmapData::PixelType type) const { - return new QRasterPixmapData(type); + return new QRasterPixmapData(type); } QPlatformWindow *QCocoaIntegration::createPlatformWindow(QWidget *widget, WId winId) const diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h index 660e9f8..b71879d 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.h +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm index 4e233ee..aa54fe9 100644 --- a/src/plugins/platforms/cocoa/qcocoawindow.mm +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/platforms/cocoa/qcocoawindowsurface.h b/src/plugins/platforms/cocoa/qcocoawindowsurface.h index 35f4064..5ae7be1 100644 --- a/src/plugins/platforms/cocoa/qcocoawindowsurface.h +++ b/src/plugins/platforms/cocoa/qcocoawindowsurface.h @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/platforms/cocoa/qcocoawindowsurface.mm b/src/plugins/platforms/cocoa/qcocoawindowsurface.mm index 443a486..ecf6879 100644 --- a/src/plugins/platforms/cocoa/qcocoawindowsurface.mm +++ b/src/plugins/platforms/cocoa/qcocoawindowsurface.mm @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h index 0523725..fc946e2 100644 --- a/src/plugins/platforms/cocoa/qnsview.h +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm index 60de6ba..6fda27b 100644 --- a/src/plugins/platforms/cocoa/qnsview.mm +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.h b/src/plugins/platforms/cocoa/qnswindowdelegate.h index 9fc1d63..f4dcec7 100644 --- a/src/plugins/platforms/cocoa/qnswindowdelegate.h +++ b/src/plugins/platforms/cocoa/qnswindowdelegate.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.mm b/src/plugins/platforms/cocoa/qnswindowdelegate.mm index c04602b..58dffb7 100644 --- a/src/plugins/platforms/cocoa/qnswindowdelegate.mm +++ b/src/plugins/platforms/cocoa/qnswindowdelegate.mm @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/directfb/main.cpp b/src/plugins/platforms/directfb/main.cpp index f4ece32..d9caa70 100644 --- a/src/plugins/platforms/directfb/main.cpp +++ b/src/plugins/platforms/directfb/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/eglconvenience/qeglconvenience.cpp b/src/plugins/platforms/eglconvenience/qeglconvenience.cpp index ae1ed22..ec4577a 100644 --- a/src/plugins/platforms/eglconvenience/qeglconvenience.cpp +++ b/src/plugins/platforms/eglconvenience/qeglconvenience.cpp @@ -206,7 +206,7 @@ bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes) return false; } -EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format) +EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format, bool highestPixelFormat) { EGLConfig cfg = 0; QVector<EGLint> configureAttributes = q_createConfigAttributesFromFormat(format); @@ -227,14 +227,14 @@ EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformW if (!eglChooseConfig(display, configureAttributes.constData(), 0, 0, &matching) || !matching) continue; -// // If we want the best pixel format, then return the first -// // matching configuration. -// if (match == QEgl::BestPixelFormat) { -// eglChooseConfig(display, props.properties(), &cfg, 1, &matching); -// if (matching < 1) -// continue; -// return cfg; -// } + // If we want the best pixel format, then return the first + // matching configuration. + if (highestPixelFormat) { + eglChooseConfig(display, configureAttributes.constData(), &cfg, 1, &matching); + if (matching < 1) + continue; + return cfg; + } // Fetch all of the matching configurations and find the // first that matches the pixel format we wanted. @@ -313,4 +313,12 @@ QPlatformWindowFormat qt_qPlatformWindowFormatFromConfig(EGLDisplay display, con return format; } +bool q_hasEglExtension(EGLDisplay display, const char* extensionName) +{ + QList<QByteArray> extensions = + QByteArray(reinterpret_cast<const char *> + (eglQueryString(display, EGL_EXTENSIONS))).split(' '); + return extensions.contains(extensionName); +} + QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglconvenience/qeglconvenience.h b/src/plugins/platforms/eglconvenience/qeglconvenience.h index afa69ce..8668095 100644 --- a/src/plugins/platforms/eglconvenience/qeglconvenience.h +++ b/src/plugins/platforms/eglconvenience/qeglconvenience.h @@ -46,13 +46,18 @@ #include <QtGui/QPlatformWindowFormat> #include <QtCore/QVector> +#ifdef Q_PLATFORM_WAYLAND +#include "qwaylandinclude.h" +#else #include <EGL/egl.h> +#endif QT_BEGIN_NAMESPACE QVector<EGLint> q_createConfigAttributesFromFormat(const QPlatformWindowFormat &format); bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes); -EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format); +EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format, bool highestPixelFormat = false); QPlatformWindowFormat qt_qPlatformWindowFormatFromConfig(EGLDisplay display, const EGLConfig config); +bool q_hasEglExtension(EGLDisplay display,const char* extensionName); QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp b/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp index 126dc74..9a2bc61 100644 --- a/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp +++ b/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp @@ -155,3 +155,8 @@ QPlatformWindowFormat QEGLPlatformContext::platformWindowFormat() const { return m_windowFormat; } + +EGLContext QEGLPlatformContext::eglContext() const +{ + return m_eglContext; +} diff --git a/src/plugins/platforms/eglconvenience/qeglplatformcontext.h b/src/plugins/platforms/eglconvenience/qeglplatformcontext.h index 4b98619..d688660 100644 --- a/src/plugins/platforms/eglconvenience/qeglplatformcontext.h +++ b/src/plugins/platforms/eglconvenience/qeglplatformcontext.h @@ -59,6 +59,8 @@ public: void makeDefaultSharedContext(); QPlatformWindowFormat platformWindowFormat() const; + + EGLContext eglContext() const; private: EGLContext m_eglContext; EGLDisplay m_eglDisplay; diff --git a/src/plugins/platforms/eglconvenience/qxlibeglintegration.cpp b/src/plugins/platforms/eglconvenience/qxlibeglintegration.cpp new file mode 100644 index 0000000..7f296c5 --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qxlibeglintegration.cpp @@ -0,0 +1,186 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxlibeglintegration.h" + +static int countBits(unsigned long mask) +{ + int count = 0; + while (mask != 0) { + if (mask & 1) + ++count; + mask >>= 1; + } + return count; +} + +VisualID QXlibEglIntegration::getCompatibleVisualId(Display *display, EGLConfig config) +{ + VisualID visualId = 0; + EGLint eglValue = 0; + + EGLDisplay eglDisplay = eglGetDisplay(display); + + EGLint configRedSize = 0; + eglGetConfigAttrib(eglDisplay, config, EGL_RED_SIZE, &configRedSize); + + EGLint configGreenSize = 0; + eglGetConfigAttrib(eglDisplay, config, EGL_GREEN_SIZE, &configGreenSize); + + EGLint configBlueSize = 0; + eglGetConfigAttrib(eglDisplay, config, EGL_BLUE_SIZE, &configBlueSize); + + EGLint configAlphaSize = 0; + eglGetConfigAttrib(eglDisplay, config, EGL_ALPHA_SIZE, &configAlphaSize); + + eglGetConfigAttrib(eglDisplay, config, EGL_CONFIG_ID, &eglValue); + int configId = eglValue; + + // See if EGL provided a valid VisualID: + eglGetConfigAttrib(eglDisplay, config, EGL_NATIVE_VISUAL_ID, &eglValue); + visualId = (VisualID)eglValue; + if (visualId) { + // EGL has suggested a visual id, so get the rest of the visual info for that id: + XVisualInfo visualInfoTemplate; + memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); + visualInfoTemplate.visualid = visualId; + + XVisualInfo *chosenVisualInfo; + int matchingCount = 0; + chosenVisualInfo = XGetVisualInfo(display, VisualIDMask, &visualInfoTemplate, &matchingCount); + if (chosenVisualInfo) { + // Skip size checks if implementation supports non-matching visual + // and config (http://bugreports.qt.nokia.com/browse/QTBUG-9444). + if (q_hasEglExtension(eglDisplay,"EGL_NV_post_convert_rounding")) { + XFree(chosenVisualInfo); + return visualId; + } + + int visualRedSize = countBits(chosenVisualInfo->red_mask); + int visualGreenSize = countBits(chosenVisualInfo->green_mask); + int visualBlueSize = countBits(chosenVisualInfo->blue_mask); + int visualAlphaSize = -1; // Need XRender to tell us the alpha channel size + + bool visualMatchesConfig = false; + if ( visualRedSize == configRedSize && + visualGreenSize == configGreenSize && + visualBlueSize == configBlueSize ) + { + // We need XRender to check the alpha channel size of the visual. If we don't have + // the alpha size, we don't check it against the EGL config's alpha size. + if (visualAlphaSize >= 0) + visualMatchesConfig = visualAlphaSize == configAlphaSize; + else + visualMatchesConfig = true; + } + + if (!visualMatchesConfig) { + if (visualAlphaSize >= 0) { + qWarning("Warning: EGL suggested using X Visual ID %d (ARGB%d%d%d%d) for EGL config %d (ARGB%d%d%d%d), but this is incompatable", + (int)visualId, visualAlphaSize, visualRedSize, visualGreenSize, visualBlueSize, + configId, configAlphaSize, configRedSize, configGreenSize, configBlueSize); + } else { + qWarning("Warning: EGL suggested using X Visual ID %d (RGB%d%d%d) for EGL config %d (RGB%d%d%d), but this is incompatable", + (int)visualId, visualRedSize, visualGreenSize, visualBlueSize, + configId, configRedSize, configGreenSize, configBlueSize); + } + visualId = 0; + } + } else { + qWarning("Warning: EGL suggested using X Visual ID %d for EGL config %d, but that isn't a valid ID", + (int)visualId, configId); + visualId = 0; + } + XFree(chosenVisualInfo); + } +#ifdef QT_DEBUG_X11_VISUAL_SELECTION + else + qDebug("EGL did not suggest a VisualID (EGL_NATIVE_VISUAL_ID was zero) for EGLConfig %d", configId); +#endif + + if (visualId) { +#ifdef QT_DEBUG_X11_VISUAL_SELECTION + if (configAlphaSize > 0) + qDebug("Using ARGB Visual ID %d provided by EGL for config %d", (int)visualId, configId); + else + qDebug("Using Opaque Visual ID %d provided by EGL for config %d", (int)visualId, configId); +#endif + return visualId; + } + + // Finally, try to + // use XGetVisualInfo and only use the bit depths to match on: + if (!visualId) { + XVisualInfo visualInfoTemplate; + memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); + XVisualInfo *matchingVisuals; + int matchingCount = 0; + + visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize + configAlphaSize; + matchingVisuals = XGetVisualInfo(display, + VisualDepthMask, + &visualInfoTemplate, + &matchingCount); + if (!matchingVisuals) { + // Try again without taking the alpha channel into account: + visualInfoTemplate.depth = configRedSize + configGreenSize + configBlueSize; + matchingVisuals = XGetVisualInfo(display, + VisualDepthMask, + &visualInfoTemplate, + &matchingCount); + } + + if (matchingVisuals) { + visualId = matchingVisuals[0].visualid; + XFree(matchingVisuals); + } + } + + if (visualId) { +#ifdef QT_DEBUG_X11_VISUAL_SELECTION + qDebug("Using Visual ID %d provided by XGetVisualInfo for EGL config %d", (int)visualId, configId); +#endif + return visualId; + } + + qWarning("Unable to find an X11 visual which matches EGL config %d", configId); + return (VisualID)0; +} diff --git a/src/plugins/platforms/eglconvenience/qxlibeglintegration.h b/src/plugins/platforms/eglconvenience/qxlibeglintegration.h new file mode 100644 index 0000000..51996da --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qxlibeglintegration.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTLITEEGLINTEGRATION_H +#define QTESTLITEEGLINTEGRATION_H + +#include "qeglconvenience.h" + +class QXlibEglIntegration +{ +public: + static VisualID getCompatibleVisualId(Display *display, EGLConfig config); +}; + +#endif // QTESTLITEEGLINTEGRATION_H diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp index f4a97fc..78981f9 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -65,6 +65,14 @@ QEglFSIntegration::QEglFSIntegration() #endif } +bool QEglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: return true; + default: return QPlatformIntegration::hasCapability(cap); + } +} + QPixmapData *QEglFSIntegration::createPixmapData(QPixmapData::PixelType type) const { #ifdef QEGL_EXTRA_DEBUG diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h index c199653..65b834f 100644 --- a/src/plugins/platforms/eglfs/qeglfsintegration.h +++ b/src/plugins/platforms/eglfs/qeglfsintegration.h @@ -56,6 +56,7 @@ class QEglFSIntegration : public QPlatformIntegration public: QEglFSIntegration(); + bool hasCapability(QPlatformIntegration::Capability cap) const; QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp index 19238b1..2ef12aa 100644 --- a/src/plugins/platforms/eglfs/qeglfswindow.cpp +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -62,6 +62,9 @@ void QEglFSWindow::setGeometry(const QRect &) QRect rect(m_screen->availableGeometry()); QWindowSystemInterface::handleGeometryChange(this->widget(), rect); + // Since toplevels are fullscreen, propegate the screen size back to the widget + widget()->setGeometry(rect); + QPlatformWindow::setGeometry(rect); } diff --git a/src/plugins/platforms/externalplugin.pri b/src/plugins/platforms/externalplugin.pri new file mode 100644 index 0000000..54da4d9 --- /dev/null +++ b/src/plugins/platforms/externalplugin.pri @@ -0,0 +1,29 @@ +# +# Lighthouse now has preliminarily support for building and +# loading platform plugins from outside the Qt source/build +# tree. +# +# 1) Building external plugins: +# Set QTDIR to the Qt build directory, copy this file to +# the plugin source repository and include it at the top +# of the plugin's pro file. Use QT_SOURCE_TREE if you +# want to pull in source code from Qt: +# +# include($$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri) +# +# 2) Loading external plugins: +# Specify the path to the directory containing the +# plugin on the command line, in addition to the +# platform name. +# +# ./wiggly -platformPluginPath /path/to/myPlugin -platform gullfaksA +# + +!exists($$(QTDIR)/.qmake.cache) { + error("Please set QTDIR to the Qt build directory") +} + +QT_SOURCE_TREE = $$fromfile($$(QTDIR)/.qmake.cache,QT_SOURCE_TREE) +QT_BUILD_TREE = $$fromfile($$(QTDIR)/.qmake.cache,QT_BUILD_TREE) + +include($$QT_SOURCE_TREE/src/plugins/qpluginbase.pri) diff --git a/src/plugins/platforms/fontdatabases/basicunix/basicunix.pri b/src/plugins/platforms/fontdatabases/basicunix/basicunix.pri index 21aedba..da4698d 100644 --- a/src/plugins/platforms/fontdatabases/basicunix/basicunix.pri +++ b/src/plugins/platforms/fontdatabases/basicunix/basicunix.pri @@ -73,7 +73,11 @@ contains(QT_CONFIG, freetype) { $$QT_SOURCE_TREE/src/3rdparty/freetype/src \ $$QT_SOURCE_TREE/src/3rdparty/freetype/include - DEFINES += FT2_BUILD_LIBRARY FT_CONFIG_OPTION_SYSTEM_ZLIB + DEFINES += FT2_BUILD_LIBRARY + contains(QT_CONFIG, system-zlib) { + DEFINES += FT_CONFIG_OPTION_SYSTEM_ZLIB + } + } else:contains(QT_CONFIG, system-freetype) { # pull in the proper freetype2 include directory include($$QT_SOURCE_TREE/config.tests/unix/freetype/freetype.pri) diff --git a/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp index 3534044..2a3fd5a 100644 --- a/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp +++ b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -274,6 +274,25 @@ static const char *openType[] = { "nko " // N'Ko }; +static const char *getFcFamilyForStyleHint(const QFont::StyleHint style) +{ + const char *stylehint = 0; + switch (style) { + case QFont::SansSerif: + stylehint = "sans-serif"; + break; + case QFont::Serif: + stylehint = "serif"; + break; + case QFont::TypeWriter: + stylehint = "monospace"; + break; + default: + break; + } + return stylehint; +} + void QFontconfigDatabase::populateFontDatabase() { FcFontSet *fonts; @@ -522,7 +541,7 @@ QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables:: return engine; } -QStringList QFontconfigDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const +QStringList QFontconfigDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const { QStringList fallbackFamilies; FcPattern *pattern = FcPatternCreate(); @@ -550,6 +569,12 @@ QStringList QFontconfigDatabase::fallbacksForFamily(const QString family, const FcLangSetDestroy(ls); } + const char *stylehint = getFcFamilyForStyleHint(styleHint); + if (stylehint) { + value.u.s = (const FcChar8 *)stylehint; + FcPatternAddWeak(pattern, FC_FAMILY, value, FcTrue); + } + FcConfigSubstitute(0, pattern, FcMatchPattern); FcConfigSubstitute(0, pattern, FcMatchFont); diff --git a/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h index 767c7ea..ee441f7 100644 --- a/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h +++ b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h @@ -50,7 +50,7 @@ class QFontconfigDatabase : public QBasicUnixFontDatabase public: void populateFontDatabase(); QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle); - QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const; + QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QFont::StyleHint &styleHint, const QUnicodeTables::Script &script) const; }; #endif // QFONTCONFIGDATABASE_H diff --git a/src/plugins/platforms/linuxfb/main.cpp b/src/plugins/platforms/linuxfb/main.cpp index c5f7fe0..fb14ef4 100644 --- a/src/plugins/platforms/linuxfb/main.cpp +++ b/src/plugins/platforms/linuxfb/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp index aa1d401..a088a31 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -782,6 +782,15 @@ void QLinuxFbIntegration::blank(bool on) d_ptr->blank = on; } +bool QLinuxFbIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: return true; + default: return QPlatformIntegration::hasCapability(cap); + } +} + + QPixmapData *QLinuxFbIntegration::createPixmapData(QPixmapData::PixelType type) const { return new QRasterPixmapData(type); diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h index e93495c..f361843 100644 --- a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -77,6 +77,8 @@ public: QLinuxFbIntegration(); ~QLinuxFbIntegration(); + bool hasCapability(QPlatformIntegration::Capability cap) const; + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QPlatformWindow *createPlatformWindow(QWidget *widget, WId WinId) const; QWindowSurface *createWindowSurface(QWidget *widget, WId WinId) const; diff --git a/src/plugins/platforms/minimal/qminimalintegration.cpp b/src/plugins/platforms/minimal/qminimalintegration.cpp index f72fadb..3a545e4 100644 --- a/src/plugins/platforms/minimal/qminimalintegration.cpp +++ b/src/plugins/platforms/minimal/qminimalintegration.cpp @@ -56,6 +56,14 @@ QMinimalIntegration::QMinimalIntegration() mScreens.append(mPrimaryScreen); } +bool QMinimalIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: return true; + default: return QPlatformIntegration::hasCapability(cap); + } +} + QPixmapData *QMinimalIntegration::createPixmapData(QPixmapData::PixelType type) const { return new QRasterPixmapData(type); diff --git a/src/plugins/platforms/minimal/qminimalintegration.h b/src/plugins/platforms/minimal/qminimalintegration.h index 133feee..5f93443 100644 --- a/src/plugins/platforms/minimal/qminimalintegration.h +++ b/src/plugins/platforms/minimal/qminimalintegration.h @@ -69,6 +69,8 @@ class QMinimalIntegration : public QPlatformIntegration public: QMinimalIntegration(); + bool hasCapability(QPlatformIntegration::Capability cap) const; + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; diff --git a/src/plugins/platforms/openkode/qopenkodeintegration.cpp b/src/plugins/platforms/openkode/qopenkodeintegration.cpp index 5176397..35e744be 100644 --- a/src/plugins/platforms/openkode/qopenkodeintegration.cpp +++ b/src/plugins/platforms/openkode/qopenkodeintegration.cpp @@ -185,6 +185,15 @@ QOpenKODEIntegration::~QOpenKODEIntegration() delete mFontDb; } + +bool QOpenKODEIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: return true; + default: return QPlatformIntegration::hasCapability(cap); + } +} + QPixmapData *QOpenKODEIntegration::createPixmapData(QPixmapData::PixelType type) const { return new QGLPixmapData(type); diff --git a/src/plugins/platforms/openkode/qopenkodeintegration.h b/src/plugins/platforms/openkode/qopenkodeintegration.h index ade3366..7582e60 100644 --- a/src/plugins/platforms/openkode/qopenkodeintegration.h +++ b/src/plugins/platforms/openkode/qopenkodeintegration.h @@ -90,6 +90,8 @@ public: QOpenKODEIntegration(); ~QOpenKODEIntegration(); + bool hasCapability(QPlatformIntegration::Capability cap) const; + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const; QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; diff --git a/src/plugins/platforms/openvglite/main.cpp b/src/plugins/platforms/openvglite/main.cpp index dc0b4a8..97321fa 100644 --- a/src/plugins/platforms/openvglite/main.cpp +++ b/src/plugins/platforms/openvglite/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/openvglite/qgraphicssystem_vglite.cpp b/src/plugins/platforms/openvglite/qgraphicssystem_vglite.cpp index 41b2303..5f7106e 100644 --- a/src/plugins/platforms/openvglite/qgraphicssystem_vglite.cpp +++ b/src/plugins/platforms/openvglite/qgraphicssystem_vglite.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/openvglite/qgraphicssystem_vglite.h b/src/plugins/platforms/openvglite/qgraphicssystem_vglite.h index 512793d..9d45bf9 100644 --- a/src/plugins/platforms/openvglite/qgraphicssystem_vglite.h +++ b/src/plugins/platforms/openvglite/qgraphicssystem_vglite.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/openvglite/qwindowsurface_vglite.cpp b/src/plugins/platforms/openvglite/qwindowsurface_vglite.cpp index c73e35a..8432ad6 100644 --- a/src/plugins/platforms/openvglite/qwindowsurface_vglite.cpp +++ b/src/plugins/platforms/openvglite/qwindowsurface_vglite.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/platforms/openvglite/qwindowsurface_vglite.h b/src/plugins/platforms/openvglite/qwindowsurface_vglite.h index 59faba8..6d66c42 100644 --- a/src/plugins/platforms/openvglite/qwindowsurface_vglite.h +++ b/src/plugins/platforms/openvglite/qwindowsurface_vglite.h @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro index 26ccd44..57015e7 100644 --- a/src/plugins/platforms/platforms.pro +++ b/src/plugins/platforms/platforms.pro @@ -2,3 +2,7 @@ TEMPLATE = subdirs SUBDIRS += minimal +contains(QT_CONFIG, wayland) { + SUBDIRS += wayland +} + diff --git a/src/plugins/platforms/qvfb/main.cpp b/src/plugins/platforms/qvfb/main.cpp index 997e544..5c3b72b 100644 --- a/src/plugins/platforms/qvfb/main.cpp +++ b/src/plugins/platforms/qvfb/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/qvfb/qvfbintegration.cpp b/src/plugins/platforms/qvfb/qvfbintegration.cpp index 0cc3938..ddde800 100644 --- a/src/plugins/platforms/qvfb/qvfbintegration.cpp +++ b/src/plugins/platforms/qvfb/qvfbintegration.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/qvfb/qvfbintegration.h b/src/plugins/platforms/qvfb/qvfbintegration.h index 198a45c..33e31a5 100644 --- a/src/plugins/platforms/qvfb/qvfbintegration.h +++ b/src/plugins/platforms/qvfb/qvfbintegration.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/qvfb/qvfbwindowsurface.cpp b/src/plugins/platforms/qvfb/qvfbwindowsurface.cpp index 6699072..85918eb 100644 --- a/src/plugins/platforms/qvfb/qvfbwindowsurface.cpp +++ b/src/plugins/platforms/qvfb/qvfbwindowsurface.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/platforms/qvfb/qvfbwindowsurface.h b/src/plugins/platforms/qvfb/qvfbwindowsurface.h index 9228189..9f828d3 100644 --- a/src/plugins/platforms/qvfb/qvfbwindowsurface.h +++ b/src/plugins/platforms/qvfb/qvfbwindowsurface.h @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/platforms/testlite/qtestliteintegration.cpp b/src/plugins/platforms/testlite/qtestliteintegration.cpp deleted file mode 100644 index 68e9051..0000000 --- a/src/plugins/platforms/testlite/qtestliteintegration.cpp +++ /dev/null @@ -1,153 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - - - -#include "qtestliteintegration.h" -#include "qtestlitewindowsurface.h" -#include <QtGui/private/qpixmap_raster_p.h> -#include <QtCore/qdebug.h> - -#include <QPlatformCursor> - -#include "qtestlitewindow.h" -#include "qgenericunixfontdatabase.h" - -#ifndef QT_NO_OPENGL -#include <GL/glx.h> -#include <private/qwindowsurface_gl_p.h> -#include <private/qpixmapdata_gl_p.h> -#endif //QT_NO_OPENGL - -QT_BEGIN_NAMESPACE - -class MyCursor : QPlatformCursor -{ -public: - MyCursor(QPlatformScreen *screen) : QPlatformCursor(screen) {} - - void changeCursor(QCursor * cursor, QWidget * widget) { - QTestLiteWindow *w = 0; - if (widget) { - QWidget *window = widget->window(); - w = static_cast<QTestLiteWindow*>(window->platformWindow()); - } else { - // No X11 cursor control when there is no widget under the cursor - return; - } - - //qDebug() << "changeCursor" << widget << ws; - if (!w) - return; - - w->setCursor(cursor); - } -}; - - -QTestLiteIntegration::QTestLiteIntegration(bool useOpenGL) - : mUseOpenGL(useOpenGL) - , mFontDb(new QGenericUnixFontDatabase()) -{ - xd = new MyDisplay; - - mPrimaryScreen = new QTestLiteScreen(); - - mPrimaryScreen->mGeometry = QRect - (0, 0, xd->width, xd->height); - mPrimaryScreen->mDepth = 32; - mPrimaryScreen->mFormat = QImage::Format_RGB32; - mPrimaryScreen->mPhysicalSize = - QSize(xd->physicalWidth, xd->physicalHeight); - - mScreens.append(mPrimaryScreen); - - - (void)new MyCursor(mPrimaryScreen); - -} - -QPixmapData *QTestLiteIntegration::createPixmapData(QPixmapData::PixelType type) const -{ -#ifndef QT_NO_OPENGL - if (mUseOpenGL) - return new QGLPixmapData(type); -#endif - return new QRasterPixmapData(type); -} - -QWindowSurface *QTestLiteIntegration::createWindowSurface(QWidget *widget, WId) const -{ -#ifndef QT_NO_OPENGL - if (mUseOpenGL) - return new QGLWindowSurface(widget); -#endif - return new QTestLiteWindowSurface(mPrimaryScreen, widget); -} - - -QPlatformWindow *QTestLiteIntegration::createPlatformWindow(QWidget *widget, WId /*winId*/) const -{ - return new QTestLiteWindow(this, mPrimaryScreen, widget); -} - - - -QPixmap QTestLiteIntegration::grabWindow(WId window, int x, int y, int width, int height) const -{ - QImage img = xd->grabWindow(window, x, y, width, height); - return QPixmap::fromImage(img); -} - -QPlatformFontDatabase *QTestLiteIntegration::fontDatabase() const -{ - return mFontDb; -} - -bool QTestLiteIntegration::hasOpenGL() const -{ -#ifndef QT_NO_OPENGL - return glXQueryExtension(xd->display, 0, 0) != 0; -#endif - return false; -} - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestlitewindow.cpp b/src/plugins/platforms/testlite/qtestlitewindow.cpp deleted file mode 100644 index b52aae9..0000000 --- a/src/plugins/platforms/testlite/qtestlitewindow.cpp +++ /dev/null @@ -1,1586 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtOpenVG module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, 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. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qtestliteintegration.h" -#include <QWindowSystemInterface> -#include <private/qwindowsurface_p.h> -#include <QtGui/private/qapplication_p.h> - -#include "qtestlitewindow.h" - -#include <QBitmap> -#include <QCursor> -#include <QDateTime> -#include <QPixmap> -#include <QImage> -#include <QSocketNotifier> - -#include <qdebug.h> -#include <QTimer> -#include <QApplication> - -#ifndef QT_NO_OPENGL -#include "qglxintegration.h" -#endif - -#include <stdio.h> -#include <stdlib.h> - - -#include <X11/Xatom.h> - -#include <X11/cursorfont.h> - - - -//### remove stuff we don't want from qt_x11_p.h -#undef ATOM -#undef X11 - -//#define MYX11_DEBUG - -QT_BEGIN_NAMESPACE - -static int (*original_x_errhandler)(Display *dpy, XErrorEvent *); -static bool seen_badwindow; - - -static Atom wmProtocolsAtom; -static Atom wmDeleteWindowAtom; - -class MyX11CursorNode -{ -public: - MyX11CursorNode(int id, Cursor c) { idValue = id; cursorValue = c; refCount = 1; } - QDateTime expiration() { return t; } - void setExpiration(QDateTime val) { t = val; } - MyX11CursorNode * ante() { return before; } - void setAnte(MyX11CursorNode *node) { before = node; } - MyX11CursorNode * post() { return after; } - void setPost(MyX11CursorNode *node) { after = node; } - Cursor cursor() { return cursorValue; } - int id() { return idValue; } - unsigned int refCount; - -private: - MyX11CursorNode *before; - MyX11CursorNode *after; - QDateTime t; - Cursor cursorValue; - int idValue; - - Display * display; -}; - - - - - -class MyX11Cursors : public QObject -{ - Q_OBJECT -public: - MyX11Cursors(Display * d); - ~MyX11Cursors() { timer.stop(); } - void incrementUseCount(int id); - void decrementUseCount(int id); - void createNode(int id, Cursor c); - bool exists(int id) { return lookupMap.contains(id); } - Cursor cursor(int id); -public slots: - void timeout(); - -private: - void removeNode(MyX11CursorNode *node); - void insertNode(MyX11CursorNode *node); - - // linked list of cursors currently not assigned to any window - MyX11CursorNode *firstExpired; - MyX11CursorNode *lastExpired; - - QHash<int, MyX11CursorNode *> lookupMap; - QTimer timer; - - Display *display; - - int removalDelay; -}; - - - - - -QTestLiteWindow::QTestLiteWindow(const QTestLiteIntegration *platformIntegration, - QTestLiteScreen */*screen*/, QWidget *window) - :QPlatformWindow(window), mGLContext(0) -{ - xd = platformIntegration->xd; - xd->windowList.append(this); - { - int x = window->x(); - int y = window->y(); - int w = window->width(); - int h = window->height(); - - if(window->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL - && QApplicationPrivate::platformIntegration()->hasOpenGL() ) { -#ifndef QT_NO_OPENGL - XVisualInfo *visualInfo = QGLXGLContext::findVisualInfo(xd,window->platformWindowFormat()); - Colormap cmap = XCreateColormap(xd->display,xd->rootWindow(),visualInfo->visual,AllocNone); - - XSetWindowAttributes a; - a.colormap = cmap; - x_window = XCreateWindow(xd->display, xd->rootWindow(),x, y, w, h, - 0, visualInfo->depth, InputOutput, visualInfo->visual, - CWColormap, &a); -#endif //QT_NO_OPENGL - } else { - x_window = XCreateSimpleWindow(xd->display, xd->rootWindow(), - x, y, w, h, 0 /*border_width*/, - xd->blackPixel(), xd->whitePixel()); - } - -#ifdef MYX11_DEBUG - qDebug() << "QTestLiteWindow::QTestLiteWindow creating" << hex << x_window << window; -#endif - } - - width = -1; - height = -1; - xpos = -1; - ypos = -1; - - XSetWindowBackgroundPixmap(xd->display, x_window, XNone); - - XSelectInput(xd->display, x_window, ExposureMask | KeyPressMask | KeyReleaseMask | - EnterWindowMask | LeaveWindowMask | FocusChangeMask | - PointerMotionMask | ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | - StructureNotifyMask); - - gc = createGC(); - - XChangeProperty (xd->display, x_window, - wmProtocolsAtom, - XA_ATOM, 32, PropModeAppend, - (unsigned char *) &wmDeleteWindowAtom, 1); - currentCursor = -1; -} - - -QTestLiteWindow::~QTestLiteWindow() -{ -#ifdef MYX11_DEBUG - qDebug() << "~QTestLiteWindow" << hex << x_window; -#endif - delete mGLContext; - XFreeGC(xd->display, gc); - XDestroyWindow(xd->display, x_window); - - xd->windowList.removeAll(this); -} - - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Mouse event stuff - - - - -static Qt::MouseButtons translateMouseButtons(int s) -{ - Qt::MouseButtons ret = 0; - if (s & Button1Mask) - ret |= Qt::LeftButton; - if (s & Button2Mask) - ret |= Qt::MidButton; - if (s & Button3Mask) - ret |= Qt::RightButton; - return ret; -} - - -static Qt::KeyboardModifiers translateModifiers(int s) -{ - const uchar qt_alt_mask = Mod1Mask; - const uchar qt_meta_mask = Mod4Mask; - - - Qt::KeyboardModifiers ret = 0; - if (s & ShiftMask) - ret |= Qt::ShiftModifier; - if (s & ControlMask) - ret |= Qt::ControlModifier; - if (s & qt_alt_mask) - ret |= Qt::AltModifier; - if (s & qt_meta_mask) - ret |= Qt::MetaModifier; -#if 0 - if (s & qt_mode_switch_mask) - ret |= Qt::GroupSwitchModifier; -#endif - return ret; -} - -void QTestLiteWindow::handleMouseEvent(QEvent::Type type, XButtonEvent *e) -{ - static QPoint mousePoint; - - Qt::MouseButton button = Qt::NoButton; - Qt::MouseButtons buttons = translateMouseButtons(e->state); - Qt::KeyboardModifiers modifiers = translateModifiers(e->state); - if (type != QEvent::MouseMove) { - switch (e->button) { - case Button1: button = Qt::LeftButton; break; - case Button2: button = Qt::MidButton; break; - case Button3: button = Qt::RightButton; break; - case Button4: - case Button5: - case 6: - case 7: { - //mouse wheel - if (type == QEvent::MouseButtonPress) { - //logic borrowed from qapplication_x11.cpp - int delta = 120 * ((e->button == Button4 || e->button == 6) ? 1 : -1); - bool hor = (((e->button == Button4 || e->button == Button5) - && (modifiers & Qt::AltModifier)) - || (e->button == 6 || e->button == 7)); - QWindowSystemInterface::handleWheelEvent(widget(), e->time, - QPoint(e->x, e->y), - QPoint(e->x_root, e->y_root), - delta, hor ? Qt::Horizontal : Qt::Vertical); - } - return; - } - default: break; - } - } - - buttons ^= button; // X event uses state *before*, Qt uses state *after* - - QWindowSystemInterface::handleMouseEvent(widget(), e->time, QPoint(e->x, e->y), - QPoint(e->x_root, e->y_root), - buttons); - - mousePoint = QPoint(e->x_root, e->y_root); -} - -void QTestLiteWindow::handleCloseEvent() -{ - QWindowSystemInterface::handleCloseEvent(widget()); -} - - -void QTestLiteWindow::handleEnterEvent() -{ - QWindowSystemInterface::handleEnterEvent(widget()); -} - -void QTestLiteWindow::handleLeaveEvent() -{ - QWindowSystemInterface::handleLeaveEvent(widget()); -} - - -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -// Key event stuff -- not pretty either -// -// What we want to do is to port Robert's keytable code properly - -// keyboard mapping table -static const unsigned int keyTbl[] = { - - // misc keys - - XK_Escape, Qt::Key_Escape, - XK_Tab, Qt::Key_Tab, - XK_ISO_Left_Tab, Qt::Key_Backtab, - XK_BackSpace, Qt::Key_Backspace, - XK_Return, Qt::Key_Return, - XK_Insert, Qt::Key_Insert, - XK_Delete, Qt::Key_Delete, - XK_Clear, Qt::Key_Delete, - XK_Pause, Qt::Key_Pause, - XK_Print, Qt::Key_Print, - 0x1005FF60, Qt::Key_SysReq, // hardcoded Sun SysReq - 0x1007ff00, Qt::Key_SysReq, // hardcoded X386 SysReq - - // cursor movement - - XK_Home, Qt::Key_Home, - XK_End, Qt::Key_End, - XK_Left, Qt::Key_Left, - XK_Up, Qt::Key_Up, - XK_Right, Qt::Key_Right, - XK_Down, Qt::Key_Down, - XK_Prior, Qt::Key_PageUp, - XK_Next, Qt::Key_PageDown, - - // modifiers - - XK_Shift_L, Qt::Key_Shift, - XK_Shift_R, Qt::Key_Shift, - XK_Shift_Lock, Qt::Key_Shift, - XK_Control_L, Qt::Key_Control, - XK_Control_R, Qt::Key_Control, - XK_Meta_L, Qt::Key_Meta, - XK_Meta_R, Qt::Key_Meta, - XK_Alt_L, Qt::Key_Alt, - XK_Alt_R, Qt::Key_Alt, - XK_Caps_Lock, Qt::Key_CapsLock, - XK_Num_Lock, Qt::Key_NumLock, - XK_Scroll_Lock, Qt::Key_ScrollLock, - XK_Super_L, Qt::Key_Super_L, - XK_Super_R, Qt::Key_Super_R, - XK_Menu, Qt::Key_Menu, - XK_Hyper_L, Qt::Key_Hyper_L, - XK_Hyper_R, Qt::Key_Hyper_R, - XK_Help, Qt::Key_Help, - 0x1000FF74, Qt::Key_Backtab, // hardcoded HP backtab - 0x1005FF10, Qt::Key_F11, // hardcoded Sun F36 (labeled F11) - 0x1005FF11, Qt::Key_F12, // hardcoded Sun F37 (labeled F12) - - // numeric and function keypad keys - - XK_KP_Space, Qt::Key_Space, - XK_KP_Tab, Qt::Key_Tab, - XK_KP_Enter, Qt::Key_Enter, - //XK_KP_F1, Qt::Key_F1, - //XK_KP_F2, Qt::Key_F2, - //XK_KP_F3, Qt::Key_F3, - //XK_KP_F4, Qt::Key_F4, - XK_KP_Home, Qt::Key_Home, - XK_KP_Left, Qt::Key_Left, - XK_KP_Up, Qt::Key_Up, - XK_KP_Right, Qt::Key_Right, - XK_KP_Down, Qt::Key_Down, - XK_KP_Prior, Qt::Key_PageUp, - XK_KP_Next, Qt::Key_PageDown, - XK_KP_End, Qt::Key_End, - XK_KP_Begin, Qt::Key_Clear, - XK_KP_Insert, Qt::Key_Insert, - XK_KP_Delete, Qt::Key_Delete, - XK_KP_Equal, Qt::Key_Equal, - XK_KP_Multiply, Qt::Key_Asterisk, - XK_KP_Add, Qt::Key_Plus, - XK_KP_Separator, Qt::Key_Comma, - XK_KP_Subtract, Qt::Key_Minus, - XK_KP_Decimal, Qt::Key_Period, - XK_KP_Divide, Qt::Key_Slash, - - // International input method support keys - - // International & multi-key character composition - XK_ISO_Level3_Shift, Qt::Key_AltGr, - XK_Multi_key, Qt::Key_Multi_key, - XK_Codeinput, Qt::Key_Codeinput, - XK_SingleCandidate, Qt::Key_SingleCandidate, - XK_MultipleCandidate, Qt::Key_MultipleCandidate, - XK_PreviousCandidate, Qt::Key_PreviousCandidate, - - // Misc Functions - XK_Mode_switch, Qt::Key_Mode_switch, - XK_script_switch, Qt::Key_Mode_switch, - - // Japanese keyboard support - XK_Kanji, Qt::Key_Kanji, - XK_Muhenkan, Qt::Key_Muhenkan, - //XK_Henkan_Mode, Qt::Key_Henkan_Mode, - XK_Henkan_Mode, Qt::Key_Henkan, - XK_Henkan, Qt::Key_Henkan, - XK_Romaji, Qt::Key_Romaji, - XK_Hiragana, Qt::Key_Hiragana, - XK_Katakana, Qt::Key_Katakana, - XK_Hiragana_Katakana, Qt::Key_Hiragana_Katakana, - XK_Zenkaku, Qt::Key_Zenkaku, - XK_Hankaku, Qt::Key_Hankaku, - XK_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku, - XK_Touroku, Qt::Key_Touroku, - XK_Massyo, Qt::Key_Massyo, - XK_Kana_Lock, Qt::Key_Kana_Lock, - XK_Kana_Shift, Qt::Key_Kana_Shift, - XK_Eisu_Shift, Qt::Key_Eisu_Shift, - XK_Eisu_toggle, Qt::Key_Eisu_toggle, - //XK_Kanji_Bangou, Qt::Key_Kanji_Bangou, - //XK_Zen_Koho, Qt::Key_Zen_Koho, - //XK_Mae_Koho, Qt::Key_Mae_Koho, - XK_Kanji_Bangou, Qt::Key_Codeinput, - XK_Zen_Koho, Qt::Key_MultipleCandidate, - XK_Mae_Koho, Qt::Key_PreviousCandidate, - -#ifdef XK_KOREAN - // Korean keyboard support - XK_Hangul, Qt::Key_Hangul, - XK_Hangul_Start, Qt::Key_Hangul_Start, - XK_Hangul_End, Qt::Key_Hangul_End, - XK_Hangul_Hanja, Qt::Key_Hangul_Hanja, - XK_Hangul_Jamo, Qt::Key_Hangul_Jamo, - XK_Hangul_Romaja, Qt::Key_Hangul_Romaja, - //XK_Hangul_Codeinput, Qt::Key_Hangul_Codeinput, - XK_Hangul_Codeinput, Qt::Key_Codeinput, - XK_Hangul_Jeonja, Qt::Key_Hangul_Jeonja, - XK_Hangul_Banja, Qt::Key_Hangul_Banja, - XK_Hangul_PreHanja, Qt::Key_Hangul_PreHanja, - XK_Hangul_PostHanja, Qt::Key_Hangul_PostHanja, - //XK_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate, - //XK_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate, - //XK_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate, - XK_Hangul_SingleCandidate, Qt::Key_SingleCandidate, - XK_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate, - XK_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate, - XK_Hangul_Special, Qt::Key_Hangul_Special, - //XK_Hangul_switch, Qt::Key_Hangul_switch, - XK_Hangul_switch, Qt::Key_Mode_switch, -#endif // XK_KOREAN - - // dead keys - XK_dead_grave, Qt::Key_Dead_Grave, - XK_dead_acute, Qt::Key_Dead_Acute, - XK_dead_circumflex, Qt::Key_Dead_Circumflex, - XK_dead_tilde, Qt::Key_Dead_Tilde, - XK_dead_macron, Qt::Key_Dead_Macron, - XK_dead_breve, Qt::Key_Dead_Breve, - XK_dead_abovedot, Qt::Key_Dead_Abovedot, - XK_dead_diaeresis, Qt::Key_Dead_Diaeresis, - XK_dead_abovering, Qt::Key_Dead_Abovering, - XK_dead_doubleacute, Qt::Key_Dead_Doubleacute, - XK_dead_caron, Qt::Key_Dead_Caron, - XK_dead_cedilla, Qt::Key_Dead_Cedilla, - XK_dead_ogonek, Qt::Key_Dead_Ogonek, - XK_dead_iota, Qt::Key_Dead_Iota, - XK_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound, - XK_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound, - XK_dead_belowdot, Qt::Key_Dead_Belowdot, - XK_dead_hook, Qt::Key_Dead_Hook, - XK_dead_horn, Qt::Key_Dead_Horn, - -#if 0 - // Special multimedia keys - // currently only tested with MS internet keyboard - - // browsing keys - XF86XK_Back, Qt::Key_Back, - XF86XK_Forward, Qt::Key_Forward, - XF86XK_Stop, Qt::Key_Stop, - XF86XK_Refresh, Qt::Key_Refresh, - XF86XK_Favorites, Qt::Key_Favorites, - XF86XK_AudioMedia, Qt::Key_LaunchMedia, - XF86XK_OpenURL, Qt::Key_OpenUrl, - XF86XK_HomePage, Qt::Key_HomePage, - XF86XK_Search, Qt::Key_Search, - - // media keys - XF86XK_AudioLowerVolume, Qt::Key_VolumeDown, - XF86XK_AudioMute, Qt::Key_VolumeMute, - XF86XK_AudioRaiseVolume, Qt::Key_VolumeUp, - XF86XK_AudioPlay, Qt::Key_MediaPlay, - XF86XK_AudioStop, Qt::Key_MediaStop, - XF86XK_AudioPrev, Qt::Key_MediaPrevious, - XF86XK_AudioNext, Qt::Key_MediaNext, - XF86XK_AudioRecord, Qt::Key_MediaRecord, - - // launch keys - XF86XK_Mail, Qt::Key_LaunchMail, - XF86XK_MyComputer, Qt::Key_Launch0, - XF86XK_Calculator, Qt::Key_Launch1, - XF86XK_Standby, Qt::Key_Standby, - - XF86XK_Launch0, Qt::Key_Launch2, - XF86XK_Launch1, Qt::Key_Launch3, - XF86XK_Launch2, Qt::Key_Launch4, - XF86XK_Launch3, Qt::Key_Launch5, - XF86XK_Launch4, Qt::Key_Launch6, - XF86XK_Launch5, Qt::Key_Launch7, - XF86XK_Launch6, Qt::Key_Launch8, - XF86XK_Launch7, Qt::Key_Launch9, - XF86XK_Launch8, Qt::Key_LaunchA, - XF86XK_Launch9, Qt::Key_LaunchB, - XF86XK_LaunchA, Qt::Key_LaunchC, - XF86XK_LaunchB, Qt::Key_LaunchD, - XF86XK_LaunchC, Qt::Key_LaunchE, - XF86XK_LaunchD, Qt::Key_LaunchF, -#endif - -#if 0 - // Qtopia keys - QTOPIAXK_Select, Qt::Key_Select, - QTOPIAXK_Yes, Qt::Key_Yes, - QTOPIAXK_No, Qt::Key_No, - QTOPIAXK_Cancel, Qt::Key_Cancel, - QTOPIAXK_Printer, Qt::Key_Printer, - QTOPIAXK_Execute, Qt::Key_Execute, - QTOPIAXK_Sleep, Qt::Key_Sleep, - QTOPIAXK_Play, Qt::Key_Play, - QTOPIAXK_Zoom, Qt::Key_Zoom, - QTOPIAXK_Context1, Qt::Key_Context1, - QTOPIAXK_Context2, Qt::Key_Context2, - QTOPIAXK_Context3, Qt::Key_Context3, - QTOPIAXK_Context4, Qt::Key_Context4, - QTOPIAXK_Call, Qt::Key_Call, - QTOPIAXK_Hangup, Qt::Key_Hangup, - QTOPIAXK_Flip, Qt::Key_Flip, -#endif - 0, 0 -}; - - -static int lookupCode(unsigned int xkeycode) -{ - if (xkeycode >= XK_F1 && xkeycode <= XK_F35) - return Qt::Key_F1 + (int(xkeycode) - XK_F1); - - const unsigned int *p = keyTbl; - while (*p) { - if (*p == xkeycode) - return *++p; - p += 2; - } - - return 0; -} - - -static Qt::KeyboardModifiers modifierFromKeyCode(int qtcode) -{ - switch (qtcode) { - case Qt::Key_Control: - return Qt::ControlModifier; - case Qt::Key_Alt: - return Qt::AltModifier; - case Qt::Key_Shift: - return Qt::ShiftModifier; - case Qt::Key_Meta: - return Qt::MetaModifier; - default: - return Qt::NoModifier; - } -} - -void QTestLiteWindow::handleKeyEvent(QEvent::Type type, void *ev) -{ - XKeyEvent *e = static_cast<XKeyEvent*>(ev); - - KeySym keySym; - QByteArray chars; - chars.resize(513); - - int count = XLookupString(e, chars.data(), chars.size(), &keySym, 0); - Q_UNUSED(count); -// qDebug() << "QTLWS::handleKeyEvent" << count << hex << "XKeysym:" << keySym; -// if (count) -// qDebug() << hex << int(chars[0]) << "String:" << chars; - - Qt::KeyboardModifiers modifiers = translateModifiers(e->state); - - int qtcode = lookupCode(keySym); -// qDebug() << "lookup: " << hex << keySym << qtcode << "mod" << modifiers; - - //X11 specifies state *before*, Qt expects state *after* the event - - modifiers ^= modifierFromKeyCode(qtcode); - - if (qtcode) { - QWindowSystemInterface::handleKeyEvent(widget(), e->time, type, qtcode, modifiers); - } else if (chars[0]) { - int qtcode = chars.toUpper()[0]; //Not exactly right... - if (modifiers & Qt::ControlModifier && qtcode < ' ') - qtcode = chars[0] + '@'; - QWindowSystemInterface::handleKeyEvent(0, e->time, type, qtcode, modifiers, QString::fromLatin1(chars)); - } else { - qWarning() << "unknown X keycode" << hex << e->keycode << keySym; - } -} - -void QTestLiteWindow::setGeometry(const QRect &rect) -{ - XMoveResizeWindow(xd->display, x_window, rect.x(), rect.y(), rect.width(), rect.height()); - QPlatformWindow::setGeometry(rect); -} - - -Qt::WindowFlags QTestLiteWindow::windowFlags() const -{ - return window_flags; -} - -WId QTestLiteWindow::winId() const -{ - return x_window; -} - -void QTestLiteWindow::setParent(const QPlatformWindow *window) -{ - QPoint point = widget()->mapTo(widget()->nativeParentWidget(),QPoint()); - XReparentWindow(xd->display,x_window,window->winId(),point.x(),point.y()); -} - -void QTestLiteWindow::raise() -{ - XRaiseWindow(xd->display, x_window); -} - -void QTestLiteWindow::lower() -{ - XLowerWindow(xd->display, x_window); -} - -void QTestLiteWindow::setWindowTitle(const QString &title) -{ - QByteArray ba = title.toLatin1(); //We're not making a general solution here... - XTextProperty windowName; - windowName.value = (unsigned char *)ba.constData(); - windowName.encoding = XA_STRING; - windowName.format = 8; - windowName.nitems = ba.length(); - - XSetWMName(xd->display, x_window, &windowName); -} - -GC QTestLiteWindow::createGC() -{ - GC gc; - - gc = XCreateGC(xd->display, x_window, 0, 0); - if (gc < 0) { - qWarning("QTestLiteWindow::createGC() could not create GC"); - } - return gc; -} - -void QTestLiteWindow::paintEvent() -{ -#ifdef MYX11_DEBUG -// qDebug() << "QTestLiteWindow::paintEvent" << shm_img.size() << painted; -#endif - - if (QWindowSurface *surface = widget()->windowSurface()) - surface->flush(widget(), QRect(xpos,ypos,width, height), QPoint()); -} - - -void QTestLiteWindow::resizeEvent(XConfigureEvent *e) -{ - if ((e->width != width || e->height != height) && e->x == 0 && e->y == 0) { - //qDebug() << "resize with bogus pos" << e->x << e->y << e->width << e->height << "window"<< hex << window; - } else { - //qDebug() << "geometry change" << e->x << e->y << e->width << e->height << "window"<< hex << window; - xpos = e->x; - ypos = e->y; - } - width = e->width; - height = e->height; - -#ifdef MYX11_DEBUG - qDebug() << hex << x_window << dec << "ConfigureNotify" << e->x << e->y << e->width << e->height << "geometry" << xpos << ypos << width << height; -#endif - - QWindowSystemInterface::handleGeometryChange(widget(), QRect(xpos, ypos, width, height)); -} - - -void QTestLiteWindow::mousePressEvent(XButtonEvent *e) -{ - static long prevTime = 0; - static Window prevWindow; - static int prevX = -999; - static int prevY = -999; - - QEvent::Type type = QEvent::MouseButtonPress; - - if (e->window == prevWindow && long(e->time) - prevTime < QApplication::doubleClickInterval() - && qAbs(e->x - prevX) < 5 && qAbs(e->y - prevY) < 5) { - type = QEvent::MouseButtonDblClick; - prevTime = e->time - QApplication::doubleClickInterval(); //no double click next time - } else { - prevTime = e->time; - } - prevWindow = e->window; - prevX = e->x; - prevY = e->y; - - handleMouseEvent(type, e); -} - - - -// WindowFlag stuff, lots of copied code from qwidget_x11.cpp... - -//We're hacking here... - - -// MWM support -struct QtMWMHints { - ulong flags, functions, decorations; - long input_mode; - ulong status; -}; - -enum { - MWM_HINTS_FUNCTIONS = (1L << 0), - - MWM_FUNC_ALL = (1L << 0), - MWM_FUNC_RESIZE = (1L << 1), - MWM_FUNC_MOVE = (1L << 2), - MWM_FUNC_MINIMIZE = (1L << 3), - MWM_FUNC_MAXIMIZE = (1L << 4), - MWM_FUNC_CLOSE = (1L << 5), - - MWM_HINTS_DECORATIONS = (1L << 1), - - MWM_DECOR_ALL = (1L << 0), - MWM_DECOR_BORDER = (1L << 1), - MWM_DECOR_RESIZEH = (1L << 2), - MWM_DECOR_TITLE = (1L << 3), - MWM_DECOR_MENU = (1L << 4), - MWM_DECOR_MINIMIZE = (1L << 5), - MWM_DECOR_MAXIMIZE = (1L << 6), - - MWM_HINTS_INPUT_MODE = (1L << 2), - - MWM_INPUT_MODELESS = 0L, - MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L, - MWM_INPUT_FULL_APPLICATION_MODAL = 3L -}; - -static Atom mwm_hint_atom = XNone; - -#if 0 -static QtMWMHints GetMWMHints(Display *display, Window window) -{ - QtMWMHints mwmhints; - - Atom type; - int format; - ulong nitems, bytesLeft; - uchar *data = 0; - if ((XGetWindowProperty(display, window, mwm_hint_atom, 0, 5, false, - mwm_hint_atom, &type, &format, &nitems, &bytesLeft, - &data) == Success) - && (type == mwm_hint_atom - && format == 32 - && nitems >= 5)) { - mwmhints = *(reinterpret_cast<QtMWMHints *>(data)); - } else { - mwmhints.flags = 0L; - mwmhints.functions = MWM_FUNC_ALL; - mwmhints.decorations = MWM_DECOR_ALL; - mwmhints.input_mode = 0L; - mwmhints.status = 0L; - } - - if (data) - XFree(data); - - return mwmhints; -} -#endif - -static void SetMWMHints(Display *display, Window window, const QtMWMHints &mwmhints) -{ - if (mwmhints.flags != 0l) { - XChangeProperty(display, window, mwm_hint_atom, mwm_hint_atom, 32, - PropModeReplace, (unsigned char *) &mwmhints, 5); - } else { - XDeleteProperty(display, window, mwm_hint_atom); - } -} - -// Returns true if we should set WM_TRANSIENT_FOR on \a w -static inline bool isTransient(const QWidget *w) -{ - return ((w->windowType() == Qt::Dialog - || w->windowType() == Qt::Sheet - || w->windowType() == Qt::Tool - || w->windowType() == Qt::SplashScreen - || w->windowType() == Qt::ToolTip - || w->windowType() == Qt::Drawer - || w->windowType() == Qt::Popup) - && !w->testAttribute(Qt::WA_X11BypassTransientForHint)); -} - - - -Qt::WindowFlags QTestLiteWindow::setWindowFlags(Qt::WindowFlags flags) -{ -// Q_ASSERT(flags & Qt::Window); - window_flags = flags; - - if (mwm_hint_atom == XNone) { - mwm_hint_atom = XInternAtom(xd->display, "_MOTIF_WM_HINTS\0", False); - } - -#ifdef MYX11_DEBUG - qDebug() << "QTestLiteWindow::setWindowFlags" << hex << x_window << "flags" << flags; -#endif - Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask)); - - if (type == Qt::ToolTip) - flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint; - if (type == Qt::Popup) - flags |= Qt::X11BypassWindowManagerHint; - - bool topLevel = (flags & Qt::Window); - bool popup = (type == Qt::Popup); - bool dialog = (type == Qt::Dialog - || type == Qt::Sheet); - bool desktop = (type == Qt::Desktop); - bool tool = (type == Qt::Tool || type == Qt::SplashScreen - || type == Qt::ToolTip || type == Qt::Drawer); - - - Q_UNUSED(topLevel); - Q_UNUSED(dialog); - Q_UNUSED(desktop); - - - bool tooltip = (type == Qt::ToolTip); - - XSetWindowAttributes wsa; - - QtMWMHints mwmhints; - mwmhints.flags = 0L; - mwmhints.functions = 0L; - mwmhints.decorations = 0; - mwmhints.input_mode = 0L; - mwmhints.status = 0L; - - - ulong wsa_mask = 0; - if (type != Qt::SplashScreen) { // && customize) { - mwmhints.flags |= MWM_HINTS_DECORATIONS; - - bool customize = flags & Qt::CustomizeWindowHint; - if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) { - mwmhints.decorations |= MWM_DECOR_BORDER; - mwmhints.decorations |= MWM_DECOR_RESIZEH; - - if (flags & Qt::WindowTitleHint) - mwmhints.decorations |= MWM_DECOR_TITLE; - - if (flags & Qt::WindowSystemMenuHint) - mwmhints.decorations |= MWM_DECOR_MENU; - - if (flags & Qt::WindowMinimizeButtonHint) { - mwmhints.decorations |= MWM_DECOR_MINIMIZE; - mwmhints.functions |= MWM_FUNC_MINIMIZE; - } - - if (flags & Qt::WindowMaximizeButtonHint) { - mwmhints.decorations |= MWM_DECOR_MAXIMIZE; - mwmhints.functions |= MWM_FUNC_MAXIMIZE; - } - - if (flags & Qt::WindowCloseButtonHint) - mwmhints.functions |= MWM_FUNC_CLOSE; - } - } else { - // if type == Qt::SplashScreen - mwmhints.decorations = MWM_DECOR_ALL; - } - - if (tool) { - wsa.save_under = True; - wsa_mask |= CWSaveUnder; - } - - if (flags & Qt::X11BypassWindowManagerHint) { - wsa.override_redirect = True; - wsa_mask |= CWOverrideRedirect; - } -#if 0 - if (wsa_mask && initializeWindow) { - Q_ASSERT(id); - XChangeWindowAttributes(dpy, id, wsa_mask, &wsa); - } -#endif - if (mwmhints.functions != 0) { - mwmhints.flags |= MWM_HINTS_FUNCTIONS; - mwmhints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE; - } else { - mwmhints.functions = MWM_FUNC_ALL; - } - - if (!(flags & Qt::FramelessWindowHint) - && flags & Qt::CustomizeWindowHint - && flags & Qt::WindowTitleHint - && !(flags & - (Qt::WindowMinimizeButtonHint - | Qt::WindowMaximizeButtonHint - | Qt::WindowCloseButtonHint))) { - // a special case - only the titlebar without any button - mwmhints.flags = MWM_HINTS_FUNCTIONS; - mwmhints.functions = MWM_FUNC_MOVE | MWM_FUNC_RESIZE; - mwmhints.decorations = 0; - } - - SetMWMHints(xd->display, x_window, mwmhints); - -//##### only if initializeWindow??? - - if (popup || tooltip) { // popup widget -#ifdef MYX11_DEBUG - qDebug() << "Doing XChangeWindowAttributes for popup" << wsa.override_redirect; -#endif - // set EWMH window types - // setNetWmWindowTypes(); - - wsa.override_redirect = True; - wsa.save_under = True; - XChangeWindowAttributes(xd->display, x_window, CWOverrideRedirect | CWSaveUnder, - &wsa); - } else { -#ifdef MYX11_DEBUG - qDebug() << "Doing XChangeWindowAttributes for non-popup"; -#endif - } - - return flags; -} - -void QTestLiteWindow::setVisible(bool visible) -{ -#ifdef MYX11_DEBUG - qDebug() << "QTestLiteWindow::setVisible" << visible << hex << x_window; -#endif - if (visible) - XMapWindow(xd->display, x_window); - else - XUnmapWindow(xd->display, x_window); -} - - -void QTestLiteWindow::setCursor(QCursor * cursor) -{ - int id = cursor->handle(); - if (id == currentCursor) - return; - Cursor c; - if (!xd->cursors->exists(id)) { - if (cursor->shape() == Qt::BitmapCursor) - c = createCursorBitmap(cursor); - else - c = createCursorShape(cursor->shape()); - if (!c) { - return; - } - xd->cursors->createNode(id, c); - } else { - xd->cursors->incrementUseCount(id); - c = xd->cursors->cursor(id); - } - - if (currentCursor != -1) - xd->cursors->decrementUseCount(currentCursor); - currentCursor = id; - - XDefineCursor(xd->display, x_window, c); - XFlush(xd->display); -} - -QPlatformGLContext *QTestLiteWindow::glContext() const -{ - if (!QApplicationPrivate::platformIntegration()->hasOpenGL()) - return 0; - if (!mGLContext) { - QTestLiteWindow *that = const_cast<QTestLiteWindow *>(this); -#ifndef QT_NO_OPENGL - that->mGLContext = new QGLXGLContext(x_window, xd,widget()->platformWindowFormat()); -#endif - } - return mGLContext; -} - -Cursor QTestLiteWindow::createCursorBitmap(QCursor * cursor) -{ - XColor bg, fg; - bg.red = 255 << 8; - bg.green = 255 << 8; - bg.blue = 255 << 8; - fg.red = 0; - fg.green = 0; - fg.blue = 0; - QPoint spot = cursor->hotSpot(); - Window rootwin = x_window; - - QImage mapImage = cursor->bitmap()->toImage().convertToFormat(QImage::Format_MonoLSB); - QImage maskImage = cursor->mask()->toImage().convertToFormat(QImage::Format_MonoLSB); - - int width = cursor->bitmap()->width(); - int height = cursor->bitmap()->height(); - int bytesPerLine = mapImage.bytesPerLine(); - int destLineSize = width / 8; - if (width % 8) - destLineSize++; - - const uchar * map = mapImage.bits(); - const uchar * mask = maskImage.bits(); - - char * mapBits = new char[height * destLineSize]; - char * maskBits = new char[height * destLineSize]; - for (int i = 0; i < height; i++) { - memcpy(mapBits + (destLineSize * i),map + (bytesPerLine * i), destLineSize); - memcpy(maskBits + (destLineSize * i),mask + (bytesPerLine * i), destLineSize); - } - - Pixmap cp = XCreateBitmapFromData(xd->display, rootwin, mapBits, width, height); - Pixmap mp = XCreateBitmapFromData(xd->display, rootwin, maskBits, width, height); - Cursor c = XCreatePixmapCursor(xd->display, cp, mp, &fg, &bg, spot.x(), spot.y()); - XFreePixmap(xd->display, cp); - XFreePixmap(xd->display, mp); - delete[] mapBits; - delete[] maskBits; - - return c; -} - -Cursor QTestLiteWindow::createCursorShape(int cshape) -{ - Cursor cursor = 0; - - if (cshape < 0 || cshape > Qt::LastCursor) - return 0; - - switch (cshape) { - case Qt::ArrowCursor: - cursor = XCreateFontCursor(xd->display, XC_left_ptr); - break; - case Qt::UpArrowCursor: - cursor = XCreateFontCursor(xd->display, XC_center_ptr); - break; - case Qt::CrossCursor: - cursor = XCreateFontCursor(xd->display, XC_crosshair); - break; - case Qt::WaitCursor: - cursor = XCreateFontCursor(xd->display, XC_watch); - break; - case Qt::IBeamCursor: - cursor = XCreateFontCursor(xd->display, XC_xterm); - break; - case Qt::SizeAllCursor: - cursor = XCreateFontCursor(xd->display, XC_fleur); - break; - case Qt::PointingHandCursor: - cursor = XCreateFontCursor(xd->display, XC_hand2); - break; - case Qt::SizeBDiagCursor: - cursor = XCreateFontCursor(xd->display, XC_top_right_corner); - break; - case Qt::SizeFDiagCursor: - cursor = XCreateFontCursor(xd->display, XC_bottom_right_corner); - break; - case Qt::SizeVerCursor: - case Qt::SplitVCursor: - cursor = XCreateFontCursor(xd->display, XC_sb_v_double_arrow); - break; - case Qt::SizeHorCursor: - case Qt::SplitHCursor: - cursor = XCreateFontCursor(xd->display, XC_sb_h_double_arrow); - break; - case Qt::WhatsThisCursor: - cursor = XCreateFontCursor(xd->display, XC_question_arrow); - break; - case Qt::ForbiddenCursor: - cursor = XCreateFontCursor(xd->display, XC_circle); - break; - case Qt::BusyCursor: - cursor = XCreateFontCursor(xd->display, XC_watch); - break; - - default: //default cursor for all the rest - break; - } - return cursor; -} - - -MyX11Cursors::MyX11Cursors(Display * d) : firstExpired(0), lastExpired(0), display(d), removalDelay(3) -{ - connect(&timer, SIGNAL(timeout()), this, SLOT(timeout())); -} - -void MyX11Cursors::insertNode(MyX11CursorNode * node) -{ - QDateTime now = QDateTime::currentDateTime(); - QDateTime timeout = now.addSecs(removalDelay); - node->setExpiration(timeout); - node->setPost(0); - if (lastExpired) { - lastExpired->setPost(node); - node->setAnte(lastExpired); - } - lastExpired = node; - if (!firstExpired) { - firstExpired = node; - node->setAnte(0); - int interval = removalDelay * 1000; - timer.setInterval(interval); - timer.start(); - } -} - -void MyX11Cursors::removeNode(MyX11CursorNode * node) -{ - MyX11CursorNode *pre = node->ante(); - MyX11CursorNode *post = node->post(); - if (pre) - pre->setPost(post); - if (post) - post->setAnte(pre); - if (node == lastExpired) - lastExpired = pre; - if (node == firstExpired) { - firstExpired = post; - if (!firstExpired) { - timer.stop(); - return; - } - int interval = QDateTime::currentDateTime().secsTo(firstExpired->expiration()) * 1000; - timer.stop(); - timer.setInterval(interval); - timer.start(); - } -} - -void MyX11Cursors::incrementUseCount(int id) -{ - MyX11CursorNode * node = lookupMap.value(id); - Q_ASSERT(node); - if (!node->refCount) - removeNode(node); - node->refCount++; -} - -void MyX11Cursors::decrementUseCount(int id) -{ - MyX11CursorNode * node = lookupMap.value(id); - Q_ASSERT(node); - node->refCount--; - if (!node->refCount) - insertNode(node); -} - -void MyX11Cursors::createNode(int id, Cursor c) -{ - MyX11CursorNode * node = new MyX11CursorNode(id, c); - lookupMap.insert(id, node); -} - -void MyX11Cursors::timeout() -{ - MyX11CursorNode * node; - node = firstExpired; - QDateTime now = QDateTime::currentDateTime(); - while (node && now.secsTo(node->expiration()) < 1) { - Cursor c = node->cursor(); - int id = node->id(); - lookupMap.take(id); - MyX11CursorNode * tmp = node; - node = node->post(); - if (node) - node->setAnte(0); - delete tmp; - XFreeCursor(display, c); - } - firstExpired = node; - if (node == 0) { - timer.stop(); - lastExpired = 0; - } - else { - int interval = QDateTime::currentDateTime().secsTo(firstExpired->expiration()) * 1000; - timer.setInterval(interval); - timer.start(); - } -} - -Cursor MyX11Cursors::cursor(int id) -{ - MyX11CursorNode * node = lookupMap.value(id); - Q_ASSERT(node); - return node->cursor(); -} - - - -/******************************************************************** - -MyDisplay class - perhaps better placed in qplatformintegration_testlite? - -*********************************************************************/ - -//### copied from qapplication_x11.cpp - -static int qt_x_errhandler(Display *dpy, XErrorEvent *err) -{ - -qDebug() << "qt_x_errhandler" << err->error_code; - - switch (err->error_code) { - case BadAtom: -#if 0 - if (err->request_code == 20 /* X_GetProperty */ - && (err->resourceid == XA_RESOURCE_MANAGER - || err->resourceid == XA_RGB_DEFAULT_MAP - || err->resourceid == ATOM(_NET_SUPPORTED) - || err->resourceid == ATOM(_NET_SUPPORTING_WM_CHECK) - || err->resourceid == ATOM(KDE_FULL_SESSION) - || err->resourceid == ATOM(KWIN_RUNNING) - || err->resourceid == ATOM(XdndProxy) - || err->resourceid == ATOM(XdndAware)) - - - ) { - // Perhaps we're running under SECURITY reduction? :/ - return 0; - } -#endif - qDebug() << "BadAtom"; - break; - - case BadWindow: - if (err->request_code == 2 /* X_ChangeWindowAttributes */ - || err->request_code == 38 /* X_QueryPointer */) { - for (int i = 0; i < ScreenCount(dpy); ++i) { - if (err->resourceid == RootWindow(dpy, i)) { - // Perhaps we're running under SECURITY reduction? :/ - return 0; - } - } - } - seen_badwindow = true; - if (err->request_code == 25 /* X_SendEvent */) { - for (int i = 0; i < ScreenCount(dpy); ++i) { - if (err->resourceid == RootWindow(dpy, i)) { - // Perhaps we're running under SECURITY reduction? :/ - return 0; - } - } -#if 0 - if (X11->xdndHandleBadwindow()) { - qDebug("xdndHandleBadwindow returned true"); - return 0; - } -#endif - } -#if 0 - if (X11->ignore_badwindow) - return 0; -#endif - break; - - case BadMatch: - if (err->request_code == 42 /* X_SetInputFocus */) - return 0; - break; - - default: -#if 0 //!defined(QT_NO_XINPUT) - if (err->request_code == X11->xinput_major - && err->error_code == (X11->xinput_errorbase + XI_BadDevice) - && err->minor_code == 3 /* X_OpenDevice */) { - return 0; - } -#endif - break; - } - - char errstr[256]; - XGetErrorText( dpy, err->error_code, errstr, 256 ); - char buffer[256]; - char request_str[256]; - qsnprintf(buffer, 256, "%d", err->request_code); - XGetErrorDatabaseText(dpy, "XRequest", buffer, "", request_str, 256); - if (err->request_code < 128) { - // X error for a normal protocol request - qWarning( "X Error: %s %d\n" - " Major opcode: %d (%s)\n" - " Resource id: 0x%lx", - errstr, err->error_code, - err->request_code, - request_str, - err->resourceid ); - } else { - // X error for an extension request - const char *extensionName = 0; -#if 0 - if (err->request_code == X11->xrender_major) - extensionName = "RENDER"; - else if (err->request_code == X11->xrandr_major) - extensionName = "RANDR"; - else if (err->request_code == X11->xinput_major) - extensionName = "XInputExtension"; - else if (err->request_code == X11->mitshm_major) - extensionName = "MIT-SHM"; -#endif - char minor_str[256]; - if (extensionName) { - qsnprintf(buffer, 256, "%s.%d", extensionName, err->minor_code); - XGetErrorDatabaseText(dpy, "XRequest", buffer, "", minor_str, 256); - } else { - extensionName = "Uknown extension"; - qsnprintf(minor_str, 256, "Unknown request"); - } - qWarning( "X Error: %s %d\n" - " Extension: %d (%s)\n" - " Minor opcode: %d (%s)\n" - " Resource id: 0x%lx", - errstr, err->error_code, - err->request_code, - extensionName, - err->minor_code, - minor_str, - err->resourceid ); - } - - // ### we really should distinguish between severe, non-severe and - // ### application specific errors - - return 0; -} - - -#ifdef KeyPress -#undef KeyPress -#endif -#ifdef KeyRelease -#undef KeyRelease -#endif - -bool MyDisplay::handleEvent(XEvent *xe) -{ - //qDebug() << "handleEvent" << xe->xany.type << xe->xany.window; - int quit = false; - QTestLiteWindow *xw = 0; - foreach (QTestLiteWindow *w, windowList) { - if (w->winId() == xe->xany.window) { - xw = w; - break; - } - } - if (!xw) { -#ifdef MYX11_DEBUG - qWarning() << "Unknown window" << hex << xe->xany.window << "received event" << xe->type; -#endif - return quit; - } - - switch (xe->type) { - - case ClientMessage: - if (xe->xclient.format == 32 && xe->xclient.message_type == wmProtocolsAtom) { - Atom a = xe->xclient.data.l[0]; - if (a == wmDeleteWindowAtom) - xw->handleCloseEvent(); -#ifdef MYX11_DEBUG - qDebug() << "ClientMessage WM_PROTOCOLS" << a; -#endif - } -#ifdef MYX11_DEBUG - else - qDebug() << "ClientMessage" << xe->xclient.format << xe->xclient.message_type; -#endif - break; - - case Expose: - if (xw) - if (xe->xexpose.count == 0) - xw->paintEvent(); - break; - case ConfigureNotify: - if (xw) - xw->resizeEvent(&xe->xconfigure); - break; - - case ButtonPress: - xw->mousePressEvent(&xe->xbutton); - break; - - case ButtonRelease: - xw->handleMouseEvent(QEvent::MouseButtonRelease, &xe->xbutton); - break; - - case MotionNotify: - xw->handleMouseEvent(QEvent::MouseMove, &xe->xbutton); - break; - - case XKeyPress: - xw->handleKeyEvent(QEvent::KeyPress, &xe->xkey); - break; - - case XKeyRelease: - xw->handleKeyEvent(QEvent::KeyRelease, &xe->xkey); - break; - - case EnterNotify: - xw->handleEnterEvent(); - break; - - case LeaveNotify: - xw->handleLeaveEvent(); - break; - - default: -#ifdef MYX11_DEBUG - qDebug() << hex << xe->xany.window << "Other X event" << xe->type; -#endif - break; - } - return quit; -}; - - - -MyDisplay::MyDisplay() -{ - char *display_name = getenv("DISPLAY"); - display = XOpenDisplay(display_name); - if (!display) { - fprintf(stderr, "Cannot connect to X server: %s\n", - display_name); - exit(1); - } - -#ifndef DONT_USE_MIT_SHM - Status MIT_SHM_extension_supported = XShmQueryExtension (display); - Q_ASSERT(MIT_SHM_extension_supported == True); -#endif - original_x_errhandler = XSetErrorHandler(qt_x_errhandler); - - if (qgetenv("DO_X_SYNCHRONIZE").toInt()) - XSynchronize(display, true); - - screen = DefaultScreen(display); - width = DisplayWidth(display, screen); - height = DisplayHeight(display, screen); - physicalWidth = DisplayWidthMM(display, screen); - physicalHeight = DisplayHeightMM(display, screen); - - int xSocketNumber = XConnectionNumber(display); -#ifdef MYX11_DEBUG - qDebug() << "X socket:"<< xSocketNumber; -#endif - QSocketNotifier *sock = new QSocketNotifier(xSocketNumber, QSocketNotifier::Read, this); - connect(sock, SIGNAL(activated(int)), this, SLOT(eventDispatcher())); - - wmProtocolsAtom = XInternAtom (display, "WM_PROTOCOLS", False); - wmDeleteWindowAtom = XInternAtom (display, "WM_DELETE_WINDOW", False); - - cursors = new MyX11Cursors(display); -} - - -MyDisplay::~MyDisplay() -{ - XCloseDisplay(display); -} - - -void MyDisplay::eventDispatcher() -{ -// qDebug() << "eventDispatcher"; - - - ulong marker = XNextRequest(display); -// int i = 0; - while (XPending(display)) { - XEvent event; - XNextEvent(display, &event); - /* done = */ - handleEvent(&event); - - if (event.xany.serial >= marker) { -#ifdef MYX11_DEBUG - qDebug() << "potential livelock averted"; -#endif -#if 0 - if (XEventsQueued(display, QueuedAfterFlush)) { - qDebug() << " with events queued"; - QTimer::singleShot(0, this, SLOT(eventDispatcher())); - } -#endif - break; - } - } -} - - -QImage MyDisplay::grabWindow(Window window, int x, int y, int w, int h) -{ - if (w == 0 || h ==0) - return QImage(); - - //WinId 0 means the desktop widget - if (!window) - window = rootWindow(); - - XWindowAttributes window_attr; - if (!XGetWindowAttributes(display, window, &window_attr)) - return QImage(); - - if (w < 0) - w = window_attr.width - x; - if (h < 0) - h = window_attr.height - y; - - // Ideally, we should also limit ourselves to the screen area, but the Qt docs say - // that it's "unsafe" to go outside the screen, so we can ignore that problem. - - //We're definitely not optimizing for speed... - XImage *xi = XGetImage(display, window, x, y, w, h, AllPlanes, ZPixmap); - - if (!xi) - return QImage(); - - //taking a copy to make sure we have ownership -- not fast - QImage result = QImage( (uchar*) xi->data, xi->width, xi->height, xi->bytes_per_line, QImage::Format_RGB32 ).copy(); - - XDestroyImage(xi); - - return result; -} - - - - - - - -QT_END_NAMESPACE -#include "qtestlitewindow.moc" diff --git a/src/plugins/platforms/testlite/testlite.pro b/src/plugins/platforms/testlite/testlite.pro deleted file mode 100644 index 05bd384..0000000 --- a/src/plugins/platforms/testlite/testlite.pro +++ /dev/null @@ -1,29 +0,0 @@ -TARGET = qtestlite - -include(../../qpluginbase.pri) -QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms - -SOURCES = \ - main.cpp \ - qtestliteintegration.cpp \ - qtestlitewindowsurface.cpp \ - qtestlitewindow.cpp - -HEADERS = \ - qtestliteintegration.h \ - qtestlitewindowsurface.h \ - qtestlitewindow.h - - -LIBS += -lX11 -lXext - -include (../fontdatabases/genericunix/genericunix.pri) - -contains(QT_CONFIG, opengl) { - QT += opengl - HEADERS += qglxintegration.h - SOURCES += qglxintegration.cpp -} - -target.path += $$[QT_INSTALL_PLUGINS]/platforms -INSTALLS += target diff --git a/src/plugins/platforms/uikit/README b/src/plugins/platforms/uikit/README new file mode 100644 index 0000000..b2984fc --- /dev/null +++ b/src/plugins/platforms/uikit/README @@ -0,0 +1,45 @@ +This is a proof-of-concept implemenation of a UIKit based +QPA plugin. Note that this is completely unsupported, and it is probable +that many parts of QtCore and other Qt Modules don't work properly. + +1) Build Qt + +The example Xcode project in the examples subdirectory requires that you do shadow +builds of Qt in qt-lighthouse-ios-simulator and qt-lighthouse-ios-device directories +parallel to the sources. To build for simulator make sure that both the Simulator +configuration *and* the simulator specific target are active. To build for device +make sure that both the Device configuration *and* the device specific target are +active. + +The setup is configured to use the iOS 4.2 SDKs, you might want to edit the mkspecs +to fit your need. + +After configuring and building Qt you need to also build src/plugins/platforms/uikit. + +Simulator: +---------- +configure -qpa -xplatform qws/macx-iphonesimulator-g++ -arch i386 -developer-build -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -no-opengl -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations + +Device: +------- +configure -qpa -xplatform qws/macx-iphonedevice-g++ -arch armv7 -developer-build -release -no-accessibility -no-qt3support -no-multimedia -no-phonon -no-phonon-backend -no-svg -no-webkit -no-scripttools -no-openssl -no-sql-mysql -no-sql-odbc -no-cups -no-iconv -no-dbus -no-opengl -static -nomake tools -nomake demos -nomake docs -nomake examples -nomake translations + +2) XCode setup: +- there are examples in the examples subdirectory of the platform plugin +- to create something fresh do something like: + - Xcode: Create a "View-based Appplication" + - remove the nibs and view controller and app controller files + - remove the reference to "Main nib file" from plist file + - create a main.mm like in the examples + - add the qmlapplicationviewer sources to your project (including the moc_*.h) + (best to link, not copy), the code for this is from the Qt Creator + mobile Qt Quick application template + - Add the Qt .a libraries, uikit platform plugin and libz (v1.2.3) to Frameworks + - add "$(SRCROOT)/../../../../qt-lighthouse-ios-device/include" (or -simulator) + to the include search paths. + - add "$(SRCROOT)/../qmltest" to the include search path if you didn't copy but + linked to the qmlapplicationviewer + - for device set the architecture to armv7 only + +3) Done: Build and Run. + diff --git a/src/plugins/platforms/uikit/examples/qmltest/main.mm b/src/plugins/platforms/uikit/examples/qmltest/main.mm new file mode 100644 index 0000000..6fd5629 --- /dev/null +++ b/src/plugins/platforms/uikit/examples/qmltest/main.mm @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// main.m +// qmltest +// +// Created by Eike Troll on 18.02.11. +// Copyright 2011 __MyCompanyName__. All rights reserved. +// + +#import <UIKit/UIKit.h> + +#include "qmlapplicationviewer/qmlapplicationviewer.h" + +#include <QtGui/QApplication> +#include <QtCore/QtPlugin> + +Q_IMPORT_PLUGIN(UIKit) + +int main(int argc, char *argv[]) { + + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + + setenv("QT_QPA_PLATFORM","uikit",1); + + QApplication app(argc, argv); + QmlApplicationViewer viewer; + viewer.setOrientation(QmlApplicationViewer::ScreenOrientationAuto); + NSString *resourcePath = [[NSBundle mainBundle] resourcePath]; + viewer.setMainQmlFile(QString::fromUtf8([[resourcePath stringByAppendingPathComponent:@"qml/main.qml"] UTF8String])); + viewer.showMaximized(); + int retVal = app.exec(); + [pool release]; + return retVal; +} diff --git a/src/plugins/platforms/uikit/examples/qmltest/qml/main.qml b/src/plugins/platforms/uikit/examples/qmltest/qml/main.qml new file mode 100644 index 0000000..889a6d0 --- /dev/null +++ b/src/plugins/platforms/uikit/examples/qmltest/qml/main.qml @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the examples of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:BSD$ +** You may use this file under the terms of the BSD license as follows: +** +** "Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions are +** met: +** * Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** * Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in +** the documentation and/or other materials provided with the +** distribution. +** * Neither the name of Nokia Corporation and its Subsidiary(-ies) nor +** the names of its contributors may be used to endorse or promote +** products derived from this software without specific prior written +** permission. +** +** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE." +** $QT_END_LICENSE$ +** +****************************************************************************/ + +import QtQuick 1.0 + +Rectangle { + id: box + width: 350; height: 250 + + Rectangle { + id: redSquare + width: 80; height: 80 + anchors.top: parent.top; anchors.left: parent.left; anchors.margins: 10 + color: "red" + + Text { text: "Click"; font.pixelSize: 16; anchors.centerIn: parent } + + MouseArea { + anchors.fill: parent + hoverEnabled: true + acceptedButtons: Qt.LeftButton | Qt.RightButton + + onEntered: info.text = 'Entered' + onExited: info.text = 'Exited (pressed=' + pressed + ')' + + onPressed: { + info.text = 'Pressed (button=' + (mouse.button == Qt.RightButton ? 'right' : 'left') + + ' shift=' + (mouse.modifiers & Qt.ShiftModifier ? 'true' : 'false') + ')' + var posInBox = redSquare.mapToItem(box, mouse.x, mouse.y) + posInfo.text = + mouse.x + ',' + mouse.y + ' in square' + + ' (' + posInBox.x + ',' + posInBox.y + ' in window)' + } + + onReleased: { + info.text = 'Released (isClick=' + mouse.isClick + ' wasHeld=' + mouse.wasHeld + ')' + posInfo.text = '' + } + + onPressAndHold: info.text = 'Press and hold' + onClicked: info.text = 'Clicked (wasHeld=' + mouse.wasHeld + ')' + onDoubleClicked: info.text = 'Double clicked' + } + } + + Rectangle { + id: blueSquare + width: 80; height: 80 + x: box.width - width - 10; y: 10 // making this item draggable, so don't use anchors + color: "blue" + + Text { text: "Drag"; font.pixelSize: 16; color: "white"; anchors.centerIn: parent } + + MouseArea { + anchors.fill: parent + drag.target: blueSquare + drag.axis: Drag.XandYAxis + drag.minimumX: 0 + drag.maximumX: box.width - parent.width + drag.minimumY: 0 + drag.maximumY: box.height - parent.width + } + } + + Text { + id: info + anchors.bottom: posInfo.top; anchors.horizontalCenter: parent.horizontalCenter; anchors.margins: 30 + + onTextChanged: console.log(text) + } + + Text { + id: posInfo + anchors.bottom: parent.bottom; anchors.horizontalCenter: parent.horizontalCenter; anchors.margins: 30 + } +} diff --git a/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/moc_qmlapplicationviewer.cpp b/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/moc_qmlapplicationviewer.cpp new file mode 100644 index 0000000..a2b40ec --- /dev/null +++ b/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/moc_qmlapplicationviewer.cpp @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +/**************************************************************************** +** Meta object code from reading C++ file 'qmlapplicationviewer.h' +** +** Created: Fri Feb 18 17:53:42 2011 +** by: The Qt Meta Object Compiler version 62 (Qt 4.7.2) +** +** WARNING! All changes made in this file will be lost! +*****************************************************************************/ + +#include "qmlapplicationviewer.h" +#if !defined(Q_MOC_OUTPUT_REVISION) +#error "The header file 'qmlapplicationviewer.h' doesn't include <QObject>." +#elif Q_MOC_OUTPUT_REVISION != 62 +#error "This file was generated using the moc from 4.7.2. It" +#error "cannot be used with the include files from this version of Qt." +#error "(The moc has changed too much.)" +#endif + +QT_BEGIN_MOC_NAMESPACE +static const uint qt_meta_data_QmlApplicationViewer[] = { + + // content: + 5, // revision + 0, // classname + 0, 0, // classinfo + 0, 0, // methods + 0, 0, // properties + 0, 0, // enums/sets + 0, 0, // constructors + 0, // flags + 0, // signalCount + + 0 // eod +}; + +static const char qt_meta_stringdata_QmlApplicationViewer[] = { + "QmlApplicationViewer\0" +}; + +const QMetaObject QmlApplicationViewer::staticMetaObject = { + { &QDeclarativeView::staticMetaObject, qt_meta_stringdata_QmlApplicationViewer, + qt_meta_data_QmlApplicationViewer, 0 } +}; + +#ifdef Q_NO_DATA_RELOCATION +const QMetaObject &QmlApplicationViewer::getStaticMetaObject() { return staticMetaObject; } +#endif //Q_NO_DATA_RELOCATION + +const QMetaObject *QmlApplicationViewer::metaObject() const +{ + return QObject::d_ptr->metaObject ? QObject::d_ptr->metaObject : &staticMetaObject; +} + +void *QmlApplicationViewer::qt_metacast(const char *_clname) +{ + if (!_clname) return 0; + if (!strcmp(_clname, qt_meta_stringdata_QmlApplicationViewer)) + return static_cast<void*>(const_cast< QmlApplicationViewer*>(this)); + return QDeclarativeView::qt_metacast(_clname); +} + +int QmlApplicationViewer::qt_metacall(QMetaObject::Call _c, int _id, void **_a) +{ + _id = QDeclarativeView::qt_metacall(_c, _id, _a); + if (_id < 0) + return _id; + return _id; +} +QT_END_MOC_NAMESPACE diff --git a/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/qmlapplicationviewer.cpp b/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/qmlapplicationviewer.cpp new file mode 100644 index 0000000..72f8c52 --- /dev/null +++ b/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/qmlapplicationviewer.cpp @@ -0,0 +1,196 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// checksum 0x17fa version 0x3000a +/* + This file was generated by the Qt Quick Application wizard of Qt Creator. + QmlApplicationViewer is a convenience class containing mobile device specific + code such as screen orientation handling. Also QML paths and debugging are + handled here. + It is recommended not to modify this file, since newer versions of Qt Creator + may offer an updated version of it. +*/ + +#include "qmlapplicationviewer.h" + +#include <QtCore/QCoreApplication> +#include <QtCore/QDir> +#include <QtCore/QFileInfo> +#include <QtDeclarative/QDeclarativeComponent> +#include <QtDeclarative/QDeclarativeEngine> +#include <QtDeclarative/QDeclarativeContext> + +#if defined(QMLJSDEBUGGER) +#include <qt_private/qdeclarativedebughelper_p.h> +#endif + +#if defined(QMLJSDEBUGGER) && !defined(NO_JSDEBUGGER) +#include <jsdebuggeragent.h> +#endif +#if defined(QMLJSDEBUGGER) && !defined(NO_QMLOBSERVER) +#include <qdeclarativeviewobserver.h> +#endif + +#if defined(QMLJSDEBUGGER) + +// Enable debugging before any QDeclarativeEngine is created +struct QmlJsDebuggingEnabler +{ + QmlJsDebuggingEnabler() + { + QDeclarativeDebugHelper::enableDebugging(); + } +}; + +// Execute code in constructor before first QDeclarativeEngine is instantiated +static QmlJsDebuggingEnabler enableDebuggingHelper; + +#endif // QMLJSDEBUGGER + +class QmlApplicationViewerPrivate +{ + QString mainQmlFile; + friend class QmlApplicationViewer; + static QString adjustPath(const QString &path); +}; + +QString QmlApplicationViewerPrivate::adjustPath(const QString &path) +{ +#ifdef Q_OS_UNIX +#ifdef Q_OS_MAC + if (!QDir::isAbsolutePath(path)) + return QCoreApplication::applicationDirPath() + + QLatin1String("/../Resources/") + path; +#else + const QString pathInShareDir = QCoreApplication::applicationDirPath() + + QLatin1String("/../share/") + + QFileInfo(QCoreApplication::applicationFilePath()).fileName() + + QLatin1Char('/') + path; + if (QFileInfo(pathInShareDir).exists()) + return pathInShareDir; +#endif +#endif + return path; +} + +QmlApplicationViewer::QmlApplicationViewer(QWidget *parent) : + QDeclarativeView(parent), + m_d(new QmlApplicationViewerPrivate) +{ + connect(engine(), SIGNAL(quit()), SLOT(close())); + setResizeMode(QDeclarativeView::SizeRootObjectToView); +#if defined(QMLJSDEBUGGER) && !defined(NO_JSDEBUGGER) + new QmlJSDebugger::JSDebuggerAgent(engine()); +#endif +#if defined(QMLJSDEBUGGER) && !defined(NO_QMLOBSERVER) + new QmlJSDebugger::QDeclarativeViewObserver(this, parent); +#endif +} + +QmlApplicationViewer::~QmlApplicationViewer() +{ + delete m_d; +} + +void QmlApplicationViewer::setMainQmlFile(const QString &file) +{ + m_d->mainQmlFile = QmlApplicationViewerPrivate::adjustPath(file); + setSource(QUrl::fromLocalFile(m_d->mainQmlFile)); +} + +void QmlApplicationViewer::addImportPath(const QString &path) +{ + engine()->addImportPath(QmlApplicationViewerPrivate::adjustPath(path)); +} + +void QmlApplicationViewer::setOrientation(ScreenOrientation orientation) +{ +//#if defined(Q_OS_SYMBIAN) +// // If the version of Qt on the device is < 4.7.2, that attribute won't work +// if (orientation != ScreenOrientationAuto) { +// const QStringList v = QString::fromAscii(qVersion()).split(QLatin1Char('.')); +// if (v.count() == 3 && (v.at(0).toInt() << 16 | v.at(1).toInt() << 8 | v.at(2).toInt()) < 0x040702) { +// qWarning("Screen orientation locking only supported with Qt 4.7.2 and above"); +// return; +// } +// } +//#endif // Q_OS_SYMBIAN +// +// Qt::WidgetAttribute attribute; +// switch (orientation) { +//#if QT_VERSION < 0x040702 +// // Qt < 4.7.2 does not yet have the Qt::WA_*Orientation attributes +// case ScreenOrientationLockPortrait: +// attribute = static_cast<Qt::WidgetAttribute>(128); +// break; +// case ScreenOrientationLockLandscape: +// attribute = static_cast<Qt::WidgetAttribute>(129); +// break; +// default: +// case ScreenOrientationAuto: +// attribute = static_cast<Qt::WidgetAttribute>(130); +// break; +//#else // QT_VERSION < 0x040702 +// case ScreenOrientationLockPortrait: +// attribute = Qt::WA_LockPortraitOrientation; +// break; +// case ScreenOrientationLockLandscape: +// attribute = Qt::WA_LockLandscapeOrientation; +// break; +// default: +// case ScreenOrientationAuto: +// attribute = Qt::WA_AutoOrientation; +// break; +//#endif // QT_VERSION < 0x040702 +// }; +// setAttribute(attribute, true); +} + +void QmlApplicationViewer::showExpanded() +{ +#ifdef Q_OS_SYMBIAN + showFullScreen(); +#elif defined(Q_WS_MAEMO_5) || defined(Q_WS_MAEMO_6) + showMaximized(); +#else + show(); +#endif +} diff --git a/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/qmlapplicationviewer.h b/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/qmlapplicationviewer.h new file mode 100644 index 0000000..01b2af0 --- /dev/null +++ b/src/plugins/platforms/uikit/examples/qmltest/qmlapplicationviewer/qmlapplicationviewer.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// checksum 0x5a59 version 0x3000a +/* + This file was generated by the Qt Quick Application wizard of Qt Creator. + QmlApplicationViewer is a convenience class containing mobile device specific + code such as screen orientation handling. Also QML paths and debugging are + handled here. + It is recommended not to modify this file, since newer versions of Qt Creator + may offer an updated version of it. +*/ + +#ifndef QMLAPPLICATIONVIEWER_H +#define QMLAPPLICATIONVIEWER_H + +#include <QtDeclarative/QDeclarativeView> + +class QmlApplicationViewer : public QDeclarativeView +{ + Q_OBJECT + +public: + enum ScreenOrientation { + ScreenOrientationLockPortrait, + ScreenOrientationLockLandscape, + ScreenOrientationAuto + }; + + explicit QmlApplicationViewer(QWidget *parent = 0); + virtual ~QmlApplicationViewer(); + + void setMainQmlFile(const QString &file); + void addImportPath(const QString &path); + void setOrientation(ScreenOrientation orientation); + void showExpanded(); + +private: + class QmlApplicationViewerPrivate *m_d; +}; + +#endif // QMLAPPLICATIONVIEWER_H diff --git a/src/plugins/platforms/uikit/examples/qmltest/qmltest-Info.plist b/src/plugins/platforms/uikit/examples/qmltest/qmltest-Info.plist new file mode 100644 index 0000000..1566585 --- /dev/null +++ b/src/plugins/platforms/uikit/examples/qmltest/qmltest-Info.plist @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> +<plist version="1.0"> +<dict> + <key>CFBundleDevelopmentRegion</key> + <string>English</string> + <key>CFBundleDisplayName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundleExecutable</key> + <string>${EXECUTABLE_NAME}</string> + <key>CFBundleIconFile</key> + <string></string> + <key>CFBundleIdentifier</key> + <string>com.yourcompany.${PRODUCT_NAME:rfc1034identifier}</string> + <key>CFBundleInfoDictionaryVersion</key> + <string>6.0</string> + <key>CFBundleName</key> + <string>${PRODUCT_NAME}</string> + <key>CFBundlePackageType</key> + <string>APPL</string> + <key>CFBundleSignature</key> + <string>????</string> + <key>CFBundleVersion</key> + <string>1.0</string> + <key>LSRequiresIPhoneOS</key> + <true/> +</dict> +</plist> diff --git a/src/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj b/src/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj new file mode 100755 index 0000000..fc4f1df --- /dev/null +++ b/src/plugins/platforms/uikit/examples/qmltest/qmltest.xcodeproj/project.pbxproj @@ -0,0 +1,463 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 45; + objects = { + +/* Begin PBXBuildFile section */ + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; + D3CAA7C813264AAD008BB877 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7C713264AAD008BB877 /* main.mm */; }; + D3CAA7E613264EA6008BB877 /* moc_qmlapplicationviewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7E313264EA6008BB877 /* moc_qmlapplicationviewer.cpp */; }; + D3CAA7E713264EA6008BB877 /* qmlapplicationviewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7E413264EA6008BB877 /* qmlapplicationviewer.cpp */; }; + D3CAA7EC13264F52008BB877 /* main.mm in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7C713264AAD008BB877 /* main.mm */; }; + D3CAA7ED13264F52008BB877 /* moc_qmlapplicationviewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7E313264EA6008BB877 /* moc_qmlapplicationviewer.cpp */; }; + D3CAA7EE13264F52008BB877 /* qmlapplicationviewer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = D3CAA7E413264EA6008BB877 /* qmlapplicationviewer.cpp */; }; + D3CAA7F013264F52008BB877 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; + D3CAA7F113264F52008BB877 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + D3CAA7F213264F52008BB877 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 288765A40DF7441C002DB57D /* CoreGraphics.framework */; }; + D3CAA7FA13264F8A008BB877 /* libz.1.2.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA7F913264F8A008BB877 /* libz.1.2.3.dylib */; }; + D3CAA81113264FF0008BB877 /* libz.1.2.3.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA7F913264F8A008BB877 /* libz.1.2.3.dylib */; }; + D3CAA81B13265056008BB877 /* libQtCore_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA81613265056008BB877 /* libQtCore_debug.a */; }; + D3CAA81C13265056008BB877 /* libQtDeclarative_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA81713265056008BB877 /* libQtDeclarative_debug.a */; }; + D3CAA81D13265056008BB877 /* libQtGui_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA81813265056008BB877 /* libQtGui_debug.a */; }; + D3CAA81E13265056008BB877 /* libQtScript_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA81913265056008BB877 /* libQtScript_debug.a */; }; + D3CAA81F13265056008BB877 /* libQtSql_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA81A13265056008BB877 /* libQtSql_debug.a */; }; + D3CAA8211326507D008BB877 /* libquikit_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA8201326507D008BB877 /* libquikit_debug.a */; }; + D3CAA82813265220008BB877 /* libQtNetwork_debug.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3CAA82713265220008BB877 /* libQtNetwork_debug.a */; }; + D3CAA88A132652E5008BB877 /* fonts in Resources */ = {isa = PBXBuildFile; fileRef = D3CAA836132652E5008BB877 /* fonts */; }; + D3CAA88B132652E5008BB877 /* fonts in Resources */ = {isa = PBXBuildFile; fileRef = D3CAA836132652E5008BB877 /* fonts */; }; + D3CAA89113265310008BB877 /* qml in Resources */ = {isa = PBXBuildFile; fileRef = D3CAA88E13265310008BB877 /* qml */; }; + D3CAA89213265310008BB877 /* qml in Resources */ = {isa = PBXBuildFile; fileRef = D3CAA88E13265310008BB877 /* qml */; }; + D3D817B2132A2CFD00CDE422 /* libQtCore.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817AA132A2CFD00CDE422 /* libQtCore.a */; }; + D3D817B3132A2CFD00CDE422 /* libQtDeclarative.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817AB132A2CFD00CDE422 /* libQtDeclarative.a */; }; + D3D817B4132A2CFD00CDE422 /* libQtGui.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817AC132A2CFD00CDE422 /* libQtGui.a */; }; + D3D817B5132A2CFD00CDE422 /* libQtNetwork.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817AD132A2CFD00CDE422 /* libQtNetwork.a */; }; + D3D817B6132A2CFD00CDE422 /* libQtScript.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817AE132A2CFD00CDE422 /* libQtScript.a */; }; + D3D817B7132A2CFD00CDE422 /* libQtSql.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817AF132A2CFD00CDE422 /* libQtSql.a */; }; + D3D817B8132A2CFD00CDE422 /* libQtXml.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817B0132A2CFD00CDE422 /* libQtXml.a */; }; + D3D817B9132A2CFD00CDE422 /* libQtXmlPatterns.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817B1132A2CFD00CDE422 /* libQtXmlPatterns.a */; }; + D3D817BB132A2D0E00CDE422 /* libquikit.a in Frameworks */ = {isa = PBXBuildFile; fileRef = D3D817BA132A2D0E00CDE422 /* libquikit.a */; }; +/* End PBXBuildFile section */ + +/* Begin PBXFileReference section */ + 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; + 1D6058910D05DD3D006BFB54 /* qmltest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = qmltest.app; sourceTree = BUILT_PRODUCTS_DIR; }; + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 288765A40DF7441C002DB57D /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; + 32CA4F630368D1EE00C91783 /* qmltest_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = qmltest_Prefix.pch; sourceTree = "<group>"; }; + 8D1107310486CEB800E47090 /* qmltest-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "qmltest-Info.plist"; plistStructureDefinitionIdentifier = "com.apple.xcode.plist.structure-definition.iphone.info-plist"; sourceTree = "<group>"; }; + D3CAA7C713264AAD008BB877 /* main.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = main.mm; sourceTree = "<group>"; }; + D3CAA7E313264EA6008BB877 /* moc_qmlapplicationviewer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = moc_qmlapplicationviewer.cpp; path = qmlapplicationviewer/moc_qmlapplicationviewer.cpp; sourceTree = "<group>"; }; + D3CAA7E413264EA6008BB877 /* qmlapplicationviewer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = qmlapplicationviewer.cpp; path = qmlapplicationviewer/qmlapplicationviewer.cpp; sourceTree = "<group>"; }; + D3CAA7E513264EA6008BB877 /* qmlapplicationviewer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = qmlapplicationviewer.h; path = qmlapplicationviewer/qmlapplicationviewer.h; sourceTree = "<group>"; }; + D3CAA7F613264F52008BB877 /* qmltest.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = qmltest.app; sourceTree = BUILT_PRODUCTS_DIR; }; + D3CAA7F913264F8A008BB877 /* libz.1.2.3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.1.2.3.dylib; path = usr/lib/libz.1.2.3.dylib; sourceTree = SDKROOT; }; + D3CAA81613265056008BB877 /* libQtCore_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtCore_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtCore_debug.a"; sourceTree = SOURCE_ROOT; }; + D3CAA81713265056008BB877 /* libQtDeclarative_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtDeclarative_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtDeclarative_debug.a"; sourceTree = SOURCE_ROOT; }; + D3CAA81813265056008BB877 /* libQtGui_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtGui_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtGui_debug.a"; sourceTree = SOURCE_ROOT; }; + D3CAA81913265056008BB877 /* libQtScript_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtScript_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtScript_debug.a"; sourceTree = SOURCE_ROOT; }; + D3CAA81A13265056008BB877 /* libQtSql_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtSql_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtSql_debug.a"; sourceTree = SOURCE_ROOT; }; + D3CAA8201326507D008BB877 /* libquikit_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libquikit_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/plugins/platforms/libquikit_debug.a"; sourceTree = SOURCE_ROOT; }; + D3CAA82713265220008BB877 /* libQtNetwork_debug.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtNetwork_debug.a; path = "../../../../../../../qt-lighthouse-ios-simulator/lib/libQtNetwork_debug.a"; sourceTree = SOURCE_ROOT; }; + D3CAA836132652E5008BB877 /* fonts */ = {isa = PBXFileReference; lastKnownFileType = folder; name = fonts; path = ../../../../../../lib/fonts; sourceTree = SOURCE_ROOT; }; + D3CAA88E13265310008BB877 /* qml */ = {isa = PBXFileReference; lastKnownFileType = folder; path = qml; sourceTree = SOURCE_ROOT; }; + D3D817AA132A2CFD00CDE422 /* libQtCore.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtCore.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtCore.a"; sourceTree = SOURCE_ROOT; }; + D3D817AB132A2CFD00CDE422 /* libQtDeclarative.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtDeclarative.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtDeclarative.a"; sourceTree = SOURCE_ROOT; }; + D3D817AC132A2CFD00CDE422 /* libQtGui.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtGui.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtGui.a"; sourceTree = SOURCE_ROOT; }; + D3D817AD132A2CFD00CDE422 /* libQtNetwork.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtNetwork.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtNetwork.a"; sourceTree = SOURCE_ROOT; }; + D3D817AE132A2CFD00CDE422 /* libQtScript.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtScript.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtScript.a"; sourceTree = SOURCE_ROOT; }; + D3D817AF132A2CFD00CDE422 /* libQtSql.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtSql.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtSql.a"; sourceTree = SOURCE_ROOT; }; + D3D817B0132A2CFD00CDE422 /* libQtXml.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtXml.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtXml.a"; sourceTree = SOURCE_ROOT; }; + D3D817B1132A2CFD00CDE422 /* libQtXmlPatterns.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libQtXmlPatterns.a; path = "../../../../../../../qt-lighthouse-ios-device/lib/libQtXmlPatterns.a"; sourceTree = SOURCE_ROOT; }; + D3D817BA132A2D0E00CDE422 /* libquikit.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libquikit.a; path = "../../../../../../../qt-lighthouse-ios-device/plugins/platforms/libquikit.a"; sourceTree = SOURCE_ROOT; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + 1D60588F0D05DD3D006BFB54 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */, + 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */, + 288765A50DF7441C002DB57D /* CoreGraphics.framework in Frameworks */, + D3CAA7FA13264F8A008BB877 /* libz.1.2.3.dylib in Frameworks */, + D3CAA81B13265056008BB877 /* libQtCore_debug.a in Frameworks */, + D3CAA81C13265056008BB877 /* libQtDeclarative_debug.a in Frameworks */, + D3CAA81D13265056008BB877 /* libQtGui_debug.a in Frameworks */, + D3CAA81E13265056008BB877 /* libQtScript_debug.a in Frameworks */, + D3CAA81F13265056008BB877 /* libQtSql_debug.a in Frameworks */, + D3CAA8211326507D008BB877 /* libquikit_debug.a in Frameworks */, + D3CAA82813265220008BB877 /* libQtNetwork_debug.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3CAA7EF13264F52008BB877 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + D3CAA7F013264F52008BB877 /* Foundation.framework in Frameworks */, + D3CAA7F113264F52008BB877 /* UIKit.framework in Frameworks */, + D3CAA7F213264F52008BB877 /* CoreGraphics.framework in Frameworks */, + D3CAA81113264FF0008BB877 /* libz.1.2.3.dylib in Frameworks */, + D3D817B2132A2CFD00CDE422 /* libQtCore.a in Frameworks */, + D3D817B3132A2CFD00CDE422 /* libQtDeclarative.a in Frameworks */, + D3D817B4132A2CFD00CDE422 /* libQtGui.a in Frameworks */, + D3D817B5132A2CFD00CDE422 /* libQtNetwork.a in Frameworks */, + D3D817B6132A2CFD00CDE422 /* libQtScript.a in Frameworks */, + D3D817B7132A2CFD00CDE422 /* libQtSql.a in Frameworks */, + D3D817B8132A2CFD00CDE422 /* libQtXml.a in Frameworks */, + D3D817B9132A2CFD00CDE422 /* libQtXmlPatterns.a in Frameworks */, + D3D817BB132A2D0E00CDE422 /* libquikit.a in Frameworks */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + 19C28FACFE9D520D11CA2CBB /* Products */ = { + isa = PBXGroup; + children = ( + 1D6058910D05DD3D006BFB54 /* qmltest.app */, + D3CAA7F613264F52008BB877 /* qmltest.app */, + ); + name = Products; + sourceTree = "<group>"; + }; + 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = { + isa = PBXGroup; + children = ( + 29B97315FDCFA39411CA2CEA /* Other Sources */, + 29B97317FDCFA39411CA2CEA /* Resources */, + D3CAA7E213264E8C008BB877 /* QMLApplicationViewer */, + 29B97323FDCFA39411CA2CEA /* Frameworks */, + 19C28FACFE9D520D11CA2CBB /* Products */, + ); + name = CustomTemplate; + sourceTree = "<group>"; + }; + 29B97315FDCFA39411CA2CEA /* Other Sources */ = { + isa = PBXGroup; + children = ( + 32CA4F630368D1EE00C91783 /* qmltest_Prefix.pch */, + D3CAA7C713264AAD008BB877 /* main.mm */, + ); + name = "Other Sources"; + sourceTree = "<group>"; + }; + 29B97317FDCFA39411CA2CEA /* Resources */ = { + isa = PBXGroup; + children = ( + D3CAA88E13265310008BB877 /* qml */, + D3CAA836132652E5008BB877 /* fonts */, + 8D1107310486CEB800E47090 /* qmltest-Info.plist */, + ); + name = Resources; + sourceTree = "<group>"; + }; + 29B97323FDCFA39411CA2CEA /* Frameworks */ = { + isa = PBXGroup; + children = ( + D3CAA81513265035008BB877 /* Simulator */, + D3CAA8141326500A008BB877 /* Device */, + 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */, + 1D30AB110D05D00D00671497 /* Foundation.framework */, + 288765A40DF7441C002DB57D /* CoreGraphics.framework */, + D3CAA7F913264F8A008BB877 /* libz.1.2.3.dylib */, + ); + name = Frameworks; + sourceTree = "<group>"; + }; + D3CAA7E213264E8C008BB877 /* QMLApplicationViewer */ = { + isa = PBXGroup; + children = ( + D3CAA7E313264EA6008BB877 /* moc_qmlapplicationviewer.cpp */, + D3CAA7E413264EA6008BB877 /* qmlapplicationviewer.cpp */, + D3CAA7E513264EA6008BB877 /* qmlapplicationviewer.h */, + ); + name = QMLApplicationViewer; + sourceTree = "<group>"; + }; + D3CAA8141326500A008BB877 /* Device */ = { + isa = PBXGroup; + children = ( + D3D817BA132A2D0E00CDE422 /* libquikit.a */, + D3D817AA132A2CFD00CDE422 /* libQtCore.a */, + D3D817AB132A2CFD00CDE422 /* libQtDeclarative.a */, + D3D817AC132A2CFD00CDE422 /* libQtGui.a */, + D3D817AD132A2CFD00CDE422 /* libQtNetwork.a */, + D3D817AE132A2CFD00CDE422 /* libQtScript.a */, + D3D817AF132A2CFD00CDE422 /* libQtSql.a */, + D3D817B0132A2CFD00CDE422 /* libQtXml.a */, + D3D817B1132A2CFD00CDE422 /* libQtXmlPatterns.a */, + ); + name = Device; + sourceTree = "<group>"; + }; + D3CAA81513265035008BB877 /* Simulator */ = { + isa = PBXGroup; + children = ( + D3CAA8201326507D008BB877 /* libquikit_debug.a */, + D3CAA81613265056008BB877 /* libQtCore_debug.a */, + D3CAA81713265056008BB877 /* libQtDeclarative_debug.a */, + D3CAA81813265056008BB877 /* libQtGui_debug.a */, + D3CAA82713265220008BB877 /* libQtNetwork_debug.a */, + D3CAA81913265056008BB877 /* libQtScript_debug.a */, + D3CAA81A13265056008BB877 /* libQtSql_debug.a */, + ); + name = Simulator; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + 1D6058900D05DD3D006BFB54 /* qmltest simulator */ = { + isa = PBXNativeTarget; + buildConfigurationList = 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "qmltest simulator" */; + buildPhases = ( + 1D60588D0D05DD3D006BFB54 /* Resources */, + 1D60588E0D05DD3D006BFB54 /* Sources */, + 1D60588F0D05DD3D006BFB54 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "qmltest simulator"; + productName = qmltest; + productReference = 1D6058910D05DD3D006BFB54 /* qmltest.app */; + productType = "com.apple.product-type.application"; + }; + D3CAA7E813264F52008BB877 /* qmltest device */ = { + isa = PBXNativeTarget; + buildConfigurationList = D3CAA7F313264F52008BB877 /* Build configuration list for PBXNativeTarget "qmltest device" */; + buildPhases = ( + D3CAA7E913264F52008BB877 /* Resources */, + D3CAA7EB13264F52008BB877 /* Sources */, + D3CAA7EF13264F52008BB877 /* Frameworks */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "qmltest device"; + productName = qmltest; + productReference = D3CAA7F613264F52008BB877 /* qmltest.app */; + productType = "com.apple.product-type.application"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + 29B97313FDCFA39411CA2CEA /* Project object */ = { + isa = PBXProject; + buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "qmltest" */; + compatibilityVersion = "Xcode 3.1"; + developmentRegion = English; + hasScannedForEncodings = 1; + knownRegions = ( + English, + Japanese, + French, + German, + ); + mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + 1D6058900D05DD3D006BFB54 /* qmltest simulator */, + D3CAA7E813264F52008BB877 /* qmltest device */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXResourcesBuildPhase section */ + 1D60588D0D05DD3D006BFB54 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3CAA88A132652E5008BB877 /* fonts in Resources */, + D3CAA89113265310008BB877 /* qml in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3CAA7E913264F52008BB877 /* Resources */ = { + isa = PBXResourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3CAA88B132652E5008BB877 /* fonts in Resources */, + D3CAA89213265310008BB877 /* qml in Resources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXResourcesBuildPhase section */ + +/* Begin PBXSourcesBuildPhase section */ + 1D60588E0D05DD3D006BFB54 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3CAA7C813264AAD008BB877 /* main.mm in Sources */, + D3CAA7E613264EA6008BB877 /* moc_qmlapplicationviewer.cpp in Sources */, + D3CAA7E713264EA6008BB877 /* qmlapplicationviewer.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; + D3CAA7EB13264F52008BB877 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + D3CAA7EC13264F52008BB877 /* main.mm in Sources */, + D3CAA7ED13264F52008BB877 /* moc_qmlapplicationviewer.cpp in Sources */, + D3CAA7EE13264F52008BB877 /* qmlapplicationviewer.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + 1D6058940D05DD3E006BFB54 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = qmltest_Prefix.pch; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-simulator/include\"/**"; + INFOPLIST_FILE = "qmltest-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-simulator/lib\"", + "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-simulator/plugins/platforms\"", + ); + PRODUCT_NAME = qmltest; + }; + name = Debug; + }; + 1D6058950D05DD3E006BFB54 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = qmltest_Prefix.pch; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-simulator/include\"/**"; + INFOPLIST_FILE = "qmltest-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-simulator/lib\"", + "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-simulator/plugins/platforms\"", + ); + PRODUCT_NAME = qmltest; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; + C01FCF4F08A954540054247B /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + PREBINDING = NO; + SDKROOT = iphoneos; + }; + name = Debug; + }; + C01FCF5008A954540054247B /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ARCHS = "$(ARCHS_STANDARD_32_BIT)"; + "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; + GCC_C_LANGUAGE_STANDARD = c99; + GCC_WARN_ABOUT_RETURN_TYPE = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; + PREBINDING = NO; + SDKROOT = iphoneos; + }; + name = Release; + }; + D3CAA7F413264F52008BB877 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; + COPY_PHASE_STRIP = NO; + GCC_DYNAMIC_NO_PIC = NO; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = qmltest_Prefix.pch; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-device/include\"/**"; + INFOPLIST_FILE = "qmltest-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-device/lib\"", + "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-device/plugins/platforms\"", + ); + PRODUCT_NAME = qmltest; + }; + name = Debug; + }; + D3CAA7F513264F52008BB877 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + ARCHS = "$(ARCHS_UNIVERSAL_IPHONE_OS)"; + COPY_PHASE_STRIP = YES; + GCC_PRECOMPILE_PREFIX_HEADER = YES; + GCC_PREFIX_HEADER = qmltest_Prefix.pch; + HEADER_SEARCH_PATHS = "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-device/include\"/**"; + INFOPLIST_FILE = "qmltest-Info.plist"; + LIBRARY_SEARCH_PATHS = ( + "$(inherited)", + "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-device/lib\"", + "\"$(SRCROOT)/../../../../../../../qt-lighthouse-ios-device/plugins/platforms\"", + ); + PRODUCT_NAME = qmltest; + VALIDATE_PRODUCT = YES; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + 1D6058960D05DD3E006BFB54 /* Build configuration list for PBXNativeTarget "qmltest simulator" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + 1D6058940D05DD3E006BFB54 /* Debug */, + 1D6058950D05DD3E006BFB54 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + C01FCF4E08A954540054247B /* Build configuration list for PBXProject "qmltest" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + C01FCF4F08A954540054247B /* Debug */, + C01FCF5008A954540054247B /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + D3CAA7F313264F52008BB877 /* Build configuration list for PBXNativeTarget "qmltest device" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + D3CAA7F413264F52008BB877 /* Debug */, + D3CAA7F513264F52008BB877 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = 29B97313FDCFA39411CA2CEA /* Project object */; +} diff --git a/src/plugins/platforms/uikit/examples/qmltest/qmltest_Prefix.pch b/src/plugins/platforms/uikit/examples/qmltest/qmltest_Prefix.pch new file mode 100644 index 0000000..c06715c --- /dev/null +++ b/src/plugins/platforms/uikit/examples/qmltest/qmltest_Prefix.pch @@ -0,0 +1,8 @@ +// +// Prefix header for all source files of the 'qmltest' target in the 'qmltest' project +// + +#ifdef __OBJC__ + #import <Foundation/Foundation.h> + #import <UIKit/UIKit.h> +#endif diff --git a/src/plugins/platforms/uikit/main.mm b/src/plugins/platforms/uikit/main.mm new file mode 100644 index 0000000..1ef69fa --- /dev/null +++ b/src/plugins/platforms/uikit/main.mm @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <UIKit/UIKit.h> + +#include <QtGui/QPlatformIntegrationPlugin> +#include "quikitintegration.h" + +QT_BEGIN_NAMESPACE + +class QUIKitIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QUIKitIntegrationPlugin::keys() const +{ + QStringList list; + list << "UIKit"; + return list; +} + +QPlatformIntegration * QUIKitIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "uikit") + return new QUIKitIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(UIKit, QUIKitIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikiteventloop.h b/src/plugins/platforms/uikit/quikiteventloop.h new file mode 100644 index 0000000..cf5c682 --- /dev/null +++ b/src/plugins/platforms/uikit/quikiteventloop.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QUIKITEVENTLOOP_H +#define QUIKITEVENTLOOP_H + +#include <QtGui/QPlatformEventLoopIntegration> + +@class EventLoopHelper; +@class NSTimer; + +QT_BEGIN_NAMESPACE + +class QUIKitEventLoop : public QPlatformEventLoopIntegration +{ +public: + QUIKitEventLoop(); + ~QUIKitEventLoop(); + + void startEventLoop(); + void quitEventLoop(); + void qtNeedsToProcessEvents(); + + EventLoopHelper *mHelper; + NSTimer *mTimer; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/uikit/quikiteventloop.mm b/src/plugins/platforms/uikit/quikiteventloop.mm new file mode 100644 index 0000000..70757b1 --- /dev/null +++ b/src/plugins/platforms/uikit/quikiteventloop.mm @@ -0,0 +1,160 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "quikiteventloop.h" +#include "quikitwindow.h" +#include "quikitwindowsurface.h" + +#include <UIKit/UIKit.h> + +#include <QtGui/QApplication> +#include <QtGui/QWidget> +#include <QtDebug> + +@interface QUIKitAppDelegate : NSObject <UIApplicationDelegate> { +} +@end + +@interface EventLoopHelper : NSObject { + QUIKitEventLoop *mIntegration; +} + +- (id)initWithEventLoopIntegration:(QUIKitEventLoop *)integration; + +- (void)processEvents; +- (void)processEventsAndSchedule; + +@end + +@implementation QUIKitAppDelegate + +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + Q_UNUSED(launchOptions) + foreach (QWidget *widget, qApp->topLevelWidgets()) { + QRect geom = widget->geometry(); + CGRect bar = application.statusBarFrame; + if (geom.y() <= bar.size.height) { + geom.setY(bar.size.height); + widget->setGeometry(geom); + } + QUIKitWindow *platformWindow = static_cast<QUIKitWindow *>(widget->platformWindow()); + platformWindow->ensureNativeWindow(); + QUIKitWindowSurface *surface = static_cast<QUIKitWindowSurface*>(widget->windowSurface()); + UIView *view = surface->nativeView(); + [platformWindow->nativeWindow() addSubview:view]; + [platformWindow->nativeWindow() makeKeyAndVisible]; + } + return YES; +} + +- (void)applicationWillTerminate:(UIApplication *)application +{ + Q_UNUSED(application) + // TODO this isn't called for some reason + qDebug() << "quit"; + qApp->quit(); +} + +@end + +@implementation EventLoopHelper + +- (id)initWithEventLoopIntegration:(QUIKitEventLoop *)integration +{ + if ((self = [self init])) { + mIntegration = integration; + } + return self; +} + +- (void)processEvents +{ + QPlatformEventLoopIntegration::processEvents(); +} + +- (void)processEventsAndSchedule +{ + QPlatformEventLoopIntegration::processEvents(); + qint64 nextTime = mIntegration->nextTimerEvent(); + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + NSDate *nextDate = [[NSDate date] dateByAddingTimeInterval:((double)nextTime/1000)]; + [mIntegration->mTimer setFireDate:nextDate]; + [pool release]; +} + +@end + +QT_BEGIN_NAMESPACE + +QUIKitEventLoop::QUIKitEventLoop() +{ + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + mHelper = [[EventLoopHelper alloc] initWithEventLoopIntegration:this]; + mTimer = [[NSTimer timerWithTimeInterval:0.030 target:mHelper selector:@selector(processEventsAndSchedule) userInfo:nil repeats:YES] retain]; + [pool release]; +} + +QUIKitEventLoop::~QUIKitEventLoop() +{ + [mTimer release]; + [mHelper release]; +} + +void QUIKitEventLoop::startEventLoop() +{ + NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init]; + [[NSRunLoop currentRunLoop] addTimer:[mTimer autorelease] forMode:NSDefaultRunLoopMode]; + UIApplicationMain(qApp->argc(), qApp->argv(), nil, @"QUIKitAppDelegate"); + [pool release]; +} + +void QUIKitEventLoop::quitEventLoop() +{ + +} + +void QUIKitEventLoop::qtNeedsToProcessEvents() +{ + [mHelper performSelectorOnMainThread:@selector(processEvents) withObject:nil waitUntilDone:NO]; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikitintegration.h b/src/plugins/platforms/uikit/quikitintegration.h new file mode 100644 index 0000000..a986e92 --- /dev/null +++ b/src/plugins/platforms/uikit/quikitintegration.h @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLATFORMINTEGRATION_UIKIT_H +#define QPLATFORMINTEGRATION_UIKIT_H + +#include <QtGui/QPlatformIntegration> + +QT_BEGIN_NAMESPACE + +class QUIKitIntegration : public QPlatformIntegration +{ +public: + QUIKitIntegration(); + ~QUIKitIntegration(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QList<QPlatformScreen *> screens() const; + + QPlatformFontDatabase *fontDatabase() const; + + QPlatformEventLoopIntegration *createEventLoopIntegration() const; + +private: + QList<QPlatformScreen *> mScreens; +}; + +QT_END_NAMESPACE + +#endif + diff --git a/src/plugins/platforms/uikit/quikitintegration.mm b/src/plugins/platforms/uikit/quikitintegration.mm new file mode 100644 index 0000000..d4b4192 --- /dev/null +++ b/src/plugins/platforms/uikit/quikitintegration.mm @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "quikitintegration.h" +#include "quikitwindow.h" +#include "quikitwindowsurface.h" +#include "quikitscreen.h" +#include "quikiteventloop.h" + +#include <QtGui/QApplication> + +#include <private/qpixmap_raster_p.h> + +#include <UIKit/UIKit.h> + +#include <QtDebug> + +QT_BEGIN_NAMESPACE + +QUIKitIntegration::QUIKitIntegration() +{ + mScreens << new QUIKitScreen(0); +} + +QUIKitIntegration::~QUIKitIntegration() +{ +} + +QPixmapData *QUIKitIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QPlatformWindow *QUIKitIntegration::createPlatformWindow(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + return new QUIKitWindow(widget); +} + +QList<QPlatformScreen *> QUIKitIntegration::screens() const +{ + return mScreens; +} + +QWindowSurface *QUIKitIntegration::createWindowSurface(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + return new QUIKitWindowSurface(widget); +} + +QPlatformEventLoopIntegration *QUIKitIntegration::createEventLoopIntegration() const +{ + return new QUIKitEventLoop(); +} + +QPlatformFontDatabase * QUIKitIntegration::fontDatabase() const +{ + static bool initialized = false; + if (!initialized) { + initialized = true; + setenv("QT_QPA_FONTDIR",[[[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:@"fonts"] UTF8String],1); + } + return QPlatformIntegration::fontDatabase(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikitscreen.h b/src/plugins/platforms/uikit/quikitscreen.h new file mode 100644 index 0000000..15c7d69 --- /dev/null +++ b/src/plugins/platforms/uikit/quikitscreen.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QUIKITSCREEN_H +#define QUIKITSCREEN_H + +#include <UIKit/UIKit.h> + +#include <QtGui/QPlatformScreen> + +QT_BEGIN_NAMESPACE + +class QUIKitScreen : public QPlatformScreen +{ +public: + QUIKitScreen(int screenIndex); + ~QUIKitScreen(); + + QRect geometry() const { return m_geometry; } + int depth() const { return m_depth; } + QImage::Format format() const { return m_format; } + QSize physicalSize() const { return m_physicalSize; } + + UIScreen *uiScreen() const; + +private: + QRect m_geometry; + int m_depth; + QImage::Format m_format; + QSize m_physicalSize; + int m_index; +}; + +QT_END_NAMESPACE + + +#endif diff --git a/src/plugins/platforms/uikit/quikitscreen.mm b/src/plugins/platforms/uikit/quikitscreen.mm new file mode 100644 index 0000000..ec94e3a --- /dev/null +++ b/src/plugins/platforms/uikit/quikitscreen.mm @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "quikitscreen.h" + +#include <QtDebug> + +QT_BEGIN_NAMESPACE + +QUIKitScreen::QUIKitScreen(int screenIndex) + : QPlatformScreen(), + m_index(screenIndex) +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + UIScreen *screen = [[UIScreen screens] objectAtIndex:screenIndex]; + UIScreenMode *mode = [screen currentMode]; + CGSize size = [mode size]; + m_geometry = QRect(0, 0, size.width, size.height); + CGRect bounds = [screen bounds]; // in 'points', 1p == 1/160in + +// qreal xDpi = size.width * 160. / bounds.size.width; +// qreal yDpi = size.height * 160. / bounds.size.height; +// qDebug() << xDpi << yDpi; + + m_format = QImage::Format_ARGB32; + + m_depth = 24; + + const qreal inch = 25.4; + m_physicalSize = QSize(qRound(bounds.size.width * inch / 160.), qRound(bounds.size.height * inch / 160.)); + [pool release]; +} + +QUIKitScreen::~QUIKitScreen() +{ +} + +UIScreen *QUIKitScreen::uiScreen() const +{ + return [[UIScreen screens] objectAtIndex:m_index]; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikitwindow.h b/src/plugins/platforms/uikit/quikitwindow.h new file mode 100644 index 0000000..d5a6690 --- /dev/null +++ b/src/plugins/platforms/uikit/quikitwindow.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QUIKITWINDOW_H +#define QUIKITWINDOW_H + +#include <QPlatformWindow> +#include <UIKit/UIKit.h> + +QT_BEGIN_NAMESPACE + +class QUIKitScreen; + +class QUIKitWindow : public QPlatformWindow +{ +public: + explicit QUIKitWindow(QWidget *tlw); + ~QUIKitWindow(); + + UIWindow *nativeWindow() const { return mWindow; } + void setGeometry(const QRect &rect); + + UIWindow *ensureNativeWindow(); + +private: + QUIKitScreen *mScreen; + UIWindow *mWindow; +}; + +QT_END_NAMESPACE + +#endif // QUIKITWINDOW_H diff --git a/src/plugins/platforms/uikit/quikitwindow.mm b/src/plugins/platforms/uikit/quikitwindow.mm new file mode 100644 index 0000000..ebdee06 --- /dev/null +++ b/src/plugins/platforms/uikit/quikitwindow.mm @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "quikitwindow.h" + +#include "quikitscreen.h" + +#include <QtDebug> + +QT_BEGIN_NAMESPACE + +QUIKitWindow::QUIKitWindow(QWidget *tlw) : + QPlatformWindow(tlw), + mWindow(nil) +{ + mScreen = static_cast<QUIKitScreen *>(QPlatformScreen::platformScreenForWidget(tlw)); + CGRect screenBounds = [mScreen->uiScreen() bounds]; + QRect geom(screenBounds.origin.x, screenBounds.origin.y, screenBounds.size.width, screenBounds.size.height); + setGeometry(geom); + // TODO ensure the native window if the application is already running +} + +QUIKitWindow::~QUIKitWindow() +{ + [mWindow release]; +} + +void QUIKitWindow::setGeometry(const QRect &rect) +{ + if (mWindow) { + mWindow.frame = CGRectMake(rect.x(), rect.y(), rect.width(), rect.height()); + [mWindow setNeedsDisplay]; + } + QPlatformWindow::setGeometry(rect); +} + +UIWindow *QUIKitWindow::ensureNativeWindow() +{ + if (!mWindow) { + CGRect screenBounds = [mScreen->uiScreen() bounds]; + QRect geom = geometry(); + CGRect frame = CGRectMake(geom.x(), geom.y(), geom.width(), geom.height()); + mWindow = [[UIWindow alloc] initWithFrame:frame]; + mWindow.screen = mScreen->uiScreen(); + mWindow.frame = frame; // for some reason setting the screen resets frame.origin + [mWindow setNeedsDisplay]; + } + return mWindow; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/quikitwindowsurface.h b/src/plugins/platforms/uikit/quikitwindowsurface.h new file mode 100644 index 0000000..50d02b4 --- /dev/null +++ b/src/plugins/platforms/uikit/quikitwindowsurface.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QUIKITWINDOWSURFACE_H +#define QUIKITWINDOWSURFACE_H + +#include <QtGui/QPlatformIntegration> +#include <QtGui/QImage> +#include <QtGui/QWindowSystemInterface> + +#include <UIKit/UIKit.h> + +@interface QImageView : UIView +{ + CGImageRef m_cgImage; + QWidget *m_widget; +} + +- (void)setImage:(QImage *)image; +- (void)setWidget:(QWidget *)widget; + +//- (QList<struct QWindowSystemInterface::TouchPoint>)touchPointsForTouches:(NSSet *)touches; +- (void)sendMouseEventForTouches:(NSSet *)touches withEvent:(UIEvent *)event fakeButtons:(Qt::MouseButtons)buttons; +@end + +QT_BEGIN_NAMESPACE + +class QUIKitWindowSurface : public QWindowSurface +{ +public: + QUIKitWindowSurface(QWidget *window); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize (const QSize &size); + + QImageView *nativeView() const { return mView; } +private: + QImage *mImage; + QImageView *mView; +}; + +QT_END_NAMESPACE + +#endif // QUIKITWINDOWSURFACE_H diff --git a/src/plugins/platforms/uikit/quikitwindowsurface.mm b/src/plugins/platforms/uikit/quikitwindowsurface.mm new file mode 100644 index 0000000..1274fca --- /dev/null +++ b/src/plugins/platforms/uikit/quikitwindowsurface.mm @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "quikitwindowsurface.h" +#include "quikitwindow.h" + +#include <QtDebug> + +@implementation QImageView + +- (void)dealloc +{ + CGImageRelease(m_cgImage); + [super dealloc]; +} + +- (void)setImage:(QImage *)image +{ + CGImageRelease(m_cgImage); + + const uchar *imageData = image->bits(); + int bitDepth = image->depth(); + int colorBufferSize = 8; + int bytesPrLine = image->bytesPerLine(); + int width = image->width(); + int height = image->height(); + + CGColorSpaceRef cgColourSpaceRef = CGColorSpaceCreateDeviceRGB(); + + CGDataProviderRef cgDataProviderRef = CGDataProviderCreateWithData( + NULL, + imageData, + image->byteCount(), + NULL); + + m_cgImage = CGImageCreate(width, + height, + colorBufferSize, + bitDepth, + bytesPrLine, + cgColourSpaceRef, + kCGImageAlphaPremultipliedFirst | kCGBitmapByteOrder32Little, + cgDataProviderRef, + NULL, + false, + kCGRenderingIntentDefault); + + CGDataProviderRelease(cgDataProviderRef); + CGColorSpaceRelease(cgColourSpaceRef); +} + +- (void)setWidget:(QWidget *)widget +{ + m_widget = widget; +} + +- (void)drawRect:(CGRect)rect +{ + + if (!m_cgImage) + return; + + CGContextRef cgContext = UIGraphicsGetCurrentContext(); + CGContextSaveGState( cgContext ); + + int dy = rect.origin.y + CGRectGetMaxY(rect); + CGContextTranslateCTM(cgContext, 0, dy); + CGContextScaleCTM(cgContext, 1, -1); + CGImageRef subImage = CGImageCreateWithImageInRect(m_cgImage, rect); + CGContextDrawImage(cgContext,rect,subImage); + CGImageRelease(subImage); + + CGContextRestoreGState(cgContext); +} + +//- (QList<struct QWindowSystemInterface::TouchPoint>)touchPointsForTouches:(NSSet *)touches +//{ +// NSEnumerator *enumerator = [touches objectEnumerator]; +// id touch; +// int count = 0; +// QList<struct QWindowSystemInterface::TouchPoint> result; +// while ((touch = [enumerator nextObject])) { +// CGPoint locationInView = [touch locationInView:self]; +// CGRect bounds = [self bounds]; +// struct QWindowSystemInterface::TouchPoint p; +// p.id = count; +// p.isPrimary = true; +// p.normalPosition = QPointF(locationInView.x / bounds.size.width, +// locationInView.y / bounds.size.height); +// p.area = QRectF(locationInView.x, locationInView.y, 1, 1); +// p.pressure = 1.; +// switch ([touch phase]) { +// case UITouchPhaseBegan: +// p.state = Qt::TouchPointPressed; +// break; +// case UITouchPhaseMoved: +// p.state = Qt::TouchPointMoved; +// break; +// case UITouchPhaseStationary: +// p.state = Qt::TouchPointStationary; +// break; +// case UITouchPhaseEnded: +// case UITouchPhaseCancelled: +// p.state = Qt::TouchPointReleased; +// break; +// } +// result << p; +// qDebug() << p.id << ":" << p.normalPosition << p.area << p.state; +// ++count; +// } +// qDebug() << result.size(); +// return result; +//} + +- (void)sendMouseEventForTouches:(NSSet *)touches withEvent:(UIEvent *)event fakeButtons:(Qt::MouseButtons)buttons +{ + UITouch *touch = [touches anyObject]; + CGPoint locationInView = [touch locationInView:self]; + QPoint p(locationInView.x, locationInView.y); + // TODO handle global touch point? for status bar? + QWindowSystemInterface::handleMouseEvent(m_widget, (ulong)(event.timestamp*1000), + p, p, buttons); +} + +- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event +{ + //QWindowSystemInterface::handleTouchEvent(m_widget, (ulong)(event.timestamp*1000), + // QEvent::TouchBegin, QTouchEvent::TouchScreen, + // [self touchPointsForTouches:touches]); + [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::LeftButton]; +} + +- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event +{ + //QWindowSystemInterface::handleTouchEvent(m_widget, (ulong)(event.timestamp*1000), + // QEvent::TouchUpdate, QTouchEvent::TouchScreen, + // [self touchPointsForTouches:touches]); + [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::LeftButton]; +} + +- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event +{ + //QWindowSystemInterface::handleTouchEvent(m_widget, (ulong)(event.timestamp*1000), + // QEvent::TouchEnd, QTouchEvent::TouchScreen, + // [self touchPointsForTouches:touches]); + [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::NoButton]; +} + +- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event +{ + //QWindowSystemInterface::handleTouchEvent(m_widget, (ulong)(event.timestamp*1000), + // QEvent::TouchEnd, QTouchEvent::TouchScreen, + // [self touchPointsForTouches:touches]); + [self sendMouseEventForTouches:touches withEvent:event fakeButtons:Qt::NoButton]; +} + +@end + +QT_BEGIN_NAMESPACE + +QUIKitWindowSurface::QUIKitWindowSurface(QWidget *window) + : QWindowSurface(window) +{ + QUIKitWindow *platformWindow = static_cast<QUIKitWindow *>(window->platformWindow()); + Q_ASSERT(platformWindow); + const QRect geo = window->geometry(); + mView = [[QImageView alloc] initWithFrame:CGRectMake(geo.x(),geo.y(),geo.width(),geo.height())]; + [mView setMultipleTouchEnabled:YES]; + [mView setWidget:window]; + mImage = new QImage(window->size(),QImage::Format_ARGB32_Premultiplied); + [mView setImage:mImage]; + if (platformWindow->nativeWindow()) { + [platformWindow->nativeWindow() addSubview:mView]; + [mView setNeedsDisplay]; + } +} + +QPaintDevice *QUIKitWindowSurface::paintDevice() +{ + return mImage; +} + +void QUIKitWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(offset); + + QRect geo = region.boundingRect(); + [mView setNeedsDisplayInRect:CGRectMake(geo.x(),geo.y(),geo.width(),geo.height())]; +} + +void QUIKitWindowSurface::resize (const QSize &size) +{ + QWindowSurface::resize(size); + + delete mImage; + mImage = new QImage(size,QImage::Format_ARGB32_Premultiplied); + [mView setImage:mImage]; + const QRect geo = geometry(); + [mView setFrame:CGRectMake(geo.x(), geo.y(), size.width(), size.height())]; + [mView setNeedsDisplay]; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/uikit/uikit.pro b/src/plugins/platforms/uikit/uikit.pro new file mode 100644 index 0000000..b73c334 --- /dev/null +++ b/src/plugins/platforms/uikit/uikit.pro @@ -0,0 +1,23 @@ +TARGET = quikit +include(../../qpluginbase.pri) +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +OBJECTIVE_SOURCES = main.mm \ + quikitintegration.mm \ + quikitwindow.mm \ + quikitscreen.mm \ + quikiteventloop.mm \ + quikitwindowsurface.mm + +OBJECTIVE_HEADERS = quikitintegration.h \ + quikitwindow.h \ + quikitscreen.h \ + quikiteventloop.h \ + quikitwindowsurface.h + +#add libz for freetype. +LIBS += -lz + +#include(../fontdatabases/basicunix/basicunix.pri) +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target diff --git a/src/plugins/platforms/vnc/main.cpp b/src/plugins/platforms/vnc/main.cpp index e051e2d..890b8f8 100644 --- a/src/plugins/platforms/vnc/main.cpp +++ b/src/plugins/platforms/vnc/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/vnc/qvnccursor.cpp b/src/plugins/platforms/vnc/qvnccursor.cpp index e83696d..dbcdef3 100644 --- a/src/plugins/platforms/vnc/qvnccursor.cpp +++ b/src/plugins/platforms/vnc/qvnccursor.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/platforms/vnc/qvnccursor.h b/src/plugins/platforms/vnc/qvnccursor.h index eeb3686..8eb26e0 100644 --- a/src/plugins/platforms/vnc/qvnccursor.h +++ b/src/plugins/platforms/vnc/qvnccursor.h @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage diff --git a/src/plugins/platforms/vnc/qvncintegration.cpp b/src/plugins/platforms/vnc/qvncintegration.cpp index b36ff33..b99ff3f 100644 --- a/src/plugins/platforms/vnc/qvncintegration.cpp +++ b/src/plugins/platforms/vnc/qvncintegration.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -152,6 +152,15 @@ QVNCIntegration::QVNCIntegration(const QStringList& paramList) screen->setDirty(screenRect); } +bool QVNCIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: return true; + default: return QPlatformIntegration::hasCapability(cap); + } +} + + QPixmapData *QVNCIntegration::createPixmapData(QPixmapData::PixelType type) const { return new QRasterPixmapData(type); diff --git a/src/plugins/platforms/vnc/qvncintegration.h b/src/plugins/platforms/vnc/qvncintegration.h index dfc0e6b..ef16dfa 100644 --- a/src/plugins/platforms/vnc/qvncintegration.h +++ b/src/plugins/platforms/vnc/qvncintegration.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -81,6 +81,7 @@ class QVNCIntegration : public QPlatformIntegration public: QVNCIntegration(const QStringList& paramList); + bool hasCapability(QPlatformIntegration::Capability cap) const; QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; diff --git a/src/plugins/platforms/vnc/qvncserver.cpp b/src/plugins/platforms/vnc/qvncserver.cpp index 288d1bc..be2de7c 100644 --- a/src/plugins/platforms/vnc/qvncserver.cpp +++ b/src/plugins/platforms/vnc/qvncserver.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/vnc/qvncserver.h b/src/plugins/platforms/vnc/qvncserver.h index 7244bdf..3b514a5 100644 --- a/src/plugins/platforms/vnc/qvncserver.h +++ b/src/plugins/platforms/vnc/qvncserver.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** diff --git a/src/plugins/platforms/wayland/main.cpp b/src/plugins/platforms/wayland/main.cpp new file mode 100644 index 0000000..6dc1c2b --- /dev/null +++ b/src/plugins/platforms/wayland/main.cpp @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui/QPlatformIntegrationPlugin> +#include "qwaylandintegration.h" + +QT_BEGIN_NAMESPACE + +class QWaylandIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QWaylandIntegrationPlugin::keys() const +{ + QStringList list; + list << "Wayland"; + list << "WaylandGL"; + return list; +} + +QPlatformIntegration *QWaylandIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "wayland") + return new QWaylandIntegration; + if (system.toLower() == "waylandgl") + return new QWaylandIntegration(true); + + return 0; +} + +Q_EXPORT_PLUGIN2(wayland, QWaylandIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandbuffer.h b/src/plugins/platforms/wayland/qwaylandbuffer.h new file mode 100644 index 0000000..643e89c --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandbuffer.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDBUFFER_H +#define QWAYLANDBUFFER_H + +#include <QtCore/QSize> + +#include <wayland-client-protocol.h> + +class QWaylandBuffer { +public: + QWaylandBuffer() { } + virtual ~QWaylandBuffer() { } + wl_buffer *buffer() {return mBuffer;} + virtual QSize size() const = 0; + +protected: + struct wl_buffer *mBuffer; +}; + +#endif // QWAYLANDBUFFER_H diff --git a/src/plugins/platforms/wayland/qwaylandcursor.cpp b/src/plugins/platforms/wayland/qwaylandcursor.cpp new file mode 100644 index 0000000..614686f --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandcursor.cpp @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandcursor.h" + +#include "qwaylanddisplay.h" +#include "qwaylandinputdevice.h" +#include "qwaylandshmsurface.h" +#include "qwaylandscreen.h" + +#include <QtGui/QImageReader> + +#define DATADIR "/usr/share" + +static const struct pointer_image { + const char *filename; + int hotspot_x, hotspot_y; +} pointer_images[] = { + /* FIXME: Half of these are wrong... */ + /* Qt::ArrowCursor */ + { DATADIR "/wayland/left_ptr.png", 10, 5 }, + /* Qt::UpArrowCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::CrossCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::WaitCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::IBeamCursor */ + { DATADIR "/wayland/xterm.png", 15, 15 }, + /* Qt::SizeVerCursor */ + { DATADIR "/wayland/top_side.png", 18, 8 }, + /* Qt::SizeHorCursor */ + { DATADIR "/wayland/bottom_left_corner.png", 6, 30 }, + /* Qt::SizeBDiagCursor */ + { DATADIR "/wayland/bottom_right_corner.png", 28, 28 }, + /* Qt::SizeFDiagCursor */ + { DATADIR "/wayland/bottom_side.png", 16, 20 }, + /* Qt::SizeAllCursor */ + { DATADIR "/wayland/left_side.png", 10, 20 }, + /* Qt::BlankCursor */ + { DATADIR "/wayland/right_side.png", 30, 19 }, + /* Qt::SplitVCursor */ + { DATADIR "/wayland/sb_v_double_arrow.png", 15, 15 }, + /* Qt::SplitHCursor */ + { DATADIR "/wayland/sb_h_double_arrow.png", 15, 15 }, + /* Qt::PointingHandCursor */ + { DATADIR "/wayland/hand2.png", 14, 8 }, + /* Qt::ForbiddenCursor */ + { DATADIR "/wayland/top_right_corner.png", 26, 8 }, + /* Qt::WhatsThisCursor */ + { DATADIR "/wayland/top_right_corner.png", 26, 8 }, + /* Qt::BusyCursor */ + { DATADIR "/wayland/top_right_corner.png", 26, 8 }, + /* Qt::OpenHandCursor */ + { DATADIR "/wayland/hand1.png", 18, 11 }, + /* Qt::ClosedHandCursor */ + { DATADIR "/wayland/grabbing.png", 20, 17 }, + /* Qt::DragCopyCursor */ + { DATADIR "/wayland/dnd-copy.png", 13, 13 }, + /* Qt::DragMoveCursor */ + { DATADIR "/wayland/dnd-move.png", 13, 13 }, + /* Qt::DragLinkCursor */ + { DATADIR "/wayland/dnd-link.png", 13, 13 }, +}; + +QWaylandCursor::QWaylandCursor(QWaylandScreen *screen) + : QPlatformCursor(screen) + , mBuffer(0) + , mDisplay(screen->display()) +{ +} + +void QWaylandCursor::changeCursor(QCursor *cursor, QWidget *widget) +{ + const struct pointer_image *p; + + if (widget == NULL) + return; + + p = NULL; + + switch (cursor->shape()) { + case Qt::ArrowCursor: + p = &pointer_images[cursor->shape()]; + break; + case Qt::UpArrowCursor: + case Qt::CrossCursor: + case Qt::WaitCursor: + break; + case Qt::IBeamCursor: + p = &pointer_images[cursor->shape()]; + break; + case Qt::SizeVerCursor: /* 5 */ + case Qt::SizeHorCursor: + case Qt::SizeBDiagCursor: + case Qt::SizeFDiagCursor: + case Qt::SizeAllCursor: + case Qt::BlankCursor: /* 10 */ + break; + case Qt::SplitVCursor: + case Qt::SplitHCursor: + case Qt::PointingHandCursor: + p = &pointer_images[cursor->shape()]; + break; + case Qt::ForbiddenCursor: + case Qt::WhatsThisCursor: /* 15 */ + case Qt::BusyCursor: + break; + case Qt::OpenHandCursor: + case Qt::ClosedHandCursor: + case Qt::DragCopyCursor: + case Qt::DragMoveCursor: /* 20 */ + case Qt::DragLinkCursor: + p = &pointer_images[cursor->shape()]; + break; + + default: + case Qt::BitmapCursor: + break; + } + + if (!p) { + p = &pointer_images[0]; + qWarning("unhandled cursor %d", cursor->shape()); + } + + QImageReader reader(p->filename); + + if (!reader.canRead()) + return; + + if (mBuffer == NULL || mBuffer->size() != reader.size()) { + if (mBuffer) + delete mBuffer; + + mBuffer = new QWaylandShmBuffer(mDisplay, reader.size(), + QImage::Format_ARGB32); + } + + reader.read(mBuffer->image()); + + mDisplay->setCursor(mBuffer, p->hotspot_x, p->hotspot_y); +} + +void QWaylandDisplay::setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y) +{ + /* Qt doesn't tell us which input device we should set the cursor + * for, so set it for all devices. */ + for (int i = 0; i < mInputDevices.count(); i++) { + QWaylandInputDevice *inputDevice = mInputDevices.at(i); + inputDevice->attach(buffer, x, y); + } +} diff --git a/src/plugins/platforms/wayland/qwaylandcursor.h b/src/plugins/platforms/wayland/qwaylandcursor.h new file mode 100644 index 0000000..254cb94 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandcursor.h @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDCURSOR_H +#define QWAYLANDCURSOR_H + +#include <QtGui/QPlatformCursor> + +class QWaylandShmBuffer; +class QWaylandDisplay; +class QWaylandScreen; + +class QWaylandCursor : QPlatformCursor { +public: + QWaylandCursor(QWaylandScreen *screen); + + void changeCursor(QCursor *cursor, QWidget *widget); + QWaylandShmBuffer *mBuffer; + QWaylandDisplay *mDisplay; +}; + +#endif // QWAYLANDCURSOR_H diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp new file mode 100644 index 0000000..27f4334 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -0,0 +1,247 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylanddisplay.h" + +#include "qwaylandwindow.h" +#include "qwaylandscreen.h" +#include "qwaylandcursor.h" +#include "qwaylandinputdevice.h" + +#include <unistd.h> +#include <fcntl.h> +#include <stdio.h> + +struct wl_surface *QWaylandDisplay::createSurface() +{ + return wl_compositor_create_surface(mCompositor); +} + +struct wl_buffer *QWaylandDisplay::createShmBuffer(int fd, + int width, int height, + uint32_t stride, + struct wl_visual *visual) +{ + return wl_shm_create_buffer(mShm, fd, width, height, stride, visual); +} + +struct wl_visual *QWaylandDisplay::rgbVisual() +{ + return wl_display_get_rgb_visual(mDisplay); +} + +struct wl_visual *QWaylandDisplay::argbVisual() +{ + return wl_display_get_argb_visual(mDisplay); +} + +struct wl_visual *QWaylandDisplay::argbPremultipliedVisual() +{ + return wl_display_get_premultiplied_argb_visual(mDisplay); +} + +struct wl_egl_display *QWaylandDisplay::nativeDisplay() +{ + return mNativeEglDisplay; +} + +void QWaylandDisplay::shellHandleConfigure(void *data, struct wl_shell *shell, + uint32_t time, uint32_t edges, + struct wl_surface *surface, + int32_t width, int32_t height) +{ + Q_UNUSED(data); + Q_UNUSED(shell); + Q_UNUSED(time); + Q_UNUSED(edges); + QWaylandWindow *ww = (QWaylandWindow *) wl_surface_get_user_data(surface); + + ww->configure(time, edges, 0, 0, width, height); +} + +const struct wl_shell_listener QWaylandDisplay::shellListener = { + QWaylandDisplay::shellHandleConfigure, +}; + +void QWaylandDisplay::outputHandleGeometry(void *data, + struct wl_output *output, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + QWaylandDisplay *waylandDisplay = (QWaylandDisplay *) data; + + QRect outputRect = QRect(x, y, width, height); + waylandDisplay->createNewScreen(output, outputRect); +} + +const struct wl_output_listener QWaylandDisplay::outputListener = { + QWaylandDisplay::outputHandleGeometry +}; + +void QWaylandDisplay::displayHandleGlobal(struct wl_display *display, + uint32_t id, + const char *interface, + uint32_t version, void *data) +{ + Q_UNUSED(version); + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + + if (strcmp(interface, "compositor") == 0) { + qwd->mCompositor = wl_compositor_create(display, id); + } else if (strcmp(interface, "shm") == 0) { + qwd->mShm = wl_shm_create(display, id); + } else if (strcmp(interface, "shell") == 0) { + qwd->mShell = wl_shell_create(display, id); + wl_shell_add_listener(qwd->mShell, &shellListener, qwd); + } else if (strcmp(interface, "output") == 0) { + struct wl_output *output = wl_output_create(display, id); + wl_output_add_listener(output, &outputListener, qwd); + } else if (strcmp(interface, "input_device") == 0) { + QWaylandInputDevice *inputDevice = + new QWaylandInputDevice(display, id); + qwd->mInputDevices.append(inputDevice); + } +} + +void QWaylandDisplay::iterate() +{ + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE | WL_DISPLAY_WRITABLE); +} + +void QWaylandDisplay::readEvents(void) +{ + wl_display_iterate(mDisplay, WL_DISPLAY_READABLE); +} + +int +QWaylandDisplay::sourceUpdate(uint32_t mask, void *data) +{ + QWaylandDisplay *qwd = (QWaylandDisplay *) data; + + /* FIXME: We get a callback here when we ask wl_display for the + * fd, but at that point we don't have the socket notifier as we + * need the fd to create that. We'll probably need to split that + * API into get_fd and set_update_func functions. */ + if (qwd->mWriteNotifier == NULL) + return 0; + + qwd->mWriteNotifier->setEnabled(mask & WL_DISPLAY_WRITABLE); + + return 0; +} + +void QWaylandDisplay::flushRequests(void) +{ + wl_display_iterate(mDisplay, WL_DISPLAY_WRITABLE); +} + +QWaylandDisplay::QWaylandDisplay(void) + : mWriteNotifier(0) +{ +#ifdef QT_WAYLAND_GL_SUPPORT + EGLint major, minor; +#endif + mDisplay = wl_display_connect(NULL); + if (mDisplay == NULL) { + fprintf(stderr, "failed to create display: %m\n"); + return; + } + + wl_display_add_global_listener(mDisplay, + QWaylandDisplay::displayHandleGlobal, this); + +#ifdef QT_WAYLAND_GL_SUPPORT + mNativeEglDisplay = wl_egl_display_create(mDisplay); +#else + mNativeEglDisplay = 0; +#endif + + readEvents(); + +#ifdef QT_WAYLAND_GL_SUPPORT + mEglDisplay = eglGetDisplay((EGLNativeDisplayType)mNativeEglDisplay); + if (mEglDisplay == NULL) { + qWarning("EGL not available"); + } else { + if (!eglInitialize(mEglDisplay, &major, &minor)) { + qWarning("failed to initialize EGL display"); + return; + } + } +#else + mEglDisplay = 0; +#endif + + int fd = wl_display_get_fd(mDisplay, sourceUpdate, this); + mReadNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); + connect(mReadNotifier, + SIGNAL(activated(int)), this, SLOT(readEvents())); + + mWriteNotifier = new QSocketNotifier(fd, QSocketNotifier::Write, this); + connect(mWriteNotifier, + SIGNAL(activated(int)), this, SLOT(flushRequests())); + mWriteNotifier->setEnabled(false); +} + +QWaylandDisplay::~QWaylandDisplay(void) +{ + close(mFd); +#ifdef QT_WAYLAND_GL_SUPPORT + eglTerminate(mEglDisplay); +#endif + wl_display_destroy(mDisplay); +} + +void QWaylandDisplay::createNewScreen(struct wl_output *output, QRect geometry) +{ + QWaylandScreen *waylandScreen = new QWaylandScreen(this,output,geometry); + mScreens.append(waylandScreen); +} + +void QWaylandDisplay::syncCallback(wl_display_sync_func_t func, void *data) +{ + wl_display_sync_callback(mDisplay, func, data); +} + +void QWaylandDisplay::frameCallback(wl_display_frame_func_t func, void *data) +{ + wl_display_frame_callback(mDisplay, func, data); +} diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.h b/src/plugins/platforms/wayland/qwaylanddisplay.h new file mode 100644 index 0000000..d994ffe --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddisplay.h @@ -0,0 +1,125 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDDISPLAY_H +#define QWAYLANDDISPLAY_H + +#include <QtCore/QObject> +#include <QtCore/QRect> +#include <QtCore/QDataStream> +#include <QtCore/QTextStream> +#include <QtCore/QMetaType> +#include <QtGui> + +#include "qwaylandinclude.h" + +class QWaylandInputDevice; +class QSocketNotifier; +class QWaylandBuffer; +class QPlatformScreen; +class QWaylandScreen; + +class QWaylandDisplay : public QObject { + Q_OBJECT + +public: + QWaylandDisplay(void); + ~QWaylandDisplay(void); + + void createNewScreen(struct wl_output *output, QRect geometry); + QList<QPlatformScreen *> screens() const { return mScreens; } + struct wl_surface *createSurface(); + struct wl_buffer *createShmBuffer(int fd, int width, int height, + uint32_t stride, + struct wl_visual *visual); + struct wl_visual *rgbVisual(); + struct wl_visual *argbVisual(); + struct wl_visual *argbPremultipliedVisual(); + struct wl_egl_display *nativeDisplay(); + EGLDisplay eglDisplay() { return mEglDisplay; } + + void setCursor(QWaylandBuffer *buffer, int32_t x, int32_t y); + + void syncCallback(wl_display_sync_func_t func, void *data); + void frameCallback(wl_display_frame_func_t func, void *data); + + void iterate(); + +public slots: + void readEvents(void); + void flushRequests(void); + +private: + struct wl_display *mDisplay; + struct wl_compositor *mCompositor; + struct wl_shm *mShm; + struct wl_shell *mShell; + char *mDeviceName; + int mFd; + QList<QPlatformScreen *> mScreens; + QList<QWaylandInputDevice *> mInputDevices; + QSocketNotifier *mReadNotifier; + QSocketNotifier *mWriteNotifier; + EGLDisplay mEglDisplay; + struct wl_egl_display *mNativeEglDisplay; + + static void displayHandleGlobal(struct wl_display *display, + uint32_t id, + const char *interface, + uint32_t version, void *data); + + static void outputHandleGeometry(void *data, + struct wl_output *output, + int32_t x, int32_t y, + int32_t width, int32_t height); + + static void shellHandleConfigure(void *data, struct wl_shell *shell, + uint32_t time, uint32_t edges, + struct wl_surface *surface, + int32_t width, int32_t height); + + static int sourceUpdate(uint32_t mask, void *data); + + static const struct wl_output_listener outputListener; + static const struct wl_shell_listener shellListener; +}; + +#endif // QWAYLANDDISPLAY_H diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp new file mode 100644 index 0000000..a8bc352 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.cpp @@ -0,0 +1,183 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylanddrmsurface.h" + +#include "qwaylanddisplay.h" +#include "qwaylandwindow.h" +#include "qwaylandscreen.h" + +#include <QtOpenGL/QGLFramebufferObject> +#include <QtOpenGL/QGLContext> + +#include <QtOpenGL/private/qglengineshadermanager_p.h> + +QT_BEGIN_NAMESPACE + + + +static void drawTexture(const QRectF &rect, GLuint tex_id, const QSize &texSize, const QRectF &br) +{ + const GLenum target = GL_TEXTURE_2D; + QRectF src = br.isEmpty() + ? QRectF(QPointF(), texSize) + : QRectF(QPointF(br.x(), texSize.height() - br.bottom()), br.size()); + + if (target == GL_TEXTURE_2D) { + qreal width = texSize.width(); + qreal height = texSize.height(); + + src.setLeft(src.left() / width); + src.setRight(src.right() / width); + src.setTop(src.top() / height); + src.setBottom(src.bottom() / height); + } + + const GLfloat tx1 = src.left(); + const GLfloat tx2 = src.right(); + const GLfloat ty1 = src.top(); + const GLfloat ty2 = src.bottom(); + + GLfloat texCoordArray[4*2] = { + tx1, ty2, tx2, ty2, tx2, ty1, tx1, ty1 + }; + + GLfloat vertexArray[4*2]; + vertexArray[0] = rect.left(); vertexArray[1] = rect.top(); + vertexArray[2] = rect.right(); vertexArray[3] = rect.top(); + vertexArray[4] = rect.right(); vertexArray[5] = rect.bottom(); + vertexArray[6] = rect.left(); vertexArray[7] = rect.bottom(); + + glVertexAttribPointer(QT_VERTEX_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, vertexArray); + glVertexAttribPointer(QT_TEXTURE_COORDS_ATTR, 2, GL_FLOAT, GL_FALSE, 0, texCoordArray); + + glBindTexture(target, tex_id); + + glEnableVertexAttribArray(QT_VERTEX_COORDS_ATTR); + glEnableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + glDisableVertexAttribArray(QT_VERTEX_COORDS_ATTR); + glDisableVertexAttribArray(QT_TEXTURE_COORDS_ATTR); + + glBindTexture(target, 0); +} + +static void blitTexture(QGLContext *ctx, GLuint texture, const QSize &viewport, const QSize &texSize, const QRect &targetRect, const QRect &sourceRect) +{ + glDisable(GL_DEPTH_TEST); + glDisable(GL_SCISSOR_TEST); + glDisable(GL_BLEND); + glViewport(0, 0, viewport.width(), viewport.height()); + + QGLShaderProgram *blitProgram = + QGLEngineSharedShaders::shadersForContext(ctx)->blitProgram(); + blitProgram->bind(); + blitProgram->setUniformValue("imageTexture", 0 /*QT_IMAGE_TEXTURE_UNIT*/); + + // The shader manager's blit program does not multiply the + // vertices by the pmv matrix, so we need to do the effect + // of the orthographic projection here ourselves. + QRectF r; + qreal w = viewport.width(); + qreal h = viewport.height(); + r.setLeft((targetRect.left() / w) * 2.0f - 1.0f); + if (targetRect.right() == (viewport.width() - 1)) + r.setRight(1.0f); + else + r.setRight((targetRect.right() / w) * 2.0f - 1.0f); + r.setBottom((targetRect.top() / h) * 2.0f - 1.0f); + if (targetRect.bottom() == (viewport.height() - 1)) + r.setTop(1.0f); + else + r.setTop((targetRect.bottom() / w) * 2.0f - 1.0f); + + drawTexture(r, texture, texSize, sourceRect); +} + +QWaylandDrmWindowSurface::QWaylandDrmWindowSurface(QWidget *window) + : QWindowSurface(window) + , mDisplay(QWaylandScreen::waylandScreenFromWidget(window)->display()) + , mPaintDevice(0) +{ + +} + +QWaylandDrmWindowSurface::~QWaylandDrmWindowSurface() +{ + delete mPaintDevice; +} + +QPaintDevice *QWaylandDrmWindowSurface::paintDevice() +{ + return mPaintDevice; +} + +void QWaylandDrmWindowSurface::beginPaint(const QRegion &) +{ + window()->platformWindow()->glContext()->makeCurrent(); + glClearColor(0,0,0,0xff); + glClear(GL_COLOR_BUFFER_BIT); +} + +void QWaylandDrmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(offset); + Q_UNUSED(region); + QWaylandWindow *ww = (QWaylandWindow *) widget->platformWindow(); + + if (mPaintDevice->isBound()) + mPaintDevice->release(); + + QRect rect(0,0,size().width(),size().height()); + QGLContext *ctx = QGLContext::fromPlatformGLContext(ww->glContext()); + blitTexture(ctx,mPaintDevice->texture(),size(),mPaintDevice->size(),rect,rect); + ww->glContext()->swapBuffers(); +} + +void QWaylandDrmWindowSurface::resize(const QSize &size) +{ + QWindowSurface::resize(size); + window()->platformWindow()->glContext()->makeCurrent(); + delete mPaintDevice; + mPaintDevice = new QGLFramebufferObject(size,QGLFramebufferObject::CombinedDepthStencil,GL_TEXTURE_2D,GL_RGBA); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylanddrmsurface.h b/src/plugins/platforms/wayland/qwaylanddrmsurface.h new file mode 100644 index 0000000..78418ee --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylanddrmsurface.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDDRMSURFACE_H +#define QWAYLANDDRMSURFACE_H + +#include "qwaylanddisplay.h" + +#include <QtGui/private/qwindowsurface_p.h> + +class QGLFramebufferObject; + +class QWaylandDrmWindowSurface : public QWindowSurface +{ +public: + QWaylandDrmWindowSurface(QWidget *window); + ~QWaylandDrmWindowSurface(); + + void beginPaint(const QRegion &); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + + void resize(const QSize &size); + +private: + + QWaylandDisplay *mDisplay; + QGLFramebufferObject *mPaintDevice; +}; + +#endif // QWAYLANDDRMSURFACE_H diff --git a/src/plugins/platforms/wayland/qwaylandeglwindow.cpp b/src/plugins/platforms/wayland/qwaylandeglwindow.cpp new file mode 100644 index 0000000..ed54bb9 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandeglwindow.cpp @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandeglwindow.h" + +#include "qwaylandscreen.h" +#include "qwaylandglcontext.h" +#include "qwaylandinclude.h" + +QWaylandEglWindow::QWaylandEglWindow(QWidget *window) + : QWaylandWindow(window) + , mGLContext(0) + , mWaylandEglWindow(0) +{ + //super creates a new surface + newSurfaceCreated(); +} + +QWaylandEglWindow::~QWaylandEglWindow() +{ + if (mGLContext) + delete mGLContext; +} + +QWaylandWindow::WindowType QWaylandEglWindow::windowType() const +{ + return QWaylandWindow::Egl; +} + +void QWaylandEglWindow::setGeometry(const QRect &rect) +{ + QWaylandWindow::setGeometry(rect); + if (mWaylandEglWindow) { + wl_egl_window_resize(mWaylandEglWindow,rect.width(),rect.height(),0,0); + } +} + +void QWaylandEglWindow::setParent(const QPlatformWindow *parent) +{ + const QWaylandWindow *wParent = static_cast<const QWaylandWindow *>(parent); + + mParentWindow = wParent; +} + +QPlatformGLContext * QWaylandEglWindow::glContext() const +{ + if (!mGLContext) { + QWaylandEglWindow *that = const_cast<QWaylandEglWindow *>(this); + that->mGLContext = new QWaylandGLContext(that->mDisplay,widget()->platformWindowFormat()); + + EGLNativeWindowType window(reinterpret_cast<EGLNativeWindowType>(mWaylandEglWindow)); + EGLSurface surface = eglCreateWindowSurface(mDisplay->eglDisplay(),mGLContext->eglConfig(),window,NULL); + that->mGLContext->setEglSurface(surface); + } + + return mGLContext; +} + +void QWaylandEglWindow::newSurfaceCreated() +{ + if (mWaylandEglWindow) { + wl_egl_window_destroy(mWaylandEglWindow); + } + wl_visual *visual = QWaylandScreen::waylandScreenFromWidget(widget())->visual(); + QSize size = geometry().size(); + if (!size.isValid()) + size = QSize(0,0); + + mWaylandEglWindow = wl_egl_window_create(mDisplay->nativeDisplay(),mSurface,size.width(),size.height(),visual); + if (mGLContext) { + EGLNativeWindowType window(reinterpret_cast<EGLNativeWindowType>(mWaylandEglWindow)); + EGLSurface surface = eglCreateWindowSurface(mDisplay->eglDisplay(),mGLContext->eglConfig(),window,NULL); + mGLContext->setEglSurface(surface); + } +} diff --git a/src/plugins/platforms/wayland/qwaylandeglwindow.h b/src/plugins/platforms/wayland/qwaylandeglwindow.h new file mode 100644 index 0000000..4b3bb5b --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandeglwindow.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDEGLWINDOW_H +#define QWAYLANDEGLWINDOW_H + +#include "qwaylandwindow.h" + +class QWaylandGLContext; + +class QWaylandEglWindow : public QWaylandWindow +{ +public: + QWaylandEglWindow(QWidget *window); + ~QWaylandEglWindow(); + WindowType windowType() const; + void setGeometry(const QRect &rect); + void setParent(const QPlatformWindow *parent); + QPlatformGLContext *glContext() const; +protected: + void newSurfaceCreated(); +private: + QWaylandGLContext *mGLContext; + struct wl_egl_window *mWaylandEglWindow; + EGLConfig mConfig; + + const QWaylandWindow *mParentWindow; +}; + +#endif // QWAYLANDEGLWINDOW_H diff --git a/src/plugins/platforms/wayland/qwaylandglcontext.cpp b/src/plugins/platforms/wayland/qwaylandglcontext.cpp new file mode 100644 index 0000000..3720567 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandglcontext.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandglcontext.h" + +#include "qwaylanddisplay.h" +#include "qwaylandwindow.h" +#include "qwaylanddrmsurface.h" + +#include "../eglconvenience/qeglconvenience.h" + +#include <QtGui/QPlatformGLContext> +#include <QtGui/QPlatformWindowFormat> + +Q_GLOBAL_STATIC(QMutex,qt_defaultSharedContextMutex) + +QWaylandGLContext::QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format) + : QPlatformGLContext() + , mDisplay(wd) + , mSurface(EGL_NO_SURFACE) + , mConfig(q_configFromQPlatformWindowFormat(mDisplay->eglDisplay(),format,true)) + , mFormat(qt_qPlatformWindowFormatFromConfig(mDisplay->eglDisplay(),mConfig)) +{ + QPlatformGLContext *sharePlatformContext = 0; + if (format.useDefaultSharedContext()) { + if (!QPlatformGLContext::defaultSharedContext()) { + if (qt_defaultSharedContextMutex()->tryLock()){ + createDefaultSharedContex(wd); + qt_defaultSharedContextMutex()->unlock(); + } else { + qt_defaultSharedContextMutex()->lock(); //wait to the the shared context is created + qt_defaultSharedContextMutex()->unlock(); + } + } + sharePlatformContext = QPlatformGLContext::defaultSharedContext(); + } else { + sharePlatformContext = format.sharedGLContext(); + } + mFormat.setSharedContext(sharePlatformContext); + EGLContext shareEGLContext = EGL_NO_CONTEXT; + if (sharePlatformContext) + shareEGLContext = static_cast<const QWaylandGLContext*>(sharePlatformContext)->mContext; + + eglBindAPI(EGL_OPENGL_ES_API); + + QVector<EGLint> eglContextAttrs; + eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); + eglContextAttrs.append(2); + eglContextAttrs.append(EGL_NONE); + + mContext = eglCreateContext(mDisplay->eglDisplay(), mConfig, + shareEGLContext, eglContextAttrs.constData()); +} + +QWaylandGLContext::QWaylandGLContext() + : QPlatformGLContext() + , mDisplay(0) + , mContext(EGL_NO_CONTEXT) + , mSurface(EGL_NO_SURFACE) + , mConfig(0) +{ } + +QWaylandGLContext::~QWaylandGLContext() +{ + eglDestroyContext(mDisplay->eglDisplay(),mContext); +} + +void QWaylandGLContext::makeCurrent() +{ + QPlatformGLContext::makeCurrent(); + if (mSurface == EGL_NO_SURFACE) { + qWarning("makeCurrent with EGL_NO_SURFACE"); + } + eglMakeCurrent(mDisplay->eglDisplay(), mSurface, mSurface, mContext); +} + +void QWaylandGLContext::doneCurrent() +{ + QPlatformGLContext::doneCurrent(); + eglMakeCurrent(mDisplay->eglDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); +} + +void QWaylandGLContext::swapBuffers() +{ + eglSwapBuffers(mDisplay->eglDisplay(),mSurface); +} + +void *QWaylandGLContext::getProcAddress(const QString &string) +{ + return (void *) eglGetProcAddress(string.toLatin1().data()); +} + +void QWaylandGLContext::createDefaultSharedContex(QWaylandDisplay *display) +{ + QVector<EGLint> eglContextAttrs; + eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); + eglContextAttrs.append(2); + eglContextAttrs.append(EGL_NONE); + + QWaylandGLContext *defaultSharedContext = new QWaylandGLContext; + defaultSharedContext->mDisplay = display; + defaultSharedContext->mContext = eglCreateContext(mDisplay->eglDisplay(),mConfig, + EGL_NO_CONTEXT, eglContextAttrs.constData()); + QPlatformGLContext::setDefaultSharedContext(defaultSharedContext); +} + +void QWaylandGLContext::setEglSurface(EGLSurface surface) +{ + doneCurrent(); + mSurface = surface; +} + +EGLConfig QWaylandGLContext::eglConfig() const +{ + return mConfig; +} + diff --git a/src/plugins/platforms/wayland/qwaylandglcontext.h b/src/plugins/platforms/wayland/qwaylandglcontext.h new file mode 100644 index 0000000..dd319fd --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandglcontext.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDGLCONTEXT_H +#define QWAYLANDGLCONTEXT_H + +#include "qwaylanddisplay.h" + +#include <QtGui/QPlatformGLContext> + +class QWaylandWindow; +class QWaylandDrmWindowSurface; + +#include "qwaylandinclude.h" + +class QWaylandGLContext : public QPlatformGLContext { +public: + QWaylandGLContext(QWaylandDisplay *wd, const QPlatformWindowFormat &format); + ~QWaylandGLContext(); + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void* getProcAddress(const QString&); + + QPlatformWindowFormat platformWindowFormat() const { return mFormat; } + + void setEglSurface(EGLSurface surface); + EGLConfig eglConfig() const; +private: + QWaylandDisplay *mDisplay; + + EGLContext mContext; + EGLSurface mSurface; + EGLConfig mConfig; + QPlatformWindowFormat mFormat; + + void createDefaultSharedContex(QWaylandDisplay *display); + QWaylandGLContext(); + +}; + + +#endif // QWAYLANDGLCONTEXT_H diff --git a/src/plugins/platforms/wayland/qwaylandinclude.h b/src/plugins/platforms/wayland/qwaylandinclude.h new file mode 100644 index 0000000..0135251 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandinclude.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDINCLUDE_H +#define QWAYLANDINCLUDE_H + +#include <wayland-client.h> + +#ifdef QT_WAYLAND_GL_SUPPORT +#include <wayland-egl.h> + +#define GL_GLEXT_PROTOTYPES +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +#define EGL_EGLEXT_PROTOTYPES + #include <EGL/egl.h> + #include <EGL/eglext.h> + +#else +typedef void* EGLDisplay; +typedef void* EGLConfig; +#endif + +#endif // QWAYLANDINCLUDE_H diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.cpp b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp new file mode 100644 index 0000000..47f9c91 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.cpp @@ -0,0 +1,329 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandinputdevice.h" + +#include "qwaylandintegration.h" +#include "qwaylandwindow.h" +#include "qwaylandbuffer.h" + +#include <QWindowSystemInterface> + +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtGui/QPlatformWindow> + +#include <unistd.h> +#include <fcntl.h> + +#ifndef QT_NO_WAYLAND_XKB +#include <X11/extensions/XKBcommon.h> +#include <X11/keysym.h> +#endif + +QWaylandInputDevice::QWaylandInputDevice(struct wl_display *display, + uint32_t id) + : mDisplay(display) + , mInputDevice(wl_input_device_create(display, id)) + , mPointerFocus(NULL) + , mKeyboardFocus(NULL) + , mButtons(0) +{ + wl_input_device_add_listener(mInputDevice, + &inputDeviceListener, + this); + wl_input_device_set_user_data(mInputDevice, this); + +#ifndef QT_NO_WAYLAND_XKB + struct xkb_rule_names names; + names.rules = "evdev"; + names.model = "pc105"; + names.layout = "us"; + names.variant = ""; + names.options = ""; + + mXkb = xkb_compile_keymap_from_rules(&names); +#endif +} + +void QWaylandInputDevice::inputHandleMotion(void *data, + struct wl_input_device *input_device, + uint32_t time, + int32_t x, int32_t y, + int32_t surface_x, int32_t surface_y) +{ + Q_UNUSED(input_device); + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window = inputDevice->mPointerFocus; + + inputDevice->mSurfacePos = QPoint(surface_x, surface_y); + inputDevice->mGlobalPos = QPoint(x, y); + inputDevice->mTime = time; + QWindowSystemInterface::handleMouseEvent(window->widget(), + time, + inputDevice->mSurfacePos, + inputDevice->mGlobalPos, + inputDevice->mButtons); +} + +void QWaylandInputDevice::inputHandleButton(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t button, uint32_t state) +{ + Q_UNUSED(input_device); + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window = inputDevice->mPointerFocus; + Qt::MouseButton qt_button; + + switch (button) { + case 272: + qt_button = Qt::LeftButton; + break; + case 273: + qt_button = Qt::RightButton; + break; + case 274: + qt_button = Qt::MiddleButton; + break; + default: + return; + } + + if (state) + inputDevice->mButtons |= qt_button; + else + inputDevice->mButtons &= ~qt_button; + + inputDevice->mTime = time; + QWindowSystemInterface::handleMouseEvent(window->widget(), + time, + inputDevice->mSurfacePos, + inputDevice->mGlobalPos, + inputDevice->mButtons); +} + +#ifndef QT_NO_WAYLAND_XKB +static Qt::KeyboardModifiers translateModifiers(int s) +{ + const uchar qt_alt_mask = XKB_COMMON_MOD1_MASK; + const uchar qt_meta_mask = XKB_COMMON_MOD4_MASK; + + Qt::KeyboardModifiers ret = 0; + if (s & XKB_COMMON_SHIFT_MASK) + ret |= Qt::ShiftModifier; + if (s & XKB_COMMON_CONTROL_MASK) + ret |= Qt::ControlModifier; + if (s & qt_alt_mask) + ret |= Qt::AltModifier; + if (s & qt_meta_mask) + ret |= Qt::MetaModifier; + + return ret; +} + +static uint32_t translateKey(uint32_t sym, char *string, size_t size) +{ + Q_UNUSED(size); + string[0] = '\0'; + + switch (sym) { + case XK_Escape: return Qt::Key_Escape; + case XK_Tab: return Qt::Key_Tab; + case XK_ISO_Left_Tab: return Qt::Key_Backtab; + case XK_BackSpace: return Qt::Key_Backspace; + case XK_Return: return Qt::Key_Return; + case XK_Insert: return Qt::Key_Insert; + case XK_Delete: return Qt::Key_Delete; + case XK_Clear: return Qt::Key_Delete; + case XK_Pause: return Qt::Key_Pause; + case XK_Print: return Qt::Key_Print; + + case XK_Home: return Qt::Key_Home; + case XK_End: return Qt::Key_End; + case XK_Left: return Qt::Key_Left; + case XK_Up: return Qt::Key_Up; + case XK_Right: return Qt::Key_Right; + case XK_Down: return Qt::Key_Down; + case XK_Prior: return Qt::Key_PageUp; + case XK_Next: return Qt::Key_PageDown; + + case XK_Shift_L: return Qt::Key_Shift; + case XK_Shift_R: return Qt::Key_Shift; + case XK_Shift_Lock: return Qt::Key_Shift; + case XK_Control_L: return Qt::Key_Control; + case XK_Control_R: return Qt::Key_Control; + case XK_Meta_L: return Qt::Key_Meta; + case XK_Meta_R: return Qt::Key_Meta; + case XK_Alt_L: return Qt::Key_Alt; + case XK_Alt_R: return Qt::Key_Alt; + case XK_Caps_Lock: return Qt::Key_CapsLock; + case XK_Num_Lock: return Qt::Key_NumLock; + case XK_Scroll_Lock: return Qt::Key_ScrollLock; + case XK_Super_L: return Qt::Key_Super_L; + case XK_Super_R: return Qt::Key_Super_R; + case XK_Menu: return Qt::Key_Menu; + + default: + string[0] = sym; + string[1] = '\0'; + return toupper(sym); + } +} +#endif + +void QWaylandInputDevice::inputHandleKey(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t key, uint32_t state) +{ +#ifndef QT_NO_WAYLAND_XKB + Q_UNUSED(input_device); + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window = inputDevice->mKeyboardFocus; + uint32_t code, sym, level; + Qt::KeyboardModifiers modifiers; + QEvent::Type type; + char s[2]; + + code = key + inputDevice->mXkb->min_key_code; + + level = 0; + if (inputDevice->mModifiers & Qt::ShiftModifier && + XkbKeyGroupWidth(inputDevice->mXkb, code, 0) > 1) + level = 1; + + sym = XkbKeySymEntry(inputDevice->mXkb, code, level, 0); + + modifiers = translateModifiers(inputDevice->mXkb->map->modmap[code]); + + if (state) { + inputDevice->mModifiers |= modifiers; + type = QEvent::KeyPress; + } else { + inputDevice->mModifiers &= ~modifiers; + type = QEvent::KeyRelease; + } + + sym = translateKey(sym, s, sizeof s); + + qWarning("keycode %d, sym %d, string %d, modifiers 0x%x", + code, sym, s[0], (int) inputDevice->mModifiers); + + if (window) { + QWindowSystemInterface::handleKeyEvent(window->widget(), + time, type, sym, + inputDevice->mModifiers, + QString::fromLatin1(s)); + } +#endif +} + +void QWaylandInputDevice::inputHandlePointerFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y, int32_t sx, int32_t sy) +{ + Q_UNUSED(input_device); + Q_UNUSED(x); + Q_UNUSED(y); + Q_UNUSED(sx); + Q_UNUSED(sy); + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window; + + if (inputDevice->mPointerFocus) { + window = inputDevice->mPointerFocus; + QWindowSystemInterface::handleLeaveEvent(window->widget()); + inputDevice->mPointerFocus = NULL; + } + + if (surface) { + window = (QWaylandWindow *) wl_surface_get_user_data(surface); + QWindowSystemInterface::handleEnterEvent(window->widget()); + inputDevice->mPointerFocus = window; + } + + inputDevice->mTime = time; +} + +void QWaylandInputDevice::inputHandleKeyboardFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, + struct wl_surface *surface, + struct wl_array *keys) +{ +#ifndef QT_NO_WAYLAND_XKB + Q_UNUSED(input_device); + Q_UNUSED(time); + QWaylandInputDevice *inputDevice = (QWaylandInputDevice *) data; + QWaylandWindow *window; + uint32_t *k, *end; + uint32_t code; + + end = (uint32_t *) ((char *) keys->data + keys->size); + inputDevice->mModifiers = 0; + for (k = (uint32_t *) keys->data; k < end; k++) { + code = *k + inputDevice->mXkb->min_key_code; + inputDevice->mModifiers |= + translateModifiers(inputDevice->mXkb->map->modmap[code]); + } + + if (surface) { + window = (QWaylandWindow *) wl_surface_get_user_data(surface); + inputDevice->mKeyboardFocus = window; + QWindowSystemInterface::handleWindowActivated(window->widget()); + } else { + inputDevice->mKeyboardFocus = NULL; + QWindowSystemInterface::handleWindowActivated(0); + } +#endif +} + +const struct wl_input_device_listener QWaylandInputDevice::inputDeviceListener = { + QWaylandInputDevice::inputHandleMotion, + QWaylandInputDevice::inputHandleButton, + QWaylandInputDevice::inputHandleKey, + QWaylandInputDevice::inputHandlePointerFocus, + QWaylandInputDevice::inputHandleKeyboardFocus, +}; + +void QWaylandInputDevice::attach(QWaylandBuffer *buffer, int x, int y) +{ + wl_input_device_attach(mInputDevice, mTime, buffer->buffer(), x, y); +} diff --git a/src/plugins/platforms/wayland/qwaylandinputdevice.h b/src/plugins/platforms/wayland/qwaylandinputdevice.h new file mode 100644 index 0000000..2328db8 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandinputdevice.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDINPUTDEVICE_H +#define QWAYLANDINPUTDEVICE_H + +#include "qwaylandwindow.h" + +#include <QSocketNotifier> +#include <QObject> +#include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformScreen> + +#include <wayland-client.h> + +QT_BEGIN_NAMESPACE + +class QWaylandWindow; + +class QWaylandInputDevice { +public: + QWaylandInputDevice(struct wl_display *display, uint32_t id); + void attach(QWaylandBuffer *buffer, int x, int y); + +private: + struct wl_display *mDisplay; + struct wl_input_device *mInputDevice; + QWaylandWindow *mPointerFocus; + QWaylandWindow *mKeyboardFocus; + static const struct wl_input_device_listener inputDeviceListener; + Qt::MouseButtons mButtons; + QPoint mSurfacePos; + QPoint mGlobalPos; + struct xkb_desc *mXkb; + Qt::KeyboardModifiers mModifiers; + uint32_t mTime; + + static void inputHandleMotion(void *data, + struct wl_input_device *input_device, + uint32_t time, + int32_t x, int32_t y, + int32_t sx, int32_t sy); + static void inputHandleButton(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t button, uint32_t state); + static void inputHandleKey(void *data, + struct wl_input_device *input_device, + uint32_t time, uint32_t key, uint32_t state); + static void inputHandlePointerFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, struct wl_surface *surface, + int32_t x, int32_t y, int32_t sx, int32_t sy); + static void inputHandleKeyboardFocus(void *data, + struct wl_input_device *input_device, + uint32_t time, + struct wl_surface *surface, + struct wl_array *keys); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wayland/qwaylandintegration.cpp b/src/plugins/platforms/wayland/qwaylandintegration.cpp new file mode 100644 index 0000000..267a037 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandintegration.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandintegration.h" + +#include "qwaylanddisplay.h" +#include "qwaylandshmsurface.h" +#include "qwaylanddrmsurface.h" +#include "qwaylandshmwindow.h" +#include "qwaylandeglwindow.h" + +#include "qgenericunixfontdatabase.h" + +#include <QtGui/QWindowSystemInterface> +#include <QtGui/QPlatformCursor> +#include <QtGui/QPlatformWindowFormat> + +#include <QtGui/private/qpixmap_raster_p.h> +#ifdef QT_WAYLAND_GL_SUPPORT +#include <QtOpenGL/private/qpixmapdata_gl_p.h> +#endif + +QWaylandIntegration::QWaylandIntegration(bool useOpenGL) + : mFontDb(new QGenericUnixFontDatabase()) + , mDisplay(new QWaylandDisplay()) + , mUseOpenGL(useOpenGL) +{ +} + +QList<QPlatformScreen *> +QWaylandIntegration::screens() const +{ + return mDisplay->screens(); +} + +bool QWaylandIntegration::hasCapability(QPlatformIntegration::Capability cap) const +{ + switch (cap) { + case ThreadedPixmaps: return true; + default: return QPlatformIntegration::hasCapability(cap); + } +} + +QPixmapData *QWaylandIntegration::createPixmapData(QPixmapData::PixelType type) const +{ +#ifdef QT_WAYLAND_GL_SUPPORT + if (mUseOpenGL) + return new QGLPixmapData(type); +#endif + return new QRasterPixmapData(type); +} + +QPlatformWindow *QWaylandIntegration::createPlatformWindow(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + bool useOpenGL = mUseOpenGL || (widget->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL); + if (useOpenGL) + return new QWaylandEglWindow(widget); + + return new QWaylandShmWindow(widget); +} + +QWindowSurface *QWaylandIntegration::createWindowSurface(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + Q_UNUSED(winId); + bool useOpenGL = mUseOpenGL || (widget->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL); + if (useOpenGL) + return new QWaylandDrmWindowSurface(widget); + + return new QWaylandShmWindowSurface(widget); +} + +QPlatformFontDatabase *QWaylandIntegration::fontDatabase() const +{ + return mFontDb; +} diff --git a/src/plugins/platforms/wayland/qwaylandintegration.h b/src/plugins/platforms/wayland/qwaylandintegration.h new file mode 100644 index 0000000..067b6e4 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandintegration.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QPLATFORMINTEGRATION_WAYLAND_H +#define QPLATFORMINTEGRATION_WAYLAND_H + +#include <QtGui/QPlatformIntegration> + +QT_BEGIN_NAMESPACE + +class QWaylandBuffer; +class QWaylandDisplay; + +class QWaylandIntegration : public QPlatformIntegration +{ +public: + QWaylandIntegration(bool useOpenGL = false); + + bool hasCapability(QPlatformIntegration::Capability cap) const; + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QList<QPlatformScreen *> screens() const; + + QPlatformFontDatabase *fontDatabase() const; + +private: + QPlatformFontDatabase *mFontDb; + QWaylandDisplay *mDisplay; + bool mUseOpenGL; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wayland/qwaylandscreen.cpp b/src/plugins/platforms/wayland/qwaylandscreen.cpp new file mode 100644 index 0000000..35e2532 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandscreen.cpp @@ -0,0 +1,106 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandscreen.h" + +#include "qwaylanddisplay.h" +#include "qwaylandcursor.h" + +QWaylandScreen::QWaylandScreen(QWaylandDisplay *waylandDisplay, struct wl_output *output, QRect geometry) + : QPlatformScreen() + , mWaylandDisplay(waylandDisplay) + , mOutput(output) + , mGeometry(geometry) + , mDepth(32) + , mFormat(QImage::Format_ARGB32_Premultiplied) + , mWaylandCursor(new QWaylandCursor(this)) +{ +} + +QWaylandScreen::~QWaylandScreen() +{ + delete mWaylandCursor; +} + +QWaylandDisplay * QWaylandScreen::display() const +{ + return mWaylandDisplay; +} + +QRect QWaylandScreen::geometry() const +{ + return mGeometry; +} + +int QWaylandScreen::depth() const +{ + return mDepth; +} + +QImage::Format QWaylandScreen::format() const +{ + return mFormat; +} + +QWaylandScreen * QWaylandScreen::waylandScreenFromWidget(QWidget *widget) +{ + QPlatformScreen *platformScreen = QPlatformScreen::platformScreenForWidget(widget); + return static_cast<QWaylandScreen *>(platformScreen); +} + +wl_visual * QWaylandScreen::visual() const +{ + struct wl_visual *visual; + + switch (format()) { + case QImage::Format_ARGB32: + visual = mWaylandDisplay->argbVisual(); + break; + case QImage::Format_ARGB32_Premultiplied: + visual = mWaylandDisplay->argbPremultipliedVisual(); + break; + default: + qDebug("unsupported buffer format %d requested\n", format()); + visual = mWaylandDisplay->argbVisual(); + break; + } + return visual; +} diff --git a/src/plugins/platforms/wayland/qwaylandscreen.h b/src/plugins/platforms/wayland/qwaylandscreen.h new file mode 100644 index 0000000..7784646 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandscreen.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDSCREEN_H +#define QWAYLANDSCREEN_H + +#include <QtGui/QPlatformScreen> + +class QWaylandDisplay; +class QWaylandCursor; +struct wl_visual; + +class QWaylandScreen : public QPlatformScreen +{ +public: + QWaylandScreen(QWaylandDisplay *waylandDisplay, struct wl_output *output, QRect geometry); + ~QWaylandScreen(); + + QWaylandDisplay *display() const; + + QRect geometry() const; + int depth() const; + QImage::Format format() const; + + wl_visual *visual() const; + + static QWaylandScreen *waylandScreenFromWidget(QWidget *widget); + +private: + QWaylandDisplay *mWaylandDisplay; + struct wl_output *mOutput; + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + QSize mPhysicalSize; + QWaylandCursor *mWaylandCursor; +}; + +#endif // QWAYLANDSCREEN_H diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.cpp b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp new file mode 100644 index 0000000..54da9a1 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandshmsurface.cpp @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ +#include "qwaylandshmsurface.h" + +#include <QtCore/qdebug.h> +#include <QtGui/private/qapplication_p.h> + +#include "qwaylanddisplay.h" +#include "qwaylandshmwindow.h" +#include "qwaylandscreen.h" + +#include <wayland-client.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/mman.h> + +QT_BEGIN_NAMESPACE + +QWaylandShmBuffer::QWaylandShmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format) +{ + int stride = size.width() * 4; + int alloc = stride * size.height(); + char filename[] = "/tmp/wayland-shm-XXXXXX"; + int fd = mkstemp(filename); + if (fd < 0) + qWarning("open %s failed: %s", filename, strerror(errno)); + if (ftruncate(fd, alloc) < 0) { + qWarning("ftruncate failed: %s", strerror(errno)); + close(fd); + return; + } + uchar *data = (uchar *) + mmap(NULL, alloc, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + unlink(filename); + + if (data == (uchar *) MAP_FAILED) { + qWarning("mmap /dev/zero failed: %s", strerror(errno)); + close(fd); + return; + } + + mImage = QImage(data, size.width(), size.height(), stride, format); + mBuffer = display->createShmBuffer(fd, size.width(), size.height(), + stride, display->argbVisual()); + close(fd); +} + +QWaylandShmBuffer::~QWaylandShmBuffer(void) +{ + munmap((void *) mImage.constBits(), mImage.byteCount()); + wl_buffer_destroy(mBuffer); +} + +QWaylandShmWindowSurface::QWaylandShmWindowSurface(QWidget *window) + : QWindowSurface(window) + , mBuffer(0) + , mDisplay(QWaylandScreen::waylandScreenFromWidget(window)->display()) + , mWaitingForFrameSync(false) +{ +} + +QWaylandShmWindowSurface::~QWaylandShmWindowSurface() +{ +} + +QPaintDevice *QWaylandShmWindowSurface::paintDevice() +{ + return mBuffer->image(); +} + +void QWaylandShmWindowSurface::beginPaint(const QRegion &) +{ + while (mWaitingForFrameSync) { + mDisplay->iterate(); + } +} + +void QWaylandShmWindowSurface::frameCallback(void *data, uint32_t time) +{ + QWaylandShmWindowSurface *self = static_cast<QWaylandShmWindowSurface*>(data); + self->mWaitingForFrameSync = false; +} + +void QWaylandShmWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(offset); + QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->platformWindow()); + Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm); + + QVector<QRect> rects = region.rects(); + for (int i = 0; i < rects.size(); i++) { + waylandWindow->damage(rects.at(i)); + } + mWaitingForFrameSync = true; + mDisplay->frameCallback(QWaylandShmWindowSurface::frameCallback, this); +} + +void QWaylandShmWindowSurface::resize(const QSize &size) +{ + QWaylandShmWindow *waylandWindow = static_cast<QWaylandShmWindow *>(window()->platformWindow()); + Q_ASSERT(waylandWindow->windowType() == QWaylandWindow::Shm); + + QWindowSurface::resize(size); + QImage::Format format = QPlatformScreen::platformScreenForWidget(window())->format(); + + if (mBuffer != NULL && mBuffer->size() == size) + return; + + if (mBuffer != NULL) + delete mBuffer; + + mBuffer = new QWaylandShmBuffer(mDisplay, size, format); + + waylandWindow->attach(mBuffer); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/wayland/qwaylandshmsurface.h b/src/plugins/platforms/wayland/qwaylandshmsurface.h new file mode 100644 index 0000000..02b324a --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandshmsurface.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_WAYLAND_H +#define QWINDOWSURFACE_WAYLAND_H + +#include "qwaylandbuffer.h" +#include <QtGui/private/qwindowsurface_p.h> + +#include <QtGui/QPlatformWindow> + +QT_BEGIN_NAMESPACE + +class QWaylandDisplay; + +class QWaylandShmBuffer : public QWaylandBuffer { +public: + QWaylandShmBuffer(QWaylandDisplay *display, + const QSize &size, QImage::Format format); + ~QWaylandShmBuffer(); + QSize size() const { return mImage.size(); } + QImage *image() { return &mImage; } +private: + QImage mImage; +}; + +class QWaylandShmWindowSurface : public QWindowSurface +{ +public: + QWaylandShmWindowSurface(QWidget *window); + ~QWaylandShmWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + void beginPaint(const QRegion &); + +private: + static void frameCallback(void *data, uint32_t time);\ + + QWaylandShmBuffer *mBuffer; + QWaylandDisplay *mDisplay; + bool mWaitingForFrameSync; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/wayland/qwaylandshmwindow.cpp b/src/plugins/platforms/wayland/qwaylandshmwindow.cpp new file mode 100644 index 0000000..cafd2d0 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandshmwindow.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandshmwindow.h" + +#include "qwaylandbuffer.h" + +QWaylandShmWindow::QWaylandShmWindow(QWidget *widget) + : QWaylandWindow(widget) + , mBuffer(0) +{ + newSurfaceCreated(); +} + +QWaylandShmWindow::~QWaylandShmWindow() +{ + +} + +QWaylandWindow::WindowType QWaylandShmWindow::windowType() const +{ + return QWaylandWindow::Shm; +} + +QPlatformGLContext * QWaylandShmWindow::glContext() const +{ + qWarning("Trying to retrieve a glContext from a Raster window surface!"); + return 0; +} + +void QWaylandShmWindow::attach(QWaylandBuffer *buffer) +{ + mBuffer = buffer; + if (mSurface) { + wl_surface_attach(mSurface, buffer->buffer(),0,0); + } +} + + +void QWaylandShmWindow::damage(const QRect &rect) +{ + wl_surface_damage(mSurface, + rect.x(), rect.y(), rect.width(), rect.height()); +} + +void QWaylandShmWindow::newSurfaceCreated() +{ + if (mBuffer) { + wl_surface_attach(mSurface,mBuffer->buffer(),0,0); + } +} diff --git a/src/plugins/platforms/wayland/qwaylandshmwindow.h b/src/plugins/platforms/wayland/qwaylandshmwindow.h new file mode 100644 index 0000000..14a29d2 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandshmwindow.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDSHMWINDOW_H +#define QWAYLANDSHMWINDOW_H + +#include "qwaylandwindow.h" + +class QWaylandShmWindow : public QWaylandWindow +{ +public: + QWaylandShmWindow(QWidget *widget); + ~QWaylandShmWindow(); + + WindowType windowType() const; + QPlatformGLContext *glContext() const; + void attach(QWaylandBuffer *buffer); + void damage(const QRect &rect); +protected: + void newSurfaceCreated(); +private: + QWaylandBuffer *mBuffer; +}; + +#endif // QWAYLANDSHMWINDOW_H diff --git a/src/plugins/platforms/wayland/qwaylandwindow.cpp b/src/plugins/platforms/wayland/qwaylandwindow.cpp new file mode 100644 index 0000000..a912a83 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandwindow.cpp @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwaylandwindow.h" + +#include "qwaylanddisplay.h" +#include "qwaylandscreen.h" + +#include <QtGui/QWidget> +#include <QtGui/QWindowSystemInterface> + +#include <QDebug> + +QWaylandWindow::QWaylandWindow(QWidget *window) + : QPlatformWindow(window) + , mDisplay(QWaylandScreen::waylandScreenFromWidget(window)->display()) +{ + static WId id = 1; + mWindowId = id++; + + mSurface = mDisplay->createSurface(); +} + +QWaylandWindow::~QWaylandWindow() +{ +} + +WId QWaylandWindow::winId() const +{ + return mWindowId; +} + +void QWaylandWindow::setParent(const QPlatformWindow *parent) +{ + Q_UNUSED(parent); + qWarning("Trying to add a raster window as a sub-window"); +} + +void QWaylandWindow::setVisible(bool visible) +{ + if (!mSurface) { + mSurface = mDisplay->createSurface(); + newSurfaceCreated(); + } + + if (visible) { + wl_surface_set_user_data(mSurface, this); + wl_surface_map_toplevel(mSurface); + } else { + wl_surface_destroy(mSurface); + mSurface = NULL; + } +} + +void QWaylandWindow::configure(uint32_t time, uint32_t edges, + int32_t x, int32_t y, + int32_t width, int32_t height) +{ + Q_UNUSED(time); + Q_UNUSED(edges); + QRect geometry = QRect(x, y, width, height); + + setGeometry(geometry); + + QWindowSystemInterface::handleGeometryChange(widget(), geometry); +} diff --git a/src/plugins/platforms/wayland/qwaylandwindow.h b/src/plugins/platforms/wayland/qwaylandwindow.h new file mode 100644 index 0000000..3b51ee7 --- /dev/null +++ b/src/plugins/platforms/wayland/qwaylandwindow.h @@ -0,0 +1,83 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the config.tests of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWAYLANDWINDOW_H +#define QWAYLANDWINDOW_H + +#include <QtGui/QPlatformWindow> + +#include <stdint.h> +#include "qwaylanddisplay.h" + +class QWaylandDisplay; +class QWaylandBuffer; +struct wl_egl_window; + +class QWaylandWindow : public QPlatformWindow +{ +public: + enum WindowType { + Shm, + Egl + }; + + QWaylandWindow(QWidget *window); + ~QWaylandWindow(); + + virtual WindowType windowType() const = 0; + WId winId() const; + void setVisible(bool visible); + void setParent(const QPlatformWindow *parent); + + void configure(uint32_t time, uint32_t edges, + int32_t x, int32_t y, int32_t width, int32_t height); + +protected: + struct wl_surface *mSurface; + virtual void newSurfaceCreated() = 0; + QWaylandDisplay *mDisplay; + WId mWindowId; + + +}; + + +#endif // QWAYLANDWINDOW_H diff --git a/src/plugins/platforms/wayland/wayland.pro b/src/plugins/platforms/wayland/wayland.pro new file mode 100644 index 0000000..face860 --- /dev/null +++ b/src/plugins/platforms/wayland/wayland.pro @@ -0,0 +1,58 @@ +TARGET = qwayland +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +DEFINES += Q_PLATFORM_WAYLAND +DEFINES += $$QMAKE_DEFINES_WAYLAND + +SOURCES = main.cpp \ + qwaylandintegration.cpp \ + qwaylandshmsurface.cpp \ + qwaylandinputdevice.cpp \ + qwaylandcursor.cpp \ + qwaylanddisplay.cpp \ + qwaylandwindow.cpp \ + qwaylandscreen.cpp \ + qwaylandshmwindow.cpp + +HEADERS = qwaylandintegration.h \ + qwaylandcursor.h \ + qwaylanddisplay.h \ + qwaylandwindow.h \ + qwaylandscreen.h \ + qwaylandshmsurface.h \ + qwaylanddrmsurface.h \ + qwaylandbuffer.h \ + qwaylandinclude.h \ + qwaylandeglwindow.h \ + qwaylandshmwindow.h + +INCLUDEPATH += $$QMAKE_INCDIR_WAYLAND +LIBS += $$QMAKE_LIBS_WAYLAND +QMAKE_CXXFLAGS += $$QMAKE_CFLAGS_WAYLAND + +contains(QT_CONFIG, opengles2) { + QT += opengl + LIBS += -lwayland-egl -lEGL + + SOURCES += qwaylanddrmsurface.cpp \ + qwaylandglcontext.cpp \ + ../eglconvenience/qeglconvenience.cpp \ + qwaylandeglwindow.cpp + + HEADERS += qwaylandglcontext.h \ + ../eglconvenience/qeglconvenience.h \ + + DEFINES += QT_WAYLAND_GL_SUPPORT +} + +unix:isEmpty(QMAKE_INCDIR_WAYLAND) { + CONFIG += link_pkgconfig + PKGCONFIG += libdrm +} + +include (../fontdatabases/genericunix/genericunix.pri) + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target diff --git a/src/plugins/platforms/xcb/README b/src/plugins/platforms/xcb/README new file mode 100644 index 0000000..e88596b --- /dev/null +++ b/src/plugins/platforms/xcb/README @@ -0,0 +1,2 @@ +Required packages: +libxcb1 libxcb1-dev libx11-xcb1 libx11-xcb-dev libxcb-keysyms1 libxcb-keysyms1-dev libxcb-image0 libxcb-image0-dev libxcb-shm0 libxcb-shm0-dev libxcb-icccm1 libxcb-icccm1-dev diff --git a/src/plugins/platforms/xcb/main.cpp b/src/plugins/platforms/xcb/main.cpp new file mode 100644 index 0000000..89bc66e --- /dev/null +++ b/src/plugins/platforms/xcb/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QtGui/QPlatformIntegrationPlugin> +#include "qxcbintegration.h" + +QT_BEGIN_NAMESPACE + +class QXcbIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QXcbIntegrationPlugin::keys() const +{ + QStringList list; + list << "xcb"; + return list; +} + +QPlatformIntegration* QXcbIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "xcb") + return new QXcbIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(xcb, QXcbIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qdri2context.cpp b/src/plugins/platforms/xcb/qdri2context.cpp new file mode 100644 index 0000000..0079f91 --- /dev/null +++ b/src/plugins/platforms/xcb/qdri2context.cpp @@ -0,0 +1,271 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qdri2context.h" + +#include "qxcbwindow.h" +#include "qxcbconnection.h" + +#include <QtCore/QDebug> +#include <QtGui/QWidget> + +#include <xcb/dri2.h> +#include <xcb/xfixes.h> + +#define MESA_EGL_NO_X11_HEADERS +#define EGL_EGLEXT_PROTOTYPES +#include <EGL/egl.h> +#include <EGL/eglext.h> + +#define GL_GLEXT_PROTOTYPES +#include <GLES2/gl2.h> +#include <GLES2/gl2ext.h> + +class QDri2ContextPrivate +{ +public: + QDri2ContextPrivate(QXcbWindow *window) + : qXcbWindow(window) + , windowFormat(window->widget()->platformWindowFormat()) + , image(0) + { + } + + xcb_window_t xcbWindow() { return qXcbWindow->window(); } + xcb_connection_t *xcbConnection() { return qXcbWindow->xcb_connection(); } + + QXcbWindow *qXcbWindow; + QPlatformWindowFormat windowFormat; + + EGLContext eglContext; + + EGLImageKHR image; + + GLuint fbo; + GLuint rbo; + GLuint depth; + + QSize size; +}; + +QDri2Context::QDri2Context(QXcbWindow *window) + : d_ptr(new QDri2ContextPrivate(window)) +{ + Q_D(QDri2Context); + + static const EGLint contextAttribs[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + eglBindAPI(EGL_OPENGL_ES_API); + + EGLContext shareContext = EGL_NO_CONTEXT; + if (window->widget()->platformWindowFormat().sharedGLContext()) { + QDri2Context *context = static_cast<QDri2Context *>(window->widget()->platformWindowFormat().sharedGLContext()); + shareContext = context->d_func()->eglContext; + } + d->eglContext = eglCreateContext(EGL_DISPLAY_FROM_XCB(d->qXcbWindow), NULL, + shareContext, contextAttribs); + + if (d->eglContext == EGL_NO_CONTEXT) { + qDebug() << "No eglContext!" << eglGetError(); + } + + EGLBoolean makeCurrentSuccess = eglMakeCurrent(EGL_DISPLAY_FROM_XCB(d->qXcbWindow),EGL_NO_SURFACE,EGL_NO_SURFACE,d->eglContext); + if (!makeCurrentSuccess) { + qDebug() << "eglMakeCurrent failed!" << eglGetError(); + } + + xcb_dri2_create_drawable (d->xcbConnection(), d->xcbWindow()); + + glGenFramebuffers(1,&d->fbo); + glBindFramebuffer(GL_FRAMEBUFFER,d->fbo); + glActiveTexture(GL_TEXTURE0); + + glGenRenderbuffers(1, &d->rbo); + glBindRenderbuffer(GL_RENDERBUFFER, d->rbo); + + glGenRenderbuffers(1,&d->depth); + glBindRenderbuffer(GL_RENDERBUFFER, d->depth); + + resize(d->qXcbWindow->widget()->geometry().size()); + + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, d->rbo); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERER,d->depth); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERER,d->depth); + + //restore the old current context + const QPlatformGLContext *currentContext = QPlatformGLContext::currentContext(); + if (currentContext) + const_cast<QPlatformGLContext*>(currentContext)->makeCurrent(); +} + +QDri2Context::~QDri2Context() +{ + //cleanup +} + +void QDri2Context::makeCurrent() +{ + QPlatformGLContext::makeCurrent(); + Q_D(QDri2Context); + + eglMakeCurrent(EGL_DISPLAY_FROM_XCB(d->qXcbWindow),EGL_NO_SURFACE,EGL_NO_SURFACE,d->eglContext); + glBindFramebuffer(GL_FRAMEBUFFER,d->fbo); + +} + +void QDri2Context::doneCurrent() +{ + QPlatformGLContext::doneCurrent(); + Q_D(QDri2Context); + eglMakeCurrent(EGL_DISPLAY_FROM_XCB(d->qXcbWindow),EGL_NO_SURFACE,EGL_NO_SURFACE,EGL_NO_CONTEXT); +} + +void QDri2Context::swapBuffers() +{ + Q_D(QDri2Context); + xcb_rectangle_t rectangle; + rectangle.x = 0; + rectangle.y = 0; + rectangle.width = d->qXcbWindow->widget()->geometry().width(); + rectangle.height = d->qXcbWindow->widget()->geometry().height(); + + xcb_xfixes_region_t xfixesRegion = xcb_generate_id(d->xcbConnection()); + xcb_xfixes_create_region(d->xcbConnection(), xfixesRegion, + 1, &rectangle); + + xcb_dri2_copy_region_cookie_t cookie = xcb_dri2_copy_region_unchecked(d->xcbConnection(), + d->qXcbWindow->window(), + xfixesRegion, + XCB_DRI2_ATTACHMENT_BUFFER_FRONT_LEFT, + XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT); + + xcb_dri2_copy_region_reply_t *reply = xcb_dri2_copy_region_reply(d->xcbConnection(),cookie,NULL); + + //cleanup + delete reply; + xcb_xfixes_destroy_region(d->xcbConnection(), xfixesRegion); + +} + +void * QDri2Context::getProcAddress(const QString &procName) +{ + return (void *)eglGetProcAddress(qPrintable(procName)); +} + +void QDri2Context::resize(const QSize &size) +{ + Q_D(QDri2Context); + d->size= size; + + glBindFramebuffer(GL_FRAMEBUFFER,d->fbo); + + xcb_dri2_dri2_buffer_t *backBfr = backBuffer(); + + if (d->image) { + qDebug() << "destroing image"; + eglDestroyImageKHR(EGL_DISPLAY_FROM_XCB(d->qXcbWindow),d->image); + } + + EGLint imgAttribs[] = { + EGL_WIDTH, d->size.width(), + EGL_HEIGHT, d->size.height(), + EGL_DRM_BUFFER_STRIDE_MESA, backBfr->pitch /4, + EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, + EGL_NONE + }; + + d->image = eglCreateImageKHR(EGL_DISPLAY_FROM_XCB(d->qXcbWindow), + EGL_NO_CONTEXT, + EGL_DRM_BUFFER_MESA, + (EGLClientBuffer) backBfr->name, + imgAttribs); + + glBindRenderbuffer(GL_RENDERBUFFER, d->rbo); + glEGLImageTargetRenderbufferStorageOES(GL_RENDERBUFFER, + d->image); + + glBindRenderbuffer(GL_RENDERBUFFER, d->depth); + glRenderbufferStorage(GL_RENDERBUFFER,GL_DEPTH24_STENCIL8_OES,d->size.width(), d->size.height()); + +} + +QPlatformWindowFormat QDri2Context::platformWindowFormat() const +{ + Q_D(const QDri2Context); + return d->windowFormat; +} + +xcb_dri2_dri2_buffer_t * QDri2Context::backBuffer() +{ + Q_D(QDri2Context); + + unsigned int backBufferAttachment = XCB_DRI2_ATTACHMENT_BUFFER_BACK_LEFT; + xcb_dri2_get_buffers_cookie_t cookie = xcb_dri2_get_buffers_unchecked (d->xcbConnection(), + d->xcbWindow(), + 1, 1, &backBufferAttachment); + + xcb_dri2_get_buffers_reply_t *reply = xcb_dri2_get_buffers_reply (d->xcbConnection(), cookie, NULL); + if (!reply) { + qDebug() << "failed to get buffers reply"; + return 0; + } + + xcb_dri2_dri2_buffer_t *buffers = xcb_dri2_get_buffers_buffers (reply); + if (!buffers) { + qDebug() << "failed to get buffers"; + return 0; + } + + Q_ASSERT(reply->count == 1); + + delete reply; + + return buffers; +} + +void * QDri2Context::eglContext() const +{ + Q_D(QDri2Context); + return d->eglContext; +} diff --git a/src/plugins/platforms/xcb/qdri2context.h b/src/plugins/platforms/xcb/qdri2context.h new file mode 100644 index 0000000..42dd6bd --- /dev/null +++ b/src/plugins/platforms/xcb/qdri2context.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QDRI2CONTEXT_H +#define QDRI2CONTEXT_H + +#include <QtGui/QPlatformGLContext> + +class QXcbWindow; +class QDri2ContextPrivate; + +struct xcb_dri2_dri2_buffer_t; + +class QDri2Context : public QPlatformGLContext +{ + Q_DECLARE_PRIVATE(QDri2Context); +public: + QDri2Context(QXcbWindow *window); + ~QDri2Context(); + + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void* getProcAddress(const QString& procName); + + void resize(const QSize &size); + + QPlatformWindowFormat platformWindowFormat() const; + + void *eglContext() const; + +protected: + xcb_dri2_dri2_buffer_t *backBuffer(); + QScopedPointer<QDri2ContextPrivate> d_ptr; +private: + Q_DISABLE_COPY(QDri2Context) +}; + +#endif // QDRI2CONTEXT_H diff --git a/src/plugins/platforms/testlite/qglxintegration.cpp b/src/plugins/platforms/xcb/qglxintegration.cpp index a4b7b69..e94b6a6 100644 --- a/src/plugins/platforms/testlite/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/qglxintegration.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -43,7 +43,8 @@ #include <QLibrary> #include <QGLFormat> -#include "qtestlitewindow.h" +#include "qxcbwindow.h" +#include "qxcbscreen.h" #include <X11/Xlib.h> #include <X11/Xutil.h> @@ -55,11 +56,9 @@ #include <dlfcn.h> #endif -QT_BEGIN_NAMESPACE +QMutex QGLXContext::m_defaultSharedContextMutex(QMutex::Recursive); -QMutex QGLXGLContext::m_defaultSharedContextMutex(QMutex::Recursive); - -QVector<int> QGLXGLContext::buildSpec(const QPlatformWindowFormat &format) +QVector<int> QGLXContext::buildSpec(const QPlatformWindowFormat &format) { QVector<int> spec(48); int i = 0; @@ -107,11 +106,11 @@ QVector<int> QGLXGLContext::buildSpec(const QPlatformWindowFormat &format) spec[i++] = format.samples() == -1 ? 4 : format.samples(); } - spec[i++] = XNone; + spec[i++] = None; return spec; } -GLXFBConfig QGLXGLContext::findConfig(const MyDisplay *xd, const QPlatformWindowFormat &format) +GLXFBConfig QGLXContext::findConfig(const QXcbScreen *screen, const QPlatformWindowFormat &format) { bool reduced = true; GLXFBConfig chosenConfig = 0; @@ -120,7 +119,7 @@ GLXFBConfig QGLXGLContext::findConfig(const MyDisplay *xd, const QPlatformWindow QVector<int> spec = buildSpec(reducedFormat); int confcount = 0; GLXFBConfig *configs; - configs = glXChooseFBConfig(xd->display,xd->screen,spec.constData(),&confcount); + configs = glXChooseFBConfig(DISPLAY_FROM_XCB(screen), screen->screenNumber(), spec.constData(), &confcount); if (confcount) { for (int i = 0; i < confcount; i++) { @@ -128,7 +127,7 @@ GLXFBConfig QGLXGLContext::findConfig(const MyDisplay *xd, const QPlatformWindow // Make sure we try to get an ARGB visual if the format asked for an alpha: if (reducedFormat.alpha()) { int alphaSize; - glXGetFBConfigAttrib(xd->display,configs[i],GLX_ALPHA_SIZE,&alphaSize); + glXGetFBConfigAttrib(DISPLAY_FROM_XCB(screen), configs[i], GLX_ALPHA_SIZE, &alphaSize); if (alphaSize > 0) break; } else { @@ -147,14 +146,14 @@ GLXFBConfig QGLXGLContext::findConfig(const MyDisplay *xd, const QPlatformWindow return chosenConfig; } -XVisualInfo *QGLXGLContext::findVisualInfo(const MyDisplay *xd, const QPlatformWindowFormat &format) +XVisualInfo *QGLXContext::findVisualInfo(const QXcbScreen *screen, const QPlatformWindowFormat &format) { - GLXFBConfig config = QGLXGLContext::findConfig(xd,format); - XVisualInfo *visualInfo = glXGetVisualFromFBConfig(xd->display,config); + GLXFBConfig config = QGLXContext::findConfig(screen,format); + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(DISPLAY_FROM_XCB(screen), config); return visualInfo; } -QPlatformWindowFormat QGLXGLContext::platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext ctx) +QPlatformWindowFormat QGLXContext::platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext ctx) { QPlatformWindowFormat format; int redSize = 0; @@ -210,7 +209,7 @@ QPlatformWindowFormat QGLXGLContext::platformWindowFromGLXFBConfig(Display *disp return format; } -QPlatformWindowFormat QGLXGLContext::reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced) +QPlatformWindowFormat QGLXContext::reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced) { QPlatformWindowFormat retFormat = format; *reduced = true; @@ -235,9 +234,9 @@ QPlatformWindowFormat QGLXGLContext::reducePlatformWindowFormat(const QPlatformW return retFormat; } -QGLXGLContext::QGLXGLContext(Window window, MyDisplay *xd, const QPlatformWindowFormat &format) +QGLXContext::QGLXContext(Window window, QXcbScreen *screen, const QPlatformWindowFormat &format) : QPlatformGLContext() - , m_xd(xd) + , m_screen(screen) , m_drawable((Drawable)window) , m_context(0) { @@ -246,7 +245,7 @@ QGLXGLContext::QGLXGLContext(Window window, MyDisplay *xd, const QPlatformWindow if (format.useDefaultSharedContext()) { if (!QPlatformGLContext::defaultSharedContext()) { if (m_defaultSharedContextMutex.tryLock()){ - createDefaultSharedContex(xd); + createDefaultSharedContex(screen); m_defaultSharedContextMutex.unlock(); } else { m_defaultSharedContextMutex.lock(); //wait to the the shared context is created @@ -259,32 +258,26 @@ QGLXGLContext::QGLXGLContext(Window window, MyDisplay *xd, const QPlatformWindow } GLXContext shareGlxContext = 0; if (sharePlatformContext) - shareGlxContext = static_cast<const QGLXGLContext*>(sharePlatformContext)->glxContext(); - - GLXFBConfig config = findConfig(xd,format); - m_context = glXCreateNewContext(xd->display,config,GLX_RGBA_TYPE,shareGlxContext,TRUE); - m_windowFormat = QGLXGLContext::platformWindowFromGLXFBConfig(xd->display,config,m_context); + shareGlxContext = static_cast<const QGLXContext*>(sharePlatformContext)->glxContext(); -#ifdef MYX11_DEBUG - qDebug() << "QGLXGLContext::create context" << m_context; -#endif + GLXFBConfig config = findConfig(screen,format); + m_context = glXCreateNewContext(DISPLAY_FROM_XCB(screen), config, GLX_RGBA_TYPE, shareGlxContext, TRUE); + m_windowFormat = QGLXContext::platformWindowFromGLXFBConfig(DISPLAY_FROM_XCB(screen), config, m_context); } -QGLXGLContext::QGLXGLContext(MyDisplay *display, Drawable drawable, GLXContext context) - : QPlatformGLContext(), m_xd(display), m_drawable(drawable), m_context(context) +QGLXContext::QGLXContext(QXcbScreen *screen, Drawable drawable, GLXContext context) + : QPlatformGLContext(), m_screen(screen), m_drawable(drawable), m_context(context) { } -QGLXGLContext::~QGLXGLContext() +QGLXContext::~QGLXContext() { - if (m_context) { - qDebug("Destroying GLX context 0x%p", m_context); - glXDestroyContext(m_xd->display, m_context); - } + if (m_context) + glXDestroyContext(DISPLAY_FROM_XCB(m_screen), m_context); } -void QGLXGLContext::createDefaultSharedContex(MyDisplay *xd) +void QGLXContext::createDefaultSharedContex(QXcbScreen *screen) { int x = 0; int y = 0; @@ -293,45 +286,42 @@ void QGLXGLContext::createDefaultSharedContex(MyDisplay *xd) QPlatformWindowFormat format = QPlatformWindowFormat::defaultFormat(); GLXContext context; - GLXFBConfig config = findConfig(xd,format); + GLXFBConfig config = findConfig(screen,format); if (config) { - XVisualInfo *visualInfo = glXGetVisualFromFBConfig(xd->display,config); - Colormap cmap = XCreateColormap(xd->display,xd->rootWindow(),visualInfo->visual,AllocNone); + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(DISPLAY_FROM_XCB(screen), config); + Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(screen), screen->root(), visualInfo->visual, AllocNone); XSetWindowAttributes a; a.colormap = cmap; - Window sharedWindow = XCreateWindow(xd->display, xd->rootWindow(),x, y, w, h, + Window sharedWindow = XCreateWindow(DISPLAY_FROM_XCB(screen), screen->root(), x, y, w, h, 0, visualInfo->depth, InputOutput, visualInfo->visual, CWColormap, &a); - context = glXCreateNewContext(xd->display,config,GLX_RGBA_TYPE,0,TRUE); - QPlatformGLContext *sharedContext = new QGLXGLContext(xd,sharedWindow,context); + context = glXCreateNewContext(DISPLAY_FROM_XCB(screen), config, GLX_RGBA_TYPE, 0, TRUE); + QPlatformGLContext *sharedContext = new QGLXContext(screen, sharedWindow, context); QPlatformGLContext::setDefaultSharedContext(sharedContext); } else { qWarning("Warning no shared context created"); } } -void QGLXGLContext::makeCurrent() +void QGLXContext::makeCurrent() { QPlatformGLContext::makeCurrent(); -#ifdef MYX11_DEBUG - qDebug("QGLXGLContext::makeCurrent(window=0x%x, ctx=0x%x)", m_drawable, m_context); -#endif - glXMakeCurrent(m_xd->display, m_drawable, m_context); + glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), m_drawable, m_context); } -void QGLXGLContext::doneCurrent() +void QGLXContext::doneCurrent() { QPlatformGLContext::doneCurrent(); - glXMakeCurrent(m_xd->display, 0, 0); + glXMakeCurrent(DISPLAY_FROM_XCB(m_screen), 0, 0); } -void QGLXGLContext::swapBuffers() +void QGLXContext::swapBuffers() { - glXSwapBuffers(m_xd->display, m_drawable); + glXSwapBuffers(DISPLAY_FROM_XCB(m_screen), m_drawable); } -void* QGLXGLContext::getProcAddress(const QString& procName) +void* QGLXContext::getProcAddress(const QString& procName) { typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *); static qt_glXGetProcAddressARB glXGetProcAddressARB = 0; @@ -340,7 +330,7 @@ void* QGLXGLContext::getProcAddress(const QString& procName) if (resolved && !glXGetProcAddressARB) return 0; if (!glXGetProcAddressARB) { - QList<QByteArray> glxExt = QByteArray(glXGetClientString(m_xd->display, GLX_EXTENSIONS)).split(' '); + QList<QByteArray> glxExt = QByteArray(glXGetClientString(DISPLAY_FROM_XCB(m_screen), GLX_EXTENSIONS)).split(' '); if (glxExt.contains("GLX_ARB_get_proc_address")) { #if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) void *handle = dlopen(NULL, RTLD_LAZY); @@ -364,9 +354,7 @@ void* QGLXGLContext::getProcAddress(const QString& procName) return glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(procName.toLatin1().data())); } -QPlatformWindowFormat QGLXGLContext::platformWindowFormat() const +QPlatformWindowFormat QGLXContext::platformWindowFormat() const { return m_windowFormat; } - -QT_END_NAMESPACE diff --git a/src/plugins/platforms/xcb/qglxintegration.h b/src/plugins/platforms/xcb/qglxintegration.h new file mode 100644 index 0000000..f2e20c4 --- /dev/null +++ b/src/plugins/platforms/xcb/qglxintegration.h @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGLXINTEGRATION_H +#define QGLXINTEGRATION_H + +#include "qxcbwindow.h" + +#include <QtGui/QPlatformGLContext> +#include <QtGui/QPlatformWindowFormat> + +#include <QtCore/QMutex> + +#include <GL/glx.h> + +class QGLXContext : public QPlatformGLContext +{ +public: + QGLXContext(Window window, QXcbScreen *xd, const QPlatformWindowFormat &format); + ~QGLXContext(); + + virtual void makeCurrent(); + virtual void doneCurrent(); + virtual void swapBuffers(); + virtual void* getProcAddress(const QString& procName); + + GLXContext glxContext() const { return m_context; } + + QPlatformWindowFormat platformWindowFormat() const; + + static XVisualInfo *findVisualInfo(const QXcbScreen *xd, const QPlatformWindowFormat &format); + +private: + static GLXFBConfig findConfig(const QXcbScreen *xd,const QPlatformWindowFormat &format); + static QVector<int> buildSpec(const QPlatformWindowFormat &format); + static QPlatformWindowFormat platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext context); + static QPlatformWindowFormat reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced); + + QXcbScreen *m_screen; + Drawable m_drawable; + GLXContext m_context; + QPlatformWindowFormat m_windowFormat; + + QGLXContext (QXcbScreen *screen, Drawable drawable, GLXContext context); + static QMutex m_defaultSharedContextMutex; + static void createDefaultSharedContex(QXcbScreen *xd); +}; + +#endif diff --git a/src/plugins/platforms/xcb/qxcbconnection.cpp b/src/plugins/platforms/xcb/qxcbconnection.cpp new file mode 100644 index 0000000..191699b --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbconnection.cpp @@ -0,0 +1,557 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbconnection.h" +#include "qxcbkeyboard.h" +#include "qxcbscreen.h" +#include "qxcbwindow.h" + +#include <QtAlgorithms> +#include <QSocketNotifier> +#include <QtGui/private/qapplication_p.h> + +#include <QtCore/QDebug> + +#include <stdio.h> +#include <errno.h> + +#ifdef XCB_USE_XLIB +#include <X11/Xlib.h> +#include <X11/Xlib-xcb.h> +#endif + +#ifdef XCB_USE_EGL //dont pull in eglext prototypes +#include <EGL/egl.h> +#endif + +#ifdef XCB_USE_DRI2 +#include <xcb/dri2.h> +#include <xcb/xfixes.h> +extern "C" { +#include <xf86drm.h> +} +#define MESA_EGL_NO_X11_HEADERS +#define EGL_EGLEXT_PROTOTYPES +#include <EGL/egl.h> +#include <EGL/eglext.h> +#endif + +QXcbConnection::QXcbConnection(const char *displayName) + : m_displayName(displayName ? QByteArray(displayName) : qgetenv("DISPLAY")) +#ifdef XCB_USE_DRI2 + , m_dri2_major(0) + , m_dri2_minor(0) + , m_dri2_support_probed(false) + , m_has_support_for_dri2(false) +#endif +{ + int primaryScreen = 0; + +#ifdef XCB_USE_XLIB + Display *dpy = XOpenDisplay(m_displayName.constData()); + primaryScreen = DefaultScreen(dpy); + m_connection = XGetXCBConnection(dpy); + XSetEventQueueOwner(dpy, XCBOwnsEventQueue); + m_xlib_display = dpy; +#ifdef XCB_USE_EGL + EGLDisplay eglDisplay = eglGetDisplay(dpy); + m_egl_display = eglDisplay; + EGLint major, minor; + eglBindAPI(EGL_OPENGL_ES_API); + m_has_egl = eglInitialize(eglDisplay,&major,&minor); +#endif //XCB_USE_EGL +#else + m_connection = xcb_connect(m_displayName.constData(), &primaryScreen); + +#endif //XCB_USE_XLIB + m_setup = xcb_get_setup(xcb_connection()); + + xcb_screen_iterator_t it = xcb_setup_roots_iterator(m_setup); + + int screenNumber = 0; + while (it.rem) { + m_screens << new QXcbScreen(this, it.data, screenNumber++); + xcb_screen_next(&it); + } + + QSocketNotifier *socket = new QSocketNotifier(xcb_get_file_descriptor(xcb_connection()), QSocketNotifier::Read, this); + connect(socket, SIGNAL(activated(int)), this, SLOT(eventDispatcher())); + + m_keyboard = new QXcbKeyboard(this); + + initializeAllAtoms(); + +#ifdef XCB_USE_DRI2 + initializeDri2(); +#endif +} + +QXcbConnection::~QXcbConnection() +{ + qDeleteAll(m_screens); + +#ifdef XCB_USE_XLIB + XCloseDisplay((Display *)m_xlib_display); +#else + xcb_disconnect(xcb_connection()); +#endif + + delete m_keyboard; +} + +QXcbWindow *platformWindowFromId(xcb_window_t id) +{ + QWidget *widget = QWidget::find(id); + if (widget) + return static_cast<QXcbWindow *>(widget->platformWindow()); + return 0; +} + +#define HANDLE_PLATFORM_WINDOW_EVENT(event_t, window, handler) \ +{ \ + event_t *e = (event_t *)event; \ + if (QXcbWindow *platformWindow = platformWindowFromId(e->window)) \ + platformWindow->handler(e); \ +} \ +break; + +#define HANDLE_KEYBOARD_EVENT(event_t, handler) \ +{ \ + event_t *e = (event_t *)event; \ + if (QXcbWindow *platformWindow = platformWindowFromId(e->event)) \ + m_keyboard->handler(platformWindow->widget(), e); \ +} \ +break; + +//#define XCB_EVENT_DEBUG + +void printXcbEvent(const char *message, xcb_generic_event_t *event) +{ +#ifdef XCB_EVENT_DEBUG +#define PRINT_XCB_EVENT(event) \ + case event: \ + printf("%s: %d - %s\n", message, event, #event); \ + break; + + switch (event->response_type & ~0x80) { + PRINT_XCB_EVENT(XCB_KEY_PRESS); + PRINT_XCB_EVENT(XCB_KEY_RELEASE); + PRINT_XCB_EVENT(XCB_BUTTON_PRESS); + PRINT_XCB_EVENT(XCB_BUTTON_RELEASE); + PRINT_XCB_EVENT(XCB_MOTION_NOTIFY); + PRINT_XCB_EVENT(XCB_ENTER_NOTIFY); + PRINT_XCB_EVENT(XCB_LEAVE_NOTIFY); + PRINT_XCB_EVENT(XCB_FOCUS_IN); + PRINT_XCB_EVENT(XCB_FOCUS_OUT); + PRINT_XCB_EVENT(XCB_KEYMAP_NOTIFY); + PRINT_XCB_EVENT(XCB_EXPOSE); + PRINT_XCB_EVENT(XCB_GRAPHICS_EXPOSURE); + PRINT_XCB_EVENT(XCB_VISIBILITY_NOTIFY); + PRINT_XCB_EVENT(XCB_CREATE_NOTIFY); + PRINT_XCB_EVENT(XCB_DESTROY_NOTIFY); + PRINT_XCB_EVENT(XCB_UNMAP_NOTIFY); + PRINT_XCB_EVENT(XCB_MAP_NOTIFY); + PRINT_XCB_EVENT(XCB_MAP_REQUEST); + PRINT_XCB_EVENT(XCB_REPARENT_NOTIFY); + PRINT_XCB_EVENT(XCB_CONFIGURE_NOTIFY); + PRINT_XCB_EVENT(XCB_CONFIGURE_REQUEST); + PRINT_XCB_EVENT(XCB_GRAVITY_NOTIFY); + PRINT_XCB_EVENT(XCB_RESIZE_REQUEST); + PRINT_XCB_EVENT(XCB_CIRCULATE_NOTIFY); + PRINT_XCB_EVENT(XCB_CIRCULATE_REQUEST); + PRINT_XCB_EVENT(XCB_PROPERTY_NOTIFY); + PRINT_XCB_EVENT(XCB_SELECTION_CLEAR); + PRINT_XCB_EVENT(XCB_SELECTION_REQUEST); + PRINT_XCB_EVENT(XCB_SELECTION_NOTIFY); + PRINT_XCB_EVENT(XCB_COLORMAP_NOTIFY); + PRINT_XCB_EVENT(XCB_CLIENT_MESSAGE); + PRINT_XCB_EVENT(XCB_MAPPING_NOTIFY); + default: + printf("%s: %d - %s\n", message, event->response_type, "unknown"); + } +#else + Q_UNUSED(message); + Q_UNUSED(event); +#endif +} + +void QXcbConnection::eventDispatcher() +{ + while (xcb_generic_event_t *event = xcb_poll_for_event(xcb_connection())) { + bool handled = true; + switch (event->response_type & ~0x80) { + case XCB_EXPOSE: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_expose_event_t, window, handleExposeEvent); + case XCB_BUTTON_PRESS: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_press_event_t, event, handleButtonPressEvent); + case XCB_BUTTON_RELEASE: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_button_release_event_t, event, handleButtonReleaseEvent); + case XCB_MOTION_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_motion_notify_event_t, event, handleMotionNotifyEvent); + case XCB_CONFIGURE_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_configure_notify_event_t, event, handleConfigureNotifyEvent); + case XCB_CLIENT_MESSAGE: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_client_message_event_t, window, handleClientMessageEvent); + case XCB_ENTER_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_enter_notify_event_t, event, handleEnterNotifyEvent); + case XCB_LEAVE_NOTIFY: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_leave_notify_event_t, event, handleLeaveNotifyEvent); + case XCB_FOCUS_IN: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_in_event_t, event, handleFocusInEvent); + case XCB_FOCUS_OUT: + HANDLE_PLATFORM_WINDOW_EVENT(xcb_focus_out_event_t, event, handleFocusOutEvent); + case XCB_KEY_PRESS: + HANDLE_KEYBOARD_EVENT(xcb_key_press_event_t, handleKeyPressEvent); + case XCB_KEY_RELEASE: + HANDLE_KEYBOARD_EVENT(xcb_key_release_event_t, handleKeyReleaseEvent); + case XCB_MAPPING_NOTIFY: + m_keyboard->handleMappingNotifyEvent((xcb_mapping_notify_event_t *)event); + break; + default: + handled = false; + return; + } + if (handled) + printXcbEvent("Handled XCB event", event); + else + printXcbEvent("Unhandled XCB event", event); + } +} + +static const char * xcb_atomnames = { + // window-manager <-> client protocols + "WM_PROTOCOLS\0" + "WM_DELETE_WINDOW\0" + "WM_TAKE_FOCUS\0" + "_NET_WM_PING\0" + "_NET_WM_CONTEXT_HELP\0" + "_NET_WM_SYNC_REQUEST\0" + "_NET_WM_SYNC_REQUEST_COUNTER\0" + + // ICCCM window state + "WM_STATE\0" + "WM_CHANGE_STATE\0" + + // Session management + "WM_CLIENT_LEADER\0" + "WM_WINDOW_ROLE\0" + "SM_CLIENT_ID\0" + + // Clipboard + "CLIPBOARD\0" + "INCR\0" + "TARGETS\0" + "MULTIPLE\0" + "TIMESTAMP\0" + "SAVE_TARGETS\0" + "CLIP_TEMPORARY\0" + "_QT_SELECTION\0" + "_QT_CLIPBOARD_SENTINEL\0" + "_QT_SELECTION_SENTINEL\0" + "CLIPBOARD_MANAGER\0" + + "RESOURCE_MANAGER\0" + + "_XSETROOT_ID\0" + + "_QT_SCROLL_DONE\0" + "_QT_INPUT_ENCODING\0" + + "_MOTIF_WM_HINTS\0" + + "DTWM_IS_RUNNING\0" + "ENLIGHTENMENT_DESKTOP\0" + "_DT_SAVE_MODE\0" + "_SGI_DESKS_MANAGER\0" + + // EWMH (aka NETWM) + "_NET_SUPPORTED\0" + "_NET_VIRTUAL_ROOTS\0" + "_NET_WORKAREA\0" + + "_NET_MOVERESIZE_WINDOW\0" + "_NET_WM_MOVERESIZE\0" + + "_NET_WM_NAME\0" + "_NET_WM_ICON_NAME\0" + "_NET_WM_ICON\0" + + "_NET_WM_PID\0" + + "_NET_WM_WINDOW_OPACITY\0" + + "_NET_WM_STATE\0" + "_NET_WM_STATE_ABOVE\0" + "_NET_WM_STATE_BELOW\0" + "_NET_WM_STATE_FULLSCREEN\0" + "_NET_WM_STATE_MAXIMIZED_HORZ\0" + "_NET_WM_STATE_MAXIMIZED_VERT\0" + "_NET_WM_STATE_MODAL\0" + "_NET_WM_STATE_STAYS_ON_TOP\0" + "_NET_WM_STATE_DEMANDS_ATTENTION\0" + + "_NET_WM_USER_TIME\0" + "_NET_WM_USER_TIME_WINDOW\0" + "_NET_WM_FULL_PLACEMENT\0" + + "_NET_WM_WINDOW_TYPE\0" + "_NET_WM_WINDOW_TYPE_DESKTOP\0" + "_NET_WM_WINDOW_TYPE_DOCK\0" + "_NET_WM_WINDOW_TYPE_TOOLBAR\0" + "_NET_WM_WINDOW_TYPE_MENU\0" + "_NET_WM_WINDOW_TYPE_UTILITY\0" + "_NET_WM_WINDOW_TYPE_SPLASH\0" + "_NET_WM_WINDOW_TYPE_DIALOG\0" + "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0" + "_NET_WM_WINDOW_TYPE_POPUP_MENU\0" + "_NET_WM_WINDOW_TYPE_TOOLTIP\0" + "_NET_WM_WINDOW_TYPE_NOTIFICATION\0" + "_NET_WM_WINDOW_TYPE_COMBO\0" + "_NET_WM_WINDOW_TYPE_DND\0" + "_NET_WM_WINDOW_TYPE_NORMAL\0" + "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0" + + "_KDE_NET_WM_FRAME_STRUT\0" + + "_NET_STARTUP_INFO\0" + "_NET_STARTUP_INFO_BEGIN\0" + + "_NET_SUPPORTING_WM_CHECK\0" + + "_NET_WM_CM_S0\0" + + "_NET_SYSTEM_TRAY_VISUAL\0" + + "_NET_ACTIVE_WINDOW\0" + + // Property formats + "COMPOUND_TEXT\0" + "TEXT\0" + "UTF8_STRING\0" + + // xdnd + "XdndEnter\0" + "XdndPosition\0" + "XdndStatus\0" + "XdndLeave\0" + "XdndDrop\0" + "XdndFinished\0" + "XdndTypeList\0" + "XdndActionList\0" + + "XdndSelection\0" + + "XdndAware\0" + "XdndProxy\0" + + "XdndActionCopy\0" + "XdndActionLink\0" + "XdndActionMove\0" + "XdndActionPrivate\0" + + // Motif DND + "_MOTIF_DRAG_AND_DROP_MESSAGE\0" + "_MOTIF_DRAG_INITIATOR_INFO\0" + "_MOTIF_DRAG_RECEIVER_INFO\0" + "_MOTIF_DRAG_WINDOW\0" + "_MOTIF_DRAG_TARGETS\0" + + "XmTRANSFER_SUCCESS\0" + "XmTRANSFER_FAILURE\0" + + // Xkb + "_XKB_RULES_NAMES\0" + + // XEMBED + "_XEMBED\0" + "_XEMBED_INFO\0" + + // Wacom old. (before version 0.10) + "Wacom Stylus\0" + "Wacom Cursor\0" + "Wacom Eraser\0" + + // Tablet + "STYLUS\0" + "ERASER\0" +}; + +xcb_atom_t QXcbConnection::atom(QXcbAtom::Atom atom) +{ + return m_allAtoms[atom]; +} + +void QXcbConnection::initializeAllAtoms() { + const char *names[QXcbAtom::NAtoms]; + const char *ptr = xcb_atomnames; + + int i = 0; + while (*ptr) { + names[i++] = ptr; + while (*ptr) + ++ptr; + ++ptr; + } + + Q_ASSERT(i == QXcbAtom::NPredefinedAtoms); + + QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_"); + settings_atom_name += m_displayName; + names[i++] = settings_atom_name; + + xcb_intern_atom_cookie_t cookies[QXcbAtom::NAtoms]; + + Q_ASSERT(i == QXcbAtom::NAtoms); + for (i = 0; i < QXcbAtom::NAtoms; ++i) + cookies[i] = xcb_intern_atom(xcb_connection(), false, strlen(names[i]), names[i]); + + for (i = 0; i < QXcbAtom::NAtoms; ++i) + m_allAtoms[i] = xcb_intern_atom_reply(xcb_connection(), cookies[i], 0)->atom; +} + +#if defined(XCB_USE_EGL) +bool QXcbConnection::hasEgl() const +{ + return m_has_egl; +} +#endif // defined(XCB_USE_EGL) + +#ifdef XCB_USE_DRI2 +void QXcbConnection::initializeDri2() +{ + xcb_dri2_connect_cookie_t connect_cookie = xcb_dri2_connect_unchecked (m_connection, + m_screens[0]->root(), + XCB_DRI2_DRIVER_TYPE_DRI); + + xcb_dri2_connect_reply_t *connect = xcb_dri2_connect_reply (m_connection, + connect_cookie, NULL); + + if (! connect || connect->driver_name_length + connect->device_name_length == 0) { + qDebug() << "Failed to connect to dri2"; + return; + } + + m_dri2_device_name = QByteArray(xcb_dri2_connect_device_name (connect), + xcb_dri2_connect_device_name_length (connect)); + delete connect; + + int fd = open(m_dri2_device_name.constData(), O_RDWR); + if (fd < 0) { + qDebug() << "InitializeDri2: Could'nt open device << dri2DeviceName"; + m_dri2_device_name = QByteArray(); + return; + } + + drm_magic_t magic; + if (drmGetMagic(fd, &magic)) { + qDebug() << "Failed to get drmMagic"; + return; + } + + xcb_dri2_authenticate_cookie_t authenticate_cookie = xcb_dri2_authenticate_unchecked(m_connection, + m_screens[0]->root(), magic); + xcb_dri2_authenticate_reply_t *authenticate = xcb_dri2_authenticate_reply(m_connection, + authenticate_cookie, NULL); + if (authenticate == NULL || !authenticate->authenticated) { + fprintf(stderr, "DRI2: failed to authenticate\n"); + free(authenticate); + return; + } + + delete authenticate; + + EGLDisplay display = eglGetDRMDisplayMESA(fd); + if (!display) { + fprintf(stderr, "failed to create display\n"); + return; + } + + m_egl_display = display; + EGLint major,minor; + if (!eglInitialize(display, &major, &minor)) { + fprintf(stderr, "failed to initialize display\n"); + return; + } +} + +bool QXcbConnection::hasSupportForDri2() const +{ + if (!m_dri2_support_probed) { + xcb_generic_error_t *error = 0; + + xcb_prefetch_extension_data (m_connection, &xcb_xfixes_id); + xcb_prefetch_extension_data (m_connection, &xcb_dri2_id); + + xcb_xfixes_query_version_cookie_t xfixes_query_cookie = xcb_xfixes_query_version(m_connection, + XCB_XFIXES_MAJOR_VERSION, + XCB_XFIXES_MINOR_VERSION); + + xcb_dri2_query_version_cookie_t dri2_query_cookie = xcb_dri2_query_version (m_connection, + XCB_DRI2_MAJOR_VERSION, + XCB_DRI2_MINOR_VERSION); + + xcb_xfixes_query_version_reply_t *xfixes_query = xcb_xfixes_query_version_reply (m_connection, + xfixes_query_cookie, &error); + if (!xfixes_query || error || xfixes_query->major_version < 2) { + delete error; + delete xfixes_query; + return false; + } + delete xfixes_query; + + xcb_dri2_query_version_reply_t *dri2_query = xcb_dri2_query_version_reply (m_connection, + dri2_query_cookie, &error); + if (!dri2_query || error) { + delete error; + delete dri2_query; + return false; + } + + QXcbConnection *that = const_cast<QXcbConnection *>(this); + that->m_dri2_major = dri2_query->major_version; + that->m_dri2_minor = dri2_query->minor_version; + + that->m_has_support_for_dri2 = true; + that->m_dri2_support_probed = true; + } + return m_has_support_for_dri2; +} +#endif //XCB_USE_DRI2 diff --git a/src/plugins/platforms/xcb/qxcbconnection.h b/src/plugins/platforms/xcb/qxcbconnection.h new file mode 100644 index 0000000..e00fbb1 --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbconnection.h @@ -0,0 +1,294 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBCONNECTION_H +#define QXCBCONNECTION_H + +#include <xcb/xcb.h> + +#include <QList> +#include <QObject> + +class QXcbScreen; + +namespace QXcbAtom { + enum Atom { + // window-manager <-> client protocols + WM_PROTOCOLS, + WM_DELETE_WINDOW, + WM_TAKE_FOCUS, + _NET_WM_PING, + _NET_WM_CONTEXT_HELP, + _NET_WM_SYNC_REQUEST, + _NET_WM_SYNC_REQUEST_COUNTER, + + // ICCCM window state + WM_STATE, + WM_CHANGE_STATE, + + // Session management + WM_CLIENT_LEADER, + WM_WINDOW_ROLE, + SM_CLIENT_ID, + + // Clipboard + CLIPBOARD, + INCR, + TARGETS, + MULTIPLE, + TIMESTAMP, + SAVE_TARGETS, + CLIP_TEMPORARY, + _QT_SELECTION, + _QT_CLIPBOARD_SENTINEL, + _QT_SELECTION_SENTINEL, + CLIPBOARD_MANAGER, + + RESOURCE_MANAGER, + + _XSETROOT_ID, + + _QT_SCROLL_DONE, + _QT_INPUT_ENCODING, + + _MOTIF_WM_HINTS, + + DTWM_IS_RUNNING, + ENLIGHTENMENT_DESKTOP, + _DT_SAVE_MODE, + _SGI_DESKS_MANAGER, + + // EWMH (aka NETWM) + _NET_SUPPORTED, + _NET_VIRTUAL_ROOTS, + _NET_WORKAREA, + + _NET_MOVERESIZE_WINDOW, + _NET_WM_MOVERESIZE, + + _NET_WM_NAME, + _NET_WM_ICON_NAME, + _NET_WM_ICON, + + _NET_WM_PID, + + _NET_WM_WINDOW_OPACITY, + + _NET_WM_STATE, + _NET_WM_STATE_ABOVE, + _NET_WM_STATE_BELOW, + _NET_WM_STATE_FULLSCREEN, + _NET_WM_STATE_MAXIMIZED_HORZ, + _NET_WM_STATE_MAXIMIZED_VERT, + _NET_WM_STATE_MODAL, + _NET_WM_STATE_STAYS_ON_TOP, + _NET_WM_STATE_DEMANDS_ATTENTION, + + _NET_WM_USER_TIME, + _NET_WM_USER_TIME_WINDOW, + _NET_WM_FULL_PLACEMENT, + + _NET_WM_WINDOW_TYPE, + _NET_WM_WINDOW_TYPE_DESKTOP, + _NET_WM_WINDOW_TYPE_DOCK, + _NET_WM_WINDOW_TYPE_TOOLBAR, + _NET_WM_WINDOW_TYPE_MENU, + _NET_WM_WINDOW_TYPE_UTILITY, + _NET_WM_WINDOW_TYPE_SPLASH, + _NET_WM_WINDOW_TYPE_DIALOG, + _NET_WM_WINDOW_TYPE_DROPDOWN_MENU, + _NET_WM_WINDOW_TYPE_POPUP_MENU, + _NET_WM_WINDOW_TYPE_TOOLTIP, + _NET_WM_WINDOW_TYPE_NOTIFICATION, + _NET_WM_WINDOW_TYPE_COMBO, + _NET_WM_WINDOW_TYPE_DND, + _NET_WM_WINDOW_TYPE_NORMAL, + _KDE_NET_WM_WINDOW_TYPE_OVERRIDE, + + _KDE_NET_WM_FRAME_STRUT, + + _NET_STARTUP_INFO, + _NET_STARTUP_INFO_BEGIN, + + _NET_SUPPORTING_WM_CHECK, + + _NET_WM_CM_S0, + + _NET_SYSTEM_TRAY_VISUAL, + + _NET_ACTIVE_WINDOW, + + // Property formats + COMPOUND_TEXT, + TEXT, + UTF8_STRING, + + // Xdnd + XdndEnter, + XdndPosition, + XdndStatus, + XdndLeave, + XdndDrop, + XdndFinished, + XdndTypelist, + XdndActionList, + + XdndSelection, + + XdndAware, + XdndProxy, + + XdndActionCopy, + XdndActionLink, + XdndActionMove, + XdndActionPrivate, + + // Motif DND + _MOTIF_DRAG_AND_DROP_MESSAGE, + _MOTIF_DRAG_INITIATOR_INFO, + _MOTIF_DRAG_RECEIVER_INFO, + _MOTIF_DRAG_WINDOW, + _MOTIF_DRAG_TARGETS, + + XmTRANSFER_SUCCESS, + XmTRANSFER_FAILURE, + + // Xkb + _XKB_RULES_NAMES, + + // XEMBED + _XEMBED, + _XEMBED_INFO, + + XWacomStylus, + XWacomCursor, + XWacomEraser, + + XTabletStylus, + XTabletEraser, + + NPredefinedAtoms, + + _QT_SETTINGS_TIMESTAMP = NPredefinedAtoms, + NAtoms + }; +} + +class QXcbKeyboard; + +class QXcbConnection : public QObject +{ + Q_OBJECT +public: + QXcbConnection(const char *displayName = 0); + ~QXcbConnection(); + + QList<QXcbScreen *> screens() const { return m_screens; } + int primaryScreen() const { return m_primaryScreen; } + + xcb_atom_t atom(QXcbAtom::Atom atom); + + const char *displayName() const { return m_displayName.constData(); } + + xcb_connection_t *xcb_connection() const { return m_connection; } + + QXcbKeyboard *keyboard() const { return m_keyboard; } + +#ifdef XCB_USE_XLIB + void *xlib_display() const { return m_xlib_display; } +#endif + +#ifdef XCB_USE_DRI2 + bool hasSupportForDri2() const; + QByteArray dri2DeviceName() const { return m_dri2_device_name; } +#endif +#ifdef XCB_USE_EGL + bool hasEgl() const; +#endif +#if defined(XCB_USE_EGL) || defined(XCB_USE_DRI2) + void *egl_display() const { return m_egl_display; } +#endif + +private slots: + void eventDispatcher(); + +private: + void initializeAllAtoms(); +#ifdef XCB_USE_DRI2 + void initializeDri2(); +#endif + + xcb_connection_t *m_connection; + const xcb_setup_t *m_setup; + + QList<QXcbScreen *> m_screens; + int m_primaryScreen; + + xcb_atom_t m_allAtoms[QXcbAtom::NAtoms]; + + QByteArray m_displayName; + + QXcbKeyboard *m_keyboard; + +#if defined(XCB_USE_XLIB) + void *m_xlib_display; +#endif + +#ifdef XCB_USE_DRI2 + uint32_t m_dri2_major; + uint32_t m_dri2_minor; + bool m_dri2_support_probed; + bool m_has_support_for_dri2; + QByteArray m_dri2_device_name; +#endif +#if defined(XCB_USE_EGL) || defined(XCB_USE_DRI2) + void *m_egl_display; + bool m_has_egl; +#endif +}; + +#define DISPLAY_FROM_XCB(object) ((Display *)(object->connection()->xlib_display())) + +#if defined(XCB_USE_DRI2) || defined(XCB_USE_EGL) +#define EGL_DISPLAY_FROM_XCB(object) ((EGLDisplay)(object->connection()->egl_display())) +#endif //endifXCB_USE_DRI2 + +#endif diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp new file mode 100644 index 0000000..63c26a1 --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbintegration.cpp @@ -0,0 +1,142 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbintegration.h" +#include "qxcbconnection.h" +#include "qxcbscreen.h" +#include "qxcbwindow.h" +#include "qxcbwindowsurface.h" +#include "qxcbnativeinterface.h" + +#include <xcb/xcb.h> + +#include <private/qpixmap_raster_p.h> + +#include "qgenericunixfontdatabase.h" + +#include <stdio.h> + +#ifdef XCB_USE_EGL +#include <EGL/egl.h> +#endif + +QXcbIntegration::QXcbIntegration() + : m_connection(new QXcbConnection) +{ + foreach (QXcbScreen *screen, m_connection->screens()) + m_screens << screen; + + m_fontDatabase = new QGenericUnixFontDatabase(); + m_nativeInterface = new QXcbNativeInterface; +} + +QXcbIntegration::~QXcbIntegration() +{ + delete m_connection; +} + +QPixmapData *QXcbIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QPlatformWindow *QXcbIntegration::createPlatformWindow(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + return new QXcbWindow(widget); +} + +QWindowSurface *QXcbIntegration::createWindowSurface(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + return new QXcbWindowSurface(widget); +} + +QList<QPlatformScreen *> QXcbIntegration::screens() const +{ + return m_screens; +} + +void QXcbIntegration::moveToScreen(QWidget *window, int screen) +{ + Q_UNUSED(window); + Q_UNUSED(screen); +} + +bool QXcbIntegration::isVirtualDesktop() +{ + return false; +} + +QPlatformFontDatabase *QXcbIntegration::fontDatabase() const +{ + return m_fontDatabase; +} + +QPixmap QXcbIntegration::grabWindow(WId window, int x, int y, int width, int height) const +{ + Q_UNUSED(window); + Q_UNUSED(x); + Q_UNUSED(y); + Q_UNUSED(width); + Q_UNUSED(height); + return QPixmap(); +} + + +bool QXcbIntegration::hasOpenGL() const +{ +#if defined(XCB_USE_GLX) + return true; +#elif defined(XCB_USE_EGL) + return m_connection->hasEgl(); +#elif defined(XCB_USE_DRI2) + if (m_connection->hasSupportForDri2()) { + return true; + } +#endif + return false; +} + +QPlatformNativeInterface * QXcbIntegration::nativeInterface() const +{ + return m_nativeInterface; +} diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h new file mode 100644 index 0000000..6c9634e --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbintegration.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBINTEGRATION_H +#define QXCBINTEGRATION_H + +#include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformScreen> + +QT_BEGIN_NAMESPACE + +class QXcbConnection; + +class QXcbIntegration : public QPlatformIntegration +{ +public: + QXcbIntegration(); + ~QXcbIntegration(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QList<QPlatformScreen *> screens() const; + void moveToScreen(QWidget *window, int screen); + bool isVirtualDesktop(); + QPixmap grabWindow(WId window, int x, int y, int width, int height) const; + + QPlatformFontDatabase *fontDatabase() const; + bool hasOpenGL() const; + + QPlatformNativeInterface *nativeInterface()const; + +private: + QList<QPlatformScreen *> m_screens; + QXcbConnection *m_connection; + + QPlatformFontDatabase *m_fontDatabase; + QPlatformNativeInterface *m_nativeInterface; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.cpp b/src/plugins/platforms/xcb/qxcbkeyboard.cpp new file mode 100644 index 0000000..ec9a009 --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbkeyboard.cpp @@ -0,0 +1,967 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbkeyboard.h" + +#include <xcb/xcb_keysyms.h> + +#include <X11/keysym.h> + +#include <QtGui/QWindowSystemInterface> +#include <QtCore/QTextCodec> + +#include <stdio.h> + +#ifndef XK_ISO_Left_Tab +#define XK_ISO_Left_Tab 0xFE20 +#endif + +#ifndef XK_dead_hook +#define XK_dead_hook 0xFE61 +#endif + +#ifndef XK_dead_horn +#define XK_dead_horn 0xFE62 +#endif + +#ifndef XK_Codeinput +#define XK_Codeinput 0xFF37 +#endif + +#ifndef XK_Kanji_Bangou +#define XK_Kanji_Bangou 0xFF37 /* same as codeinput */ +#endif + +// Fix old X libraries +#ifndef XK_KP_Home +#define XK_KP_Home 0xFF95 +#endif +#ifndef XK_KP_Left +#define XK_KP_Left 0xFF96 +#endif +#ifndef XK_KP_Up +#define XK_KP_Up 0xFF97 +#endif +#ifndef XK_KP_Right +#define XK_KP_Right 0xFF98 +#endif +#ifndef XK_KP_Down +#define XK_KP_Down 0xFF99 +#endif +#ifndef XK_KP_Prior +#define XK_KP_Prior 0xFF9A +#endif +#ifndef XK_KP_Next +#define XK_KP_Next 0xFF9B +#endif +#ifndef XK_KP_End +#define XK_KP_End 0xFF9C +#endif +#ifndef XK_KP_Insert +#define XK_KP_Insert 0xFF9E +#endif +#ifndef XK_KP_Delete +#define XK_KP_Delete 0xFF9F +#endif + +// the next lines are taken on 10/2009 from X.org (X11/XF86keysym.h), defining some special +// multimedia keys. They are included here as not every system has them. +#define XF86XK_MonBrightnessUp 0x1008FF02 +#define XF86XK_MonBrightnessDown 0x1008FF03 +#define XF86XK_KbdLightOnOff 0x1008FF04 +#define XF86XK_KbdBrightnessUp 0x1008FF05 +#define XF86XK_KbdBrightnessDown 0x1008FF06 +#define XF86XK_Standby 0x1008FF10 +#define XF86XK_AudioLowerVolume 0x1008FF11 +#define XF86XK_AudioMute 0x1008FF12 +#define XF86XK_AudioRaiseVolume 0x1008FF13 +#define XF86XK_AudioPlay 0x1008FF14 +#define XF86XK_AudioStop 0x1008FF15 +#define XF86XK_AudioPrev 0x1008FF16 +#define XF86XK_AudioNext 0x1008FF17 +#define XF86XK_HomePage 0x1008FF18 +#define XF86XK_Mail 0x1008FF19 +#define XF86XK_Start 0x1008FF1A +#define XF86XK_Search 0x1008FF1B +#define XF86XK_AudioRecord 0x1008FF1C +#define XF86XK_Calculator 0x1008FF1D +#define XF86XK_Memo 0x1008FF1E +#define XF86XK_ToDoList 0x1008FF1F +#define XF86XK_Calendar 0x1008FF20 +#define XF86XK_PowerDown 0x1008FF21 +#define XF86XK_ContrastAdjust 0x1008FF22 +#define XF86XK_Back 0x1008FF26 +#define XF86XK_Forward 0x1008FF27 +#define XF86XK_Stop 0x1008FF28 +#define XF86XK_Refresh 0x1008FF29 +#define XF86XK_PowerOff 0x1008FF2A +#define XF86XK_WakeUp 0x1008FF2B +#define XF86XK_Eject 0x1008FF2C +#define XF86XK_ScreenSaver 0x1008FF2D +#define XF86XK_WWW 0x1008FF2E +#define XF86XK_Sleep 0x1008FF2F +#define XF86XK_Favorites 0x1008FF30 +#define XF86XK_AudioPause 0x1008FF31 +#define XF86XK_AudioMedia 0x1008FF32 +#define XF86XK_MyComputer 0x1008FF33 +#define XF86XK_LightBulb 0x1008FF35 +#define XF86XK_Shop 0x1008FF36 +#define XF86XK_History 0x1008FF37 +#define XF86XK_OpenURL 0x1008FF38 +#define XF86XK_AddFavorite 0x1008FF39 +#define XF86XK_HotLinks 0x1008FF3A +#define XF86XK_BrightnessAdjust 0x1008FF3B +#define XF86XK_Finance 0x1008FF3C +#define XF86XK_Community 0x1008FF3D +#define XF86XK_AudioRewind 0x1008FF3E +#define XF86XK_BackForward 0x1008FF3F +#define XF86XK_Launch0 0x1008FF40 +#define XF86XK_Launch1 0x1008FF41 +#define XF86XK_Launch2 0x1008FF42 +#define XF86XK_Launch3 0x1008FF43 +#define XF86XK_Launch4 0x1008FF44 +#define XF86XK_Launch5 0x1008FF45 +#define XF86XK_Launch6 0x1008FF46 +#define XF86XK_Launch7 0x1008FF47 +#define XF86XK_Launch8 0x1008FF48 +#define XF86XK_Launch9 0x1008FF49 +#define XF86XK_LaunchA 0x1008FF4A +#define XF86XK_LaunchB 0x1008FF4B +#define XF86XK_LaunchC 0x1008FF4C +#define XF86XK_LaunchD 0x1008FF4D +#define XF86XK_LaunchE 0x1008FF4E +#define XF86XK_LaunchF 0x1008FF4F +#define XF86XK_ApplicationLeft 0x1008FF50 +#define XF86XK_ApplicationRight 0x1008FF51 +#define XF86XK_Book 0x1008FF52 +#define XF86XK_CD 0x1008FF53 +#define XF86XK_Calculater 0x1008FF54 +#define XF86XK_Clear 0x1008FF55 +#define XF86XK_ClearGrab 0x1008FE21 +#define XF86XK_Close 0x1008FF56 +#define XF86XK_Copy 0x1008FF57 +#define XF86XK_Cut 0x1008FF58 +#define XF86XK_Display 0x1008FF59 +#define XF86XK_DOS 0x1008FF5A +#define XF86XK_Documents 0x1008FF5B +#define XF86XK_Excel 0x1008FF5C +#define XF86XK_Explorer 0x1008FF5D +#define XF86XK_Game 0x1008FF5E +#define XF86XK_Go 0x1008FF5F +#define XF86XK_iTouch 0x1008FF60 +#define XF86XK_LogOff 0x1008FF61 +#define XF86XK_Market 0x1008FF62 +#define XF86XK_Meeting 0x1008FF63 +#define XF86XK_MenuKB 0x1008FF65 +#define XF86XK_MenuPB 0x1008FF66 +#define XF86XK_MySites 0x1008FF67 +#define XF86XK_News 0x1008FF69 +#define XF86XK_OfficeHome 0x1008FF6A +#define XF86XK_Option 0x1008FF6C +#define XF86XK_Paste 0x1008FF6D +#define XF86XK_Phone 0x1008FF6E +#define XF86XK_Reply 0x1008FF72 +#define XF86XK_Reload 0x1008FF73 +#define XF86XK_RotateWindows 0x1008FF74 +#define XF86XK_RotationPB 0x1008FF75 +#define XF86XK_RotationKB 0x1008FF76 +#define XF86XK_Save 0x1008FF77 +#define XF86XK_Send 0x1008FF7B +#define XF86XK_Spell 0x1008FF7C +#define XF86XK_SplitScreen 0x1008FF7D +#define XF86XK_Support 0x1008FF7E +#define XF86XK_TaskPane 0x1008FF7F +#define XF86XK_Terminal 0x1008FF80 +#define XF86XK_Tools 0x1008FF81 +#define XF86XK_Travel 0x1008FF82 +#define XF86XK_Video 0x1008FF87 +#define XF86XK_Word 0x1008FF89 +#define XF86XK_Xfer 0x1008FF8A +#define XF86XK_ZoomIn 0x1008FF8B +#define XF86XK_ZoomOut 0x1008FF8C +#define XF86XK_Away 0x1008FF8D +#define XF86XK_Messenger 0x1008FF8E +#define XF86XK_WebCam 0x1008FF8F +#define XF86XK_MailForward 0x1008FF90 +#define XF86XK_Pictures 0x1008FF91 +#define XF86XK_Music 0x1008FF92 +#define XF86XK_Battery 0x1008FF93 +#define XF86XK_Bluetooth 0x1008FF94 +#define XF86XK_WLAN 0x1008FF95 +#define XF86XK_UWB 0x1008FF96 +#define XF86XK_AudioForward 0x1008FF97 +#define XF86XK_AudioRepeat 0x1008FF98 +#define XF86XK_AudioRandomPlay 0x1008FF99 +#define XF86XK_Subtitle 0x1008FF9A +#define XF86XK_AudioCycleTrack 0x1008FF9B +#define XF86XK_Time 0x1008FF9F +#define XF86XK_Select 0x1008FFA0 +#define XF86XK_View 0x1008FFA1 +#define XF86XK_TopMenu 0x1008FFA2 +#define XF86XK_Suspend 0x1008FFA7 +#define XF86XK_Hibernate 0x1008FFA8 + + +// end of XF86keysyms.h + +// Special keys used by Qtopia, mapped into the X11 private keypad range. +#define QTOPIAXK_Select 0x11000601 +#define QTOPIAXK_Yes 0x11000602 +#define QTOPIAXK_No 0x11000603 +#define QTOPIAXK_Cancel 0x11000604 +#define QTOPIAXK_Printer 0x11000605 +#define QTOPIAXK_Execute 0x11000606 +#define QTOPIAXK_Sleep 0x11000607 +#define QTOPIAXK_Play 0x11000608 +#define QTOPIAXK_Zoom 0x11000609 +#define QTOPIAXK_Context1 0x1100060A +#define QTOPIAXK_Context2 0x1100060B +#define QTOPIAXK_Context3 0x1100060C +#define QTOPIAXK_Context4 0x1100060D +#define QTOPIAXK_Call 0x1100060E +#define QTOPIAXK_Hangup 0x1100060F +#define QTOPIAXK_Flip 0x11000610 + +// keyboard mapping table +static const unsigned int KeyTbl[] = { + + // misc keys + + XK_Escape, Qt::Key_Escape, + XK_Tab, Qt::Key_Tab, + XK_ISO_Left_Tab, Qt::Key_Backtab, + XK_BackSpace, Qt::Key_Backspace, + XK_Return, Qt::Key_Return, + XK_Insert, Qt::Key_Insert, + XK_Delete, Qt::Key_Delete, + XK_Clear, Qt::Key_Delete, + XK_Pause, Qt::Key_Pause, + XK_Print, Qt::Key_Print, + 0x1005FF60, Qt::Key_SysReq, // hardcoded Sun SysReq + 0x1007ff00, Qt::Key_SysReq, // hardcoded X386 SysReq + + // cursor movement + + XK_Home, Qt::Key_Home, + XK_End, Qt::Key_End, + XK_Left, Qt::Key_Left, + XK_Up, Qt::Key_Up, + XK_Right, Qt::Key_Right, + XK_Down, Qt::Key_Down, + XK_Prior, Qt::Key_PageUp, + XK_Next, Qt::Key_PageDown, + + // modifiers + + XK_Shift_L, Qt::Key_Shift, + XK_Shift_R, Qt::Key_Shift, + XK_Shift_Lock, Qt::Key_Shift, + XK_Control_L, Qt::Key_Control, + XK_Control_R, Qt::Key_Control, + XK_Meta_L, Qt::Key_Meta, + XK_Meta_R, Qt::Key_Meta, + XK_Alt_L, Qt::Key_Alt, + XK_Alt_R, Qt::Key_Alt, + XK_Caps_Lock, Qt::Key_CapsLock, + XK_Num_Lock, Qt::Key_NumLock, + XK_Scroll_Lock, Qt::Key_ScrollLock, + XK_Super_L, Qt::Key_Super_L, + XK_Super_R, Qt::Key_Super_R, + XK_Menu, Qt::Key_Menu, + XK_Hyper_L, Qt::Key_Hyper_L, + XK_Hyper_R, Qt::Key_Hyper_R, + XK_Help, Qt::Key_Help, + 0x1000FF74, Qt::Key_Backtab, // hardcoded HP backtab + 0x1005FF10, Qt::Key_F11, // hardcoded Sun F36 (labeled F11) + 0x1005FF11, Qt::Key_F12, // hardcoded Sun F37 (labeled F12) + + // numeric and function keypad keys + + XK_KP_Space, Qt::Key_Space, + XK_KP_Tab, Qt::Key_Tab, + XK_KP_Enter, Qt::Key_Enter, + //XK_KP_F1, Qt::Key_F1, + //XK_KP_F2, Qt::Key_F2, + //XK_KP_F3, Qt::Key_F3, + //XK_KP_F4, Qt::Key_F4, + XK_KP_Home, Qt::Key_Home, + XK_KP_Left, Qt::Key_Left, + XK_KP_Up, Qt::Key_Up, + XK_KP_Right, Qt::Key_Right, + XK_KP_Down, Qt::Key_Down, + XK_KP_Prior, Qt::Key_PageUp, + XK_KP_Next, Qt::Key_PageDown, + XK_KP_End, Qt::Key_End, + XK_KP_Begin, Qt::Key_Clear, + XK_KP_Insert, Qt::Key_Insert, + XK_KP_Delete, Qt::Key_Delete, + XK_KP_Equal, Qt::Key_Equal, + XK_KP_Multiply, Qt::Key_Asterisk, + XK_KP_Add, Qt::Key_Plus, + XK_KP_Separator, Qt::Key_Comma, + XK_KP_Subtract, Qt::Key_Minus, + XK_KP_Decimal, Qt::Key_Period, + XK_KP_Divide, Qt::Key_Slash, + + // International input method support keys + + // International & multi-key character composition + XK_ISO_Level3_Shift, Qt::Key_AltGr, + XK_Multi_key, Qt::Key_Multi_key, + XK_Codeinput, Qt::Key_Codeinput, + XK_SingleCandidate, Qt::Key_SingleCandidate, + XK_MultipleCandidate, Qt::Key_MultipleCandidate, + XK_PreviousCandidate, Qt::Key_PreviousCandidate, + + // Misc Functions + XK_Mode_switch, Qt::Key_Mode_switch, + XK_script_switch, Qt::Key_Mode_switch, + + // Japanese keyboard support + XK_Kanji, Qt::Key_Kanji, + XK_Muhenkan, Qt::Key_Muhenkan, + //XK_Henkan_Mode, Qt::Key_Henkan_Mode, + XK_Henkan_Mode, Qt::Key_Henkan, + XK_Henkan, Qt::Key_Henkan, + XK_Romaji, Qt::Key_Romaji, + XK_Hiragana, Qt::Key_Hiragana, + XK_Katakana, Qt::Key_Katakana, + XK_Hiragana_Katakana, Qt::Key_Hiragana_Katakana, + XK_Zenkaku, Qt::Key_Zenkaku, + XK_Hankaku, Qt::Key_Hankaku, + XK_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku, + XK_Touroku, Qt::Key_Touroku, + XK_Massyo, Qt::Key_Massyo, + XK_Kana_Lock, Qt::Key_Kana_Lock, + XK_Kana_Shift, Qt::Key_Kana_Shift, + XK_Eisu_Shift, Qt::Key_Eisu_Shift, + XK_Eisu_toggle, Qt::Key_Eisu_toggle, + //XK_Kanji_Bangou, Qt::Key_Kanji_Bangou, + //XK_Zen_Koho, Qt::Key_Zen_Koho, + //XK_Mae_Koho, Qt::Key_Mae_Koho, + XK_Kanji_Bangou, Qt::Key_Codeinput, + XK_Zen_Koho, Qt::Key_MultipleCandidate, + XK_Mae_Koho, Qt::Key_PreviousCandidate, + +#ifdef XK_KOREAN + // Korean keyboard support + XK_Hangul, Qt::Key_Hangul, + XK_Hangul_Start, Qt::Key_Hangul_Start, + XK_Hangul_End, Qt::Key_Hangul_End, + XK_Hangul_Hanja, Qt::Key_Hangul_Hanja, + XK_Hangul_Jamo, Qt::Key_Hangul_Jamo, + XK_Hangul_Romaja, Qt::Key_Hangul_Romaja, + //XK_Hangul_Codeinput, Qt::Key_Hangul_Codeinput, + XK_Hangul_Codeinput, Qt::Key_Codeinput, + XK_Hangul_Jeonja, Qt::Key_Hangul_Jeonja, + XK_Hangul_Banja, Qt::Key_Hangul_Banja, + XK_Hangul_PreHanja, Qt::Key_Hangul_PreHanja, + XK_Hangul_PostHanja, Qt::Key_Hangul_PostHanja, + //XK_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate, + //XK_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate, + //XK_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate, + XK_Hangul_SingleCandidate, Qt::Key_SingleCandidate, + XK_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate, + XK_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate, + XK_Hangul_Special, Qt::Key_Hangul_Special, + //XK_Hangul_switch, Qt::Key_Hangul_switch, + XK_Hangul_switch, Qt::Key_Mode_switch, +#endif // XK_KOREAN + + // dead keys + XK_dead_grave, Qt::Key_Dead_Grave, + XK_dead_acute, Qt::Key_Dead_Acute, + XK_dead_circumflex, Qt::Key_Dead_Circumflex, + XK_dead_tilde, Qt::Key_Dead_Tilde, + XK_dead_macron, Qt::Key_Dead_Macron, + XK_dead_breve, Qt::Key_Dead_Breve, + XK_dead_abovedot, Qt::Key_Dead_Abovedot, + XK_dead_diaeresis, Qt::Key_Dead_Diaeresis, + XK_dead_abovering, Qt::Key_Dead_Abovering, + XK_dead_doubleacute, Qt::Key_Dead_Doubleacute, + XK_dead_caron, Qt::Key_Dead_Caron, + XK_dead_cedilla, Qt::Key_Dead_Cedilla, + XK_dead_ogonek, Qt::Key_Dead_Ogonek, + XK_dead_iota, Qt::Key_Dead_Iota, + XK_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound, + XK_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound, + XK_dead_belowdot, Qt::Key_Dead_Belowdot, + XK_dead_hook, Qt::Key_Dead_Hook, + XK_dead_horn, Qt::Key_Dead_Horn, + + // Special keys from X.org - This include multimedia keys, + // wireless/bluetooth/uwb keys, special launcher keys, etc. + XF86XK_Back, Qt::Key_Back, + XF86XK_Forward, Qt::Key_Forward, + XF86XK_Stop, Qt::Key_Stop, + XF86XK_Refresh, Qt::Key_Refresh, + XF86XK_Favorites, Qt::Key_Favorites, + XF86XK_AudioMedia, Qt::Key_LaunchMedia, + XF86XK_OpenURL, Qt::Key_OpenUrl, + XF86XK_HomePage, Qt::Key_HomePage, + XF86XK_Search, Qt::Key_Search, + XF86XK_AudioLowerVolume, Qt::Key_VolumeDown, + XF86XK_AudioMute, Qt::Key_VolumeMute, + XF86XK_AudioRaiseVolume, Qt::Key_VolumeUp, + XF86XK_AudioPlay, Qt::Key_MediaPlay, + XF86XK_AudioStop, Qt::Key_MediaStop, + XF86XK_AudioPrev, Qt::Key_MediaPrevious, + XF86XK_AudioNext, Qt::Key_MediaNext, + XF86XK_AudioRecord, Qt::Key_MediaRecord, + XF86XK_Mail, Qt::Key_LaunchMail, + XF86XK_MyComputer, Qt::Key_Launch0, // ### Qt 5: remap properly + XF86XK_Calculator, Qt::Key_Launch1, + XF86XK_Memo, Qt::Key_Memo, + XF86XK_ToDoList, Qt::Key_ToDoList, + XF86XK_Calendar, Qt::Key_Calendar, + XF86XK_PowerDown, Qt::Key_PowerDown, + XF86XK_ContrastAdjust, Qt::Key_ContrastAdjust, + XF86XK_Standby, Qt::Key_Standby, + XF86XK_MonBrightnessUp, Qt::Key_MonBrightnessUp, + XF86XK_MonBrightnessDown, Qt::Key_MonBrightnessDown, + XF86XK_KbdLightOnOff, Qt::Key_KeyboardLightOnOff, + XF86XK_KbdBrightnessUp, Qt::Key_KeyboardBrightnessUp, + XF86XK_KbdBrightnessDown, Qt::Key_KeyboardBrightnessDown, + XF86XK_PowerOff, Qt::Key_PowerOff, + XF86XK_WakeUp, Qt::Key_WakeUp, + XF86XK_Eject, Qt::Key_Eject, + XF86XK_ScreenSaver, Qt::Key_ScreenSaver, + XF86XK_WWW, Qt::Key_WWW, + XF86XK_Sleep, Qt::Key_Sleep, + XF86XK_LightBulb, Qt::Key_LightBulb, + XF86XK_Shop, Qt::Key_Shop, + XF86XK_History, Qt::Key_History, + XF86XK_AddFavorite, Qt::Key_AddFavorite, + XF86XK_HotLinks, Qt::Key_HotLinks, + XF86XK_BrightnessAdjust, Qt::Key_BrightnessAdjust, + XF86XK_Finance, Qt::Key_Finance, + XF86XK_Community, Qt::Key_Community, + XF86XK_AudioRewind, Qt::Key_AudioRewind, + XF86XK_BackForward, Qt::Key_BackForward, + XF86XK_ApplicationLeft, Qt::Key_ApplicationLeft, + XF86XK_ApplicationRight, Qt::Key_ApplicationRight, + XF86XK_Book, Qt::Key_Book, + XF86XK_CD, Qt::Key_CD, + XF86XK_Calculater, Qt::Key_Calculator, + XF86XK_Clear, Qt::Key_Clear, + XF86XK_ClearGrab, Qt::Key_ClearGrab, + XF86XK_Close, Qt::Key_Close, + XF86XK_Copy, Qt::Key_Copy, + XF86XK_Cut, Qt::Key_Cut, + XF86XK_Display, Qt::Key_Display, + XF86XK_DOS, Qt::Key_DOS, + XF86XK_Documents, Qt::Key_Documents, + XF86XK_Excel, Qt::Key_Excel, + XF86XK_Explorer, Qt::Key_Explorer, + XF86XK_Game, Qt::Key_Game, + XF86XK_Go, Qt::Key_Go, + XF86XK_iTouch, Qt::Key_iTouch, + XF86XK_LogOff, Qt::Key_LogOff, + XF86XK_Market, Qt::Key_Market, + XF86XK_Meeting, Qt::Key_Meeting, + XF86XK_MenuKB, Qt::Key_MenuKB, + XF86XK_MenuPB, Qt::Key_MenuPB, + XF86XK_MySites, Qt::Key_MySites, + XF86XK_News, Qt::Key_News, + XF86XK_OfficeHome, Qt::Key_OfficeHome, + XF86XK_Option, Qt::Key_Option, + XF86XK_Paste, Qt::Key_Paste, + XF86XK_Phone, Qt::Key_Phone, + XF86XK_Reply, Qt::Key_Reply, + XF86XK_Reload, Qt::Key_Reload, + XF86XK_RotateWindows, Qt::Key_RotateWindows, + XF86XK_RotationPB, Qt::Key_RotationPB, + XF86XK_RotationKB, Qt::Key_RotationKB, + XF86XK_Save, Qt::Key_Save, + XF86XK_Send, Qt::Key_Send, + XF86XK_Spell, Qt::Key_Spell, + XF86XK_SplitScreen, Qt::Key_SplitScreen, + XF86XK_Support, Qt::Key_Support, + XF86XK_TaskPane, Qt::Key_TaskPane, + XF86XK_Terminal, Qt::Key_Terminal, + XF86XK_Tools, Qt::Key_Tools, + XF86XK_Travel, Qt::Key_Travel, + XF86XK_Video, Qt::Key_Video, + XF86XK_Word, Qt::Key_Word, + XF86XK_Xfer, Qt::Key_Xfer, + XF86XK_ZoomIn, Qt::Key_ZoomIn, + XF86XK_ZoomOut, Qt::Key_ZoomOut, + XF86XK_Away, Qt::Key_Away, + XF86XK_Messenger, Qt::Key_Messenger, + XF86XK_WebCam, Qt::Key_WebCam, + XF86XK_MailForward, Qt::Key_MailForward, + XF86XK_Pictures, Qt::Key_Pictures, + XF86XK_Music, Qt::Key_Music, + XF86XK_Battery, Qt::Key_Battery, + XF86XK_Bluetooth, Qt::Key_Bluetooth, + XF86XK_WLAN, Qt::Key_WLAN, + XF86XK_UWB, Qt::Key_UWB, + XF86XK_AudioForward, Qt::Key_AudioForward, + XF86XK_AudioRepeat, Qt::Key_AudioRepeat, + XF86XK_AudioRandomPlay, Qt::Key_AudioRandomPlay, + XF86XK_Subtitle, Qt::Key_Subtitle, + XF86XK_AudioCycleTrack, Qt::Key_AudioCycleTrack, + XF86XK_Time, Qt::Key_Time, + XF86XK_Select, Qt::Key_Select, + XF86XK_View, Qt::Key_View, + XF86XK_TopMenu, Qt::Key_TopMenu, + XF86XK_Bluetooth, Qt::Key_Bluetooth, + XF86XK_Suspend, Qt::Key_Suspend, + XF86XK_Hibernate, Qt::Key_Hibernate, + XF86XK_Launch0, Qt::Key_Launch2, // ### Qt 5: remap properly + XF86XK_Launch1, Qt::Key_Launch3, + XF86XK_Launch2, Qt::Key_Launch4, + XF86XK_Launch3, Qt::Key_Launch5, + XF86XK_Launch4, Qt::Key_Launch6, + XF86XK_Launch5, Qt::Key_Launch7, + XF86XK_Launch6, Qt::Key_Launch8, + XF86XK_Launch7, Qt::Key_Launch9, + XF86XK_Launch8, Qt::Key_LaunchA, + XF86XK_Launch9, Qt::Key_LaunchB, + XF86XK_LaunchA, Qt::Key_LaunchC, + XF86XK_LaunchB, Qt::Key_LaunchD, + XF86XK_LaunchC, Qt::Key_LaunchE, + XF86XK_LaunchD, Qt::Key_LaunchF, + XF86XK_LaunchE, Qt::Key_LaunchG, + XF86XK_LaunchF, Qt::Key_LaunchH, + + // Qtopia keys + QTOPIAXK_Select, Qt::Key_Select, + QTOPIAXK_Yes, Qt::Key_Yes, + QTOPIAXK_No, Qt::Key_No, + QTOPIAXK_Cancel, Qt::Key_Cancel, + QTOPIAXK_Printer, Qt::Key_Printer, + QTOPIAXK_Execute, Qt::Key_Execute, + QTOPIAXK_Sleep, Qt::Key_Sleep, + QTOPIAXK_Play, Qt::Key_Play, + QTOPIAXK_Zoom, Qt::Key_Zoom, + QTOPIAXK_Context1, Qt::Key_Context1, + QTOPIAXK_Context2, Qt::Key_Context2, + QTOPIAXK_Context3, Qt::Key_Context3, + QTOPIAXK_Context4, Qt::Key_Context4, + QTOPIAXK_Call, Qt::Key_Call, + QTOPIAXK_Hangup, Qt::Key_Hangup, + QTOPIAXK_Flip, Qt::Key_Flip, + + 0, 0 +}; + +static const unsigned short katakanaKeysymsToUnicode[] = { + 0x0000, 0x3002, 0x300C, 0x300D, 0x3001, 0x30FB, 0x30F2, 0x30A1, + 0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30E3, 0x30E5, 0x30E7, 0x30C3, + 0x30FC, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, + 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, + 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, + 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE, + 0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, + 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F3, 0x309B, 0x309C +}; + +static const unsigned short cyrillicKeysymsToUnicode[] = { + 0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, + 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0000, 0x045e, 0x045f, + 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, + 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0000, 0x040e, 0x040f, + 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, + 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, + 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, + 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, + 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, + 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, + 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, + 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a +}; + +static const unsigned short greekKeysymsToUnicode[] = { + 0x0000, 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c, + 0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015, + 0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc, + 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, + 0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7, + 0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, + 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7, + 0x03c8, 0x03c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static const unsigned short technicalKeysymsToUnicode[] = { + 0x0000, 0x23B7, 0x250C, 0x2500, 0x2320, 0x2321, 0x2502, 0x23A1, + 0x23A3, 0x23A4, 0x23A6, 0x239B, 0x239D, 0x239E, 0x23A0, 0x23A8, + 0x23AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222B, + 0x2234, 0x221D, 0x221E, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000, + 0x223C, 0x2243, 0x0000, 0x0000, 0x0000, 0x21D4, 0x21D2, 0x2261, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221A, 0x0000, + 0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222A, 0x2227, 0x2228, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2202, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000, + 0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193, 0x0000 +}; + +static const unsigned short specialKeysymsToUnicode[] = { + 0x25C6, 0x2592, 0x2409, 0x240C, 0x240D, 0x240A, 0x0000, 0x0000, + 0x2424, 0x240B, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0x23BA, + 0x23BB, 0x2500, 0x23BC, 0x23BD, 0x251C, 0x2524, 0x2534, 0x252C, + 0x2502, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static const unsigned short publishingKeysymsToUnicode[] = { + 0x0000, 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, + 0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025, + 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, + 0x2105, 0x0000, 0x0000, 0x2012, 0x2329, 0x0000, 0x232a, 0x0000, + 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000, + 0x0000, 0x2122, 0x2613, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25af, + 0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x0000, 0x2032, 0x2033, + 0x0000, 0x271d, 0x0000, 0x25ac, 0x25c0, 0x25b6, 0x25cf, 0x25ae, + 0x25e6, 0x25ab, 0x25ad, 0x25b3, 0x25bd, 0x2606, 0x2022, 0x25aa, + 0x25b2, 0x25bc, 0x261c, 0x261e, 0x2663, 0x2666, 0x2665, 0x0000, + 0x2720, 0x2020, 0x2021, 0x2713, 0x2717, 0x266f, 0x266d, 0x2642, + 0x2640, 0x260e, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e, 0x0000 +}; + +static const unsigned short aplKeysymsToUnicode[] = { + 0x0000, 0x0000, 0x0000, 0x003c, 0x0000, 0x0000, 0x003e, 0x0000, + 0x2228, 0x2227, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00af, 0x0000, 0x22a5, 0x2229, 0x230a, 0x0000, 0x005f, 0x0000, + 0x0000, 0x0000, 0x2218, 0x0000, 0x2395, 0x0000, 0x22a4, 0x25cb, + 0x0000, 0x0000, 0x0000, 0x2308, 0x0000, 0x0000, 0x222a, 0x0000, + 0x2283, 0x0000, 0x2282, 0x0000, 0x22a2, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x22a3, 0x0000, 0x0000, 0x0000 +}; + +static const unsigned short koreanKeysymsToUnicode[] = { + 0x0000, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, + 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f, + 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147, + 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x314f, + 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157, + 0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, + 0x3160, 0x3161, 0x3162, 0x3163, 0x11a8, 0x11a9, 0x11aa, 0x11ab, + 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3, + 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb, + 0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x316d, + 0x3171, 0x3178, 0x317f, 0x3181, 0x3184, 0x3186, 0x318d, 0x318e, + 0x11eb, 0x11f0, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9 +}; + +static QChar keysymToUnicode(unsigned char byte3, unsigned char byte4) +{ + switch (byte3) { + case 0x04: + // katakana + if (byte4 > 0xa0 && byte4 < 0xe0) + return QChar(katakanaKeysymsToUnicode[byte4 - 0xa0]); + else if (byte4 == 0x7e) + return QChar(0x203e); // Overline + break; + case 0x06: + // russian, use lookup table + if (byte4 > 0xa0) + return QChar(cyrillicKeysymsToUnicode[byte4 - 0xa0]); + break; + case 0x07: + // greek + if (byte4 > 0xa0) + return QChar(greekKeysymsToUnicode[byte4 - 0xa0]); + break; + case 0x08: + // technical + if (byte4 > 0xa0) + return QChar(technicalKeysymsToUnicode[byte4 - 0xa0]); + break; + case 0x09: + // special + if (byte4 >= 0xe0) + return QChar(specialKeysymsToUnicode[byte4 - 0xe0]); + break; + case 0x0a: + // publishing + if (byte4 > 0xa0) + return QChar(publishingKeysymsToUnicode[byte4 - 0xa0]); + break; + case 0x0b: + // APL + if (byte4 > 0xa0) + return QChar(aplKeysymsToUnicode[byte4 - 0xa0]); + break; + case 0x0e: + // Korean + if (byte4 > 0xa0) + return QChar(koreanKeysymsToUnicode[byte4 - 0xa0]); + break; + default: + break; + } + return QChar(0x0); +} + +Qt::KeyboardModifiers QXcbKeyboard::translateModifiers(int s) +{ + Qt::KeyboardModifiers ret = 0; + if (s & XCB_MOD_MASK_SHIFT) + ret |= Qt::ShiftModifier; + if (s & XCB_MOD_MASK_CONTROL) + ret |= Qt::ControlModifier; + if (s & m_alt_mask) + ret |= Qt::AltModifier; + if (s & m_meta_mask) + ret |= Qt::MetaModifier; + return ret; +} + +int QXcbKeyboard::translateKeySym(uint key) const +{ + int code = -1; + int i = 0; // any other keys + while (KeyTbl[i]) { + if (key == KeyTbl[i]) { + code = (int)KeyTbl[i+1]; + break; + } + i += 2; + } + if (m_meta_mask) { + // translate Super/Hyper keys to Meta if we're using them as the MetaModifier + if (m_meta_mask == m_super_mask && (code == Qt::Key_Super_L || code == Qt::Key_Super_R)) { + code = Qt::Key_Meta; + } else if (m_meta_mask == m_hyper_mask && (code == Qt::Key_Hyper_L || code == Qt::Key_Hyper_R)) { + code = Qt::Key_Meta; + } + } + return code; +} + +QString QXcbKeyboard::translateKeySym(xcb_keysym_t keysym, uint xmodifiers, + int &code, Qt::KeyboardModifiers &modifiers, + QByteArray &chars, int &count) +{ + // all keysyms smaller than 0xff00 are actally keys that can be mapped to unicode chars + + QTextCodec *mapper = QTextCodec::codecForLocale(); + QChar converted; + + if (/*count == 0 &&*/ keysym < 0xff00) { + unsigned char byte3 = (unsigned char)(keysym >> 8); + int mib = -1; + switch(byte3) { + case 0: // Latin 1 + case 1: // Latin 2 + case 2: //latin 3 + case 3: // latin4 + mib = byte3 + 4; break; + case 5: // arabic + mib = 82; break; + case 12: // Hebrew + mib = 85; break; + case 13: // Thai + mib = 2259; break; + case 4: // kana + case 6: // cyrillic + case 7: // greek + case 8: // technical, no mapping here at the moment + case 9: // Special + case 10: // Publishing + case 11: // APL + case 14: // Korean, no mapping + mib = -1; // manual conversion + mapper= 0; +#if !defined(QT_NO_XIM) + converted = keysymToUnicode(byte3, keysym & 0xff); +#endif + case 0x20: + // currency symbols + if (keysym >= 0x20a0 && keysym <= 0x20ac) { + mib = -1; // manual conversion + mapper = 0; + converted = (uint)keysym; + } + break; + default: + break; + } + if (mib != -1) { + mapper = QTextCodec::codecForMib(mib); + if (chars.isEmpty()) + chars.resize(1); + chars[0] = (unsigned char) (keysym & 0xff); // get only the fourth bit for conversion later + count = 1; + } + } else if (keysym >= 0x1000000 && keysym <= 0x100ffff) { + converted = (ushort) (keysym - 0x1000000); + mapper = 0; + } + if (count < (int)chars.size()-1) + chars[count] = '\0'; + + QString text; + if (!mapper && converted.unicode() != 0x0) { + text = converted; + } else if (!chars.isEmpty()) { + // convert chars (8bit) to text (unicode). + if (mapper) + text = mapper->toUnicode(chars.data(), count, 0); + if (text.isEmpty()) { + // no mapper, or codec couldn't convert to unicode (this + // can happen when running in the C locale or with no LANG + // set). try converting from latin-1 + text = QString::fromLatin1(chars); + } + } + + modifiers = translateModifiers(xmodifiers); + + // Commentary in X11/keysymdef says that X codes match ASCII, so it + // is safe to use the locale functions to process X codes in ISO8859-1. + // + // This is mainly for compatibility - applications should not use the + // Qt keycodes between 128 and 255, but should rather use the + // QKeyEvent::text(). + // + if (keysym < 128 || (keysym < 256 && (!mapper || mapper->mibEnum()==4))) { + // upper-case key, if known + code = isprint((int)keysym) ? toupper((int)keysym) : 0; + } else if (keysym >= XK_F1 && keysym <= XK_F35) { + // function keys + code = Qt::Key_F1 + ((int)keysym - XK_F1); + } else if (keysym >= XK_KP_Space && keysym <= XK_KP_9) { + if (keysym >= XK_KP_0) { + // numeric keypad keys + code = Qt::Key_0 + ((int)keysym - XK_KP_0); + } else { + code = translateKeySym(keysym); + } + modifiers |= Qt::KeypadModifier; + } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f && text.unicode()->unicode() != 0x7f && !(keysym >= XK_dead_grave && keysym <= XK_dead_horn)) { + code = text.unicode()->toUpper().unicode(); + } else { + // any other keys + code = translateKeySym(keysym); + + if (code == Qt::Key_Tab && (modifiers & Qt::ShiftModifier)) { + // map shift+tab to shift+backtab, QShortcutMap knows about it + // and will handle it. + code = Qt::Key_Backtab; + text = QString(); + } + } + + return text; +} + +QXcbKeyboard::QXcbKeyboard(QXcbConnection *connection) + : QXcbObject(connection) + , m_alt_mask(0) + , m_super_mask(0) + , m_hyper_mask(0) + , m_meta_mask(0) +{ + m_key_symbols = xcb_key_symbols_alloc(xcb_connection()); +} + +QXcbKeyboard::~QXcbKeyboard() +{ + xcb_key_symbols_free(m_key_symbols); +} + +// #define XCB_KEYBOARD_DEBUG + +void QXcbKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, xcb_keycode_t code, quint16 state, xcb_timestamp_t time) +{ + int col = state & XCB_MOD_MASK_SHIFT ? 1 : 0; + + const int altGrOffset = 4; + if (state & 128) + col += altGrOffset; + +#ifdef XCB_KEYBOARD_DEBUG + printf("key code: %d, state: %d, syms: ", code, state); + for (int i = 0; i <= 5; ++i) { + printf("%d ", xcb_key_symbols_get_keysym(m_key_symbols, code, i)); + } + printf("\n"); +#endif + + xcb_keysym_t sym = xcb_key_symbols_get_keysym(m_key_symbols, code, col); + if (sym == XCB_NO_SYMBOL) + sym = xcb_key_symbols_get_keysym(m_key_symbols, code, col ^ 0x1); + + if (state & XCB_MOD_MASK_LOCK && sym <= 0x7f && isprint(sym)) { + if (isupper(sym)) + sym = tolower(sym); + else + sym = toupper(sym); + } + + QByteArray chars; + + Qt::KeyboardModifiers modifiers; + int qtcode = 0; + int count = 0; + + QString string = translateKeySym(sym, state, qtcode, modifiers, chars, count); + + QWindowSystemInterface::handleExtendedKeyEvent(widget, time, type, qtcode, modifiers, code, 0, state, string.left(count)); +} + +void QXcbKeyboard::handleKeyPressEvent(QWidget *widget, const xcb_key_press_event_t *event) +{ + handleKeyEvent(widget, QEvent::KeyPress, event->detail, event->state, event->time); +} + +void QXcbKeyboard::handleKeyReleaseEvent(QWidget *widget, const xcb_key_release_event_t *event) +{ + handleKeyEvent(widget, QEvent::KeyRelease, event->detail, event->state, event->time); +} + +void QXcbKeyboard::handleMappingNotifyEvent(const xcb_mapping_notify_event_t *event) +{ + xcb_refresh_keyboard_mapping(m_key_symbols, const_cast<xcb_mapping_notify_event_t *>(event)); +} diff --git a/src/plugins/platforms/xcb/qxcbkeyboard.h b/src/plugins/platforms/xcb/qxcbkeyboard.h new file mode 100644 index 0000000..ddade79 --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbkeyboard.h @@ -0,0 +1,82 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBKEYBOARD_H +#define QXCBKEYBOARD_H + +#include "qxcbobject.h" + +#include "xcb/xcb_keysyms.h" + +#include <QEvent> + +class QXcbKeyboard : public QXcbObject +{ +public: + QXcbKeyboard(QXcbConnection *connection); + ~QXcbKeyboard(); + + void handleKeyPressEvent(QWidget *widget, const xcb_key_press_event_t *event); + void handleKeyReleaseEvent(QWidget *widget, const xcb_key_release_event_t *event); + + void handleMappingNotifyEvent(const xcb_mapping_notify_event_t *event); + + Qt::KeyboardModifiers translateModifiers(int s); + +private: + void handleKeyEvent(QWidget *widget, QEvent::Type type, xcb_keycode_t code, quint16 state, xcb_timestamp_t time); + + int translateKeySym(uint key) const; + QString translateKeySym(xcb_keysym_t keysym, uint xmodifiers, + int &code, Qt::KeyboardModifiers &modifiers, + QByteArray &chars, int &count); + + uint m_alt_mask; + uint m_super_mask; + uint m_hyper_mask; + uint m_meta_mask; + uint m_mode_switch_mask; + uint m_num_lock_mask; + + xcb_key_symbols_t *m_key_symbols; +}; + +#endif diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.cpp b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp new file mode 100644 index 0000000..b2ca1be --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.cpp @@ -0,0 +1,185 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbnativeinterface.h" + +#include "qxcbscreen.h" + +#include <QtGui/private/qapplication_p.h> +#include <QtCore/QMap> + +#include <QtCore/QDebug> + +#if defined(XCB_USE_EGL) +#include "../eglconvenience/qeglplatformcontext.h" +#elif defined (XCB_USE_DRI2) +#include "qdri2context.h" +#endif + +class QXcbResourceMap : public QMap<QByteArray, QXcbNativeInterface::ResourceType> +{ +public: + QXcbResourceMap() + :QMap<QByteArray, QXcbNativeInterface::ResourceType>() + { + insert("display",QXcbNativeInterface::Display); + insert("egldisplay",QXcbNativeInterface::EglDisplay); + insert("connection",QXcbNativeInterface::Connection); + insert("screen",QXcbNativeInterface::Screen); + insert("graphicsdevice",QXcbNativeInterface::GraphicsDevice); + insert("eglcontext",QXcbNativeInterface::EglContext); + } +}; + +Q_GLOBAL_STATIC(QXcbResourceMap, qXcbResourceMap) + +void *QXcbNativeInterface::nativeResourceForWidget(const QByteArray &resourceString, QWidget *widget) +{ + QByteArray lowerCaseResource = resourceString.toLower(); + ResourceType resource = qXcbResourceMap()->value(lowerCaseResource); + void *result = 0; + switch(resource) { + case Display: + result = displayForWidget(widget); + break; + case EglDisplay: + result = eglDisplayForWidget(widget); + break; + case Connection: + result = connectionForWidget(widget); + break; + case Screen: + result = qPlatformScreenForWidget(widget); + break; + case GraphicsDevice: + result = graphicsDeviceForWidget(widget); + break; + case EglContext: + result = eglContextForWidget(widget); + break; + default: + result = 0; + } + return result; +} + +QXcbScreen *QXcbNativeInterface::qPlatformScreenForWidget(QWidget *widget) +{ + QXcbScreen *screen; + if (widget) { + screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(widget)); + }else { + screen = static_cast<QXcbScreen *>(QApplicationPrivate::platformIntegration()->screens()[0]); + } + return screen; +} + +void *QXcbNativeInterface::displayForWidget(QWidget *widget) +{ +#if defined(XCB_USE_XLIB) + QXcbScreen *screen = qPlatformScreenForWidget(widget); + return screen->connection()->xlib_display(); +#else + Q_UNUSED(widget); + return 0; +#endif +} + +void *QXcbNativeInterface::eglDisplayForWidget(QWidget *widget) +{ +#if defined(XCB_USE_DRI2) || defined(XCB_USE_EGL) + QXcbScreen *screen = qPlatformScreenForWidget(widget); + return screen->connection()->egl_display(); +#else + Q_UNUSED(widget) + return 0; +#endif +} + +void *QXcbNativeInterface::connectionForWidget(QWidget *widget) +{ + QXcbScreen *screen = qPlatformScreenForWidget(widget); + return screen->xcb_connection(); +} + +void *QXcbNativeInterface::screenForWidget(QWidget *widget) +{ + QXcbScreen *screen = qPlatformScreenForWidget(widget); + return screen->screen(); +} + +void *QXcbNativeInterface::graphicsDeviceForWidget(QWidget *widget) +{ +#if defined(XCB_USE_DRI2) + QXcbScreen *screen = qPlatformScreenForWidget(widget); + QByteArray deviceName = screen->connection()->dri2DeviceName(); + return deviceName.data(); +#else + Q_UNUSED(widget); + return 0; +#endif + +} + +void * QXcbNativeInterface::eglContextForWidget(QWidget *widget) +{ + Q_ASSERT(widget); + if (!widget->platformWindow()) { + qDebug() << "QPlatformWindow does not exist for widget" << widget + << "cannot return EGLContext"; + return 0; + } + QPlatformGLContext *platformContext = widget->platformWindow()->glContext(); + if (!platformContext) { + qDebug() << "QPlatformWindow" << widget->platformWindow() << "does not have a glContext" + << "cannot return EGLContext"; + return 0; + } +#if defined(XCB_USE_EGL) + QEGLPlatformContext *eglPlatformContext = static_cast<QEGLPlatformContext *>(platformContext); + return eglPlatformContext->eglContext(); +#elif defined (XCB_USE_DRI2) + QDri2Context *dri2Context = static_cast<QDri2Context *>(platformContext); + return dri2Context->eglContext(); +#else + return 0; +#endif +} diff --git a/src/plugins/platforms/xcb/qxcbnativeinterface.h b/src/plugins/platforms/xcb/qxcbnativeinterface.h new file mode 100644 index 0000000..f60905c --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbnativeinterface.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBNATIVEINTERFACE_H +#define QXCBNATIVEINTERFACE_H + +#include <QtGui/QPlatformNativeInterface> + +class QWidget; +class QXcbScreen; + +class QXcbNativeInterface : public QPlatformNativeInterface +{ +public: + enum ResourceType { + Display, + EglDisplay, + Connection, + Screen, + GraphicsDevice, + EglContext + }; + + void *nativeResourceForWidget(const QByteArray &resourceString, QWidget *widget); + + void *displayForWidget(QWidget *widget); + void *eglDisplayForWidget(QWidget *widget); + void *connectionForWidget(QWidget *widget); + void *screenForWidget(QWidget *widget); + void *graphicsDeviceForWidget(QWidget *widget); + void *eglContextForWidget(QWidget *widget); + +private: + static QXcbScreen *qPlatformScreenForWidget(QWidget *widget); +}; + +#endif // QXCBNATIVEINTERFACE_H diff --git a/src/plugins/platforms/xcb/qxcbobject.h b/src/plugins/platforms/xcb/qxcbobject.h new file mode 100644 index 0000000..69494b0 --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbobject.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBOBJECT_H +#define QXCBOBJECT_H + +#include "qxcbconnection.h" + +class QXcbObject +{ +public: + QXcbObject(QXcbConnection *connection = 0) : m_connection(connection) {} + + void setConnection(QXcbConnection *connection) { m_connection = connection; } + QXcbConnection *connection() const { return m_connection; } + + xcb_atom_t atom(QXcbAtom::Atom atom) const { return m_connection->atom(atom); } + xcb_connection_t *xcb_connection() const { return m_connection->xcb_connection(); } + +private: + QXcbConnection *m_connection; +}; + +#endif diff --git a/src/plugins/platforms/xcb/qxcbscreen.cpp b/src/plugins/platforms/xcb/qxcbscreen.cpp new file mode 100644 index 0000000..fffeb2e --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbscreen.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbscreen.h" + +#include <stdio.h> + +QXcbScreen::QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int number) + : QXcbObject(connection) + , m_screen(screen) + , m_number(number) +{ + printf ("\n"); + printf ("Information of screen %d:\n", screen->root); + printf (" width.........: %d\n", screen->width_in_pixels); + printf (" height........: %d\n", screen->height_in_pixels); + printf (" depth.........: %d\n", screen->root_depth); + printf (" white pixel...: %x\n", screen->white_pixel); + printf (" black pixel...: %x\n", screen->black_pixel); + printf ("\n"); + + const quint32 mask = XCB_CW_EVENT_MASK; + const quint32 values[] = { + // XCB_CW_EVENT_MASK + XCB_EVENT_MASK_KEYMAP_STATE + | XCB_EVENT_MASK_ENTER_WINDOW + | XCB_EVENT_MASK_LEAVE_WINDOW + | XCB_EVENT_MASK_PROPERTY_CHANGE + }; + + xcb_change_window_attributes(xcb_connection(), screen->root, mask, values); +} + +QXcbScreen::~QXcbScreen() +{ +} + +QRect QXcbScreen::geometry() const +{ + return QRect(0, 0, m_screen->width_in_pixels, m_screen->height_in_pixels); +} + +int QXcbScreen::depth() const +{ + return m_screen->root_depth; +} + +QImage::Format QXcbScreen::format() const +{ + return QImage::Format_RGB32; +} + +QSize QXcbScreen::physicalSize() const +{ + return QSize(m_screen->width_in_millimeters, m_screen->height_in_millimeters); +} + +int QXcbScreen::screenNumber() const +{ + return m_number; +} diff --git a/src/plugins/platforms/xcb/qxcbscreen.h b/src/plugins/platforms/xcb/qxcbscreen.h new file mode 100644 index 0000000..6f69fc7 --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbscreen.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBSCREEN_H +#define QXCBSCREEN_H + +#include <QtGui/QPlatformScreen> + +#include <xcb/xcb.h> + +#include "qxcbobject.h" + +class QXcbConnection; + +class QXcbScreen : public QXcbObject, public QPlatformScreen +{ +public: + QXcbScreen(QXcbConnection *connection, xcb_screen_t *screen, int number); + ~QXcbScreen(); + + QRect geometry() const; + int depth() const; + QImage::Format format() const; + QSize physicalSize() const; + + int screenNumber() const; + + xcb_screen_t *screen() const { return m_screen; } + xcb_window_t root() const { return m_screen->root; } + +private: + xcb_screen_t *m_screen; + int m_number; +}; + +#endif diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp new file mode 100644 index 0000000..cbf50f7 --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -0,0 +1,588 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbwindow.h" + +#include "qxcbconnection.h" +#include "qxcbscreen.h" +#ifdef XCB_USE_DRI2 +#include "qdri2context.h" +#endif + +#include <xcb/xcb_icccm.h> + +#include <private/qapplication_p.h> +#include <private/qwindowsurface_p.h> + +#include <QtGui/QWindowSystemInterface> + +#include <stdio.h> + +#ifdef XCB_USE_XLIB +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#endif + +#if defined(XCB_USE_GLX) +#include "qglxintegration.h" +#elif defined(XCB_USE_EGL) +#include "../eglconvenience/qeglplatformcontext.h" +#include "../eglconvenience/qeglconvenience.h" +#include "../eglconvenience/qxlibeglintegration.h" +#endif + +// Returns true if we should set WM_TRANSIENT_FOR on \a w +static inline bool isTransient(const QWidget *w) +{ + return ((w->windowType() == Qt::Dialog + || w->windowType() == Qt::Sheet + || w->windowType() == Qt::Tool + || w->windowType() == Qt::SplashScreen + || w->windowType() == Qt::ToolTip + || w->windowType() == Qt::Drawer + || w->windowType() == Qt::Popup) + && !w->testAttribute(Qt::WA_X11BypassTransientForHint)); +} + +QXcbWindow::QXcbWindow(QWidget *tlw) + : QPlatformWindow(tlw) + , m_context(0) +{ + m_screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(tlw)); + + setConnection(m_screen->connection()); + + const quint32 mask = XCB_CW_BACK_PIXMAP | XCB_CW_EVENT_MASK; + const quint32 values[] = { + // XCB_CW_BACK_PIXMAP + XCB_NONE, + // XCB_CW_EVENT_MASK + XCB_EVENT_MASK_EXPOSURE + | XCB_EVENT_MASK_STRUCTURE_NOTIFY + | XCB_EVENT_MASK_KEY_PRESS + | XCB_EVENT_MASK_KEY_RELEASE + | XCB_EVENT_MASK_BUTTON_PRESS + | XCB_EVENT_MASK_BUTTON_RELEASE + | XCB_EVENT_MASK_BUTTON_MOTION + | XCB_EVENT_MASK_ENTER_WINDOW + | XCB_EVENT_MASK_LEAVE_WINDOW + | XCB_EVENT_MASK_PROPERTY_CHANGE + | XCB_EVENT_MASK_FOCUS_CHANGE + }; + +#if defined(XCB_USE_GLX) || defined(XCB_USE_EGL) + if (tlw->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL + && QApplicationPrivate::platformIntegration()->hasOpenGL() ) { +#if defined(XCB_USE_GLX) + XVisualInfo *visualInfo = QGLXContext::findVisualInfo(m_screen, tlw->platformWindowFormat()); +#elif defined(XCB_USE_EGL) + EGLDisplay eglDisplay = eglGetDisplay(DISPLAY_FROM_XCB(this)); + EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,tlw->platformWindowFormat(),true); + VisualID id = QXlibEglIntegration::getCompatibleVisualId(DISPLAY_FROM_XCB(this),eglConfig); + + XVisualInfo visualInfoTemplate; + memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); + visualInfoTemplate.visualid = id; + + XVisualInfo *visualInfo; + int matchingCount = 0; + visualInfo = XGetVisualInfo(DISPLAY_FROM_XCB(this), VisualIDMask, &visualInfoTemplate, &matchingCount); +#endif //XCB_USE_GLX + if (visualInfo) { + Colormap cmap = XCreateColormap(DISPLAY_FROM_XCB(this), m_screen->root(), visualInfo->visual, AllocNone); + + XSetWindowAttributes a; + a.colormap = cmap; + m_window = XCreateWindow(DISPLAY_FROM_XCB(this), m_screen->root(), tlw->x(), tlw->y(), tlw->width(), tlw->height(), + 0, visualInfo->depth, InputOutput, visualInfo->visual, + CWColormap, &a); + + printf("created GL window: %d\n", m_window); + } else { + qFatal("no window!"); + } + } else +#endif //defined(XCB_USE_GLX) || defined(XCB_USE_EGL) + { + m_window = xcb_generate_id(xcb_connection()); + + xcb_create_window(xcb_connection(), + XCB_COPY_FROM_PARENT, // depth -- same as root + m_window, // window id + m_screen->root(), // parent window id + tlw->x(), + tlw->y(), + tlw->width(), + tlw->height(), + 0, // border width + XCB_WINDOW_CLASS_INPUT_OUTPUT, // window class + m_screen->screen()->root_visual, // visual + 0, // value mask + 0); // value list + + printf("created regular window: %d\n", m_window); + } + + xcb_change_window_attributes(xcb_connection(), m_window, mask, values); + + xcb_atom_t properties[4]; + int propertyCount = 0; + properties[propertyCount++] = atom(QXcbAtom::WM_DELETE_WINDOW); + properties[propertyCount++] = atom(QXcbAtom::WM_TAKE_FOCUS); + properties[propertyCount++] = atom(QXcbAtom::_NET_WM_PING); + + if (tlw->windowFlags() & Qt::WindowContextHelpButtonHint) + properties[propertyCount++] = atom(QXcbAtom::_NET_WM_CONTEXT_HELP); + + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::WM_PROTOCOLS), + 4, + 32, + propertyCount, + properties); + + if (isTransient(tlw) && tlw->parentWidget()) { + // ICCCM 4.1.2.6 + QWidget *p = tlw->parentWidget()->window(); + xcb_window_t parentWindow = p->winId(); + xcb_change_property(xcb_connection(), XCB_PROP_MODE_REPLACE, m_window, + XCB_ATOM_WM_TRANSIENT_FOR, XCB_ATOM_WINDOW, 32, + 1, &parentWindow); + + } +} + +QXcbWindow::~QXcbWindow() +{ + xcb_destroy_window(xcb_connection(), m_window); +} + +void QXcbWindow::setGeometry(const QRect &rect) +{ + QPlatformWindow::setGeometry(rect); + + const quint32 mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y | XCB_CONFIG_WINDOW_WIDTH | XCB_CONFIG_WINDOW_HEIGHT; + const quint32 values[] = { rect.x(), rect.y(), rect.width(), rect.height() }; + + xcb_configure_window(xcb_connection(), m_window, mask, values); +} + +void QXcbWindow::setVisible(bool visible) +{ + xcb_wm_hints_t hints; + if (visible) { + if (widget()->isMinimized()) + xcb_wm_hints_set_iconic(&hints); + else + xcb_wm_hints_set_normal(&hints); + xcb_set_wm_hints(xcb_connection(), m_window, &hints); + xcb_map_window(xcb_connection(), m_window); + } else { + xcb_unmap_window(xcb_connection(), m_window); + + // send synthetic UnmapNotify event according to icccm 4.1.4 + xcb_unmap_notify_event_t event; + event.response_type = XCB_UNMAP_NOTIFY; + event.sequence = 0; // does this matter? + event.event = m_screen->root(); + event.window = m_window; + event.from_configure = false; + xcb_send_event(xcb_connection(), false, m_screen->root(), + XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY | XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (const char *)&event); + + xcb_flush(xcb_connection()); + } +} + +struct QtMWMHints { + quint32 flags, functions, decorations; + qint32 input_mode; + quint32 status; +}; + +enum { + MWM_HINTS_FUNCTIONS = (1L << 0), + + MWM_FUNC_ALL = (1L << 0), + MWM_FUNC_RESIZE = (1L << 1), + MWM_FUNC_MOVE = (1L << 2), + MWM_FUNC_MINIMIZE = (1L << 3), + MWM_FUNC_MAXIMIZE = (1L << 4), + MWM_FUNC_CLOSE = (1L << 5), + + MWM_HINTS_DECORATIONS = (1L << 1), + + MWM_DECOR_ALL = (1L << 0), + MWM_DECOR_BORDER = (1L << 1), + MWM_DECOR_RESIZEH = (1L << 2), + MWM_DECOR_TITLE = (1L << 3), + MWM_DECOR_MENU = (1L << 4), + MWM_DECOR_MINIMIZE = (1L << 5), + MWM_DECOR_MAXIMIZE = (1L << 6), + + MWM_HINTS_INPUT_MODE = (1L << 2), + + MWM_INPUT_MODELESS = 0L, + MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L, + MWM_INPUT_FULL_APPLICATION_MODAL = 3L +}; + +Qt::WindowFlags QXcbWindow::setWindowFlags(Qt::WindowFlags flags) +{ + Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask)); + + if (type == Qt::ToolTip) + flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint; + if (type == Qt::Popup) + flags |= Qt::X11BypassWindowManagerHint; + + bool topLevel = (flags & Qt::Window); + bool popup = (type == Qt::Popup); + bool dialog = (type == Qt::Dialog + || type == Qt::Sheet); + bool desktop = (type == Qt::Desktop); + bool tool = (type == Qt::Tool || type == Qt::SplashScreen + || type == Qt::ToolTip || type == Qt::Drawer); + + Q_UNUSED(topLevel); + Q_UNUSED(dialog); + Q_UNUSED(desktop); + Q_UNUSED(tool); + + bool tooltip = (type == Qt::ToolTip); + + QtMWMHints mwmhints; + mwmhints.flags = 0L; + mwmhints.functions = 0L; + mwmhints.decorations = 0; + mwmhints.input_mode = 0L; + mwmhints.status = 0L; + + if (type != Qt::SplashScreen) { + mwmhints.flags |= MWM_HINTS_DECORATIONS; + + bool customize = flags & Qt::CustomizeWindowHint; + if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) { + mwmhints.decorations |= MWM_DECOR_BORDER; + mwmhints.decorations |= MWM_DECOR_RESIZEH; + + if (flags & Qt::WindowTitleHint) + mwmhints.decorations |= MWM_DECOR_TITLE; + + if (flags & Qt::WindowSystemMenuHint) + mwmhints.decorations |= MWM_DECOR_MENU; + + if (flags & Qt::WindowMinimizeButtonHint) { + mwmhints.decorations |= MWM_DECOR_MINIMIZE; + mwmhints.functions |= MWM_FUNC_MINIMIZE; + } + + if (flags & Qt::WindowMaximizeButtonHint) { + mwmhints.decorations |= MWM_DECOR_MAXIMIZE; + mwmhints.functions |= MWM_FUNC_MAXIMIZE; + } + + if (flags & Qt::WindowCloseButtonHint) + mwmhints.functions |= MWM_FUNC_CLOSE; + } + } else { + // if type == Qt::SplashScreen + mwmhints.decorations = MWM_DECOR_ALL; + } + + if (mwmhints.functions != 0) { + mwmhints.flags |= MWM_HINTS_FUNCTIONS; + mwmhints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE; + } else { + mwmhints.functions = MWM_FUNC_ALL; + } + + if (!(flags & Qt::FramelessWindowHint) + && flags & Qt::CustomizeWindowHint + && flags & Qt::WindowTitleHint + && !(flags & + (Qt::WindowMinimizeButtonHint + | Qt::WindowMaximizeButtonHint + | Qt::WindowCloseButtonHint))) + { + // a special case - only the titlebar without any button + mwmhints.flags = MWM_HINTS_FUNCTIONS; + mwmhints.functions = MWM_FUNC_MOVE | MWM_FUNC_RESIZE; + mwmhints.decorations = 0; + } + + if (mwmhints.flags != 0l) { + xcb_change_property(xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_MOTIF_WM_HINTS), + atom(QXcbAtom::_MOTIF_WM_HINTS), + 32, + 5, + &mwmhints); + } else { + xcb_delete_property(xcb_connection(), m_window, atom(QXcbAtom::_MOTIF_WM_HINTS)); + } + + if (popup || tooltip) { + const quint32 mask = XCB_CW_OVERRIDE_REDIRECT | XCB_CW_SAVE_UNDER; + const quint32 values[] = { true, true }; + + xcb_change_window_attributes(xcb_connection(), m_window, mask, values); + } + + return QPlatformWindow::setWindowFlags(flags); +} + +WId QXcbWindow::winId() const +{ + return m_window; +} + +void QXcbWindow::setParent(const QPlatformWindow *parent) +{ + QPoint topLeft = geometry().topLeft(); + xcb_reparent_window(xcb_connection(), window(), static_cast<const QXcbWindow *>(parent)->window(), topLeft.x(), topLeft.y()); +} + +void QXcbWindow::setWindowTitle(const QString &title) +{ + QByteArray ba = title.toUtf8(); + xcb_change_property (xcb_connection(), + XCB_PROP_MODE_REPLACE, + m_window, + atom(QXcbAtom::_NET_WM_NAME), + atom(QXcbAtom::UTF8_STRING), + 8, + ba.length(), + ba.constData()); +} + +void QXcbWindow::raise() +{ + const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE; + const quint32 values[] = { XCB_STACK_MODE_ABOVE }; + xcb_configure_window(xcb_connection(), m_window, mask, values); +} + +void QXcbWindow::lower() +{ + const quint32 mask = XCB_CONFIG_WINDOW_STACK_MODE; + const quint32 values[] = { XCB_STACK_MODE_BELOW }; + xcb_configure_window(xcb_connection(), m_window, mask, values); +} + +void QXcbWindow::requestActivateWindow() +{ + xcb_set_input_focus(xcb_connection(), m_window, XCB_INPUT_FOCUS_PARENT, XCB_TIME_CURRENT_TIME); +} + +QPlatformGLContext *QXcbWindow::glContext() const +{ + if (!QApplicationPrivate::platformIntegration()->hasOpenGL()) { + printf("no opengl\n"); + return 0; + } +#if defined(XCB_USE_GLX) + if (!m_context) { + QXcbWindow *that = const_cast<QXcbWindow *>(this); + that->m_context = new QGLXContext(m_window, m_screen, widget()->platformWindowFormat()); + } +#elif defined(XCB_USE_EGL) + if (!m_context) { + EGLDisplay display = eglGetDisplay(DISPLAY_FROM_XCB(this)); + + EGLConfig config = q_configFromQPlatformWindowFormat(display,widget()->platformWindowFormat(),true); + QVector<EGLint> eglContextAttrs; + eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); + eglContextAttrs.append(2); + eglContextAttrs.append(EGL_NONE); + + EGLSurface eglSurface = eglCreateWindowSurface(display,config,(EGLNativeWindowType)m_window,0); + QXcbWindow *that = const_cast<QXcbWindow *>(this); + that->m_context = new QEGLPlatformContext(display, config, eglContextAttrs.data(), eglSurface, EGL_OPENGL_ES_API); + } +#elif defined(XCB_USE_DRI2) + if (!m_context) { + QXcbWindow *that = const_cast<QXcbWindow *>(this); + that->m_context = new QDri2Context(that); + } + +#endif + return m_context; +} + +void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event) +{ + QWindowSurface *surface = widget()->windowSurface(); + if (surface) { + QRect rect(event->x, event->y, event->width, event->height); + + surface->flush(widget(), rect, QPoint()); + } +} + +void QXcbWindow::handleClientMessageEvent(const xcb_client_message_event_t *event) +{ + if (event->format == 32 && event->type == atom(QXcbAtom::WM_PROTOCOLS)) { + if (event->data.data32[0] == atom(QXcbAtom::WM_DELETE_WINDOW)) { + QWindowSystemInterface::handleCloseEvent(widget()); + } + } +} + +void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t *event) +{ + int xpos = geometry().x(); + int ypos = geometry().y(); + + if ((event->width == geometry().width() && event->height == geometry().height()) || event->x != 0 || event->y != 0) { + xpos = event->x; + ypos = event->y; + } + + QRect rect(xpos, ypos, event->width, event->height); + QPlatformWindow::setGeometry(rect); + + QWindowSystemInterface::handleGeometryChange(widget(), rect); + +#if XCB_USE_DRI2 + if (m_context) + static_cast<QDri2Context *>(m_context)->resize(rect.size()); +#endif +} + +static Qt::MouseButtons translateMouseButtons(int s) +{ + Qt::MouseButtons ret = 0; + if (s & XCB_BUTTON_MASK_1) + ret |= Qt::LeftButton; + if (s & XCB_BUTTON_MASK_2) + ret |= Qt::MidButton; + if (s & XCB_BUTTON_MASK_3) + ret |= Qt::RightButton; + return ret; +} + +static Qt::MouseButton translateMouseButton(xcb_button_t s) +{ + switch (s) { + case 1: + return Qt::LeftButton; + case 2: + return Qt::MidButton; + case 3: + return Qt::RightButton; + default: + return Qt::NoButton; + } +} + +void QXcbWindow::handleButtonPressEvent(const xcb_button_press_event_t *event) +{ + QPoint local(event->event_x, event->event_y); + QPoint global(event->root_x, event->root_y); + + Qt::KeyboardModifiers modifiers = Qt::NoModifier; + + if (event->detail >= 4 && event->detail <= 7) { + //logic borrowed from qapplication_x11.cpp + int delta = 120 * ((event->detail == 4 || event->detail == 6) ? 1 : -1); + bool hor = (((event->detail == 4 || event->detail == 5) + && (modifiers & Qt::AltModifier)) + || (event->detail == 6 || event->detail == 7)); + + QWindowSystemInterface::handleWheelEvent(widget(), event->time, + local, global, delta, hor ? Qt::Horizontal : Qt::Vertical); + return; + } + + handleMouseEvent(event->detail, event->state, event->time, local, global); +} + +void QXcbWindow::handleButtonReleaseEvent(const xcb_button_release_event_t *event) +{ + QPoint local(event->event_x, event->event_y); + QPoint global(event->root_x, event->root_y); + + handleMouseEvent(event->detail, event->state, event->time, local, global); +} + +void QXcbWindow::handleMotionNotifyEvent(const xcb_motion_notify_event_t *event) +{ + QPoint local(event->event_x, event->event_y); + QPoint global(event->root_x, event->root_y); + + handleMouseEvent(event->detail, event->state, event->time, local, global); +} + +void QXcbWindow::handleMouseEvent(xcb_button_t detail, uint16_t state, xcb_timestamp_t time, const QPoint &local, const QPoint &global) +{ + Qt::MouseButtons buttons = translateMouseButtons(state); + Qt::MouseButton button = translateMouseButton(detail); + + buttons ^= button; // X event uses state *before*, Qt uses state *after* + + QWindowSystemInterface::handleMouseEvent(widget(), time, local, global, buttons); +} + +void QXcbWindow::handleEnterNotifyEvent(const xcb_enter_notify_event_t *) +{ + QWindowSystemInterface::handleEnterEvent(widget()); +} + +void QXcbWindow::handleLeaveNotifyEvent(const xcb_leave_notify_event_t *) +{ + QWindowSystemInterface::handleLeaveEvent(widget()); +} + +void QXcbWindow::handleFocusInEvent(const xcb_focus_in_event_t *) +{ + QWindowSystemInterface::handleWindowActivated(widget()); +} + +void QXcbWindow::handleFocusOutEvent(const xcb_focus_out_event_t *) +{ + QWindowSystemInterface::handleWindowActivated(0); +} + diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h new file mode 100644 index 0000000..1e9930d --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBWINDOW_H +#define QXCBWINDOW_H + +#include <QtGui/QPlatformWindow> +#include <QtGui/QPlatformWindowFormat> + +#include <xcb/xcb.h> + +#include "qxcbobject.h" + +class QXcbScreen; + +class QXcbWindow : public QXcbObject, public QPlatformWindow +{ +public: + QXcbWindow(QWidget *tlw); + ~QXcbWindow(); + + void setGeometry(const QRect &rect); + + void setVisible(bool visible); + Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags); + WId winId() const; + void setParent(const QPlatformWindow *window); + + void setWindowTitle(const QString &title); + void raise(); + void lower(); + + void requestActivateWindow(); + + QPlatformGLContext *glContext() const; + + xcb_window_t window() const { return m_window; } + + void handleExposeEvent(const xcb_expose_event_t *event); + void handleClientMessageEvent(const xcb_client_message_event_t *event); + void handleConfigureNotifyEvent(const xcb_configure_notify_event_t *event); + void handleButtonPressEvent(const xcb_button_press_event_t *event); + void handleButtonReleaseEvent(const xcb_button_release_event_t *event); + void handleMotionNotifyEvent(const xcb_motion_notify_event_t *event); + + void handleEnterNotifyEvent(const xcb_enter_notify_event_t *event); + void handleLeaveNotifyEvent(const xcb_leave_notify_event_t *event); + void handleFocusInEvent(const xcb_focus_in_event_t *event); + void handleFocusOutEvent(const xcb_focus_out_event_t *event); + + void handleMouseEvent(xcb_button_t detail, uint16_t state, xcb_timestamp_t time, const QPoint &local, const QPoint &global); + +private: + QXcbScreen *m_screen; + + xcb_window_t m_window; + QPlatformGLContext *m_context; +}; + +#endif diff --git a/src/plugins/platforms/xcb/qxcbwindowsurface.cpp b/src/plugins/platforms/xcb/qxcbwindowsurface.cpp new file mode 100644 index 0000000..7fed230 --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbwindowsurface.cpp @@ -0,0 +1,220 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxcbwindowsurface.h" + +#include "qxcbconnection.h" +#include "qxcbscreen.h" +#include "qxcbwindow.h" + +#include <xcb/shm.h> +#include <xcb/xcb_image.h> + +#include <sys/ipc.h> +#include <sys/shm.h> + +#include <stdio.h> + +class QXcbShmImage : public QXcbObject +{ +public: + QXcbShmImage(QXcbScreen *connection, const QSize &size); + ~QXcbShmImage() { destroy(); } + + QImage *image() { return &m_qimage; } + + void put(xcb_window_t window, const QPoint &dst, const QRect &source); + void preparePaint(const QRegion ®ion); + +private: + void destroy(); + + xcb_shm_segment_info_t m_shm_info; + + xcb_image_t *m_xcb_image; + + QImage m_qimage; + + xcb_gcontext_t m_gc; + xcb_window_t m_gc_window; + + QRegion m_dirty; +}; + +QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size) + : QXcbObject(screen->connection()) + , m_gc(0) + , m_gc_window(0) +{ + m_xcb_image = xcb_image_create_native(xcb_connection(), + size.width(), + size.height(), + XCB_IMAGE_FORMAT_Z_PIXMAP, + screen->depth(), + 0, + ~0, + 0); + m_shm_info.shmid = shmget (IPC_PRIVATE, + m_xcb_image->stride * m_xcb_image->height, IPC_CREAT|0777); + + m_shm_info.shmaddr = m_xcb_image->data = (quint8 *)shmat (m_shm_info.shmid, 0, 0); + m_shm_info.shmseg = xcb_generate_id(xcb_connection()); + + xcb_shm_attach(xcb_connection(), m_shm_info.shmseg, m_shm_info.shmid, false); + + m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, screen->format()); +} + +void QXcbShmImage::destroy() +{ + xcb_shm_detach(xcb_connection(), m_shm_info.shmseg); + xcb_image_destroy(m_xcb_image); + shmdt(m_shm_info.shmaddr); + shmctl(m_shm_info.shmid, IPC_RMID, 0); + + xcb_free_gc(xcb_connection(), m_gc); +} + +void QXcbShmImage::put(xcb_window_t window, const QPoint &target, const QRect &source) +{ + if (m_gc_window != window) { + xcb_free_gc(xcb_connection(), m_gc); + + m_gc = xcb_generate_id(xcb_connection()); + xcb_create_gc(xcb_connection(), m_gc, window, 0, 0); + + m_gc_window = window; + } + + xcb_image_shm_put(xcb_connection(), + window, + m_gc, + m_xcb_image, + m_shm_info, + source.x(), + source.y(), + target.x(), + target.y(), + source.width(), + source.height(), + false); + + m_dirty = m_dirty | source; + + xcb_flush(xcb_connection()); +} + +void QXcbShmImage::preparePaint(const QRegion ®ion) +{ + // to prevent X from reading from the image region while we're writing to it + if (m_dirty.intersects(region)) { + // from xcb_aux_sync + free(xcb_get_input_focus_reply(xcb_connection(), xcb_get_input_focus(xcb_connection()), 0)); + m_dirty = QRegion(); + } +} + +QXcbWindowSurface::QXcbWindowSurface(QWidget *widget, bool setDefaultSurface) + : QWindowSurface(widget, setDefaultSurface) + , m_image(0) +{ + setStaticContentsSupport(false); + setPartialUpdateSupport(true); + + QXcbScreen *screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(widget)); + setConnection(screen->connection()); +} + +QXcbWindowSurface::~QXcbWindowSurface() +{ +} + +QPaintDevice *QXcbWindowSurface::paintDevice() +{ + return m_image->image(); +} + +void QXcbWindowSurface::beginPaint(const QRegion ®ion) +{ + m_image->preparePaint(region); +} + +void QXcbWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(region); + Q_UNUSED(offset); + + QXcbWindow *window = static_cast<QXcbWindow *>(widget->window()->platformWindow()); + + extern QWidgetData* qt_widget_data(QWidget *); + QPoint widgetOffset = qt_qwidget_data(widget)->wrect.topLeft(); + + QVector<QRect> rects = region.rects(); + for (int i = 0; i < rects.size(); ++i) + m_image->put(window->window(), rects.at(i).topLeft() - widgetOffset, rects.at(i).translated(offset)); +} + +void QXcbWindowSurface::resize(const QSize &size) +{ + QWindowSurface::resize(size); + + QXcbScreen *screen = static_cast<QXcbScreen *>(QPlatformScreen::platformScreenForWidget(window())); + + delete m_image; + m_image = new QXcbShmImage(screen, size); +} + +extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); + +bool QXcbWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + if (m_image->image()->isNull()) + return false; + + m_image->preparePaint(area); + + const QVector<QRect> rects = area.rects(); + for (int i = 0; i < rects.size(); ++i) + qt_scrollRectInImage(*m_image->image(), rects.at(i), QPoint(dx, dy)); + + return true; +} + diff --git a/src/plugins/platforms/xcb/qxcbwindowsurface.h b/src/plugins/platforms/xcb/qxcbwindowsurface.h new file mode 100644 index 0000000..61689b1 --- /dev/null +++ b/src/plugins/platforms/xcb/qxcbwindowsurface.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXCBWINDOWSURFACE_H +#define QXCBWINDOWSURFACE_H + +#include <private/qwindowsurface_p.h> + +#include <xcb/xcb.h> + +#include "qxcbobject.h" + +class QXcbShmImage; + +class QXcbWindowSurface : public QXcbObject, public QWindowSurface +{ +public: + QXcbWindowSurface(QWidget *widget, bool setDefaultSurface = true); + ~QXcbWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + bool scroll(const QRegion &area, int dx, int dy); + + void beginPaint(const QRegion &); + +private: + QXcbShmImage *m_image; +}; + +#endif diff --git a/src/plugins/platforms/xcb/xcb.pro b/src/plugins/platforms/xcb/xcb.pro new file mode 100644 index 0000000..fdbe2cd --- /dev/null +++ b/src/plugins/platforms/xcb/xcb.pro @@ -0,0 +1,69 @@ +TARGET = xcb + +include(../../qpluginbase.pri) +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +SOURCES = \ + qxcbconnection.cpp \ + qxcbintegration.cpp \ + qxcbkeyboard.cpp \ + qxcbscreen.cpp \ + qxcbwindow.cpp \ + qxcbwindowsurface.cpp \ + main.cpp \ + qxcbnativeinterface.cpp + +HEADERS = \ + qxcbconnection.h \ + qxcbintegration.h \ + qxcbkeyboard.h \ + qxcbobject.h \ + qxcbscreen.h \ + qxcbwindow.h \ + qxcbwindowsurface.h \ + qxcbnativeinterface.h + +contains(QT_CONFIG, opengl) { + QT += opengl + +# DEFINES += XCB_USE_DRI2 + contains(DEFINES, XCB_USE_DRI2) { + LIBS += -lxcb-dri2 -lxcb-xfixes -lEGL + + CONFIG += link_pkgconfig + PKGCONFIG += libdrm + + HEADERS += qdri2context.h + SOURCES += qdri2context.cpp + + } else { + DEFINES += XCB_USE_XLIB + LIBS += -lX11 -lX11-xcb + + contains(QT_CONFIG, opengles2) { + DEFINES += XCB_USE_EGL + HEADERS += \ + ../eglconvenience/qeglplatformcontext.h \ + ../eglconvenience/qeglconvenience.h \ + ../eglconvenience/qxlibeglintegration.h + + SOURCES += \ + ../eglconvenience/qeglplatformcontext.cpp \ + ../eglconvenience/qeglconvenience.cpp \ + ../eglconvenience/qxlibeglintegration.cpp + + LIBS += -lEGL + } else { + DEFINES += XCB_USE_GLX + HEADERS += qglxintegration.h + SOURCES += qglxintegration.cpp + } + } +} + +LIBS += -lxcb -lxcb-image -lxcb-keysyms -lxcb-icccm + +include (../fontdatabases/genericunix/genericunix.pri) + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target diff --git a/src/plugins/platforms/testlite/main.cpp b/src/plugins/platforms/xlib/main.cpp index 2f6aa8b..f0bf6ff 100644 --- a/src/plugins/platforms/testlite/main.cpp +++ b/src/plugins/platforms/xlib/main.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -40,40 +40,40 @@ ****************************************************************************/ #include <QtGui/QPlatformIntegrationPlugin> -#include "qtestliteintegration.h" +#include "qxlibintegration.h" QT_BEGIN_NAMESPACE -class QTestLiteIntegrationPlugin : public QPlatformIntegrationPlugin +class QXlibIntegrationPlugin : public QPlatformIntegrationPlugin { public: QStringList keys() const; QPlatformIntegration *create(const QString&, const QStringList&); }; -QStringList QTestLiteIntegrationPlugin::keys() const +QStringList QXlibIntegrationPlugin::keys() const { QStringList list; - list << "TestLite"; + list << "Xlib"; #ifndef QT_NO_OPENGL - list << "TestLiteGL"; + list << "XlibGL"; #endif return list; } -QPlatformIntegration* QTestLiteIntegrationPlugin::create(const QString& system, const QStringList& paramList) +QPlatformIntegration* QXlibIntegrationPlugin::create(const QString& system, const QStringList& paramList) { Q_UNUSED(paramList); - if (system.toLower() == "testlite") - return new QTestLiteIntegration; + if (system.toLower() == "xlib") + return new QXlibIntegration; #ifndef QT_NO_OPENGL - if (system.toLower() == "testlitegl") - return new QTestLiteIntegration(true); + if (system.toLower() == "xlibgl") + return new QXlibIntegration(true); #endif return 0; } -Q_EXPORT_PLUGIN2(testlite, QTestLiteIntegrationPlugin) +Q_EXPORT_PLUGIN2(xlib, QXlibIntegrationPlugin) QT_END_NAMESPACE diff --git a/src/plugins/platforms/xlib/qglxintegration.cpp b/src/plugins/platforms/xlib/qglxintegration.cpp new file mode 100644 index 0000000..80011d9 --- /dev/null +++ b/src/plugins/platforms/xlib/qglxintegration.cpp @@ -0,0 +1,377 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include <QDebug> +#include <QLibrary> +#include <QGLFormat> + +#include "qxlibwindow.h" +#include "qxlibscreen.h" +#include "qxlibdisplay.h" + +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <GL/glx.h> + +#include "qglxintegration.h" + +#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) +#include <dlfcn.h> +#endif + +QT_BEGIN_NAMESPACE + +QMutex QGLXContext::m_defaultSharedContextMutex(QMutex::Recursive); + +QVector<int> QGLXContext::buildSpec(const QPlatformWindowFormat &format) +{ + QVector<int> spec(48); + int i = 0; + + spec[i++] = GLX_LEVEL; + spec[i++] = 0; + spec[i++] = GLX_DRAWABLE_TYPE; spec[i++] = GLX_WINDOW_BIT; + + if (format.rgba()) { + spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_RGBA_BIT; + spec[i++] = GLX_RED_SIZE; spec[i++] = (format.redBufferSize() == -1) ? 1 : format.redBufferSize(); + spec[i++] = GLX_GREEN_SIZE; spec[i++] = (format.greenBufferSize() == -1) ? 1 : format.greenBufferSize(); + spec[i++] = GLX_BLUE_SIZE; spec[i++] = (format.blueBufferSize() == -1) ? 1 : format.blueBufferSize(); + if (format.alpha()) { + spec[i++] = GLX_ALPHA_SIZE; spec[i++] = (format.alphaBufferSize() == -1) ? 1 : format.alphaBufferSize(); + } + + spec[i++] = GLX_ACCUM_RED_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + spec[i++] = GLX_ACCUM_GREEN_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + spec[i++] = GLX_ACCUM_BLUE_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + + if (format.alpha()) { + spec[i++] = GLX_ACCUM_ALPHA_SIZE; spec[i++] = (format.accumBufferSize() == -1) ? 1 : format.accumBufferSize(); + } + + } else { + spec[i++] = GLX_RENDER_TYPE; spec[i++] = GLX_COLOR_INDEX_BIT; //I'm really not sure if this works.... + spec[i++] = GLX_BUFFER_SIZE; spec[i++] = 8; + } + + spec[i++] = GLX_DOUBLEBUFFER; spec[i++] = format.doubleBuffer() ? True : False; + spec[i++] = GLX_STEREO; spec[i++] = format.stereo() ? True : False; + + if (format.depth()) { + spec[i++] = GLX_DEPTH_SIZE; spec[i++] = (format.depthBufferSize() == -1) ? 1 : format.depthBufferSize(); + } + + if (format.stencil()) { + spec[i++] = GLX_STENCIL_SIZE; spec[i++] = (format.stencilBufferSize() == -1) ? 1 : format.stencilBufferSize(); + } + if (format.sampleBuffers()) { + spec[i++] = GLX_SAMPLE_BUFFERS_ARB; + spec[i++] = 1; + spec[i++] = GLX_SAMPLES_ARB; + spec[i++] = format.samples() == -1 ? 4 : format.samples(); + } + + spec[i++] = XNone; + return spec; +} + +GLXFBConfig QGLXContext::findConfig(const QXlibScreen *screen, const QPlatformWindowFormat &format) +{ + bool reduced = true; + GLXFBConfig chosenConfig = 0; + QPlatformWindowFormat reducedFormat = format; + while (!chosenConfig && reduced) { + QVector<int> spec = buildSpec(reducedFormat); + int confcount = 0; + GLXFBConfig *configs; + configs = glXChooseFBConfig(screen->display()->nativeDisplay(),screen->xScreenNumber(),spec.constData(),&confcount); + if (confcount) + { + for (int i = 0; i < confcount; i++) { + chosenConfig = configs[i]; + // Make sure we try to get an ARGB visual if the format asked for an alpha: + if (reducedFormat.alpha()) { + int alphaSize; + glXGetFBConfigAttrib(screen->display()->nativeDisplay(),configs[i],GLX_ALPHA_SIZE,&alphaSize); + if (alphaSize > 0) + break; + } else { + break; // Just choose the first in the list if there's no alpha requested + } + } + + XFree(configs); + } + reducedFormat = reducePlatformWindowFormat(reducedFormat,&reduced); + } + + if (!chosenConfig) + qWarning("Warning no context created"); + + return chosenConfig; +} + +XVisualInfo *QGLXContext::findVisualInfo(const QXlibScreen *screen, const QPlatformWindowFormat &format) +{ + GLXFBConfig config = QGLXContext::findConfig(screen,format); + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(screen->display()->nativeDisplay(),config); + return visualInfo; +} + +QPlatformWindowFormat QGLXContext::platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext ctx) +{ + QPlatformWindowFormat format; + int redSize = 0; + int greenSize = 0; + int blueSize = 0; + int alphaSize = 0; + int depthSize = 0; + int stencilSize = 0; + int sampleBuffers = 0; + int sampleCount = 0; + int level = 0; + int rgba = 0; + int stereo = 0; + int accumSizeA = 0; + int accumSizeR = 0; + int accumSizeG = 0; + int accumSizeB = 0; + + XVisualInfo *vi = glXGetVisualFromFBConfig(display,config); + glXGetConfig(display,vi,GLX_RGBA,&rgba); + XFree(vi); + glXGetFBConfigAttrib(display, config, GLX_RED_SIZE, &redSize); + glXGetFBConfigAttrib(display, config, GLX_GREEN_SIZE, &greenSize); + glXGetFBConfigAttrib(display, config, GLX_BLUE_SIZE, &blueSize); + glXGetFBConfigAttrib(display, config, GLX_ALPHA_SIZE, &alphaSize); + glXGetFBConfigAttrib(display, config, GLX_DEPTH_SIZE, &depthSize); + glXGetFBConfigAttrib(display, config, GLX_STENCIL_SIZE, &stencilSize); + glXGetFBConfigAttrib(display, config, GLX_SAMPLES, &sampleBuffers); + glXGetFBConfigAttrib(display, config, GLX_LEVEL, &level); + glXGetFBConfigAttrib(display, config, GLX_STEREO, &stereo); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_ALPHA_SIZE, &accumSizeA); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_RED_SIZE, &accumSizeR); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_GREEN_SIZE, &accumSizeG); + glXGetFBConfigAttrib(display, config, GLX_ACCUM_BLUE_SIZE, &accumSizeB); + + format.setRedBufferSize(redSize); + format.setGreenBufferSize(greenSize); + format.setBlueBufferSize(blueSize); + format.setAlphaBufferSize(alphaSize); + format.setDepthBufferSize(depthSize); + format.setStencilBufferSize(stencilSize); + format.setSampleBuffers(sampleBuffers); + if (format.sampleBuffers()) { + glXGetFBConfigAttrib(display, config, GLX_SAMPLES_ARB, &sampleCount); + format.setSamples(sampleCount); + } + + format.setDirectRendering(glXIsDirect(display, ctx)); + format.setRgba(rgba); + format.setStereo(stereo); + format.setAccumBufferSize(accumSizeB); + + return format; +} + +QPlatformWindowFormat QGLXContext::reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced) +{ + QPlatformWindowFormat retFormat = format; + *reduced = true; + + if (retFormat.sampleBuffers()) { + retFormat.setSampleBuffers(false); + } else if (retFormat.stereo()) { + retFormat.setStereo(false); + } else if (retFormat.accum()) { + retFormat.setAccum(false); + }else if (retFormat.stencil()) { + retFormat.setStencil(false); + }else if (retFormat.alpha()) { + retFormat.setAlpha(false); + }else if (retFormat.depth()) { + retFormat.setDepth(false); + }else if (retFormat.doubleBuffer()) { + retFormat.setDoubleBuffer(false); + }else{ + *reduced = false; + } + return retFormat; +} + +QGLXContext::QGLXContext(Window window, QXlibScreen *screen, const QPlatformWindowFormat &format) + : QPlatformGLContext() + , m_screen(screen) + , m_drawable((Drawable)window) + , m_context(0) +{ + + const QPlatformGLContext *sharePlatformContext; + if (format.useDefaultSharedContext()) { + if (!QPlatformGLContext::defaultSharedContext()) { + if (m_defaultSharedContextMutex.tryLock()){ + createDefaultSharedContex(screen); + m_defaultSharedContextMutex.unlock(); + } else { + m_defaultSharedContextMutex.lock(); //wait to the the shared context is created + m_defaultSharedContextMutex.unlock(); + } + } + sharePlatformContext = QPlatformGLContext::defaultSharedContext(); + } else { + sharePlatformContext = format.sharedGLContext(); + } + GLXContext shareGlxContext = 0; + if (sharePlatformContext) + shareGlxContext = static_cast<const QGLXContext*>(sharePlatformContext)->glxContext(); + + GLXFBConfig config = findConfig(screen,format); + m_context = glXCreateNewContext(screen->display()->nativeDisplay(),config,GLX_RGBA_TYPE,shareGlxContext,TRUE); + m_windowFormat = QGLXContext::platformWindowFromGLXFBConfig(screen->display()->nativeDisplay(),config,m_context); + +#ifdef MYX11_DEBUG + qDebug() << "QGLXGLContext::create context" << m_context; +#endif +} + +QGLXContext::QGLXContext(QXlibScreen *screen, Drawable drawable, GLXContext context) + : QPlatformGLContext(), m_screen(screen), m_drawable(drawable), m_context(context) +{ + +} + +QGLXContext::~QGLXContext() +{ + if (m_context) { + qDebug("Destroying GLX context 0x%p", m_context); + glXDestroyContext(m_screen->display()->nativeDisplay(), m_context); + } +} + +void QGLXContext::createDefaultSharedContex(QXlibScreen *screen) +{ + int x = 0; + int y = 0; + int w = 3; + int h = 3; + + QPlatformWindowFormat format = QPlatformWindowFormat::defaultFormat(); + GLXContext context; + GLXFBConfig config = findConfig(screen,format); + if (config) { + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(screen->display()->nativeDisplay(),config); + Colormap cmap = XCreateColormap(screen->display()->nativeDisplay(),screen->rootWindow(),visualInfo->visual,AllocNone); + XSetWindowAttributes a; + a.colormap = cmap; + Window sharedWindow = XCreateWindow(screen->display()->nativeDisplay(), screen->rootWindow(),x, y, w, h, + 0, visualInfo->depth, InputOutput, visualInfo->visual, + CWColormap, &a); + + context = glXCreateNewContext(screen->display()->nativeDisplay(),config,GLX_RGBA_TYPE,0,TRUE); + QPlatformGLContext *sharedContext = new QGLXContext(screen,sharedWindow,context); + QPlatformGLContext::setDefaultSharedContext(sharedContext); + } else { + qWarning("Warning no shared context created"); + } +} + +void QGLXContext::makeCurrent() +{ + QPlatformGLContext::makeCurrent(); +#ifdef MYX11_DEBUG + qDebug("QGLXGLContext::makeCurrent(window=0x%x, ctx=0x%x)", m_drawable, m_context); +#endif + glXMakeCurrent(m_screen->display()->nativeDisplay(), m_drawable, m_context); +} + +void QGLXContext::doneCurrent() +{ + QPlatformGLContext::doneCurrent(); + glXMakeCurrent(m_screen->display()->nativeDisplay(), 0, 0); +} + +void QGLXContext::swapBuffers() +{ + glXSwapBuffers(m_screen->display()->nativeDisplay(), m_drawable); +} + +void* QGLXContext::getProcAddress(const QString& procName) +{ + typedef void *(*qt_glXGetProcAddressARB)(const GLubyte *); + static qt_glXGetProcAddressARB glXGetProcAddressARB = 0; + static bool resolved = false; + + if (resolved && !glXGetProcAddressARB) + return 0; + if (!glXGetProcAddressARB) { + QList<QByteArray> glxExt = QByteArray(glXGetClientString(m_screen->display()->nativeDisplay(), GLX_EXTENSIONS)).split(' '); + if (glxExt.contains("GLX_ARB_get_proc_address")) { +#if defined(Q_OS_LINUX) || defined(Q_OS_BSD4) + void *handle = dlopen(NULL, RTLD_LAZY); + if (handle) { + glXGetProcAddressARB = (qt_glXGetProcAddressARB) dlsym(handle, "glXGetProcAddressARB"); + dlclose(handle); + } + if (!glXGetProcAddressARB) +#endif + { + extern const QString qt_gl_library_name(); +// QLibrary lib(qt_gl_library_name()); + QLibrary lib(QLatin1String("GL")); + glXGetProcAddressARB = (qt_glXGetProcAddressARB) lib.resolve("glXGetProcAddressARB"); + } + } + resolved = true; + } + if (!glXGetProcAddressARB) + return 0; + return glXGetProcAddressARB(reinterpret_cast<const GLubyte *>(procName.toLatin1().data())); +} + +QPlatformWindowFormat QGLXContext::platformWindowFormat() const +{ + return m_windowFormat; +} + +QT_END_NAMESPACE + +#endif //!defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) diff --git a/src/plugins/platforms/testlite/qglxintegration.h b/src/plugins/platforms/xlib/qglxintegration.h index e17790e..dbb5c2e 100644 --- a/src/plugins/platforms/testlite/qglxintegration.h +++ b/src/plugins/platforms/xlib/qglxintegration.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -42,24 +42,23 @@ #ifndef Q_GLX_CONTEXT_H #define Q_GLX_CONTEXT_H -#include "qtestlitewindow.h" +#include "qxlibwindow.h" #include <QtGui/QPlatformGLContext> #include <QtGui/QPlatformWindowFormat> #include <QtCore/QMutex> +#if !defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) #include <GL/glx.h> QT_BEGIN_NAMESPACE -class MyDisplay; - -class QGLXGLContext : public QPlatformGLContext +class QGLXContext : public QPlatformGLContext { public: - QGLXGLContext(Window window, MyDisplay *xd, const QPlatformWindowFormat &format); - ~QGLXGLContext(); + QGLXContext(Window window, QXlibScreen *xd, const QPlatformWindowFormat &format); + ~QGLXContext(); virtual void makeCurrent(); virtual void doneCurrent(); @@ -70,24 +69,26 @@ public: QPlatformWindowFormat platformWindowFormat() const; - static XVisualInfo *findVisualInfo(const MyDisplay *xd, const QPlatformWindowFormat &format); + static XVisualInfo *findVisualInfo(const QXlibScreen *xd, const QPlatformWindowFormat &format); private: - static GLXFBConfig findConfig(const MyDisplay *xd,const QPlatformWindowFormat &format); + static GLXFBConfig findConfig(const QXlibScreen *xd,const QPlatformWindowFormat &format); static QVector<int> buildSpec(const QPlatformWindowFormat &format); static QPlatformWindowFormat platformWindowFromGLXFBConfig(Display *display, GLXFBConfig config, GLXContext context); static QPlatformWindowFormat reducePlatformWindowFormat(const QPlatformWindowFormat &format, bool *reduced); - MyDisplay *m_xd; + QXlibScreen *m_screen; Drawable m_drawable; GLXContext m_context; QPlatformWindowFormat m_windowFormat; - QGLXGLContext (MyDisplay *display, Drawable drawable, GLXContext context); + QGLXContext (QXlibScreen *screen, Drawable drawable, GLXContext context); static QMutex m_defaultSharedContextMutex; - static void createDefaultSharedContex(MyDisplay *xd); + static void createDefaultSharedContex(QXlibScreen *xd); }; QT_END_NAMESPACE +#endif //!defined(QT_NO_OPENGL) && !defined(QT_OPENGL_ES_2) + #endif diff --git a/src/plugins/platforms/xlib/qxlibclipboard.cpp b/src/plugins/platforms/xlib/qxlibclipboard.cpp new file mode 100644 index 0000000..dfaf552 --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibclipboard.cpp @@ -0,0 +1,677 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxlibclipboard.h" + +#include "qxlibscreen.h" +#include "qxlibmime.h" +#include "qxlibdisplay.h" + +#include <private/qapplication_p.h> + +#include <QtCore/QDebug> + +class QXlibClipboardMime : public QXlibMime +{ + Q_OBJECT +public: + QXlibClipboardMime(QClipboard::Mode mode, QXlibClipboard *clipboard) + : QXlibMime() + , m_clipboard(clipboard) + { + switch (mode) { + case QClipboard::Selection: + modeAtom = XA_PRIMARY; + break; + + case QClipboard::Clipboard: + modeAtom = QXlibStatic::atom(QXlibStatic::CLIPBOARD); + break; + + default: + qWarning("QTestLiteMime: Internal error: Unsupported clipboard mode"); + break; + } + } + +protected: + QStringList formats_sys() const + { + if (empty()) + return QStringList(); + + if (!formatList.count()) { + QXlibClipboardMime *that = const_cast<QXlibClipboardMime *>(this); + // get the list of targets from the current clipboard owner - we do this + // once so that multiple calls to this function don't require multiple + // server round trips... + that->format_atoms = m_clipboard->getDataInFormat(modeAtom,QXlibStatic::atom(QXlibStatic::TARGETS)); + + if (format_atoms.size() > 0) { + Atom *targets = (Atom *) format_atoms.data(); + int size = format_atoms.size() / sizeof(Atom); + + for (int i = 0; i < size; ++i) { + if (targets[i] == 0) + continue; + + QStringList formatsForAtom = mimeFormatsForAtom(m_clipboard->screen()->display()->nativeDisplay(),targets[i]); + for (int j = 0; j < formatsForAtom.size(); ++j) { + if (!formatList.contains(formatsForAtom.at(j))) + that->formatList.append(formatsForAtom.at(j)); + } + } + } + } + + return formatList; + } + + bool hasFormat_sys(const QString &format) const + { + QStringList list = formats(); + return list.contains(format); + } + + QVariant retrieveData_sys(const QString &fmt, QVariant::Type requestedType) const + { + if (fmt.isEmpty() || empty()) + return QByteArray(); + + (void)formats(); // trigger update of format list + + QList<Atom> atoms; + Atom *targets = (Atom *) format_atoms.data(); + int size = format_atoms.size() / sizeof(Atom); + for (int i = 0; i < size; ++i) + atoms.append(targets[i]); + + QByteArray encoding; + Atom fmtatom = mimeAtomForFormat(m_clipboard->screen()->display()->nativeDisplay(),fmt, requestedType, atoms, &encoding); + + if (fmtatom == 0) + return QVariant(); + + return mimeConvertToFormat(m_clipboard->screen()->display()->nativeDisplay(),fmtatom, m_clipboard->getDataInFormat(modeAtom,fmtatom), fmt, requestedType, encoding); + } +private: + bool empty() const + { + Window win = XGetSelectionOwner(m_clipboard->screen()->display()->nativeDisplay(), modeAtom); + + return win == XNone; + } + + + Atom modeAtom; + QXlibClipboard *m_clipboard; + QStringList formatList; + QByteArray format_atoms; +}; + +const int QXlibClipboard::clipboard_timeout = 5000; + +QXlibClipboard::QXlibClipboard(QXlibScreen *screen) + : QPlatformClipboard() + , m_screen(screen) + , m_xClipboard(0) + , m_clientClipboard(0) + , m_xSelection(0) + , m_clientSelection(0) + , m_requestor(XNone) + , m_owner(XNone) +{ +} + +const QMimeData * QXlibClipboard::mimeData(QClipboard::Mode mode) const +{ + if (mode == QClipboard::Clipboard) { + if (!m_xClipboard) { + QXlibClipboard *that = const_cast<QXlibClipboard *>(this); + that->m_xClipboard = new QXlibClipboardMime(mode,that); + } + Window clipboardOwner = XGetSelectionOwner(screen()->display()->nativeDisplay(),QXlibStatic::atom(QXlibStatic::CLIPBOARD)); + if (clipboardOwner == owner()) { + return m_clientClipboard; + } else { + return m_xClipboard; + } + } else if (mode == QClipboard::Selection) { + if (!m_xSelection) { + QXlibClipboard *that = const_cast<QXlibClipboard *>(this); + that->m_xSelection = new QXlibClipboardMime(mode,that); + } + Window clipboardOwner = XGetSelectionOwner(screen()->display()->nativeDisplay(),XA_PRIMARY); + if (clipboardOwner == owner()) { + return m_clientSelection; + } else { + return m_xSelection; + } + } + return 0; +} + +void QXlibClipboard::setMimeData(QMimeData *data, QClipboard::Mode mode) +{ + Atom modeAtom; + QMimeData **d; + switch (mode) { + case QClipboard::Selection: + modeAtom = XA_PRIMARY; + d = &m_clientSelection; + break; + + case QClipboard::Clipboard: + modeAtom = QXlibStatic::atom(QXlibStatic::CLIPBOARD); + d = &m_clientClipboard; + break; + + default: + qWarning("QClipboard::setMimeData: unsupported mode '%d'", mode); + return; + } + + Window newOwner; + + if (! data) { // no data, clear clipboard contents + newOwner = XNone; + } else { + newOwner = owner(); + + *d = data; + } + + XSetSelectionOwner(m_screen->display()->nativeDisplay(), modeAtom, newOwner, CurrentTime); + + if (XGetSelectionOwner(m_screen->display()->nativeDisplay(), modeAtom) != newOwner) { + qWarning("QClipboard::setData: Cannot set X11 selection owner"); + } + +} + +bool QXlibClipboard::supportsMode(QClipboard::Mode mode) const +{ + if (mode == QClipboard::Clipboard || mode == QClipboard::Selection) + return true; + return false; +} + + +QXlibScreen * QXlibClipboard::screen() const +{ + return m_screen; +} + +Window QXlibClipboard::requestor() const +{ + if (!m_requestor) { + int x = 0, y = 0, w = 3, h = 3; + QXlibClipboard *that = const_cast<QXlibClipboard *>(this); + Window window = XCreateSimpleWindow(m_screen->display()->nativeDisplay(), m_screen->rootWindow(), + x, y, w, h, 0 /*border_width*/, + m_screen->blackPixel(), m_screen->whitePixel()); + that->setRequestor(window); + } + return m_requestor; +} + +void QXlibClipboard::setRequestor(Window window) +{ + if (m_requestor != XNone) { + XDestroyWindow(m_screen->display()->nativeDisplay(),m_requestor); + } + m_requestor = window; +} + +Window QXlibClipboard::owner() const +{ + if (!m_owner) { + int x = 0, y = 0, w = 3, h = 3; + QXlibClipboard *that = const_cast<QXlibClipboard *>(this); + Window window = XCreateSimpleWindow(m_screen->display()->nativeDisplay(), m_screen->rootWindow(), + x, y, w, h, 0 /*border_width*/, + m_screen->blackPixel(), m_screen->whitePixel()); + that->setOwner(window); + } + return m_owner; +} + +void QXlibClipboard::setOwner(Window window) +{ + if (m_owner != XNone){ + XDestroyWindow(m_screen->display()->nativeDisplay(),m_owner); + } + m_owner = window; +} + +Atom QXlibClipboard::sendTargetsSelection(QMimeData *d, Window window, Atom property) +{ + QVector<Atom> types; + QStringList formats = QInternalMimeData::formatsHelper(d); + for (int i = 0; i < formats.size(); ++i) { + QList<Atom> atoms = QXlibMime::mimeAtomsForFormat(screen()->display()->nativeDisplay(),formats.at(i)); + for (int j = 0; j < atoms.size(); ++j) { + if (!types.contains(atoms.at(j))) + types.append(atoms.at(j)); + } + } + types.append(QXlibStatic::atom(QXlibStatic::TARGETS)); + types.append(QXlibStatic::atom(QXlibStatic::MULTIPLE)); + types.append(QXlibStatic::atom(QXlibStatic::TIMESTAMP)); + types.append(QXlibStatic::atom(QXlibStatic::SAVE_TARGETS)); + + XChangeProperty(screen()->display()->nativeDisplay(), window, property, XA_ATOM, 32, + PropModeReplace, (uchar *) types.data(), types.size()); + return property; +} + +Atom QXlibClipboard::sendSelection(QMimeData *d, Atom target, Window window, Atom property) +{ + Atom atomFormat = target; + int dataFormat = 0; + QByteArray data; + + QString fmt = QXlibMime::mimeAtomToString(screen()->display()->nativeDisplay(), target); + if (fmt.isEmpty()) { // Not a MIME type we have + qDebug() << "QClipboard: send_selection(): converting to type '%s' is not supported" << fmt.data(); + return XNone; + } + qDebug() << "QClipboard: send_selection(): converting to type '%s'" << fmt.data(); + + if (QXlibMime::mimeDataForAtom(screen()->display()->nativeDisplay(),target, d, &data, &atomFormat, &dataFormat)) { + + // don't allow INCR transfers when using MULTIPLE or to + // Motif clients (since Motif doesn't support INCR) + static Atom motif_clip_temporary = QXlibStatic::atom(QXlibStatic::CLIP_TEMPORARY); + bool allow_incr = property != motif_clip_temporary; + + // X_ChangeProperty protocol request is 24 bytes + const int increment = (XMaxRequestSize(screen()->display()->nativeDisplay()) * 4) - 24; + if (data.size() > increment && allow_incr) { + long bytes = data.size(); + XChangeProperty(screen()->display()->nativeDisplay(), window, property, + QXlibStatic::atom(QXlibStatic::INCR), 32, PropModeReplace, (uchar *) &bytes, 1); + +// (void)new QClipboardINCRTransaction(window, property, atomFormat, dataFormat, data, increment); + qDebug() << "not implemented INCRT just YET!"; + return property; + } + + // make sure we can perform the XChangeProperty in a single request + if (data.size() > increment) + return XNone; // ### perhaps use several XChangeProperty calls w/ PropModeAppend? + int dataSize = data.size() / (dataFormat / 8); + // use a single request to transfer data + XChangeProperty(screen()->display()->nativeDisplay(), window, property, atomFormat, + dataFormat, PropModeReplace, (uchar *) data.data(), + dataSize); + } + return property; +} + +void QXlibClipboard::handleSelectionRequest(XEvent *xevent) +{ + XSelectionRequestEvent *req = &xevent->xselectionrequest; + + if (requestor() && req->requestor == requestor()) { + qDebug() << "This should be caught before"; + return; + } + + XEvent event; + event.xselection.type = SelectionNotify; + event.xselection.display = req->display; + event.xselection.requestor = req->requestor; + event.xselection.selection = req->selection; + event.xselection.target = req->target; + event.xselection.property = XNone; + event.xselection.time = req->time; + + QMimeData *d; + if (req->selection == XA_PRIMARY) { + d = m_clientSelection; + } else if (req->selection == QXlibStatic::atom(QXlibStatic::CLIPBOARD)) { + d = m_clientClipboard; + } else { + qWarning("QClipboard: Unknown selection '%lx'", req->selection); + XSendEvent(screen()->display()->nativeDisplay(), req->requestor, False, NoEventMask, &event); + return; + } + + if (!d) { + qWarning("QClipboard: Cannot transfer data, no data available"); + XSendEvent(screen()->display()->nativeDisplay(), req->requestor, False, NoEventMask, &event); + return; + } + + Atom xa_targets = QXlibStatic::atom(QXlibStatic::TARGETS); + Atom xa_multiple = QXlibStatic::atom(QXlibStatic::MULTIPLE); + Atom xa_timestamp = QXlibStatic::atom(QXlibStatic::TIMESTAMP); + + struct AtomPair { Atom target; Atom property; } *multi = 0; + Atom multi_type = XNone; + int multi_format = 0; + int nmulti = 0; + int imulti = -1; + bool multi_writeback = false; + + if (req->target == xa_multiple) { + QByteArray multi_data; + if (req->property == XNone + || !clipboardReadProperty(req->requestor, req->property, false, &multi_data, + 0, &multi_type, &multi_format) + || multi_format != 32) { + // MULTIPLE property not formatted correctly + XSendEvent(screen()->display()->nativeDisplay(), req->requestor, False, NoEventMask, &event); + return; + } + nmulti = multi_data.size()/sizeof(*multi); + multi = new AtomPair[nmulti]; + memcpy(multi,multi_data.data(),multi_data.size()); + imulti = 0; + } + + for (; imulti < nmulti; ++imulti) { + Atom target; + Atom property; + + if (multi) { + target = multi[imulti].target; + property = multi[imulti].property; + } else { + target = req->target; + property = req->property; + if (property == XNone) // obsolete client + property = target; + } + + Atom ret = XNone; + if (target == XNone || property == XNone) { + ; + } else if (target == xa_timestamp) { +// if (d->timestamp != CurrentTime) { +// XChangeProperty(screen()->display()->nativeDisplay(), req->requestor, property, XA_INTEGER, 32, +// PropModeReplace, CurrentTime, 1); +// ret = property; +// } else { +// qWarning("QClipboard: Invalid data timestamp"); +// } + } else if (target == xa_targets) { + ret = sendTargetsSelection(d, req->requestor, property); + } else { + ret = sendSelection(d, target, req->requestor, property); + } + + if (nmulti > 0) { + if (ret == XNone) { + multi[imulti].property = XNone; + multi_writeback = true; + } + } else { + event.xselection.property = ret; + break; + } + } + + if (nmulti > 0) { + if (multi_writeback) { + // according to ICCCM 2.6.2 says to put None back + // into the original property on the requestor window + XChangeProperty(screen()->display()->nativeDisplay(), req->requestor, req->property, multi_type, 32, + PropModeReplace, (uchar *) multi, nmulti * 2); + } + + delete [] multi; + event.xselection.property = req->property; + } + + // send selection notify to requestor + XSendEvent(screen()->display()->nativeDisplay(), req->requestor, False, NoEventMask, &event); +} + +static inline int maxSelectionIncr(Display *dpy) +{ return XMaxRequestSize(dpy) > 65536 ? 65536*4 : XMaxRequestSize(dpy)*4 - 100; } + +bool QXlibClipboard::clipboardReadProperty(Window win, Atom property, bool deleteProperty, QByteArray *buffer, int *size, Atom *type, int *format) const +{ + int maxsize = maxSelectionIncr(screen()->display()->nativeDisplay()); + ulong bytes_left; // bytes_after + ulong length; // nitems + uchar *data; + Atom dummy_type; + int dummy_format; + int r; + + if (!type) // allow null args + type = &dummy_type; + if (!format) + format = &dummy_format; + + // Don't read anything, just get the size of the property data + r = XGetWindowProperty(screen()->display()->nativeDisplay(), win, property, 0, 0, False, + AnyPropertyType, type, format, + &length, &bytes_left, &data); + if (r != Success || (type && *type == XNone)) { + buffer->resize(0); + return false; + } + XFree((char*)data); + + int offset = 0, buffer_offset = 0, format_inc = 1, proplen = bytes_left; + + switch (*format) { + case 8: + default: + format_inc = sizeof(char) / 1; + break; + + case 16: + format_inc = sizeof(short) / 2; + proplen *= sizeof(short) / 2; + break; + + case 32: + format_inc = sizeof(long) / 4; + proplen *= sizeof(long) / 4; + break; + } + + int newSize = proplen; + buffer->resize(newSize); + + bool ok = (buffer->size() == newSize); + + if (ok && newSize) { + // could allocate buffer + + while (bytes_left) { + // more to read... + + r = XGetWindowProperty(screen()->display()->nativeDisplay(), win, property, offset, maxsize/4, + False, AnyPropertyType, type, format, + &length, &bytes_left, &data); + if (r != Success || (type && *type == XNone)) + break; + + offset += length / (32 / *format); + length *= format_inc * (*format) / 8; + + // Here we check if we get a buffer overflow and tries to + // recover -- this shouldn't normally happen, but it doesn't + // hurt to be defensive + if ((int)(buffer_offset + length) > buffer->size()) { + length = buffer->size() - buffer_offset; + + // escape loop + bytes_left = 0; + } + + memcpy(buffer->data() + buffer_offset, data, length); + buffer_offset += length; + + XFree((char*)data); + } + + if (*format == 8 && *type == QXlibStatic::atom(QXlibStatic::COMPOUND_TEXT)) { + // convert COMPOUND_TEXT to a multibyte string + XTextProperty textprop; + textprop.encoding = *type; + textprop.format = *format; + textprop.nitems = buffer_offset; + textprop.value = (unsigned char *) buffer->data(); + + char **list_ret = 0; + int count; + if (XmbTextPropertyToTextList(screen()->display()->nativeDisplay(), &textprop, &list_ret, + &count) == Success && count && list_ret) { + offset = buffer_offset = strlen(list_ret[0]); + buffer->resize(offset); + memcpy(buffer->data(), list_ret[0], offset); + } + if (list_ret) XFreeStringList(list_ret); + } + } + + // correct size, not 0-term. + if (size) + *size = buffer_offset; + + if (deleteProperty) + XDeleteProperty(screen()->display()->nativeDisplay(), win, property); + + screen()->display()->flush(); + + return ok; +} + +QByteArray QXlibClipboard::clipboardReadIncrementalProperty(Window win, Atom property, int nbytes, bool nullterm) +{ + XEvent event; + + QByteArray buf; + QByteArray tmp_buf; + bool alloc_error = false; + int length; + int offset = 0; + + if (nbytes > 0) { + // Reserve buffer + zero-terminator (for text data) + // We want to complete the INCR transfer even if we cannot + // allocate more memory + buf.resize(nbytes+1); + alloc_error = buf.size() != nbytes+1; + } + + for (;;) { + screen()->display()->flush(); + if (!screen()->waitForClipboardEvent(win,PropertyNotify,&event,clipboard_timeout)) + break; + if (event.xproperty.atom != property || + event.xproperty.state != PropertyNewValue) + continue; + if (clipboardReadProperty(win, property, true, &tmp_buf, &length, 0, 0)) { + if (length == 0) { // no more data, we're done + if (nullterm) { + buf.resize(offset+1); + buf[offset] = '\0'; + } else { + buf.resize(offset); + } + return buf; + } else if (!alloc_error) { + if (offset+length > (int)buf.size()) { + buf.resize(offset+length+65535); + if (buf.size() != offset+length+65535) { + alloc_error = true; + length = buf.size() - offset; + } + } + memcpy(buf.data()+offset, tmp_buf.constData(), length); + tmp_buf.resize(0); + offset += length; + } + } else { + break; + } + } + + // timed out ... create a new requestor window, otherwise the requestor + // could consider next request to be still part of this timed out request + setRequestor(0); + + return QByteArray(); +} + +QByteArray QXlibClipboard::getDataInFormat(Atom modeAtom, Atom fmtatom) +{ + QByteArray buf; + + Window win = requestor(); + + XSelectInput(screen()->display()->nativeDisplay(), win, NoEventMask); // don't listen for any events + + XDeleteProperty(screen()->display()->nativeDisplay(), win, QXlibStatic::atom(QXlibStatic::_QT_SELECTION)); + XConvertSelection(screen()->display()->nativeDisplay(), modeAtom, fmtatom, QXlibStatic::atom(QXlibStatic::_QT_SELECTION), win, CurrentTime); + screen()->display()->sync(); + + XEvent xevent; + if (!screen()->waitForClipboardEvent(win,SelectionNotify,&xevent,clipboard_timeout) || + xevent.xselection.property == XNone) { + return buf; + } + + Atom type; + XSelectInput(screen()->display()->nativeDisplay(), win, PropertyChangeMask); + + if (clipboardReadProperty(win, QXlibStatic::atom(QXlibStatic::_QT_SELECTION), true, &buf, 0, &type, 0)) { + if (type == QXlibStatic::atom(QXlibStatic::INCR)) { + int nbytes = buf.size() >= 4 ? *((int*)buf.data()) : 0; + buf = clipboardReadIncrementalProperty(win, QXlibStatic::atom(QXlibStatic::_QT_SELECTION), nbytes, false); + } + } + + XSelectInput(screen()->display()->nativeDisplay(), win, NoEventMask); + + + return buf; +} + +#include "qxlibclipboard.moc" diff --git a/src/plugins/platforms/xlib/qxlibclipboard.h b/src/plugins/platforms/xlib/qxlibclipboard.h new file mode 100644 index 0000000..15901b0 --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibclipboard.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTLITECLIPBOARD_H +#define QTESTLITECLIPBOARD_H + +#include <QPlatformClipboard> +#include "qxlibstatic.h" + +class QXlibScreen; +class QXlibClipboard : public QPlatformClipboard +{ +public: + QXlibClipboard(QXlibScreen *screen); + + const QMimeData *mimeData(QClipboard::Mode mode) const; + void setMimeData(QMimeData *data, QClipboard::Mode mode); + + bool supportsMode(QClipboard::Mode mode) const; + + QXlibScreen *screen() const; + + Window requestor() const; + void setRequestor(Window window); + + Window owner() const; + + void handleSelectionRequest(XEvent *event); + + bool clipboardReadProperty(Window win, Atom property, bool deleteProperty, QByteArray *buffer, int *size, Atom *type, int *format) const; + QByteArray clipboardReadIncrementalProperty(Window win, Atom property, int nbytes, bool nullterm); + + QByteArray getDataInFormat(Atom modeAtom, Atom fmtatom); + +private: + void setOwner(Window window); + + Atom sendTargetsSelection(QMimeData *d, Window window, Atom property); + Atom sendSelection(QMimeData *d, Atom target, Window window, Atom property); + + QXlibScreen *m_screen; + + QMimeData *m_xClipboard; + QMimeData *m_clientClipboard; + + QMimeData *m_xSelection; + QMimeData *m_clientSelection; + + Window m_requestor; + Window m_owner; + + static const int clipboard_timeout; + +}; + +#endif // QTESTLITECLIPBOARD_H diff --git a/src/plugins/platforms/xlib/qxlibcursor.cpp b/src/plugins/platforms/xlib/qxlibcursor.cpp new file mode 100644 index 0000000..042cbc9 --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibcursor.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxlibcursor.h" + +#include "qxlibintegration.h" +#include "qxlibscreen.h" +#include "qxlibwindow.h" +#include "qxlibdisplay.h" + +#include <QtGui/QBitmap> + +#include <X11/cursorfont.h> + +QT_BEGIN_NAMESPACE + +QXlibCursor::QXlibCursor(QXlibScreen *screen) + : QPlatformCursor(screen) +{ +} + +void QXlibCursor::changeCursor(QCursor *cursor, QWidget *widget) +{ + QXlibWindow *w = 0; + if (widget) { + QWidget *window = widget->window(); + w = static_cast<QXlibWindow*>(window->platformWindow()); + } else { + // No X11 cursor control when there is no widget under the cursor + return; + } + + if (!w) + return; + + int id = cursor->handle(); + + Cursor c; + if (!cursorMap.contains(id)) { + if (cursor->shape() == Qt::BitmapCursor) + c = createCursorBitmap(cursor); + else + c = createCursorShape(cursor->shape()); + if (!c) { + return; + } + cursorMap.insert(id, c); + } else { + c = cursorMap.value(id); + } + + w->setCursor(c); +} + +Cursor QXlibCursor::createCursorBitmap(QCursor * cursor) +{ + XColor bg, fg; + bg.red = 255 << 8; + bg.green = 255 << 8; + bg.blue = 255 << 8; + fg.red = 0; + fg.green = 0; + fg.blue = 0; + QPoint spot = cursor->hotSpot(); + Window rootwin = testLiteScreen()->rootWindow(); + + QImage mapImage = cursor->bitmap()->toImage().convertToFormat(QImage::Format_MonoLSB); + QImage maskImage = cursor->mask()->toImage().convertToFormat(QImage::Format_MonoLSB); + + int width = cursor->bitmap()->width(); + int height = cursor->bitmap()->height(); + int bytesPerLine = mapImage.bytesPerLine(); + int destLineSize = width / 8; + if (width % 8) + destLineSize++; + + const uchar * map = mapImage.bits(); + const uchar * mask = maskImage.bits(); + + char * mapBits = new char[height * destLineSize]; + char * maskBits = new char[height * destLineSize]; + for (int i = 0; i < height; i++) { + memcpy(mapBits + (destLineSize * i),map + (bytesPerLine * i), destLineSize); + memcpy(maskBits + (destLineSize * i),mask + (bytesPerLine * i), destLineSize); + } + + Pixmap cp = XCreateBitmapFromData(testLiteScreen()->display()->nativeDisplay(), rootwin, mapBits, width, height); + Pixmap mp = XCreateBitmapFromData(testLiteScreen()->display()->nativeDisplay(), rootwin, maskBits, width, height); + Cursor c = XCreatePixmapCursor(testLiteScreen()->display()->nativeDisplay(), cp, mp, &fg, &bg, spot.x(), spot.y()); + XFreePixmap(testLiteScreen()->display()->nativeDisplay(), cp); + XFreePixmap(testLiteScreen()->display()->nativeDisplay(), mp); + delete[] mapBits; + delete[] maskBits; + + return c; +} + +Cursor QXlibCursor::createCursorShape(int cshape) +{ + Cursor cursor = 0; + + if (cshape < 0 || cshape > Qt::LastCursor) + return 0; + + switch (cshape) { + case Qt::ArrowCursor: + cursor = XCreateFontCursor(testLiteScreen()->display()->nativeDisplay(), XC_left_ptr); + break; + case Qt::UpArrowCursor: + cursor = XCreateFontCursor(testLiteScreen()->display()->nativeDisplay(), XC_center_ptr); + break; + case Qt::CrossCursor: + cursor = XCreateFontCursor(testLiteScreen()->display()->nativeDisplay(), XC_crosshair); + break; + case Qt::WaitCursor: + cursor = XCreateFontCursor(testLiteScreen()->display()->nativeDisplay(), XC_watch); + break; + case Qt::IBeamCursor: + cursor = XCreateFontCursor(testLiteScreen()->display()->nativeDisplay(), XC_xterm); + break; + case Qt::SizeAllCursor: + cursor = XCreateFontCursor(testLiteScreen()->display()->nativeDisplay(), XC_fleur); + break; + case Qt::PointingHandCursor: + cursor = XCreateFontCursor(testLiteScreen()->display()->nativeDisplay(), XC_hand2); + break; + case Qt::SizeBDiagCursor: + cursor = XCreateFontCursor(testLiteScreen()->display()->nativeDisplay(), XC_top_right_corner); + break; + case Qt::SizeFDiagCursor: + cursor = XCreateFontCursor(testLiteScreen()->display()->nativeDisplay(), XC_bottom_right_corner); + break; + case Qt::SizeVerCursor: + case Qt::SplitVCursor: + cursor = XCreateFontCursor(testLiteScreen()->display()->nativeDisplay(), XC_sb_v_double_arrow); + break; + case Qt::SizeHorCursor: + case Qt::SplitHCursor: + cursor = XCreateFontCursor(testLiteScreen()->display()->nativeDisplay(), XC_sb_h_double_arrow); + break; + case Qt::WhatsThisCursor: + cursor = XCreateFontCursor(testLiteScreen()->display()->nativeDisplay(), XC_question_arrow); + break; + case Qt::ForbiddenCursor: + cursor = XCreateFontCursor(testLiteScreen()->display()->nativeDisplay(), XC_circle); + break; + case Qt::BusyCursor: + cursor = XCreateFontCursor(testLiteScreen()->display()->nativeDisplay(), XC_watch); + break; + + default: //default cursor for all the rest + break; + } + return cursor; +} + +QXlibScreen * QXlibCursor::testLiteScreen() const +{ + return static_cast<QXlibScreen *>(screen); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/xlib/qxlibcursor.h b/src/plugins/platforms/xlib/qxlibcursor.h new file mode 100644 index 0000000..62b13eb --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibcursor.h @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTLITECURSOR_H +#define QTESTLITECURSOR_H + +#include <QtGui/QPlatformCursor> + +#include "qxlibintegration.h" + +QT_BEGIN_NAMESPACE + +class QXlibCursor : QPlatformCursor +{ +public: + QXlibCursor(QXlibScreen *screen); + + void changeCursor(QCursor * cursor, QWidget * widget); +private: + + Cursor createCursorBitmap(QCursor * cursor); + Cursor createCursorShape(int cshape); + + QXlibScreen *testLiteScreen() const; + QMap<int, Cursor> cursorMap; +}; + +QT_END_NAMESPACE + +#endif // QTESTLITECURSOR_H diff --git a/src/plugins/platforms/xlib/qxlibdisplay.cpp b/src/plugins/platforms/xlib/qxlibdisplay.cpp new file mode 100644 index 0000000..d8aa230 --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibdisplay.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxlibdisplay.h" + +QXlibDisplay::QXlibDisplay(Display *display) + : mDisplay(display) +{ + if (!mDisplay) { + qFatal("Cannot connect to X server"); + } + mDisplayName = QString::fromLocal8Bit(DisplayString(mDisplay)); +} + +QXlibDisplay::~QXlibDisplay() +{ + XCloseDisplay(mDisplay); +} + +QString QXlibDisplay::displayName() const +{ + { return mDisplayName; } +} + + + +Display * QXlibDisplay::nativeDisplay() const +{ + return mDisplay; +} + +void QXlibDisplay::sync() const +{ + XSync(mDisplay, False); +} + +void QXlibDisplay::flush() const +{ + XFlush(mDisplay); +} diff --git a/src/plugins/platforms/xlib/qxlibdisplay.h b/src/plugins/platforms/xlib/qxlibdisplay.h new file mode 100644 index 0000000..557ab52 --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibdisplay.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QXLIBDISPLAY_H +#define QXLIBDISPLAY_H + +#include "qxlibintegration.h" + +class QXlibDisplay +{ +public: + QXlibDisplay(Display *display); + ~QXlibDisplay(); + QString displayName() const; + + Display *nativeDisplay() const; + + void sync() const; + void flush() const; +private: + Display *mDisplay; + QString mDisplayName; +}; + +#endif // QXLIBDISPLAY_H diff --git a/src/plugins/platforms/xlib/qxlibintegration.cpp b/src/plugins/platforms/xlib/qxlibintegration.cpp new file mode 100644 index 0000000..6733ed1 --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibintegration.cpp @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxlibintegration.h" +#include "qxlibwindowsurface.h" +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtCore/qdebug.h> + +#include "qxlibwindow.h" +#include "qgenericunixfontdatabase.h" +#include "qxlibscreen.h" +#include "qxlibclipboard.h" +#include "qxlibdisplay.h" + +#if !defined(QT_NO_OPENGL) +#if !defined(QT_OPENGL_ES_2) +#include <GL/glx.h> +#else +#include <EGL/egl.h> +#endif //!defined(QT_OPENGL_ES_2) +#include <private/qwindowsurface_gl_p.h> +#include <private/qpixmapdata_gl_p.h> +#endif //QT_NO_OPENGL + +QT_BEGIN_NAMESPACE + +QXlibIntegration::QXlibIntegration(bool useOpenGL) + : mUseOpenGL(useOpenGL) + , mFontDb(new QGenericUnixFontDatabase()) + , mClipboard(0) +{ + mPrimaryScreen = new QXlibScreen(); + mScreens.append(mPrimaryScreen); +} + +QPixmapData *QXlibIntegration::createPixmapData(QPixmapData::PixelType type) const +{ +#ifndef QT_NO_OPENGL + if (mUseOpenGL) + return new QGLPixmapData(type); +#endif + return new QRasterPixmapData(type); +} + +QWindowSurface *QXlibIntegration::createWindowSurface(QWidget *widget, WId) const +{ +#ifndef QT_NO_OPENGL + if (mUseOpenGL) + return new QGLWindowSurface(widget); +#endif + return new QXlibWindowSurface(widget); +} + + +QPlatformWindow *QXlibIntegration::createPlatformWindow(QWidget *widget, WId /*winId*/) const +{ + return new QXlibWindow(widget); +} + + + +QPixmap QXlibIntegration::grabWindow(WId window, int x, int y, int width, int height) const +{ + QImage image; + QWidget *widget = QWidget::find(window); + if (widget) { + QXlibScreen *screen = QXlibScreen::testLiteScreenForWidget(widget); + image = screen->grabWindow(window,x,y,width,height); + } else { + for (int i = 0; i < mScreens.size(); i++) { + QXlibScreen *screen = static_cast<QXlibScreen *>(mScreens[i]); + if (screen->rootWindow() == window) { + image = screen->grabWindow(window,x,y,width,height); + } + } + } + return QPixmap::fromImage(image); +} + +QPlatformFontDatabase *QXlibIntegration::fontDatabase() const +{ + return mFontDb; +} + +QPlatformClipboard * QXlibIntegration::clipboard() const +{ + //Use lazy init since clipboard needs QTestliteScreen + if (!mClipboard) { + QXlibIntegration *that = const_cast<QXlibIntegration *>(this); + that->mClipboard = new QXlibClipboard(mPrimaryScreen); + } + return mClipboard; +} + +bool QXlibIntegration::hasOpenGL() const +{ +#if !defined(QT_NO_OPENGL) +#if !defined(QT_OPENGL_ES_2) + QXlibScreen *screen = static_cast<const QXlibScreen *>(mScreens.at(0)); + return glXQueryExtension(screen->display()->nativeDisplay(), 0, 0) != 0; +#else + static bool eglHasbeenInitialized = false; + static bool wasEglInitialized = false; + if (!eglHasbeenInitialized) { + eglHasbeenInitialized = true; + const QXlibScreen *screen = static_cast<const QXlibScreen *>(mScreens.at(0)); + EGLint major, minor; + eglBindAPI(EGL_OPENGL_ES_API); + EGLDisplay disp = eglGetDisplay(screen->display()->nativeDisplay()); + wasEglInitialized = eglInitialize(disp,&major,&minor); + } + return wasEglInitialized; +#endif +#endif + return false; +} + + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestliteintegration.h b/src/plugins/platforms/xlib/qxlibintegration.h index 8286ef0..3bbf897 100644 --- a/src/plugins/platforms/testlite/qtestliteintegration.h +++ b/src/plugins/platforms/xlib/qxlibintegration.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -42,39 +42,22 @@ #ifndef QGRAPHICSSYSTEM_TESTLITE_H #define QGRAPHICSSYSTEM_TESTLITE_H -#include <QtGui/QPlatformIntegration> -#include <QtGui/QPlatformScreen> - //make sure textstream is included before any X11 headers #include <QtCore/QTextStream> -QT_BEGIN_NAMESPACE +#include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformScreen> -class MyDisplay; +#include "qxlibstatic.h" -class QTestLiteScreen : public QPlatformScreen -{ -public: - QTestLiteScreen() - : mDepth(16), mFormat(QImage::Format_RGB16) {} - ~QTestLiteScreen() {} - - QRect geometry() const { return mGeometry; } - int depth() const { return mDepth; } - QImage::Format format() const { return mFormat; } - QSize physicalSize() const { return mPhysicalSize; } +QT_BEGIN_NAMESPACE -public: - QRect mGeometry; - int mDepth; - QImage::Format mFormat; - QSize mPhysicalSize; -}; +class QXlibScreen; -class QTestLiteIntegration : public QPlatformIntegration +class QXlibIntegration : public QPlatformIntegration { public: - QTestLiteIntegration(bool useOpenGL = false); + QXlibIntegration(bool useOpenGL = false); QPixmapData *createPixmapData(QPixmapData::PixelType type) const; QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; @@ -85,16 +68,16 @@ public: QList<QPlatformScreen *> screens() const { return mScreens; } QPlatformFontDatabase *fontDatabase() const; + QPlatformClipboard *clipboard() const; bool hasOpenGL() const; - MyDisplay *xd; - private: bool mUseOpenGL; - QTestLiteScreen *mPrimaryScreen; + QXlibScreen *mPrimaryScreen; QList<QPlatformScreen *> mScreens; QPlatformFontDatabase *mFontDb; + QPlatformClipboard *mClipboard; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/xlib/qxlibkeyboard.cpp b/src/plugins/platforms/xlib/qxlibkeyboard.cpp new file mode 100644 index 0000000..8d94157 --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibkeyboard.cpp @@ -0,0 +1,1001 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxlibkeyboard.h" + +#include "qxlibscreen.h" +#include "qxlibdisplay.h" + +#include <QtGui/QWindowSystemInterface> + +#include <QtCore/QTextCodec> + +#ifndef XK_ISO_Left_Tab +#define XK_ISO_Left_Tab 0xFE20 +#endif + +#ifndef XK_dead_hook +#define XK_dead_hook 0xFE61 +#endif + +#ifndef XK_dead_horn +#define XK_dead_horn 0xFE62 +#endif + +#ifndef XK_Codeinput +#define XK_Codeinput 0xFF37 +#endif + +#ifndef XK_Kanji_Bangou +#define XK_Kanji_Bangou 0xFF37 /* same as codeinput */ +#endif + +// Fix old X libraries +#ifndef XK_KP_Home +#define XK_KP_Home 0xFF95 +#endif +#ifndef XK_KP_Left +#define XK_KP_Left 0xFF96 +#endif +#ifndef XK_KP_Up +#define XK_KP_Up 0xFF97 +#endif +#ifndef XK_KP_Right +#define XK_KP_Right 0xFF98 +#endif +#ifndef XK_KP_Down +#define XK_KP_Down 0xFF99 +#endif +#ifndef XK_KP_Prior +#define XK_KP_Prior 0xFF9A +#endif +#ifndef XK_KP_Next +#define XK_KP_Next 0xFF9B +#endif +#ifndef XK_KP_End +#define XK_KP_End 0xFF9C +#endif +#ifndef XK_KP_Insert +#define XK_KP_Insert 0xFF9E +#endif +#ifndef XK_KP_Delete +#define XK_KP_Delete 0xFF9F +#endif + +// the next lines are taken on 10/2009 from X.org (X11/XF86keysym.h), defining some special +// multimedia keys. They are included here as not every system has them. +#define XF86XK_MonBrightnessUp 0x1008FF02 +#define XF86XK_MonBrightnessDown 0x1008FF03 +#define XF86XK_KbdLightOnOff 0x1008FF04 +#define XF86XK_KbdBrightnessUp 0x1008FF05 +#define XF86XK_KbdBrightnessDown 0x1008FF06 +#define XF86XK_Standby 0x1008FF10 +#define XF86XK_AudioLowerVolume 0x1008FF11 +#define XF86XK_AudioMute 0x1008FF12 +#define XF86XK_AudioRaiseVolume 0x1008FF13 +#define XF86XK_AudioPlay 0x1008FF14 +#define XF86XK_AudioStop 0x1008FF15 +#define XF86XK_AudioPrev 0x1008FF16 +#define XF86XK_AudioNext 0x1008FF17 +#define XF86XK_HomePage 0x1008FF18 +#define XF86XK_Mail 0x1008FF19 +#define XF86XK_Start 0x1008FF1A +#define XF86XK_Search 0x1008FF1B +#define XF86XK_AudioRecord 0x1008FF1C +#define XF86XK_Calculator 0x1008FF1D +#define XF86XK_Memo 0x1008FF1E +#define XF86XK_ToDoList 0x1008FF1F +#define XF86XK_Calendar 0x1008FF20 +#define XF86XK_PowerDown 0x1008FF21 +#define XF86XK_ContrastAdjust 0x1008FF22 +#define XF86XK_Back 0x1008FF26 +#define XF86XK_Forward 0x1008FF27 +#define XF86XK_Stop 0x1008FF28 +#define XF86XK_Refresh 0x1008FF29 +#define XF86XK_PowerOff 0x1008FF2A +#define XF86XK_WakeUp 0x1008FF2B +#define XF86XK_Eject 0x1008FF2C +#define XF86XK_ScreenSaver 0x1008FF2D +#define XF86XK_WWW 0x1008FF2E +#define XF86XK_Sleep 0x1008FF2F +#define XF86XK_Favorites 0x1008FF30 +#define XF86XK_AudioPause 0x1008FF31 +#define XF86XK_AudioMedia 0x1008FF32 +#define XF86XK_MyComputer 0x1008FF33 +#define XF86XK_LightBulb 0x1008FF35 +#define XF86XK_Shop 0x1008FF36 +#define XF86XK_History 0x1008FF37 +#define XF86XK_OpenURL 0x1008FF38 +#define XF86XK_AddFavorite 0x1008FF39 +#define XF86XK_HotLinks 0x1008FF3A +#define XF86XK_BrightnessAdjust 0x1008FF3B +#define XF86XK_Finance 0x1008FF3C +#define XF86XK_Community 0x1008FF3D +#define XF86XK_AudioRewind 0x1008FF3E +#define XF86XK_BackForward 0x1008FF3F +#define XF86XK_Launch0 0x1008FF40 +#define XF86XK_Launch1 0x1008FF41 +#define XF86XK_Launch2 0x1008FF42 +#define XF86XK_Launch3 0x1008FF43 +#define XF86XK_Launch4 0x1008FF44 +#define XF86XK_Launch5 0x1008FF45 +#define XF86XK_Launch6 0x1008FF46 +#define XF86XK_Launch7 0x1008FF47 +#define XF86XK_Launch8 0x1008FF48 +#define XF86XK_Launch9 0x1008FF49 +#define XF86XK_LaunchA 0x1008FF4A +#define XF86XK_LaunchB 0x1008FF4B +#define XF86XK_LaunchC 0x1008FF4C +#define XF86XK_LaunchD 0x1008FF4D +#define XF86XK_LaunchE 0x1008FF4E +#define XF86XK_LaunchF 0x1008FF4F +#define XF86XK_ApplicationLeft 0x1008FF50 +#define XF86XK_ApplicationRight 0x1008FF51 +#define XF86XK_Book 0x1008FF52 +#define XF86XK_CD 0x1008FF53 +#define XF86XK_Calculater 0x1008FF54 +#define XF86XK_Clear 0x1008FF55 +#define XF86XK_ClearGrab 0x1008FE21 +#define XF86XK_Close 0x1008FF56 +#define XF86XK_Copy 0x1008FF57 +#define XF86XK_Cut 0x1008FF58 +#define XF86XK_Display 0x1008FF59 +#define XF86XK_DOS 0x1008FF5A +#define XF86XK_Documents 0x1008FF5B +#define XF86XK_Excel 0x1008FF5C +#define XF86XK_Explorer 0x1008FF5D +#define XF86XK_Game 0x1008FF5E +#define XF86XK_Go 0x1008FF5F +#define XF86XK_iTouch 0x1008FF60 +#define XF86XK_LogOff 0x1008FF61 +#define XF86XK_Market 0x1008FF62 +#define XF86XK_Meeting 0x1008FF63 +#define XF86XK_MenuKB 0x1008FF65 +#define XF86XK_MenuPB 0x1008FF66 +#define XF86XK_MySites 0x1008FF67 +#define XF86XK_News 0x1008FF69 +#define XF86XK_OfficeHome 0x1008FF6A +#define XF86XK_Option 0x1008FF6C +#define XF86XK_Paste 0x1008FF6D +#define XF86XK_Phone 0x1008FF6E +#define XF86XK_Reply 0x1008FF72 +#define XF86XK_Reload 0x1008FF73 +#define XF86XK_RotateWindows 0x1008FF74 +#define XF86XK_RotationPB 0x1008FF75 +#define XF86XK_RotationKB 0x1008FF76 +#define XF86XK_Save 0x1008FF77 +#define XF86XK_Send 0x1008FF7B +#define XF86XK_Spell 0x1008FF7C +#define XF86XK_SplitScreen 0x1008FF7D +#define XF86XK_Support 0x1008FF7E +#define XF86XK_TaskPane 0x1008FF7F +#define XF86XK_Terminal 0x1008FF80 +#define XF86XK_Tools 0x1008FF81 +#define XF86XK_Travel 0x1008FF82 +#define XF86XK_Video 0x1008FF87 +#define XF86XK_Word 0x1008FF89 +#define XF86XK_Xfer 0x1008FF8A +#define XF86XK_ZoomIn 0x1008FF8B +#define XF86XK_ZoomOut 0x1008FF8C +#define XF86XK_Away 0x1008FF8D +#define XF86XK_Messenger 0x1008FF8E +#define XF86XK_WebCam 0x1008FF8F +#define XF86XK_MailForward 0x1008FF90 +#define XF86XK_Pictures 0x1008FF91 +#define XF86XK_Music 0x1008FF92 +#define XF86XK_Battery 0x1008FF93 +#define XF86XK_Bluetooth 0x1008FF94 +#define XF86XK_WLAN 0x1008FF95 +#define XF86XK_UWB 0x1008FF96 +#define XF86XK_AudioForward 0x1008FF97 +#define XF86XK_AudioRepeat 0x1008FF98 +#define XF86XK_AudioRandomPlay 0x1008FF99 +#define XF86XK_Subtitle 0x1008FF9A +#define XF86XK_AudioCycleTrack 0x1008FF9B +#define XF86XK_Time 0x1008FF9F +#define XF86XK_Select 0x1008FFA0 +#define XF86XK_View 0x1008FFA1 +#define XF86XK_TopMenu 0x1008FFA2 +#define XF86XK_Suspend 0x1008FFA7 +#define XF86XK_Hibernate 0x1008FFA8 + + +// end of XF86keysyms.h + +// Special keys used by Qtopia, mapped into the X11 private keypad range. +#define QTOPIAXK_Select 0x11000601 +#define QTOPIAXK_Yes 0x11000602 +#define QTOPIAXK_No 0x11000603 +#define QTOPIAXK_Cancel 0x11000604 +#define QTOPIAXK_Printer 0x11000605 +#define QTOPIAXK_Execute 0x11000606 +#define QTOPIAXK_Sleep 0x11000607 +#define QTOPIAXK_Play 0x11000608 +#define QTOPIAXK_Zoom 0x11000609 +#define QTOPIAXK_Context1 0x1100060A +#define QTOPIAXK_Context2 0x1100060B +#define QTOPIAXK_Context3 0x1100060C +#define QTOPIAXK_Context4 0x1100060D +#define QTOPIAXK_Call 0x1100060E +#define QTOPIAXK_Hangup 0x1100060F +#define QTOPIAXK_Flip 0x11000610 + +// keyboard mapping table +static const unsigned int KeyTbl[] = { + + // misc keys + + XK_Escape, Qt::Key_Escape, + XK_Tab, Qt::Key_Tab, + XK_ISO_Left_Tab, Qt::Key_Backtab, + XK_BackSpace, Qt::Key_Backspace, + XK_Return, Qt::Key_Return, + XK_Insert, Qt::Key_Insert, + XK_Delete, Qt::Key_Delete, + XK_Clear, Qt::Key_Delete, + XK_Pause, Qt::Key_Pause, + XK_Print, Qt::Key_Print, + 0x1005FF60, Qt::Key_SysReq, // hardcoded Sun SysReq + 0x1007ff00, Qt::Key_SysReq, // hardcoded X386 SysReq + + // cursor movement + + XK_Home, Qt::Key_Home, + XK_End, Qt::Key_End, + XK_Left, Qt::Key_Left, + XK_Up, Qt::Key_Up, + XK_Right, Qt::Key_Right, + XK_Down, Qt::Key_Down, + XK_Prior, Qt::Key_PageUp, + XK_Next, Qt::Key_PageDown, + + // modifiers + + XK_Shift_L, Qt::Key_Shift, + XK_Shift_R, Qt::Key_Shift, + XK_Shift_Lock, Qt::Key_Shift, + XK_Control_L, Qt::Key_Control, + XK_Control_R, Qt::Key_Control, + XK_Meta_L, Qt::Key_Meta, + XK_Meta_R, Qt::Key_Meta, + XK_Alt_L, Qt::Key_Alt, + XK_Alt_R, Qt::Key_Alt, + XK_Caps_Lock, Qt::Key_CapsLock, + XK_Num_Lock, Qt::Key_NumLock, + XK_Scroll_Lock, Qt::Key_ScrollLock, + XK_Super_L, Qt::Key_Super_L, + XK_Super_R, Qt::Key_Super_R, + XK_Menu, Qt::Key_Menu, + XK_Hyper_L, Qt::Key_Hyper_L, + XK_Hyper_R, Qt::Key_Hyper_R, + XK_Help, Qt::Key_Help, + 0x1000FF74, Qt::Key_Backtab, // hardcoded HP backtab + 0x1005FF10, Qt::Key_F11, // hardcoded Sun F36 (labeled F11) + 0x1005FF11, Qt::Key_F12, // hardcoded Sun F37 (labeled F12) + + // numeric and function keypad keys + + XK_KP_Space, Qt::Key_Space, + XK_KP_Tab, Qt::Key_Tab, + XK_KP_Enter, Qt::Key_Enter, + //XK_KP_F1, Qt::Key_F1, + //XK_KP_F2, Qt::Key_F2, + //XK_KP_F3, Qt::Key_F3, + //XK_KP_F4, Qt::Key_F4, + XK_KP_Home, Qt::Key_Home, + XK_KP_Left, Qt::Key_Left, + XK_KP_Up, Qt::Key_Up, + XK_KP_Right, Qt::Key_Right, + XK_KP_Down, Qt::Key_Down, + XK_KP_Prior, Qt::Key_PageUp, + XK_KP_Next, Qt::Key_PageDown, + XK_KP_End, Qt::Key_End, + XK_KP_Begin, Qt::Key_Clear, + XK_KP_Insert, Qt::Key_Insert, + XK_KP_Delete, Qt::Key_Delete, + XK_KP_Equal, Qt::Key_Equal, + XK_KP_Multiply, Qt::Key_Asterisk, + XK_KP_Add, Qt::Key_Plus, + XK_KP_Separator, Qt::Key_Comma, + XK_KP_Subtract, Qt::Key_Minus, + XK_KP_Decimal, Qt::Key_Period, + XK_KP_Divide, Qt::Key_Slash, + + // International input method support keys + + // International & multi-key character composition + XK_ISO_Level3_Shift, Qt::Key_AltGr, + XK_Multi_key, Qt::Key_Multi_key, + XK_Codeinput, Qt::Key_Codeinput, + XK_SingleCandidate, Qt::Key_SingleCandidate, + XK_MultipleCandidate, Qt::Key_MultipleCandidate, + XK_PreviousCandidate, Qt::Key_PreviousCandidate, + + // Misc Functions + XK_Mode_switch, Qt::Key_Mode_switch, + XK_script_switch, Qt::Key_Mode_switch, + + // Japanese keyboard support + XK_Kanji, Qt::Key_Kanji, + XK_Muhenkan, Qt::Key_Muhenkan, + //XK_Henkan_Mode, Qt::Key_Henkan_Mode, + XK_Henkan_Mode, Qt::Key_Henkan, + XK_Henkan, Qt::Key_Henkan, + XK_Romaji, Qt::Key_Romaji, + XK_Hiragana, Qt::Key_Hiragana, + XK_Katakana, Qt::Key_Katakana, + XK_Hiragana_Katakana, Qt::Key_Hiragana_Katakana, + XK_Zenkaku, Qt::Key_Zenkaku, + XK_Hankaku, Qt::Key_Hankaku, + XK_Zenkaku_Hankaku, Qt::Key_Zenkaku_Hankaku, + XK_Touroku, Qt::Key_Touroku, + XK_Massyo, Qt::Key_Massyo, + XK_Kana_Lock, Qt::Key_Kana_Lock, + XK_Kana_Shift, Qt::Key_Kana_Shift, + XK_Eisu_Shift, Qt::Key_Eisu_Shift, + XK_Eisu_toggle, Qt::Key_Eisu_toggle, + //XK_Kanji_Bangou, Qt::Key_Kanji_Bangou, + //XK_Zen_Koho, Qt::Key_Zen_Koho, + //XK_Mae_Koho, Qt::Key_Mae_Koho, + XK_Kanji_Bangou, Qt::Key_Codeinput, + XK_Zen_Koho, Qt::Key_MultipleCandidate, + XK_Mae_Koho, Qt::Key_PreviousCandidate, + +#ifdef XK_KOREAN + // Korean keyboard support + XK_Hangul, Qt::Key_Hangul, + XK_Hangul_Start, Qt::Key_Hangul_Start, + XK_Hangul_End, Qt::Key_Hangul_End, + XK_Hangul_Hanja, Qt::Key_Hangul_Hanja, + XK_Hangul_Jamo, Qt::Key_Hangul_Jamo, + XK_Hangul_Romaja, Qt::Key_Hangul_Romaja, + //XK_Hangul_Codeinput, Qt::Key_Hangul_Codeinput, + XK_Hangul_Codeinput, Qt::Key_Codeinput, + XK_Hangul_Jeonja, Qt::Key_Hangul_Jeonja, + XK_Hangul_Banja, Qt::Key_Hangul_Banja, + XK_Hangul_PreHanja, Qt::Key_Hangul_PreHanja, + XK_Hangul_PostHanja, Qt::Key_Hangul_PostHanja, + //XK_Hangul_SingleCandidate,Qt::Key_Hangul_SingleCandidate, + //XK_Hangul_MultipleCandidate,Qt::Key_Hangul_MultipleCandidate, + //XK_Hangul_PreviousCandidate,Qt::Key_Hangul_PreviousCandidate, + XK_Hangul_SingleCandidate, Qt::Key_SingleCandidate, + XK_Hangul_MultipleCandidate,Qt::Key_MultipleCandidate, + XK_Hangul_PreviousCandidate,Qt::Key_PreviousCandidate, + XK_Hangul_Special, Qt::Key_Hangul_Special, + //XK_Hangul_switch, Qt::Key_Hangul_switch, + XK_Hangul_switch, Qt::Key_Mode_switch, +#endif // XK_KOREAN + + // dead keys + XK_dead_grave, Qt::Key_Dead_Grave, + XK_dead_acute, Qt::Key_Dead_Acute, + XK_dead_circumflex, Qt::Key_Dead_Circumflex, + XK_dead_tilde, Qt::Key_Dead_Tilde, + XK_dead_macron, Qt::Key_Dead_Macron, + XK_dead_breve, Qt::Key_Dead_Breve, + XK_dead_abovedot, Qt::Key_Dead_Abovedot, + XK_dead_diaeresis, Qt::Key_Dead_Diaeresis, + XK_dead_abovering, Qt::Key_Dead_Abovering, + XK_dead_doubleacute, Qt::Key_Dead_Doubleacute, + XK_dead_caron, Qt::Key_Dead_Caron, + XK_dead_cedilla, Qt::Key_Dead_Cedilla, + XK_dead_ogonek, Qt::Key_Dead_Ogonek, + XK_dead_iota, Qt::Key_Dead_Iota, + XK_dead_voiced_sound, Qt::Key_Dead_Voiced_Sound, + XK_dead_semivoiced_sound, Qt::Key_Dead_Semivoiced_Sound, + XK_dead_belowdot, Qt::Key_Dead_Belowdot, + XK_dead_hook, Qt::Key_Dead_Hook, + XK_dead_horn, Qt::Key_Dead_Horn, + + // Special keys from X.org - This include multimedia keys, + // wireless/bluetooth/uwb keys, special launcher keys, etc. + XF86XK_Back, Qt::Key_Back, + XF86XK_Forward, Qt::Key_Forward, + XF86XK_Stop, Qt::Key_Stop, + XF86XK_Refresh, Qt::Key_Refresh, + XF86XK_Favorites, Qt::Key_Favorites, + XF86XK_AudioMedia, Qt::Key_LaunchMedia, + XF86XK_OpenURL, Qt::Key_OpenUrl, + XF86XK_HomePage, Qt::Key_HomePage, + XF86XK_Search, Qt::Key_Search, + XF86XK_AudioLowerVolume, Qt::Key_VolumeDown, + XF86XK_AudioMute, Qt::Key_VolumeMute, + XF86XK_AudioRaiseVolume, Qt::Key_VolumeUp, + XF86XK_AudioPlay, Qt::Key_MediaPlay, + XF86XK_AudioStop, Qt::Key_MediaStop, + XF86XK_AudioPrev, Qt::Key_MediaPrevious, + XF86XK_AudioNext, Qt::Key_MediaNext, + XF86XK_AudioRecord, Qt::Key_MediaRecord, + XF86XK_Mail, Qt::Key_LaunchMail, + XF86XK_MyComputer, Qt::Key_Launch0, // ### Qt 5: remap properly + XF86XK_Calculator, Qt::Key_Launch1, + XF86XK_Memo, Qt::Key_Memo, + XF86XK_ToDoList, Qt::Key_ToDoList, + XF86XK_Calendar, Qt::Key_Calendar, + XF86XK_PowerDown, Qt::Key_PowerDown, + XF86XK_ContrastAdjust, Qt::Key_ContrastAdjust, + XF86XK_Standby, Qt::Key_Standby, + XF86XK_MonBrightnessUp, Qt::Key_MonBrightnessUp, + XF86XK_MonBrightnessDown, Qt::Key_MonBrightnessDown, + XF86XK_KbdLightOnOff, Qt::Key_KeyboardLightOnOff, + XF86XK_KbdBrightnessUp, Qt::Key_KeyboardBrightnessUp, + XF86XK_KbdBrightnessDown, Qt::Key_KeyboardBrightnessDown, + XF86XK_PowerOff, Qt::Key_PowerOff, + XF86XK_WakeUp, Qt::Key_WakeUp, + XF86XK_Eject, Qt::Key_Eject, + XF86XK_ScreenSaver, Qt::Key_ScreenSaver, + XF86XK_WWW, Qt::Key_WWW, + XF86XK_Sleep, Qt::Key_Sleep, + XF86XK_LightBulb, Qt::Key_LightBulb, + XF86XK_Shop, Qt::Key_Shop, + XF86XK_History, Qt::Key_History, + XF86XK_AddFavorite, Qt::Key_AddFavorite, + XF86XK_HotLinks, Qt::Key_HotLinks, + XF86XK_BrightnessAdjust, Qt::Key_BrightnessAdjust, + XF86XK_Finance, Qt::Key_Finance, + XF86XK_Community, Qt::Key_Community, + XF86XK_AudioRewind, Qt::Key_AudioRewind, + XF86XK_BackForward, Qt::Key_BackForward, + XF86XK_ApplicationLeft, Qt::Key_ApplicationLeft, + XF86XK_ApplicationRight, Qt::Key_ApplicationRight, + XF86XK_Book, Qt::Key_Book, + XF86XK_CD, Qt::Key_CD, + XF86XK_Calculater, Qt::Key_Calculator, + XF86XK_Clear, Qt::Key_Clear, + XF86XK_ClearGrab, Qt::Key_ClearGrab, + XF86XK_Close, Qt::Key_Close, + XF86XK_Copy, Qt::Key_Copy, + XF86XK_Cut, Qt::Key_Cut, + XF86XK_Display, Qt::Key_Display, + XF86XK_DOS, Qt::Key_DOS, + XF86XK_Documents, Qt::Key_Documents, + XF86XK_Excel, Qt::Key_Excel, + XF86XK_Explorer, Qt::Key_Explorer, + XF86XK_Game, Qt::Key_Game, + XF86XK_Go, Qt::Key_Go, + XF86XK_iTouch, Qt::Key_iTouch, + XF86XK_LogOff, Qt::Key_LogOff, + XF86XK_Market, Qt::Key_Market, + XF86XK_Meeting, Qt::Key_Meeting, + XF86XK_MenuKB, Qt::Key_MenuKB, + XF86XK_MenuPB, Qt::Key_MenuPB, + XF86XK_MySites, Qt::Key_MySites, + XF86XK_News, Qt::Key_News, + XF86XK_OfficeHome, Qt::Key_OfficeHome, + XF86XK_Option, Qt::Key_Option, + XF86XK_Paste, Qt::Key_Paste, + XF86XK_Phone, Qt::Key_Phone, + XF86XK_Reply, Qt::Key_Reply, + XF86XK_Reload, Qt::Key_Reload, + XF86XK_RotateWindows, Qt::Key_RotateWindows, + XF86XK_RotationPB, Qt::Key_RotationPB, + XF86XK_RotationKB, Qt::Key_RotationKB, + XF86XK_Save, Qt::Key_Save, + XF86XK_Send, Qt::Key_Send, + XF86XK_Spell, Qt::Key_Spell, + XF86XK_SplitScreen, Qt::Key_SplitScreen, + XF86XK_Support, Qt::Key_Support, + XF86XK_TaskPane, Qt::Key_TaskPane, + XF86XK_Terminal, Qt::Key_Terminal, + XF86XK_Tools, Qt::Key_Tools, + XF86XK_Travel, Qt::Key_Travel, + XF86XK_Video, Qt::Key_Video, + XF86XK_Word, Qt::Key_Word, + XF86XK_Xfer, Qt::Key_Xfer, + XF86XK_ZoomIn, Qt::Key_ZoomIn, + XF86XK_ZoomOut, Qt::Key_ZoomOut, + XF86XK_Away, Qt::Key_Away, + XF86XK_Messenger, Qt::Key_Messenger, + XF86XK_WebCam, Qt::Key_WebCam, + XF86XK_MailForward, Qt::Key_MailForward, + XF86XK_Pictures, Qt::Key_Pictures, + XF86XK_Music, Qt::Key_Music, + XF86XK_Battery, Qt::Key_Battery, + XF86XK_Bluetooth, Qt::Key_Bluetooth, + XF86XK_WLAN, Qt::Key_WLAN, + XF86XK_UWB, Qt::Key_UWB, + XF86XK_AudioForward, Qt::Key_AudioForward, + XF86XK_AudioRepeat, Qt::Key_AudioRepeat, + XF86XK_AudioRandomPlay, Qt::Key_AudioRandomPlay, + XF86XK_Subtitle, Qt::Key_Subtitle, + XF86XK_AudioCycleTrack, Qt::Key_AudioCycleTrack, + XF86XK_Time, Qt::Key_Time, + XF86XK_Select, Qt::Key_Select, + XF86XK_View, Qt::Key_View, + XF86XK_TopMenu, Qt::Key_TopMenu, + XF86XK_Bluetooth, Qt::Key_Bluetooth, + XF86XK_Suspend, Qt::Key_Suspend, + XF86XK_Hibernate, Qt::Key_Hibernate, + XF86XK_Launch0, Qt::Key_Launch2, // ### Qt 5: remap properly + XF86XK_Launch1, Qt::Key_Launch3, + XF86XK_Launch2, Qt::Key_Launch4, + XF86XK_Launch3, Qt::Key_Launch5, + XF86XK_Launch4, Qt::Key_Launch6, + XF86XK_Launch5, Qt::Key_Launch7, + XF86XK_Launch6, Qt::Key_Launch8, + XF86XK_Launch7, Qt::Key_Launch9, + XF86XK_Launch8, Qt::Key_LaunchA, + XF86XK_Launch9, Qt::Key_LaunchB, + XF86XK_LaunchA, Qt::Key_LaunchC, + XF86XK_LaunchB, Qt::Key_LaunchD, + XF86XK_LaunchC, Qt::Key_LaunchE, + XF86XK_LaunchD, Qt::Key_LaunchF, + XF86XK_LaunchE, Qt::Key_LaunchG, + XF86XK_LaunchF, Qt::Key_LaunchH, + + // Qtopia keys + QTOPIAXK_Select, Qt::Key_Select, + QTOPIAXK_Yes, Qt::Key_Yes, + QTOPIAXK_No, Qt::Key_No, + QTOPIAXK_Cancel, Qt::Key_Cancel, + QTOPIAXK_Printer, Qt::Key_Printer, + QTOPIAXK_Execute, Qt::Key_Execute, + QTOPIAXK_Sleep, Qt::Key_Sleep, + QTOPIAXK_Play, Qt::Key_Play, + QTOPIAXK_Zoom, Qt::Key_Zoom, + QTOPIAXK_Context1, Qt::Key_Context1, + QTOPIAXK_Context2, Qt::Key_Context2, + QTOPIAXK_Context3, Qt::Key_Context3, + QTOPIAXK_Context4, Qt::Key_Context4, + QTOPIAXK_Call, Qt::Key_Call, + QTOPIAXK_Hangup, Qt::Key_Hangup, + QTOPIAXK_Flip, Qt::Key_Flip, + + 0, 0 +}; + +static const unsigned short katakanaKeysymsToUnicode[] = { + 0x0000, 0x3002, 0x300C, 0x300D, 0x3001, 0x30FB, 0x30F2, 0x30A1, + 0x30A3, 0x30A5, 0x30A7, 0x30A9, 0x30E3, 0x30E5, 0x30E7, 0x30C3, + 0x30FC, 0x30A2, 0x30A4, 0x30A6, 0x30A8, 0x30AA, 0x30AB, 0x30AD, + 0x30AF, 0x30B1, 0x30B3, 0x30B5, 0x30B7, 0x30B9, 0x30BB, 0x30BD, + 0x30BF, 0x30C1, 0x30C4, 0x30C6, 0x30C8, 0x30CA, 0x30CB, 0x30CC, + 0x30CD, 0x30CE, 0x30CF, 0x30D2, 0x30D5, 0x30D8, 0x30DB, 0x30DE, + 0x30DF, 0x30E0, 0x30E1, 0x30E2, 0x30E4, 0x30E6, 0x30E8, 0x30E9, + 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EF, 0x30F3, 0x309B, 0x309C +}; + +static const unsigned short cyrillicKeysymsToUnicode[] = { + 0x0000, 0x0452, 0x0453, 0x0451, 0x0454, 0x0455, 0x0456, 0x0457, + 0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x0000, 0x045e, 0x045f, + 0x2116, 0x0402, 0x0403, 0x0401, 0x0404, 0x0405, 0x0406, 0x0407, + 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x0000, 0x040e, 0x040f, + 0x044e, 0x0430, 0x0431, 0x0446, 0x0434, 0x0435, 0x0444, 0x0433, + 0x0445, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e, + 0x043f, 0x044f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0436, 0x0432, + 0x044c, 0x044b, 0x0437, 0x0448, 0x044d, 0x0449, 0x0447, 0x044a, + 0x042e, 0x0410, 0x0411, 0x0426, 0x0414, 0x0415, 0x0424, 0x0413, + 0x0425, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e, + 0x041f, 0x042f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0416, 0x0412, + 0x042c, 0x042b, 0x0417, 0x0428, 0x042d, 0x0429, 0x0427, 0x042a +}; + +static const unsigned short greekKeysymsToUnicode[] = { + 0x0000, 0x0386, 0x0388, 0x0389, 0x038a, 0x03aa, 0x0000, 0x038c, + 0x038e, 0x03ab, 0x0000, 0x038f, 0x0000, 0x0000, 0x0385, 0x2015, + 0x0000, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03ca, 0x0390, 0x03cc, + 0x03cd, 0x03cb, 0x03b0, 0x03ce, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, + 0x0398, 0x0399, 0x039a, 0x039b, 0x039c, 0x039d, 0x039e, 0x039f, + 0x03a0, 0x03a1, 0x03a3, 0x0000, 0x03a4, 0x03a5, 0x03a6, 0x03a7, + 0x03a8, 0x03a9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x03b1, 0x03b2, 0x03b3, 0x03b4, 0x03b5, 0x03b6, 0x03b7, + 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, + 0x03c0, 0x03c1, 0x03c3, 0x03c2, 0x03c4, 0x03c5, 0x03c6, 0x03c7, + 0x03c8, 0x03c9, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static const unsigned short technicalKeysymsToUnicode[] = { + 0x0000, 0x23B7, 0x250C, 0x2500, 0x2320, 0x2321, 0x2502, 0x23A1, + 0x23A3, 0x23A4, 0x23A6, 0x239B, 0x239D, 0x239E, 0x23A0, 0x23A8, + 0x23AC, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x2264, 0x2260, 0x2265, 0x222B, + 0x2234, 0x221D, 0x221E, 0x0000, 0x0000, 0x2207, 0x0000, 0x0000, + 0x223C, 0x2243, 0x0000, 0x0000, 0x0000, 0x21D4, 0x21D2, 0x2261, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x221A, 0x0000, + 0x0000, 0x0000, 0x2282, 0x2283, 0x2229, 0x222A, 0x2227, 0x2228, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x2202, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0192, 0x0000, + 0x0000, 0x0000, 0x0000, 0x2190, 0x2191, 0x2192, 0x2193, 0x0000 +}; + +static const unsigned short specialKeysymsToUnicode[] = { + 0x25C6, 0x2592, 0x2409, 0x240C, 0x240D, 0x240A, 0x0000, 0x0000, + 0x2424, 0x240B, 0x2518, 0x2510, 0x250C, 0x2514, 0x253C, 0x23BA, + 0x23BB, 0x2500, 0x23BC, 0x23BD, 0x251C, 0x2524, 0x2534, 0x252C, + 0x2502, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 +}; + +static const unsigned short publishingKeysymsToUnicode[] = { + 0x0000, 0x2003, 0x2002, 0x2004, 0x2005, 0x2007, 0x2008, 0x2009, + 0x200a, 0x2014, 0x2013, 0x0000, 0x0000, 0x0000, 0x2026, 0x2025, + 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, 0x215a, + 0x2105, 0x0000, 0x0000, 0x2012, 0x2329, 0x0000, 0x232a, 0x0000, + 0x0000, 0x0000, 0x0000, 0x215b, 0x215c, 0x215d, 0x215e, 0x0000, + 0x0000, 0x2122, 0x2613, 0x0000, 0x25c1, 0x25b7, 0x25cb, 0x25af, + 0x2018, 0x2019, 0x201c, 0x201d, 0x211e, 0x0000, 0x2032, 0x2033, + 0x0000, 0x271d, 0x0000, 0x25ac, 0x25c0, 0x25b6, 0x25cf, 0x25ae, + 0x25e6, 0x25ab, 0x25ad, 0x25b3, 0x25bd, 0x2606, 0x2022, 0x25aa, + 0x25b2, 0x25bc, 0x261c, 0x261e, 0x2663, 0x2666, 0x2665, 0x0000, + 0x2720, 0x2020, 0x2021, 0x2713, 0x2717, 0x266f, 0x266d, 0x2642, + 0x2640, 0x260e, 0x2315, 0x2117, 0x2038, 0x201a, 0x201e, 0x0000 +}; + +static const unsigned short aplKeysymsToUnicode[] = { + 0x0000, 0x0000, 0x0000, 0x003c, 0x0000, 0x0000, 0x003e, 0x0000, + 0x2228, 0x2227, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x00af, 0x0000, 0x22a5, 0x2229, 0x230a, 0x0000, 0x005f, 0x0000, + 0x0000, 0x0000, 0x2218, 0x0000, 0x2395, 0x0000, 0x22a4, 0x25cb, + 0x0000, 0x0000, 0x0000, 0x2308, 0x0000, 0x0000, 0x222a, 0x0000, + 0x2283, 0x0000, 0x2282, 0x0000, 0x22a2, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, + 0x0000, 0x0000, 0x0000, 0x0000, 0x22a3, 0x0000, 0x0000, 0x0000 +}; + +static const unsigned short koreanKeysymsToUnicode[] = { + 0x0000, 0x3131, 0x3132, 0x3133, 0x3134, 0x3135, 0x3136, 0x3137, + 0x3138, 0x3139, 0x313a, 0x313b, 0x313c, 0x313d, 0x313e, 0x313f, + 0x3140, 0x3141, 0x3142, 0x3143, 0x3144, 0x3145, 0x3146, 0x3147, + 0x3148, 0x3149, 0x314a, 0x314b, 0x314c, 0x314d, 0x314e, 0x314f, + 0x3150, 0x3151, 0x3152, 0x3153, 0x3154, 0x3155, 0x3156, 0x3157, + 0x3158, 0x3159, 0x315a, 0x315b, 0x315c, 0x315d, 0x315e, 0x315f, + 0x3160, 0x3161, 0x3162, 0x3163, 0x11a8, 0x11a9, 0x11aa, 0x11ab, + 0x11ac, 0x11ad, 0x11ae, 0x11af, 0x11b0, 0x11b1, 0x11b2, 0x11b3, + 0x11b4, 0x11b5, 0x11b6, 0x11b7, 0x11b8, 0x11b9, 0x11ba, 0x11bb, + 0x11bc, 0x11bd, 0x11be, 0x11bf, 0x11c0, 0x11c1, 0x11c2, 0x316d, + 0x3171, 0x3178, 0x317f, 0x3181, 0x3184, 0x3186, 0x318d, 0x318e, + 0x11eb, 0x11f0, 0x11f9, 0x0000, 0x0000, 0x0000, 0x0000, 0x20a9 +}; + +static QChar keysymToUnicode(unsigned char byte3, unsigned char byte4) +{ + switch (byte3) { + case 0x04: + // katakana + if (byte4 > 0xa0 && byte4 < 0xe0) + return QChar(katakanaKeysymsToUnicode[byte4 - 0xa0]); + else if (byte4 == 0x7e) + return QChar(0x203e); // Overline + break; + case 0x06: + // russian, use lookup table + if (byte4 > 0xa0) + return QChar(cyrillicKeysymsToUnicode[byte4 - 0xa0]); + break; + case 0x07: + // greek + if (byte4 > 0xa0) + return QChar(greekKeysymsToUnicode[byte4 - 0xa0]); + break; + case 0x08: + // technical + if (byte4 > 0xa0) + return QChar(technicalKeysymsToUnicode[byte4 - 0xa0]); + break; + case 0x09: + // special + if (byte4 >= 0xe0) + return QChar(specialKeysymsToUnicode[byte4 - 0xe0]); + break; + case 0x0a: + // publishing + if (byte4 > 0xa0) + return QChar(publishingKeysymsToUnicode[byte4 - 0xa0]); + break; + case 0x0b: + // APL + if (byte4 > 0xa0) + return QChar(aplKeysymsToUnicode[byte4 - 0xa0]); + break; + case 0x0e: + // Korean + if (byte4 > 0xa0) + return QChar(koreanKeysymsToUnicode[byte4 - 0xa0]); + break; + default: + break; + } + return QChar(0x0); +} + +Qt::KeyboardModifiers QXlibKeyboard::translateModifiers(int s) +{ + Qt::KeyboardModifiers ret = 0; + if (s & ShiftMask) + ret |= Qt::ShiftModifier; + if (s & ControlMask) + ret |= Qt::ControlModifier; + if (s & m_alt_mask) + ret |= Qt::AltModifier; + if (s & m_meta_mask) + ret |= Qt::MetaModifier; +// if (s & m_mode_switch_mask) //doesn't seem to work correctly +// ret |= Qt::GroupSwitchModifier; + return ret; +} + +void QXlibKeyboard::setMask(KeySym sym, uint mask) +{ + if (m_alt_mask == 0 + && m_meta_mask != mask + && m_super_mask != mask + && m_hyper_mask != mask + && (sym == XK_Alt_L || sym == XK_Alt_R)) { + m_alt_mask = mask; + } + if (m_meta_mask == 0 + && m_alt_mask != mask + && m_super_mask != mask + && m_hyper_mask != mask + && (sym == XK_Meta_L || sym == XK_Meta_R)) { + m_meta_mask = mask; + } + if (m_super_mask == 0 + && m_alt_mask != mask + && m_meta_mask != mask + && m_hyper_mask != mask + && (sym == XK_Super_L || sym == XK_Super_R)) { + m_super_mask = mask; + } + if (m_hyper_mask == 0 + && m_alt_mask != mask + && m_meta_mask != mask + && m_super_mask != mask + && (sym == XK_Hyper_L || sym == XK_Hyper_R)) { + m_hyper_mask = mask; + } + if (m_mode_switch_mask == 0 + && m_alt_mask != mask + && m_meta_mask != mask + && m_super_mask != mask + && m_hyper_mask != mask + && sym == XK_Mode_switch) { + m_mode_switch_mask = mask; + } + if (m_num_lock_mask == 0 + && sym == XK_Num_Lock) { + m_num_lock_mask = mask; + } +} + +int QXlibKeyboard::translateKeySym(uint key) const +{ + int code = -1; + int i = 0; // any other keys + while (KeyTbl[i]) { + if (key == KeyTbl[i]) { + code = (int)KeyTbl[i+1]; + break; + } + i += 2; + } + if (m_meta_mask) { + // translate Super/Hyper keys to Meta if we're using them as the MetaModifier + if (m_meta_mask == m_super_mask && (code == Qt::Key_Super_L || code == Qt::Key_Super_R)) { + code = Qt::Key_Meta; + } else if (m_meta_mask == m_hyper_mask && (code == Qt::Key_Hyper_L || code == Qt::Key_Hyper_R)) { + code = Qt::Key_Meta; + } + } + return code; +} + +QString QXlibKeyboard::translateKeySym(KeySym keysym, uint xmodifiers, + int &code, Qt::KeyboardModifiers &modifiers, + QByteArray &chars, int &count) +{ + // all keysyms smaller than 0xff00 are actally keys that can be mapped to unicode chars + + QTextCodec *mapper = QTextCodec::codecForLocale(); + QChar converted; + + if (/*count == 0 &&*/ keysym < 0xff00) { + unsigned char byte3 = (unsigned char)(keysym >> 8); + int mib = -1; + switch(byte3) { + case 0: // Latin 1 + case 1: // Latin 2 + case 2: //latin 3 + case 3: // latin4 + mib = byte3 + 4; break; + case 5: // arabic + mib = 82; break; + case 12: // Hebrew + mib = 85; break; + case 13: // Thai + mib = 2259; break; + case 4: // kana + case 6: // cyrillic + case 7: // greek + case 8: // technical, no mapping here at the moment + case 9: // Special + case 10: // Publishing + case 11: // APL + case 14: // Korean, no mapping + mib = -1; // manual conversion + mapper= 0; +#if !defined(QT_NO_XIM) + converted = keysymToUnicode(byte3, keysym & 0xff); +#endif + case 0x20: + // currency symbols + if (keysym >= 0x20a0 && keysym <= 0x20ac) { + mib = -1; // manual conversion + mapper = 0; + converted = (uint)keysym; + } + break; + default: + break; + } + if (mib != -1) { + mapper = QTextCodec::codecForMib(mib); + if (chars.isEmpty()) + chars.resize(1); + chars[0] = (unsigned char) (keysym & 0xff); // get only the fourth bit for conversion later + count = 1; + } + } else if (keysym >= 0x1000000 && keysym <= 0x100ffff) { + converted = (ushort) (keysym - 0x1000000); + mapper = 0; + } + if (count < (int)chars.size()-1) + chars[count] = '\0'; + + QString text; + if (!mapper && converted.unicode() != 0x0) { + text = converted; + } else if (!chars.isEmpty()) { + // convert chars (8bit) to text (unicode). + if (mapper) + text = mapper->toUnicode(chars.data(), count, 0); + if (text.isEmpty()) { + // no mapper, or codec couldn't convert to unicode (this + // can happen when running in the C locale or with no LANG + // set). try converting from latin-1 + text = QString::fromLatin1(chars); + } + } + + modifiers = translateModifiers(xmodifiers); + + // Commentary in X11/keysymdef says that X codes match ASCII, so it + // is safe to use the locale functions to process X codes in ISO8859-1. + // + // This is mainly for compatibility - applications should not use the + // Qt keycodes between 128 and 255, but should rather use the + // QKeyEvent::text(). + // + if (keysym < 128 || (keysym < 256 && (!mapper || mapper->mibEnum()==4))) { + // upper-case key, if known + code = isprint((int)keysym) ? toupper((int)keysym) : 0; + } else if (keysym >= XK_F1 && keysym <= XK_F35) { + // function keys + code = Qt::Key_F1 + ((int)keysym - XK_F1); + } else if (keysym >= XK_KP_Space && keysym <= XK_KP_9) { + if (keysym >= XK_KP_0) { + // numeric keypad keys + code = Qt::Key_0 + ((int)keysym - XK_KP_0); + } else { + code = translateKeySym(keysym); + } + modifiers |= Qt::KeypadModifier; + } else if (text.length() == 1 && text.unicode()->unicode() > 0x1f && text.unicode()->unicode() != 0x7f && !(keysym >= XK_dead_grave && keysym <= XK_dead_horn)) { + code = text.unicode()->toUpper().unicode(); + } else { + // any other keys + code = translateKeySym(keysym); + + if (code == Qt::Key_Tab && (modifiers & Qt::ShiftModifier)) { + // map shift+tab to shift+backtab, QShortcutMap knows about it + // and will handle it. + code = Qt::Key_Backtab; + text = QString(); + } + } + + return text; +} + +QXlibKeyboard::QXlibKeyboard(QXlibScreen *screen) + : m_screen(screen) + , m_alt_mask(0) + , m_super_mask(0) + , m_hyper_mask(0) + , m_meta_mask(0) +{ + changeLayout(); +} + +void QXlibKeyboard::changeLayout() +{ + XkbDescPtr xkbDesc = XkbGetMap(m_screen->display()->nativeDisplay(), XkbAllClientInfoMask, XkbUseCoreKbd); + for (int i = xkbDesc->min_key_code; i < xkbDesc->max_key_code; ++i) { + const uint mask = xkbDesc->map->modmap ? xkbDesc->map->modmap[i] : 0; + if (mask == 0) { + // key is not bound to a modifier + continue; + } + + for (int j = 0; j < XkbKeyGroupsWidth(xkbDesc, i); ++j) { + KeySym keySym = XkbKeySym(xkbDesc, i, j); + if (keySym == NoSymbol) + continue; + setMask(keySym, mask); + } + } + XkbFreeKeyboard(xkbDesc, XkbAllComponentsMask, true); + +} + +static Qt::KeyboardModifiers modifierFromKeyCode(int qtcode) +{ + switch (qtcode) { + case Qt::Key_Control: + return Qt::ControlModifier; + case Qt::Key_Alt: + return Qt::AltModifier; + case Qt::Key_Shift: + return Qt::ShiftModifier; + case Qt::Key_Meta: + return Qt::MetaModifier; + default: + return Qt::NoModifier; + } +} + +void QXlibKeyboard::handleKeyEvent(QWidget *widget, QEvent::Type type, XKeyEvent *ev) +{ + int qtcode = 0; + Qt::KeyboardModifiers modifiers = translateModifiers(ev->state); + QByteArray chars; + chars.resize(513); + int count = 0; + KeySym keySym; + count = XLookupString(ev,chars.data(),chars.size(),&keySym,0); + QString text = translateKeySym(keySym,ev->state,qtcode,modifiers,chars,count); + QWindowSystemInterface::handleExtendedKeyEvent(widget,ev->time,type,qtcode,modifiers,ev->keycode,0,ev->state,text.left(count)); +} diff --git a/src/plugins/platforms/xlib/qxlibkeyboard.h b/src/plugins/platforms/xlib/qxlibkeyboard.h new file mode 100644 index 0000000..5e0135a --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibkeyboard.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTLITEKEYBOARD_H +#define QTESTLITEKEYBOARD_H + +#include "qxlibintegration.h" + +class QXlibKeyboard +{ +public: + QXlibKeyboard(QXlibScreen *screen); + + void changeLayout(); + + void handleKeyEvent(QWidget *widget, QEvent::Type type, XKeyEvent *ev); + + Qt::KeyboardModifiers translateModifiers(int s); + +private: + + void setMask(KeySym sym, uint mask); + int translateKeySym(uint key) const; + QString translateKeySym(KeySym keysym, uint xmodifiers, + int &code, Qt::KeyboardModifiers &modifiers, + QByteArray &chars, int &count); + + QXlibScreen *m_screen; + + uint m_alt_mask; + uint m_super_mask; + uint m_hyper_mask; + uint m_meta_mask; + uint m_mode_switch_mask; + uint m_num_lock_mask; +}; + +#endif // QTESTLITEKEYBOARD_H diff --git a/src/plugins/platforms/xlib/qxlibmime.cpp b/src/plugins/platforms/xlib/qxlibmime.cpp new file mode 100644 index 0000000..e98983d --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibmime.cpp @@ -0,0 +1,322 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxlibmime.h" + +#include "qxlibstatic.h" +#include "qxlibscreen.h" + +#include <QtCore/QTextCodec> +#include <QtGui/QImageWriter> +#include <QtCore/QBuffer> + +QXlibMime::QXlibMime() + : QInternalMimeData() +{ } + +QXlibMime::~QXlibMime() +{} + + + + + +QString QXlibMime::mimeAtomToString(Display *display, Atom a) +{ + if (!a) return 0; + + if (a == XA_STRING || a == QXlibStatic::atom(QXlibStatic::UTF8_STRING)) { + return "text/plain"; // some Xdnd clients are dumb + } + char *atom = XGetAtomName(display, a); + QString result = QString::fromLatin1(atom); + XFree(atom); + return result; +} + +Atom QXlibMime::mimeStringToAtom(Display *display, const QString &mimeType) +{ + if (mimeType.isEmpty()) + return 0; + return XInternAtom(display, mimeType.toLatin1().constData(), False); +} + +QStringList QXlibMime::mimeFormatsForAtom(Display *display, Atom a) +{ + QStringList formats; + if (a) { + QString atomName = mimeAtomToString(display, a); + formats.append(atomName); + + // special cases for string type + if (a == QXlibStatic::atom(QXlibStatic::UTF8_STRING) + || a == XA_STRING + || a == QXlibStatic::atom(QXlibStatic::TEXT) + || a == QXlibStatic::atom(QXlibStatic::COMPOUND_TEXT)) + formats.append(QLatin1String("text/plain")); + + // special cases for uris + if (atomName == QLatin1String("text/x-moz-url")) + formats.append(QLatin1String("text/uri-list")); + + // special case for images + if (a == XA_PIXMAP) + formats.append(QLatin1String("image/ppm")); + } + return formats; +} + +bool QXlibMime::mimeDataForAtom(Display *display, Atom a, QMimeData *mimeData, QByteArray *data, Atom *atomFormat, int *dataFormat) +{ + bool ret = false; + *atomFormat = a; + *dataFormat = 8; + QString atomName = mimeAtomToString(display, a); + if (QInternalMimeData::hasFormatHelper(atomName, mimeData)) { + *data = QInternalMimeData::renderDataHelper(atomName, mimeData); + if (atomName == QLatin1String("application/x-color")) + *dataFormat = 16; + ret = true; + } else { + if ((a == QXlibStatic::atom(QXlibStatic::UTF8_STRING) + || a == XA_STRING + || a == QXlibStatic::atom(QXlibStatic::TEXT) + || a == QXlibStatic::atom(QXlibStatic::COMPOUND_TEXT)) + && QInternalMimeData::hasFormatHelper(QLatin1String("text/plain"), mimeData)) { + if (a == QXlibStatic::atom(QXlibStatic::UTF8_STRING)){ + *data = QInternalMimeData::renderDataHelper(QLatin1String("text/plain"), mimeData); + ret = true; + } else if (a == XA_STRING) { + *data = QString::fromUtf8(QInternalMimeData::renderDataHelper( + QLatin1String("text/plain"), mimeData)).toLocal8Bit(); + ret = true; + } else if (a == QXlibStatic::atom(QXlibStatic::TEXT) + || a == QXlibStatic::atom(QXlibStatic::COMPOUND_TEXT)) { + // the ICCCM states that TEXT and COMPOUND_TEXT are in the + // encoding of choice, so we choose the encoding of the locale + QByteArray strData = QString::fromUtf8(QInternalMimeData::renderDataHelper( + QLatin1String("text/plain"), mimeData)).toLocal8Bit(); + char *list[] = { strData.data(), NULL }; + + XICCEncodingStyle style = (a == QXlibStatic::atom(QXlibStatic::COMPOUND_TEXT)) + ? XCompoundTextStyle : XStdICCTextStyle; + XTextProperty textprop; + if (list[0] != NULL + && XmbTextListToTextProperty(display, list, 1, style, + &textprop) == Success) { + *atomFormat = textprop.encoding; + *dataFormat = textprop.format; + *data = QByteArray((const char *) textprop.value, textprop.nitems * textprop.format / 8); + ret = true; + + XFree(textprop.value); + } + } + } else if (atomName == QLatin1String("text/x-moz-url") && + QInternalMimeData::hasFormatHelper(QLatin1String("text/uri-list"), mimeData)) { + QByteArray uri = QInternalMimeData::renderDataHelper( + QLatin1String("text/uri-list"), mimeData).split('\n').first(); + QString mozUri = QString::fromLatin1(uri, uri.size()); + mozUri += QLatin1Char('\n'); + *data = QByteArray(reinterpret_cast<const char *>(mozUri.utf16()), mozUri.length() * 2); + ret = true; + } else if ((a == XA_PIXMAP || a == XA_BITMAP) && mimeData->hasImage()) { + ret = true; + } + } + return ret && data != 0; +} + +QList<Atom> QXlibMime::mimeAtomsForFormat(Display *display, const QString &format) +{ + QList<Atom> atoms; + atoms.append(mimeStringToAtom(display, format)); + + // special cases for strings + if (format == QLatin1String("text/plain")) { + atoms.append(QXlibStatic::atom(QXlibStatic::UTF8_STRING)); + atoms.append(XA_STRING); + atoms.append(QXlibStatic::atom(QXlibStatic::TEXT)); + atoms.append(QXlibStatic::atom(QXlibStatic::COMPOUND_TEXT)); + } + + // special cases for uris + if (format == QLatin1String("text/uri-list")) { + atoms.append(mimeStringToAtom(display,QLatin1String("text/x-moz-url"))); + } + + //special cases for images + if (format == QLatin1String("image/ppm")) + atoms.append(XA_PIXMAP); + if (format == QLatin1String("image/pbm")) + atoms.append(XA_BITMAP); + + return atoms; +} + +QVariant QXlibMime::mimeConvertToFormat(Display *display, Atom a, const QByteArray &data, const QString &format, QVariant::Type requestedType, const QByteArray &encoding) +{ + QString atomName = mimeAtomToString(display,a); + if (atomName == format) + return data; + + if (!encoding.isEmpty() + && atomName == format + QLatin1String(";charset=") + QString::fromLatin1(encoding)) { + + if (requestedType == QVariant::String) { + QTextCodec *codec = QTextCodec::codecForName(encoding); + if (codec) + return codec->toUnicode(data); + } + + return data; + } + + // special cases for string types + if (format == QLatin1String("text/plain")) { + if (a == QXlibStatic::atom(QXlibStatic::UTF8_STRING)) + return QString::fromUtf8(data); + if (a == XA_STRING) + return QString::fromLatin1(data); + if (a == QXlibStatic::atom(QXlibStatic::TEXT) + || a == QXlibStatic::atom(QXlibStatic::COMPOUND_TEXT)) + // #### might be wrong for COMPUND_TEXT + return QString::fromLocal8Bit(data, data.size()); + } + + // special case for uri types + if (format == QLatin1String("text/uri-list")) { + if (atomName == QLatin1String("text/x-moz-url")) { + // we expect this as utf16 <url><space><title> + // the first part is a url that should only contain ascci char + // so it should be safe to check that the second char is 0 + // to verify that it is utf16 + if (data.size() > 1 && data.at(1) == 0) + return QString::fromRawData((const QChar *)data.constData(), + data.size() / 2).split(QLatin1Char('\n')).first().toLatin1(); + } + } + + // special cas for images + if (format == QLatin1String("image/ppm")) { + if (a == XA_PIXMAP && data.size() == sizeof(Pixmap)) { + Pixmap xpm = *((Pixmap*)data.data()); + if (!xpm) + return QByteArray(); + Window root; + int x; + int y; + uint width; + uint height; + uint border_width; + uint depth; + + XGetGeometry(display, xpm, &root, &x, &y, &width, &height, &border_width, &depth); + XImage *ximg = XGetImage(display,xpm,x,y,width,height,AllPlanes,depth==1 ? XYPixmap : ZPixmap); + QImage qimg = QXlibStatic::qimageFromXImage(ximg); + XDestroyImage(ximg); + + QImageWriter imageWriter; + imageWriter.setFormat("PPMRAW"); + QBuffer buf; + buf.open(QIODevice::WriteOnly); + imageWriter.setDevice(&buf); + imageWriter.write(qimg); + return buf.buffer(); + } + } + return QVariant(); +} + +Atom QXlibMime::mimeAtomForFormat(Display *display, const QString &format, QVariant::Type requestedType, const QList<Atom> &atoms, QByteArray *requestedEncoding) +{ + requestedEncoding->clear(); + + // find matches for string types + if (format == QLatin1String("text/plain")) { + if (atoms.contains(QXlibStatic::atom(QXlibStatic::UTF8_STRING))) + return QXlibStatic::atom(QXlibStatic::UTF8_STRING); + if (atoms.contains(QXlibStatic::atom(QXlibStatic::COMPOUND_TEXT))) + return QXlibStatic::atom(QXlibStatic::COMPOUND_TEXT); + if (atoms.contains(QXlibStatic::atom(QXlibStatic::TEXT))) + return QXlibStatic::atom(QXlibStatic::TEXT); + if (atoms.contains(XA_STRING)) + return XA_STRING; + } + + // find matches for uri types + if (format == QLatin1String("text/uri-list")) { + Atom a = mimeStringToAtom(display,format); + if (a && atoms.contains(a)) + return a; + a = mimeStringToAtom(display,QLatin1String("text/x-moz-url")); + if (a && atoms.contains(a)) + return a; + } + + // find match for image + if (format == QLatin1String("image/ppm")) { + if (atoms.contains(XA_PIXMAP)) + return XA_PIXMAP; + } + + // for string/text requests try to use a format with a well-defined charset + // first to avoid encoding problems + if (requestedType == QVariant::String + && format.startsWith(QLatin1String("text/")) + && !format.contains(QLatin1String("charset="))) { + + QString formatWithCharset = format; + formatWithCharset.append(QLatin1String(";charset=utf-8")); + + Atom a = mimeStringToAtom(display,formatWithCharset); + if (a && atoms.contains(a)) { + *requestedEncoding = "utf-8"; + return a; + } + } + + Atom a = mimeStringToAtom(display,format); + if (a && atoms.contains(a)) + return a; + + return 0; +} diff --git a/src/plugins/platforms/xlib/qxlibmime.h b/src/plugins/platforms/xlib/qxlibmime.h new file mode 100644 index 0000000..a9bc265 --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibmime.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTLITEMIME_H +#define QTESTLITEMIME_H + +#include <private/qdnd_p.h> + +#include <QtGui/QClipboard> + +#include "qxlibintegration.h" +#include "qxlibclipboard.h" + +class QXlibMime : public QInternalMimeData { + Q_OBJECT +public: + QXlibMime(); + ~QXlibMime(); + + static QList<Atom> mimeAtomsForFormat(Display *display, const QString &format); + static QString mimeAtomToString(Display *display, Atom a); + static bool mimeDataForAtom(Display *display, Atom a, QMimeData *mimeData, QByteArray *data, Atom *atomFormat, int *dataFormat); + static QStringList mimeFormatsForAtom(Display *display, Atom a); + static Atom mimeStringToAtom(Display *display, const QString &mimeType); + static QVariant mimeConvertToFormat(Display *display, Atom a, const QByteArray &data, const QString &format, QVariant::Type requestedType, const QByteArray &encoding); + static Atom mimeAtomForFormat(Display *display, const QString &format, QVariant::Type requestedType, const QList<Atom> &atoms, QByteArray *requestedEncoding); +}; + +#endif // QTESTLITEMIME_H diff --git a/src/plugins/platforms/xlib/qxlibscreen.cpp b/src/plugins/platforms/xlib/qxlibscreen.cpp new file mode 100644 index 0000000..23a2d07 --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibscreen.cpp @@ -0,0 +1,485 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxlibscreen.h" + +#include "qxlibcursor.h" +#include "qxlibwindow.h" +#include "qxlibkeyboard.h" +#include "qxlibstatic.h" +#include "qxlibclipboard.h" +#include "qxlibdisplay.h" + +#include <QtCore/QDebug> +#include <QtCore/QSocketNotifier> +#include <QtCore/QElapsedTimer> + +#include <private/qapplication_p.h> + +#include <X11/extensions/Xfixes.h> + +QT_BEGIN_NAMESPACE + +static int (*original_x_errhandler)(Display *dpy, XErrorEvent *); +static bool seen_badwindow; + +static int qt_x_errhandler(Display *dpy, XErrorEvent *err) +{ + +qDebug() << "qt_x_errhandler" << err->error_code; + + switch (err->error_code) { + case BadAtom: +#if 0 + if (err->request_code == 20 /* X_GetProperty */ + && (err->resourceid == XA_RESOURCE_MANAGER + || err->resourceid == XA_RGB_DEFAULT_MAP + || err->resourceid == ATOM(_NET_SUPPORTED) + || err->resourceid == ATOM(_NET_SUPPORTING_WM_CHECK) + || err->resourceid == ATOM(KDE_FULL_SESSION) + || err->resourceid == ATOM(KWIN_RUNNING) + || err->resourceid == ATOM(XdndProxy) + || err->resourceid == ATOM(XdndAware)) + + + ) { + // Perhaps we're running under SECURITY reduction? :/ + return 0; + } +#endif + qDebug() << "BadAtom"; + break; + + case BadWindow: + if (err->request_code == 2 /* X_ChangeWindowAttributes */ + || err->request_code == 38 /* X_QueryPointer */) { + for (int i = 0; i < ScreenCount(dpy); ++i) { + if (err->resourceid == RootWindow(dpy, i)) { + // Perhaps we're running under SECURITY reduction? :/ + return 0; + } + } + } + seen_badwindow = true; + if (err->request_code == 25 /* X_SendEvent */) { + for (int i = 0; i < ScreenCount(dpy); ++i) { + if (err->resourceid == RootWindow(dpy, i)) { + // Perhaps we're running under SECURITY reduction? :/ + return 0; + } + } +#if 0 + if (X11->xdndHandleBadwindow()) { + qDebug("xdndHandleBadwindow returned true"); + return 0; + } +#endif + } +#if 0 + if (X11->ignore_badwindow) + return 0; +#endif + break; + + case BadMatch: + if (err->request_code == 42 /* X_SetInputFocus */) + return 0; + break; + + default: +#if 0 //!defined(QT_NO_XINPUT) + if (err->request_code == X11->xinput_major + && err->error_code == (X11->xinput_errorbase + XI_BadDevice) + && err->minor_code == 3 /* X_OpenDevice */) { + return 0; + } +#endif + break; + } + + char errstr[256]; + XGetErrorText( dpy, err->error_code, errstr, 256 ); + char buffer[256]; + char request_str[256]; + qsnprintf(buffer, 256, "%d", err->request_code); + XGetErrorDatabaseText(dpy, "XRequest", buffer, "", request_str, 256); + if (err->request_code < 128) { + // X error for a normal protocol request + qWarning( "X Error: %s %d\n" + " Major opcode: %d (%s)\n" + " Resource id: 0x%lx", + errstr, err->error_code, + err->request_code, + request_str, + err->resourceid ); + } else { + // X error for an extension request + const char *extensionName = 0; +#if 0 + if (err->request_code == X11->xrender_major) + extensionName = "RENDER"; + else if (err->request_code == X11->xrandr_major) + extensionName = "RANDR"; + else if (err->request_code == X11->xinput_major) + extensionName = "XInputExtension"; + else if (err->request_code == X11->mitshm_major) + extensionName = "MIT-SHM"; +#endif + char minor_str[256]; + if (extensionName) { + qsnprintf(buffer, 256, "%s.%d", extensionName, err->minor_code); + XGetErrorDatabaseText(dpy, "XRequest", buffer, "", minor_str, 256); + } else { + extensionName = "Uknown extension"; + qsnprintf(minor_str, 256, "Unknown request"); + } + qWarning( "X Error: %s %d\n" + " Extension: %d (%s)\n" + " Minor opcode: %d (%s)\n" + " Resource id: 0x%lx", + errstr, err->error_code, + err->request_code, + extensionName, + err->minor_code, + minor_str, + err->resourceid ); + } + + // ### we really should distinguish between severe, non-severe and + // ### application specific errors + + return 0; +} + +QXlibScreen::QXlibScreen() + : mFormat(QImage::Format_RGB32) +{ + char *display_name = getenv("DISPLAY"); + Display *display = XOpenDisplay(display_name); + mDisplay = new QXlibDisplay(display); + + +#ifndef DONT_USE_MIT_SHM + Status MIT_SHM_extension_supported = XShmQueryExtension (mDisplay->nativeDisplay()); + Q_ASSERT(MIT_SHM_extension_supported == True); +#endif + original_x_errhandler = XSetErrorHandler(qt_x_errhandler); + + if (qgetenv("DO_X_SYNCHRONIZE").toInt()) + XSynchronize(mDisplay->nativeDisplay(), true); + + mScreen = DefaultScreen(mDisplay->nativeDisplay()); + XSelectInput(mDisplay->nativeDisplay(),rootWindow(), KeymapStateMask | EnterWindowMask | LeaveWindowMask | PropertyChangeMask); + int width = DisplayWidth(mDisplay->nativeDisplay(), mScreen); + int height = DisplayHeight(mDisplay->nativeDisplay(), mScreen); + mGeometry = QRect(0,0,width,height); + + int physicalWidth = DisplayWidthMM(mDisplay->nativeDisplay(), mScreen); + int physicalHeight = DisplayHeightMM(mDisplay->nativeDisplay(), mScreen); + mPhysicalSize = QSize(physicalWidth,physicalHeight); + + int xSocketNumber = XConnectionNumber(mDisplay->nativeDisplay()); + + mDepth = DefaultDepth(mDisplay->nativeDisplay(),mScreen); +#ifdef MYX11_DEBUG + qDebug() << "X socket:"<< xSocketNumber; +#endif + QSocketNotifier *sock = new QSocketNotifier(xSocketNumber, QSocketNotifier::Read, this); + connect(sock, SIGNAL(activated(int)), this, SLOT(eventDispatcher())); + + mCursor = new QXlibCursor(this); + mKeyboard = new QXlibKeyboard(this); +} + +QXlibScreen::~QXlibScreen() +{ + delete mCursor; + delete mDisplay; +} + +Window QXlibScreen::rootWindow() +{ + return RootWindow(mDisplay->nativeDisplay(), mScreen); +} + +unsigned long QXlibScreen::blackPixel() +{ + return BlackPixel(mDisplay->nativeDisplay(), mScreen); +} + +unsigned long QXlibScreen::whitePixel() +{ + return WhitePixel(mDisplay->nativeDisplay(), mScreen); +} + +#ifdef KeyPress +#undef KeyPress +#endif +#ifdef KeyRelease +#undef KeyRelease +#endif + +bool QXlibScreen::handleEvent(XEvent *xe) +{ + int quit = false; + QXlibWindow *platformWindow = 0; + QWidget *widget = QWidget::find(xe->xany.window); + if (widget) { + platformWindow = static_cast<QXlibWindow *>(widget->platformWindow()); + } + + Atom wmProtocolsAtom = QXlibStatic::atom(QXlibStatic::WM_PROTOCOLS); + Atom wmDeleteWindowAtom = QXlibStatic::atom(QXlibStatic::WM_DELETE_WINDOW); + switch (xe->type) { + + case ClientMessage: + if (xe->xclient.format == 32 && xe->xclient.message_type == wmProtocolsAtom) { + Atom a = xe->xclient.data.l[0]; + if (a == wmDeleteWindowAtom) + platformWindow->handleCloseEvent(); + } + break; + + case Expose: + if (platformWindow) + if (xe->xexpose.count == 0) + platformWindow->paintEvent(); + break; + case ConfigureNotify: + if (platformWindow) + platformWindow->resizeEvent(&xe->xconfigure); + break; + + case ButtonPress: + if (platformWindow) + platformWindow->mousePressEvent(&xe->xbutton); + break; + + case ButtonRelease: + if (platformWindow) + platformWindow->handleMouseEvent(QEvent::MouseButtonRelease, &xe->xbutton); + break; + + case MotionNotify: + if (platformWindow) + platformWindow->handleMouseEvent(QEvent::MouseMove, &xe->xbutton); + break; + + case XKeyPress: + mKeyboard->handleKeyEvent(widget,QEvent::KeyPress, &xe->xkey); + break; + + case XKeyRelease: + mKeyboard->handleKeyEvent(widget,QEvent::KeyRelease, &xe->xkey); + break; + + case EnterNotify: + if (platformWindow) + platformWindow->handleEnterEvent(); + break; + + case LeaveNotify: + if (platformWindow) + platformWindow->handleLeaveEvent(); + break; + + case XFocusIn: + if (platformWindow) + platformWindow->handleFocusInEvent(); + break; + + case XFocusOut: + if (platformWindow) + platformWindow->handleFocusOutEvent(); + break; + + case PropertyNotify: + break; + + case SelectionClear: + qDebug() << "Selection Clear!!!"; + break; + case SelectionRequest: + handleSelectionRequest(xe); + break; + case SelectionNotify: + qDebug() << "Selection Notify!!!!"; + + break; + + + default: +#ifdef MYX11_DEBUG + qDebug() << hex << xe->xany.window << "Other X event" << xe->type; +#endif + break; + } + + return quit; +} + +static Bool checkForClipboardEvents(Display *, XEvent *e, XPointer) +{ + Atom clipboard = QXlibStatic::atom(QXlibStatic::CLIPBOARD); + return ((e->type == SelectionRequest && (e->xselectionrequest.selection == XA_PRIMARY + || e->xselectionrequest.selection == clipboard)) + || (e->type == SelectionClear && (e->xselectionclear.selection == XA_PRIMARY + || e->xselectionclear.selection == clipboard))); +} + +bool QXlibScreen::waitForClipboardEvent(Window win, int type, XEvent *event, int timeout) +{ + QElapsedTimer timer; + timer.start(); + do { + if (XCheckTypedWindowEvent(mDisplay->nativeDisplay(),win,type,event)) + return true; + + // process other clipboard events, since someone is probably requesting data from us + XEvent e; + if (XCheckIfEvent(mDisplay->nativeDisplay(), &e, checkForClipboardEvents, 0)) + handleEvent(&e); + + mDisplay->flush(); + + // sleep 50 ms, so we don't use up CPU cycles all the time. + struct timeval usleep_tv; + usleep_tv.tv_sec = 0; + usleep_tv.tv_usec = 50000; + select(0, 0, 0, 0, &usleep_tv); + } while (timer.elapsed() < timeout); + return false; +} + +void QXlibScreen::eventDispatcher() +{ + ulong marker = XNextRequest(mDisplay->nativeDisplay()); + // int i = 0; + while (XPending(mDisplay->nativeDisplay())) { + XEvent event; + XNextEvent(mDisplay->nativeDisplay(), &event); + /* done = */ + handleEvent(&event); + + if (event.xany.serial >= marker) { + #ifdef MYX11_DEBUG + qDebug() << "potential livelock averted"; + #endif + #if 0 + if (XEventsQueued(mDisplay->nativeDisplay(), QueuedAfterFlush)) { + qDebug() << " with events queued"; + QTimer::singleShot(0, this, SLOT(eventDispatcher())); + } + #endif + break; + } + } +} + +QImage QXlibScreen::grabWindow(Window window, int x, int y, int w, int h) +{ + if (w == 0 || h ==0) + return QImage(); + + //WinId 0 means the desktop widget + if (!window) + window = rootWindow(); + + XWindowAttributes window_attr; + if (!XGetWindowAttributes(mDisplay->nativeDisplay(), window, &window_attr)) + return QImage(); + + if (w < 0) + w = window_attr.width - x; + if (h < 0) + h = window_attr.height - y; + + // Ideally, we should also limit ourselves to the screen area, but the Qt docs say + // that it's "unsafe" to go outside the screen, so we can ignore that problem. + + //We're definitely not optimizing for speed... + XImage *xi = XGetImage(mDisplay->nativeDisplay(), window, x, y, w, h, AllPlanes, ZPixmap); + + if (!xi) + return QImage(); + + //taking a copy to make sure we have ownership -- not fast + QImage result = QImage( (uchar*) xi->data, xi->width, xi->height, xi->bytes_per_line, QImage::Format_RGB32 ).copy(); + + XDestroyImage(xi); + + return result; +} + +QXlibScreen * QXlibScreen::testLiteScreenForWidget(QWidget *widget) +{ + QPlatformScreen *platformScreen = platformScreenForWidget(widget); + return static_cast<QXlibScreen *>(platformScreen); +} + +QXlibDisplay * QXlibScreen::display() const +{ + return mDisplay; +} + +int QXlibScreen::xScreenNumber() const +{ + return mScreen; +} + +Visual * QXlibScreen::defaultVisual() const +{ + DefaultVisual(display()->nativeDisplay(), xScreenNumber()); +} + +QXlibKeyboard * QXlibScreen::keyboard() const +{ + return mKeyboard; +} + +void QXlibScreen::handleSelectionRequest(XEvent *event) +{ + QPlatformIntegration *integration = QApplicationPrivate::platformIntegration(); + QXlibClipboard *clipboard = static_cast<QXlibClipboard *>(integration->clipboard()); + clipboard->handleSelectionRequest(event); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/xlib/qxlibscreen.h b/src/plugins/platforms/xlib/qxlibscreen.h new file mode 100644 index 0000000..35c0141 --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibscreen.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTLITESCREEN_H +#define QTESTLITESCREEN_H + +#include <QtGui/QPlatformScreen> +#include "qxlibintegration.h" + +QT_BEGIN_NAMESPACE + +class QXlibCursor; +class QXlibKeyboard; +class QXlibDisplay; + +class QXlibScreen : public QPlatformScreen +{ + Q_OBJECT +public: + QXlibScreen(); + + ~QXlibScreen(); + + QRect geometry() const { return mGeometry; } + int depth() const { return mDepth; } + QImage::Format format() const { return mFormat; } + QSize physicalSize() const { return mPhysicalSize; } + + Window rootWindow(); + unsigned long blackPixel(); + unsigned long whitePixel(); + + bool handleEvent(XEvent *xe); + bool waitForClipboardEvent(Window win, int type, XEvent *event, int timeout); + + QImage grabWindow(Window window, int x, int y, int w, int h); + + static QXlibScreen *testLiteScreenForWidget(QWidget *widget); + + QXlibDisplay *display() const; + int xScreenNumber() const; + + Visual *defaultVisual() const; + + QXlibKeyboard *keyboard() const; + +public slots: + void eventDispatcher(); + +private: + + void handleSelectionRequest(XEvent *event); + QRect mGeometry; + QSize mPhysicalSize; + int mDepth; + QImage::Format mFormat; + QXlibCursor *mCursor; + QXlibKeyboard *mKeyboard; + + QXlibDisplay * mDisplay; + int mScreen; +}; + +QT_END_NAMESPACE + +#endif // QTESTLITESCREEN_H diff --git a/src/plugins/platforms/xlib/qxlibstatic.cpp b/src/plugins/platforms/xlib/qxlibstatic.cpp new file mode 100644 index 0000000..6117781 --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibstatic.cpp @@ -0,0 +1,512 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxlibstatic.h" +#include "qxlibscreen.h" +#include "qxlibdisplay.h" + +#include <qplatformdefs.h> + +#include <QtGui/private/qapplication_p.h> +#include <QtCore/QBuffer> +#include <QtCore/QLibrary> + +#include <QDebug> + +#ifndef QT_NO_XFIXES +#include <X11/extensions/Xfixes.h> +#endif // QT_NO_XFIXES + +static const char * x11_atomnames = { + // window-manager <-> client protocols + "WM_PROTOCOLS\0" + "WM_DELETE_WINDOW\0" + "WM_TAKE_FOCUS\0" + "_NET_WM_PING\0" + "_NET_WM_CONTEXT_HELP\0" + "_NET_WM_SYNC_REQUEST\0" + "_NET_WM_SYNC_REQUEST_COUNTER\0" + + // ICCCM window state + "WM_STATE\0" + "WM_CHANGE_STATE\0" + + // Session management + "WM_CLIENT_LEADER\0" + "WM_WINDOW_ROLE\0" + "SM_CLIENT_ID\0" + + // Clipboard + "CLIPBOARD\0" + "INCR\0" + "TARGETS\0" + "MULTIPLE\0" + "TIMESTAMP\0" + "SAVE_TARGETS\0" + "CLIP_TEMPORARY\0" + "_QT_SELECTION\0" + "_QT_CLIPBOARD_SENTINEL\0" + "_QT_SELECTION_SENTINEL\0" + "CLIPBOARD_MANAGER\0" + + "RESOURCE_MANAGER\0" + + "_XSETROOT_ID\0" + + "_QT_SCROLL_DONE\0" + "_QT_INPUT_ENCODING\0" + + "_MOTIF_WM_HINTS\0" + + "DTWM_IS_RUNNING\0" + "ENLIGHTENMENT_DESKTOP\0" + "_DT_SAVE_MODE\0" + "_SGI_DESKS_MANAGER\0" + + // EWMH (aka NETWM) + "_NET_SUPPORTED\0" + "_NET_VIRTUAL_ROOTS\0" + "_NET_WORKAREA\0" + + "_NET_MOVERESIZE_WINDOW\0" + "_NET_WM_MOVERESIZE\0" + + "_NET_WM_NAME\0" + "_NET_WM_ICON_NAME\0" + "_NET_WM_ICON\0" + + "_NET_WM_PID\0" + + "_NET_WM_WINDOW_OPACITY\0" + + "_NET_WM_STATE\0" + "_NET_WM_STATE_ABOVE\0" + "_NET_WM_STATE_BELOW\0" + "_NET_WM_STATE_FULLSCREEN\0" + "_NET_WM_STATE_MAXIMIZED_HORZ\0" + "_NET_WM_STATE_MAXIMIZED_VERT\0" + "_NET_WM_STATE_MODAL\0" + "_NET_WM_STATE_STAYS_ON_TOP\0" + "_NET_WM_STATE_DEMANDS_ATTENTION\0" + + "_NET_WM_USER_TIME\0" + "_NET_WM_USER_TIME_WINDOW\0" + "_NET_WM_FULL_PLACEMENT\0" + + "_NET_WM_WINDOW_TYPE\0" + "_NET_WM_WINDOW_TYPE_DESKTOP\0" + "_NET_WM_WINDOW_TYPE_DOCK\0" + "_NET_WM_WINDOW_TYPE_TOOLBAR\0" + "_NET_WM_WINDOW_TYPE_MENU\0" + "_NET_WM_WINDOW_TYPE_UTILITY\0" + "_NET_WM_WINDOW_TYPE_SPLASH\0" + "_NET_WM_WINDOW_TYPE_DIALOG\0" + "_NET_WM_WINDOW_TYPE_DROPDOWN_MENU\0" + "_NET_WM_WINDOW_TYPE_POPUP_MENU\0" + "_NET_WM_WINDOW_TYPE_TOOLTIP\0" + "_NET_WM_WINDOW_TYPE_NOTIFICATION\0" + "_NET_WM_WINDOW_TYPE_COMBO\0" + "_NET_WM_WINDOW_TYPE_DND\0" + "_NET_WM_WINDOW_TYPE_NORMAL\0" + "_KDE_NET_WM_WINDOW_TYPE_OVERRIDE\0" + + "_KDE_NET_WM_FRAME_STRUT\0" + + "_NET_STARTUP_INFO\0" + "_NET_STARTUP_INFO_BEGIN\0" + + "_NET_SUPPORTING_WM_CHECK\0" + + "_NET_WM_CM_S0\0" + + "_NET_SYSTEM_TRAY_VISUAL\0" + + "_NET_ACTIVE_WINDOW\0" + + // Property formats + "COMPOUND_TEXT\0" + "TEXT\0" + "UTF8_STRING\0" + + // xdnd + "XdndEnter\0" + "XdndPosition\0" + "XdndStatus\0" + "XdndLeave\0" + "XdndDrop\0" + "XdndFinished\0" + "XdndTypeList\0" + "XdndActionList\0" + + "XdndSelection\0" + + "XdndAware\0" + "XdndProxy\0" + + "XdndActionCopy\0" + "XdndActionLink\0" + "XdndActionMove\0" + "XdndActionPrivate\0" + + // Motif DND + "_MOTIF_DRAG_AND_DROP_MESSAGE\0" + "_MOTIF_DRAG_INITIATOR_INFO\0" + "_MOTIF_DRAG_RECEIVER_INFO\0" + "_MOTIF_DRAG_WINDOW\0" + "_MOTIF_DRAG_TARGETS\0" + + "XmTRANSFER_SUCCESS\0" + "XmTRANSFER_FAILURE\0" + + // Xkb + "_XKB_RULES_NAMES\0" + + // XEMBED + "_XEMBED\0" + "_XEMBED_INFO\0" + + // Wacom old. (before version 0.10) + "Wacom Stylus\0" + "Wacom Cursor\0" + "Wacom Eraser\0" + + // Tablet + "STYLUS\0" + "ERASER\0" +}; + +/*! + \internal + Try to resolve a \a symbol from \a library with the version specified + by \a vernum. + + Note that, in the case of the Xfixes library, \a vernum is not the same as + \c XFIXES_MAJOR - it is a part of soname and may differ from the Xfixes + version. +*/ +static void* qt_load_library_runtime(const char *library, int vernum, + int highestVernum, const char *symbol) +{ + QList<int> versions; + // we try to load in the following order: + // explicit version -> the default one -> (from the highest (highestVernum) to the lowest (vernum) ) + if (vernum != -1) + versions << vernum; + versions << -1; + if (vernum != -1) { + for(int i = highestVernum; i > vernum; --i) + versions << i; + } + Q_FOREACH(int version, versions) { + QLatin1String libName(library); + QLibrary xfixesLib(libName, version); + void *ptr = xfixesLib.resolve(symbol); + if (ptr) + return ptr; + } + return 0; +} + +# define XFIXES_LOAD_RUNTIME(vernum, symbol, symbol_type) \ + (symbol_type)qt_load_library_runtime("libXfixes", vernum, 4, #symbol); +# define XFIXES_LOAD_V1(symbol) \ + XFIXES_LOAD_RUNTIME(1, symbol, Ptr##symbol) +# define XFIXES_LOAD_V2(symbol) \ + XFIXES_LOAD_RUNTIME(2, symbol, Ptr##symbol) + + +class QTestLiteStaticInfoPrivate +{ +public: + QTestLiteStaticInfoPrivate() + : use_xfixes(false) + , xfixes_major(0) + , xfixes_eventbase(0) + , xfixes_errorbase(0) + { + QXlibScreen *screen = qobject_cast<QXlibScreen *> (QApplicationPrivate::platformIntegration()->screens().at(0)); + Q_ASSERT(screen); + + initializeAllAtoms(screen); + initializeSupportedAtoms(screen); + + resolveXFixes(screen); + } + + bool isSupportedByWM(Atom atom) + { + if (!m_supportedAtoms) + return false; + + bool supported = false; + int i = 0; + while (m_supportedAtoms[i] != 0) { + if (m_supportedAtoms[i++] == atom) { + supported = true; + break; + } + } + + return supported; + } + + Atom atom(QXlibStatic::X11Atom atom) + { + return m_allAtoms[atom]; + } + + bool useXFixes() const { return use_xfixes; } + + int xFixesEventBase() const {return xfixes_eventbase; } + + PtrXFixesSelectSelectionInput xFixesSelectSelectionInput() const + { + return ptrXFixesSelectSelectionInput; + } + + QImage qimageFromXImage(XImage *xi) + { + QImage::Format format = QImage::Format_ARGB32_Premultiplied; + if (xi->depth == 24) + format = QImage::Format_RGB32; + else if (xi->depth == 16) + format = QImage::Format_RGB16; + + QImage image = QImage((uchar *)xi->data, xi->width, xi->height, xi->bytes_per_line, format).copy(); + + // we may have to swap the byte order + if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst) + || (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst)) + { + for (int i=0; i < image.height(); i++) { + if (xi->depth == 16) { + ushort *p = (ushort*)image.scanLine(i); + ushort *end = p + image.width(); + while (p < end) { + *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff); + p++; + } + } else { + uint *p = (uint*)image.scanLine(i); + uint *end = p + image.width(); + while (p < end) { + *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000) + | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff); + p++; + } + } + } + } + + // fix-up alpha channel + if (format == QImage::Format_RGB32) { + QRgb *p = (QRgb *)image.bits(); + for (int y = 0; y < xi->height; ++y) { + for (int x = 0; x < xi->width; ++x) + p[x] |= 0xff000000; + p += xi->bytes_per_line / 4; + } + } + + return image; + } + + +private: + + void initializeAllAtoms(QXlibScreen *screen) { + const char *names[QXlibStatic::NAtoms]; + const char *ptr = x11_atomnames; + + int i = 0; + while (*ptr) { + names[i++] = ptr; + while (*ptr) + ++ptr; + ++ptr; + } + + Q_ASSERT(i == QXlibStatic::NPredefinedAtoms); + + QByteArray settings_atom_name("_QT_SETTINGS_TIMESTAMP_"); + settings_atom_name += XDisplayName(qPrintable(screen->display()->displayName())); + names[i++] = settings_atom_name; + + Q_ASSERT(i == QXlibStatic::NAtoms); + #if 0//defined(XlibSpecificationRelease) && (XlibSpecificationRelease >= 6) + XInternAtoms(screen->display(), (char **)names, i, False, m_allAtoms); + #else + for (i = 0; i < QXlibStatic::NAtoms; ++i) + m_allAtoms[i] = XInternAtom(screen->display()->nativeDisplay(), (char *)names[i], False); + #endif + } + + void initializeSupportedAtoms(QXlibScreen *screen) + { + Atom type; + int format; + long offset = 0; + unsigned long nitems, after; + unsigned char *data = 0; + + int e = XGetWindowProperty(screen->display()->nativeDisplay(), screen->rootWindow(), + this->atom(QXlibStatic::_NET_SUPPORTED), 0, 0, + False, XA_ATOM, &type, &format, &nitems, &after, &data); + if (data) + XFree(data); + + if (e == Success && type == XA_ATOM && format == 32) { + QBuffer ts; + ts.open(QIODevice::WriteOnly); + + while (after > 0) { + XGetWindowProperty(screen->display()->nativeDisplay(), screen->rootWindow(), + this->atom(QXlibStatic::_NET_SUPPORTED), offset, 1024, + False, XA_ATOM, &type, &format, &nitems, &after, &data); + + if (type == XA_ATOM && format == 32) { + ts.write(reinterpret_cast<char *>(data), nitems * sizeof(long)); + offset += nitems; + } else + after = 0; + if (data) + XFree(data); + } + + // compute nitems + QByteArray buffer(ts.buffer()); + nitems = buffer.size() / sizeof(Atom); + m_supportedAtoms = new Atom[nitems + 1]; + Atom *a = (Atom *) buffer.data(); + uint i; + for (i = 0; i < nitems; i++) + m_supportedAtoms[i] = a[i]; + m_supportedAtoms[nitems] = 0; + + } + } + + void resolveXFixes(QXlibScreen *screen) + { +#ifndef QT_NO_XFIXES + // See if Xfixes is supported on the connected display + if (XQueryExtension(screen->display()->nativeDisplay(), "XFIXES", &xfixes_major, + &xfixes_eventbase, &xfixes_errorbase)) { + ptrXFixesQueryExtension = XFIXES_LOAD_V1(XFixesQueryExtension); + ptrXFixesQueryVersion = XFIXES_LOAD_V1(XFixesQueryVersion); + ptrXFixesSetCursorName = XFIXES_LOAD_V2(XFixesSetCursorName); + ptrXFixesSelectSelectionInput = XFIXES_LOAD_V2(XFixesSelectSelectionInput); + + if(ptrXFixesQueryExtension && ptrXFixesQueryVersion + && ptrXFixesQueryExtension(screen->display()->nativeDisplay(), &xfixes_eventbase, + &xfixes_errorbase)) { + // Xfixes is supported. + // Note: the XFixes protocol version is negotiated using QueryVersion. + // We supply the highest version we support, the X server replies with + // the highest version it supports, but no higher than the version we + // asked for. The version sent back is the protocol version the X server + // will use to talk us. If this call is removed, the behavior of the + // X server when it receives an XFixes request is undefined. + int major = 3; + int minor = 0; + ptrXFixesQueryVersion(screen->display()->nativeDisplay(), &major, &minor); + use_xfixes = (major >= 1); + xfixes_major = major; + } + } +#endif // QT_NO_XFIXES + + } + + Atom *m_supportedAtoms; + Atom m_allAtoms[QXlibStatic::NAtoms]; + +#ifndef QT_NO_XFIXES + PtrXFixesQueryExtension ptrXFixesQueryExtension; + PtrXFixesQueryVersion ptrXFixesQueryVersion; + PtrXFixesSetCursorName ptrXFixesSetCursorName; + PtrXFixesSelectSelectionInput ptrXFixesSelectSelectionInput; +#endif + + bool use_xfixes; + int xfixes_major; + int xfixes_eventbase; + int xfixes_errorbase; + +}; +Q_GLOBAL_STATIC(QTestLiteStaticInfoPrivate, qTestLiteStaticInfoPrivate); + + +Atom QXlibStatic::atom(QXlibStatic::X11Atom atom) +{ + return qTestLiteStaticInfoPrivate()->atom(atom); +} + +bool QXlibStatic::isSupportedByWM(Atom atom) +{ + return qTestLiteStaticInfoPrivate()->isSupportedByWM(atom); +} + +bool QXlibStatic::useXFixes() +{ + return qTestLiteStaticInfoPrivate()->useXFixes(); +} + +int QXlibStatic::xFixesEventBase() +{ + return qTestLiteStaticInfoPrivate()->xFixesEventBase(); +} + +#ifndef QT_NO_XFIXES +PtrXFixesSelectSelectionInput QXlibStatic::xFixesSelectSelectionInput() +{ + qDebug() << qTestLiteStaticInfoPrivate()->useXFixes(); + if (!qTestLiteStaticInfoPrivate()->useXFixes()) + return 0; + + return qTestLiteStaticInfoPrivate()->xFixesSelectSelectionInput(); +} + +QImage QXlibStatic::qimageFromXImage(XImage *xi) +{ + return qTestLiteStaticInfoPrivate()->qimageFromXImage(xi); +} +#endif //QT_NO_XFIXES diff --git a/src/plugins/platforms/xlib/qxlibstatic.h b/src/plugins/platforms/xlib/qxlibstatic.h new file mode 100644 index 0000000..72cfaec --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibstatic.h @@ -0,0 +1,413 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTESTLITESTATICINFO_H +#define QTESTLITESTATICINFO_H + +#include <QtCore/QTextStream> +#include <QtCore/QDataStream> +#include <QtCore/QMetaType> +#include <QtCore/QVariant> + +#if defined(_XLIB_H_) // crude hack, but... +#error "cannot include <X11/Xlib.h> before this file" +#endif +#define XRegisterIMInstantiateCallback qt_XRegisterIMInstantiateCallback +#define XUnregisterIMInstantiateCallback qt_XUnregisterIMInstantiateCallback +#define XSetIMValues qt_XSetIMValues +#include <X11/Xlib.h> +#undef XRegisterIMInstantiateCallback +#undef XUnregisterIMInstantiateCallback +#undef XSetIMValues + +#include <X11/Xutil.h> +#include <X11/Xos.h> +#ifdef index +# undef index +#endif +#ifdef rindex +# undef rindex +#endif +#ifdef Q_OS_VXWORS +# ifdef open +# undef open +# endif +# ifdef getpid +# undef getpid +# endif +#endif // Q_OS_VXWORKS +#include <X11/Xatom.h> + +//#define QT_NO_SHAPE +#ifdef QT_NO_SHAPE +# define XShapeCombineRegion(a,b,c,d,e,f,g) +# define XShapeCombineMask(a,b,c,d,e,f,g) +#else +# include <X11/extensions/shape.h> +#endif // QT_NO_SHAPE + + +#if !defined (QT_NO_TABLET) +# include <X11/extensions/XInput.h> +#if defined (Q_OS_IRIX) +# include <X11/extensions/SGIMisc.h> +# include <wacom.h> +#endif +#endif // QT_NO_TABLET + + +// #define QT_NO_XINERAMA +#ifndef QT_NO_XINERAMA +// XFree86 does not C++ify Xinerama (at least up to XFree86 4.0.3). +extern "C" { +# include <X11/extensions/Xinerama.h> +} +#endif // QT_NO_XINERAMA + +// #define QT_NO_XRANDR +#ifndef QT_NO_XRANDR +# include <X11/extensions/Xrandr.h> +#endif // QT_NO_XRANDR + +// #define QT_NO_XRENDER +#ifndef QT_NO_XRENDER +# include <X11/extensions/Xrender.h> +#endif // QT_NO_XRENDER + +#ifndef QT_NO_XSYNC +extern "C" { +# include "X11/extensions/sync.h" +} +#endif + +// #define QT_NO_XKB +#ifndef QT_NO_XKB +# include <X11/XKBlib.h> +#endif // QT_NO_XKB + + +#if !defined(XlibSpecificationRelease) +# define X11R4 +typedef char *XPointer; +#else +# undef X11R4 +#endif + +#ifndef QT_NO_XFIXES +typedef Bool (*PtrXFixesQueryExtension)(Display *, int *, int *); +typedef Status (*PtrXFixesQueryVersion)(Display *, int *, int *); +typedef void (*PtrXFixesSetCursorName)(Display *dpy, Cursor cursor, const char *name); +typedef void (*PtrXFixesSelectSelectionInput)(Display *dpy, Window win, Atom selection, unsigned long eventMask); +#endif // QT_NO_XFIXES + +#ifndef QT_NO_XCURSOR +#include <X11/Xcursor/Xcursor.h> +typedef Cursor (*PtrXcursorLibraryLoadCursor)(Display *, const char *); +#endif // QT_NO_XCURSOR + +#ifndef QT_NO_XINERAMA +typedef Bool (*PtrXineramaQueryExtension)(Display *dpy, int *event_base, int *error_base); +typedef Bool (*PtrXineramaIsActive)(Display *dpy); +typedef XineramaScreenInfo *(*PtrXineramaQueryScreens)(Display *dpy, int *number); +#endif // QT_NO_XINERAMA + +#ifndef QT_NO_XRANDR +typedef void (*PtrXRRSelectInput)(Display *, Window, int); +typedef int (*PtrXRRUpdateConfiguration)(XEvent *); +typedef int (*PtrXRRRootToScreen)(Display *, Window); +typedef Bool (*PtrXRRQueryExtension)(Display *, int *, int *); +#endif // QT_NO_XRANDR + +#ifndef QT_NO_XINPUT +typedef int (*PtrXCloseDevice)(Display *, XDevice *); +typedef XDeviceInfo* (*PtrXListInputDevices)(Display *, int *); +typedef XDevice* (*PtrXOpenDevice)(Display *, XID); +typedef void (*PtrXFreeDeviceList)(XDeviceInfo *); +typedef int (*PtrXSelectExtensionEvent)(Display *, Window, XEventClass *, int); +#endif // QT_NO_XINPUT + +/* + * Solaris patch 108652-47 and higher fixes crases in + * XRegisterIMInstantiateCallback, but the function doesn't seem to + * work. + * + * Instead, we disabled R6 input, and open the input method + * immediately at application start. + */ + +//######### XFree86 has wrong declarations for XRegisterIMInstantiateCallback +//######### and XUnregisterIMInstantiateCallback in at least version 3.3.2. +//######### Many old X11R6 header files lack XSetIMValues. +//######### Therefore, we have to declare these functions ourselves. + +extern "C" Bool XRegisterIMInstantiateCallback( + Display*, + struct _XrmHashBucketRec*, + char*, + char*, + XIMProc, //XFree86 has XIDProc, which has to be wrong + XPointer +); + +extern "C" Bool XUnregisterIMInstantiateCallback( + Display*, + struct _XrmHashBucketRec*, + char*, + char*, + XIMProc, //XFree86 has XIDProc, which has to be wrong + XPointer +); + +#ifndef X11R4 +# include <X11/Xlocale.h> +#endif // X11R4 + + +#ifndef QT_NO_MITSHM +# include <X11/extensions/XShm.h> +#endif // QT_NO_MITSHM + +// rename a couple of X defines to get rid of name clashes +// resolve the conflict between X11's FocusIn and QEvent::FocusIn +enum { + XFocusOut = FocusOut, + XFocusIn = FocusIn, + XKeyPress = KeyPress, + XKeyRelease = KeyRelease, + XNone = None, + XRevertToParent = RevertToParent, + XGrayScale = GrayScale, + XCursorShape = CursorShape +}; +#undef FocusOut +#undef FocusIn +#undef KeyPress +#undef KeyRelease +#undef None +#undef RevertToParent +#undef GrayScale +#undef CursorShape + +#ifdef FontChange +#undef FontChange +#endif + + +class QXlibStatic +{ +public: + enum X11Atom { + // window-manager <-> client protocols + WM_PROTOCOLS, + WM_DELETE_WINDOW, + WM_TAKE_FOCUS, + _NET_WM_PING, + _NET_WM_CONTEXT_HELP, + _NET_WM_SYNC_REQUEST, + _NET_WM_SYNC_REQUEST_COUNTER, + + // ICCCM window state + WM_STATE, + WM_CHANGE_STATE, + + // Session management + WM_CLIENT_LEADER, + WM_WINDOW_ROLE, + SM_CLIENT_ID, + + // Clipboard + CLIPBOARD, + INCR, + TARGETS, + MULTIPLE, + TIMESTAMP, + SAVE_TARGETS, + CLIP_TEMPORARY, + _QT_SELECTION, + _QT_CLIPBOARD_SENTINEL, + _QT_SELECTION_SENTINEL, + CLIPBOARD_MANAGER, + + RESOURCE_MANAGER, + + _XSETROOT_ID, + + _QT_SCROLL_DONE, + _QT_INPUT_ENCODING, + + _MOTIF_WM_HINTS, + + DTWM_IS_RUNNING, + ENLIGHTENMENT_DESKTOP, + _DT_SAVE_MODE, + _SGI_DESKS_MANAGER, + + // EWMH (aka NETWM) + _NET_SUPPORTED, + _NET_VIRTUAL_ROOTS, + _NET_WORKAREA, + + _NET_MOVERESIZE_WINDOW, + _NET_WM_MOVERESIZE, + + _NET_WM_NAME, + _NET_WM_ICON_NAME, + _NET_WM_ICON, + + _NET_WM_PID, + + _NET_WM_WINDOW_OPACITY, + + _NET_WM_STATE, + _NET_WM_STATE_ABOVE, + _NET_WM_STATE_BELOW, + _NET_WM_STATE_FULLSCREEN, + _NET_WM_STATE_MAXIMIZED_HORZ, + _NET_WM_STATE_MAXIMIZED_VERT, + _NET_WM_STATE_MODAL, + _NET_WM_STATE_STAYS_ON_TOP, + _NET_WM_STATE_DEMANDS_ATTENTION, + + _NET_WM_USER_TIME, + _NET_WM_USER_TIME_WINDOW, + _NET_WM_FULL_PLACEMENT, + + _NET_WM_WINDOW_TYPE, + _NET_WM_WINDOW_TYPE_DESKTOP, + _NET_WM_WINDOW_TYPE_DOCK, + _NET_WM_WINDOW_TYPE_TOOLBAR, + _NET_WM_WINDOW_TYPE_MENU, + _NET_WM_WINDOW_TYPE_UTILITY, + _NET_WM_WINDOW_TYPE_SPLASH, + _NET_WM_WINDOW_TYPE_DIALOG, + _NET_WM_WINDOW_TYPE_DROPDOWN_MENU, + _NET_WM_WINDOW_TYPE_POPUP_MENU, + _NET_WM_WINDOW_TYPE_TOOLTIP, + _NET_WM_WINDOW_TYPE_NOTIFICATION, + _NET_WM_WINDOW_TYPE_COMBO, + _NET_WM_WINDOW_TYPE_DND, + _NET_WM_WINDOW_TYPE_NORMAL, + _KDE_NET_WM_WINDOW_TYPE_OVERRIDE, + + _KDE_NET_WM_FRAME_STRUT, + + _NET_STARTUP_INFO, + _NET_STARTUP_INFO_BEGIN, + + _NET_SUPPORTING_WM_CHECK, + + _NET_WM_CM_S0, + + _NET_SYSTEM_TRAY_VISUAL, + + _NET_ACTIVE_WINDOW, + + // Property formats + COMPOUND_TEXT, + TEXT, + UTF8_STRING, + + // Xdnd + XdndEnter, + XdndPosition, + XdndStatus, + XdndLeave, + XdndDrop, + XdndFinished, + XdndTypelist, + XdndActionList, + + XdndSelection, + + XdndAware, + XdndProxy, + + XdndActionCopy, + XdndActionLink, + XdndActionMove, + XdndActionPrivate, + + // Motif DND + _MOTIF_DRAG_AND_DROP_MESSAGE, + _MOTIF_DRAG_INITIATOR_INFO, + _MOTIF_DRAG_RECEIVER_INFO, + _MOTIF_DRAG_WINDOW, + _MOTIF_DRAG_TARGETS, + + XmTRANSFER_SUCCESS, + XmTRANSFER_FAILURE, + + // Xkb + _XKB_RULES_NAMES, + + // XEMBED + _XEMBED, + _XEMBED_INFO, + + XWacomStylus, + XWacomCursor, + XWacomEraser, + + XTabletStylus, + XTabletEraser, + + NPredefinedAtoms, + + _QT_SETTINGS_TIMESTAMP = NPredefinedAtoms, + NAtoms + }; + + static Atom atom(X11Atom atom); + static bool isSupportedByWM(Atom atom); + + static bool useXFixes(); + static int xFixesEventBase(); + + #ifndef QT_NO_XFIXES + static PtrXFixesSelectSelectionInput xFixesSelectSelectionInput(); + #endif //QT_NO_XFIXES + + static QImage qimageFromXImage(XImage *xi); + + +}; + +#endif // QTESTLITESTATICINFO_H diff --git a/src/plugins/platforms/xlib/qxlibwindow.cpp b/src/plugins/platforms/xlib/qxlibwindow.cpp new file mode 100644 index 0000000..a7bc53c --- /dev/null +++ b/src/plugins/platforms/xlib/qxlibwindow.cpp @@ -0,0 +1,736 @@ +/**************************************************************************** +** +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, 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. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qxlibwindow.h" + +#include "qxlibintegration.h" +#include "qxlibscreen.h" +#include "qxlibkeyboard.h" +#include "qxlibstatic.h" +#include "qxlibdisplay.h" + +#include <QtGui/QWindowSystemInterface> +#include <QSocketNotifier> +#include <QApplication> +#include <QDebug> + +#include <QtGui/private/qwindowsurface_p.h> +#include <QtGui/private/qapplication_p.h> + +#if !defined(QT_NO_OPENGL) +#if !defined(QT_OPENGL_ES_2) +#include "qglxintegration.h" +#else +#include "../eglconvenience/qeglconvenience.h" +#include "../eglconvenience/qeglplatformcontext.h" +#include "../eglconvenience/qxlibeglintegration.h" +#endif //QT_OPENGL_ES_2 +#endif //QT_NO_OPENGL + +//#define MYX11_DEBUG + +QT_BEGIN_NAMESPACE + +QXlibWindow::QXlibWindow(QWidget *window) + : QPlatformWindow(window) + , mGLContext(0) + , mScreen(QXlibScreen::testLiteScreenForWidget(window)) +{ + int x = window->x(); + int y = window->y(); + int w = window->width(); + int h = window->height(); + + if(window->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenGL + && QApplicationPrivate::platformIntegration()->hasOpenGL() ) { +#if !defined(QT_NO_OPENGL) +#if !defined(QT_OPENGL_ES_2) + XVisualInfo *visualInfo = QGLXContext::findVisualInfo(mScreen,window->platformWindowFormat()); +#else + QPlatformWindowFormat windowFormat = correctColorBuffers(window->platformWindowFormat()); + + EGLDisplay eglDisplay = eglGetDisplay(mScreen->display()->nativeDisplay()); + EGLConfig eglConfig = q_configFromQPlatformWindowFormat(eglDisplay,windowFormat); + VisualID id = QXlibEglIntegration::getCompatibleVisualId(mScreen->display()->nativeDisplay(),eglConfig); + + XVisualInfo visualInfoTemplate; + memset(&visualInfoTemplate, 0, sizeof(XVisualInfo)); + visualInfoTemplate.visualid = id; + + XVisualInfo *visualInfo; + int matchingCount = 0; + visualInfo = XGetVisualInfo(mScreen->display()->nativeDisplay(), VisualIDMask, &visualInfoTemplate, &matchingCount); +#endif //!defined(QT_OPENGL_ES_2) + if (visualInfo) { + Colormap cmap = XCreateColormap(mScreen->display()->nativeDisplay(),mScreen->rootWindow(),visualInfo->visual,AllocNone); + + XSetWindowAttributes a; + a.colormap = cmap; + x_window = XCreateWindow(mScreen->display()->nativeDisplay(), mScreen->rootWindow(),x, y, w, h, + 0, visualInfo->depth, InputOutput, visualInfo->visual, + CWColormap, &a); + } else { + qFatal("no window!"); + } +#endif //!defined(QT_NO_OPENGL) + } else { + x_window = XCreateSimpleWindow(mScreen->display()->nativeDisplay(), mScreen->rootWindow(), + x, y, w, h, 0 /*border_width*/, + mScreen->blackPixel(), mScreen->whitePixel()); + } + +#ifdef MYX11_DEBUG + qDebug() << "QTestLiteWindow::QTestLiteWindow creating" << hex << x_window << window; +#endif + + XSetWindowBackgroundPixmap(mScreen->display()->nativeDisplay(), x_window, XNone); + + XSelectInput(mScreen->display()->nativeDisplay(), x_window, + ExposureMask | KeyPressMask | KeyReleaseMask | + EnterWindowMask | LeaveWindowMask | FocusChangeMask | + PointerMotionMask | ButtonPressMask | ButtonReleaseMask | + ButtonMotionMask | PropertyChangeMask | + StructureNotifyMask); + + gc = createGC(); + + Atom protocols[5]; + int n = 0; + protocols[n++] = QXlibStatic::atom(QXlibStatic::WM_DELETE_WINDOW); // support del window protocol + protocols[n++] = QXlibStatic::atom(QXlibStatic::WM_TAKE_FOCUS); // support take focus window protocol + protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_PING); // support _NET_WM_PING protocol +#ifndef QT_NO_XSYNC + protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_SYNC_REQUEST); // support _NET_WM_SYNC_REQUEST protocol +#endif // QT_NO_XSYNC + if (window->windowFlags() & Qt::WindowContextHelpButtonHint) + protocols[n++] = QXlibStatic::atom(QXlibStatic::_NET_WM_CONTEXT_HELP); + XSetWMProtocols(mScreen->display()->nativeDisplay(), x_window, protocols, n); +} + + + +QXlibWindow::~QXlibWindow() +{ +#ifdef MYX11_DEBUG + qDebug() << "~QTestLiteWindow" << hex << x_window; +#endif + delete mGLContext; + XFreeGC(mScreen->display()->nativeDisplay(), gc); + XDestroyWindow(mScreen->display()->nativeDisplay(), x_window); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Mouse event stuff +static Qt::MouseButtons translateMouseButtons(int s) +{ + Qt::MouseButtons ret = 0; + if (s & Button1Mask) + ret |= Qt::LeftButton; + if (s & Button2Mask) + ret |= Qt::MidButton; + if (s & Button3Mask) + ret |= Qt::RightButton; + return ret; +} + + + +void QXlibWindow::handleMouseEvent(QEvent::Type type, XButtonEvent *e) +{ + static QPoint mousePoint; + + Qt::MouseButton button = Qt::NoButton; + Qt::MouseButtons buttons = translateMouseButtons(e->state); + Qt::KeyboardModifiers modifiers = mScreen->keyboard()->translateModifiers(e->state); + if (type != QEvent::MouseMove) { + switch (e->button) { + case Button1: button = Qt::LeftButton; break; + case Button2: button = Qt::MidButton; break; + case Button3: button = Qt::RightButton; break; + case Button4: + case Button5: + case 6: + case 7: { + //mouse wheel + if (type == QEvent::MouseButtonPress) { + //logic borrowed from qapplication_x11.cpp + int delta = 120 * ((e->button == Button4 || e->button == 6) ? 1 : -1); + bool hor = (((e->button == Button4 || e->button == Button5) + && (modifiers & Qt::AltModifier)) + || (e->button == 6 || e->button == 7)); + QWindowSystemInterface::handleWheelEvent(widget(), e->time, + QPoint(e->x, e->y), + QPoint(e->x_root, e->y_root), + delta, hor ? Qt::Horizontal : Qt::Vertical); + } + return; + } + default: break; + } + } + + buttons ^= button; // X event uses state *before*, Qt uses state *after* + + QWindowSystemInterface::handleMouseEvent(widget(), e->time, QPoint(e->x, e->y), + QPoint(e->x_root, e->y_root), + buttons); + + mousePoint = QPoint(e->x_root, e->y_root); +} + +void QXlibWindow::handleCloseEvent() +{ + QWindowSystemInterface::handleCloseEvent(widget()); +} + + +void QXlibWindow::handleEnterEvent() +{ + QWindowSystemInterface::handleEnterEvent(widget()); +} + +void QXlibWindow::handleLeaveEvent() +{ + QWindowSystemInterface::handleLeaveEvent(widget()); +} + +void QXlibWindow::handleFocusInEvent() +{ + QWindowSystemInterface::handleWindowActivated(widget()); +} + +void QXlibWindow::handleFocusOutEvent() +{ + QWindowSystemInterface::handleWindowActivated(0); +} + + + +void QXlibWindow::setGeometry(const QRect &rect) +{ + XMoveResizeWindow(mScreen->display()->nativeDisplay(), x_window, rect.x(), rect.y(), rect.width(), rect.height()); + QPlatformWindow::setGeometry(rect); +} + + +Qt::WindowFlags QXlibWindow::windowFlags() const +{ + return mWindowFlags; +} + +WId QXlibWindow::winId() const +{ + return x_window; +} + +void QXlibWindow::setParent(const QPlatformWindow *window) +{ + QPoint topLeft = geometry().topLeft(); + XReparentWindow(mScreen->display()->nativeDisplay(),x_window,window->winId(),topLeft.x(),topLeft.y()); +} + +void QXlibWindow::raise() +{ + XRaiseWindow(mScreen->display()->nativeDisplay(), x_window); +} + +void QXlibWindow::lower() +{ + XLowerWindow(mScreen->display()->nativeDisplay(), x_window); +} + +void QXlibWindow::setWindowTitle(const QString &title) +{ + QByteArray ba = title.toLatin1(); //We're not making a general solution here... + XTextProperty windowName; + windowName.value = (unsigned char *)ba.constData(); + windowName.encoding = XA_STRING; + windowName.format = 8; + windowName.nitems = ba.length(); + + XSetWMName(mScreen->display()->nativeDisplay(), x_window, &windowName); +} + +GC QXlibWindow::createGC() +{ + GC gc; + + gc = XCreateGC(mScreen->display()->nativeDisplay(), x_window, 0, 0); + if (gc < 0) { + qWarning("QTestLiteWindow::createGC() could not create GC"); + } + return gc; +} + +void QXlibWindow::paintEvent() +{ +#ifdef MYX11_DEBUG +// qDebug() << "QTestLiteWindow::paintEvent" << shm_img.size() << painted; +#endif + + if (QWindowSurface *surface = widget()->windowSurface()) + surface->flush(widget(), widget()->geometry(), QPoint()); +} + +void QXlibWindow::requestActivateWindow() +{ + XSetInputFocus(mScreen->display()->nativeDisplay(), x_window, XRevertToParent, CurrentTime); +} + +void QXlibWindow::resizeEvent(XConfigureEvent *e) +{ + int xpos = geometry().x(); + int ypos = geometry().y(); + if ((e->width != geometry().width() || e->height != geometry().height()) && e->x == 0 && e->y == 0) { + //qDebug() << "resize with bogus pos" << e->x << e->y << e->width << e->height << "window"<< hex << window; + } else { + //qDebug() << "geometry change" << e->x << e->y << e->width << e->height << "window"<< hex << window; + xpos = e->x; + ypos = e->y; + } +#ifdef MYX11_DEBUG + qDebug() << hex << x_window << dec << "ConfigureNotify" << e->x << e->y << e->width << e->height << "geometry" << xpos << ypos << width << height; +#endif + + QRect newRect(xpos, ypos, e->width, e->height); + QWindowSystemInterface::handleGeometryChange(widget(), newRect); +} + +void QXlibWindow::mousePressEvent(XButtonEvent *e) +{ + static long prevTime = 0; + static Window prevWindow; + static int prevX = -999; + static int prevY = -999; + + QEvent::Type type = QEvent::MouseButtonPress; + + if (e->window == prevWindow && long(e->time) - prevTime < QApplication::doubleClickInterval() + && qAbs(e->x - prevX) < 5 && qAbs(e->y - prevY) < 5) { + type = QEvent::MouseButtonDblClick; + prevTime = e->time - QApplication::doubleClickInterval(); //no double click next time + } else { + prevTime = e->time; + } + prevWindow = e->window; + prevX = e->x; + prevY = e->y; + + handleMouseEvent(type, e); +} + +QXlibMWMHints QXlibWindow::getMWMHints() const +{ + QXlibMWMHints mwmhints; + + Atom type; + int format; + ulong nitems, bytesLeft; + uchar *data = 0; + Atom atomForMotifWmHints = QXlibStatic::atom(QXlibStatic::_MOTIF_WM_HINTS); + if ((XGetWindowProperty(mScreen->display()->nativeDisplay(), x_window, atomForMotifWmHints, 0, 5, false, + atomForMotifWmHints, &type, &format, &nitems, &bytesLeft, + &data) == Success) + && (type == atomForMotifWmHints + && format == 32 + && nitems >= 5)) { + mwmhints = *(reinterpret_cast<QXlibMWMHints *>(data)); + } else { + mwmhints.flags = 0L; + mwmhints.functions = MWM_FUNC_ALL; + mwmhints.decorations = MWM_DECOR_ALL; + mwmhints.input_mode = 0L; + mwmhints.status = 0L; + } + + if (data) + XFree(data); + + return mwmhints; +} + +void QXlibWindow::setMWMHints(const QXlibMWMHints &mwmhints) +{ + Atom atomForMotifWmHints = QXlibStatic::atom(QXlibStatic::_MOTIF_WM_HINTS); + if (mwmhints.flags != 0l) { + XChangeProperty(mScreen->display()->nativeDisplay(), x_window, + atomForMotifWmHints, atomForMotifWmHints, 32, + PropModeReplace, (unsigned char *) &mwmhints, 5); + } else { + XDeleteProperty(mScreen->display()->nativeDisplay(), x_window, atomForMotifWmHints); + } +} + +// Returns true if we should set WM_TRANSIENT_FOR on \a w +static inline bool isTransient(const QWidget *w) +{ + return ((w->windowType() == Qt::Dialog + || w->windowType() == Qt::Sheet + || w->windowType() == Qt::Tool + || w->windowType() == Qt::SplashScreen + || w->windowType() == Qt::ToolTip + || w->windowType() == Qt::Drawer + || w->windowType() == Qt::Popup) + && !w->testAttribute(Qt::WA_X11BypassTransientForHint)); +} + +QVector<Atom> QXlibWindow::getNetWmState() const +{ + QVector<Atom> returnValue; + + // Don't read anything, just get the size of the property data + Atom actualType; + int actualFormat; + ulong propertyLength; + ulong bytesLeft; + uchar *propertyData = 0; + if (XGetWindowProperty(mScreen->display()->nativeDisplay(), x_window, QXlibStatic::atom(QXlibStatic::_NET_WM_STATE), 0, 0, + False, XA_ATOM, &actualType, &actualFormat, + &propertyLength, &bytesLeft, &propertyData) == Success + && actualType == XA_ATOM && actualFormat == 32) { + returnValue.resize(bytesLeft / 4); + XFree((char*) propertyData); + + // fetch all data + if (XGetWindowProperty(mScreen->display()->nativeDisplay(), x_window, QXlibStatic::atom(QXlibStatic::_NET_WM_STATE), 0, + returnValue.size(), False, XA_ATOM, &actualType, &actualFormat, + &propertyLength, &bytesLeft, &propertyData) != Success) { + returnValue.clear(); + } else if (propertyLength != (ulong)returnValue.size()) { + returnValue.resize(propertyLength); + } + + // put it into netWmState + if (!returnValue.isEmpty()) { + memcpy(returnValue.data(), propertyData, returnValue.size() * sizeof(Atom)); + } + XFree((char*) propertyData); + } + + return returnValue; +} + +Qt::WindowFlags QXlibWindow::setWindowFlags(Qt::WindowFlags flags) +{ +// Q_ASSERT(flags & Qt::Window); + mWindowFlags = flags; + +#ifdef MYX11_DEBUG + qDebug() << "QTestLiteWindow::setWindowFlags" << hex << x_window << "flags" << flags; +#endif + Qt::WindowType type = static_cast<Qt::WindowType>(int(flags & Qt::WindowType_Mask)); + + if (type == Qt::ToolTip) + flags |= Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::X11BypassWindowManagerHint; + if (type == Qt::Popup) + flags |= Qt::X11BypassWindowManagerHint; + + bool topLevel = (flags & Qt::Window); + bool popup = (type == Qt::Popup); + bool dialog = (type == Qt::Dialog + || type == Qt::Sheet); + bool desktop = (type == Qt::Desktop); + bool tool = (type == Qt::Tool || type == Qt::SplashScreen + || type == Qt::ToolTip || type == Qt::Drawer); + + Q_UNUSED(topLevel); + Q_UNUSED(dialog); + Q_UNUSED(desktop); + + bool tooltip = (type == Qt::ToolTip); + + XSetWindowAttributes wsa; + + QXlibMWMHints mwmhints; + mwmhints.flags = 0L; + mwmhints.functions = 0L; + mwmhints.decorations = 0; + mwmhints.input_mode = 0L; + mwmhints.status = 0L; + + + ulong wsa_mask = 0; + if (type != Qt::SplashScreen) { // && customize) { + mwmhints.flags |= MWM_HINTS_DECORATIONS; + + bool customize = flags & Qt::CustomizeWindowHint; + if (!(flags & Qt::FramelessWindowHint) && !(customize && !(flags & Qt::WindowTitleHint))) { + mwmhints.decorations |= MWM_DECOR_BORDER; + mwmhints.decorations |= MWM_DECOR_RESIZEH; + + if (flags & Qt::WindowTitleHint) + mwmhints.decorations |= MWM_DECOR_TITLE; + + if (flags & Qt::WindowSystemMenuHint) + mwmhints.decorations |= MWM_DECOR_MENU; + + if (flags & Qt::WindowMinimizeButtonHint) { + mwmhints.decorations |= MWM_DECOR_MINIMIZE; + mwmhints.functions |= MWM_FUNC_MINIMIZE; + } + + if (flags & Qt::WindowMaximizeButtonHint) { + mwmhints.decorations |= MWM_DECOR_MAXIMIZE; + mwmhints.functions |= MWM_FUNC_MAXIMIZE; + } + + if (flags & Qt::WindowCloseButtonHint) + mwmhints.functions |= MWM_FUNC_CLOSE; + } + } else { + // if type == Qt::SplashScreen + mwmhints.decorations = MWM_DECOR_ALL; + } + + if (tool) { + wsa.save_under = True; + wsa_mask |= CWSaveUnder; + } + + if (flags & Qt::X11BypassWindowManagerHint) { + wsa.override_redirect = True; + wsa_mask |= CWOverrideRedirect; + } +#if 0 + if (wsa_mask && initializeWindow) { + Q_ASSERT(id); + XChangeWindowAttributes(dpy, id, wsa_mask, &wsa); + } +#endif + if (mwmhints.functions != 0) { + mwmhints.flags |= MWM_HINTS_FUNCTIONS; + mwmhints.functions |= MWM_FUNC_MOVE | MWM_FUNC_RESIZE; + } else { + mwmhints.functions = MWM_FUNC_ALL; + } + + if (!(flags & Qt::FramelessWindowHint) + && flags & Qt::CustomizeWindowHint + && flags & Qt::WindowTitleHint + && !(flags & + (Qt::WindowMinimizeButtonHint + | Qt::WindowMaximizeButtonHint + | Qt::WindowCloseButtonHint))) { + // a special case - only the titlebar without any button + mwmhints.flags = MWM_HINTS_FUNCTIONS; + mwmhints.functions = MWM_FUNC_MOVE | MWM_FUNC_RESIZE; + mwmhints.decorations = 0; + } + + if (widget()->windowModality() == Qt::WindowModal) { + mwmhints.input_mode = MWM_INPUT_PRIMARY_APPLICATION_MODAL; + } else if (widget()->windowModality() == Qt::ApplicationModal) { + mwmhints.input_mode = MWM_INPUT_FULL_APPLICATION_MODAL; + } + + setMWMHints(mwmhints); + + QVector<Atom> netWmState = getNetWmState(); + + if (flags & Qt::WindowStaysOnTopHint) { + if (flags & Qt::WindowStaysOnBottomHint) + qWarning() << "QWidget: Incompatible window flags: the window can't be on top and on bottom at the same time"; + if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_ABOVE))) + netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_ABOVE)); + if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_STAYS_ON_TOP))) + netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_STAYS_ON_TOP)); + } else if (flags & Qt::WindowStaysOnBottomHint) { + if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_BELOW))) + netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_BELOW)); + } + if (widget()->isFullScreen()) { + if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_FULLSCREEN))) + netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_FULLSCREEN)); + } + if (widget()->isMaximized()) { + if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MAXIMIZED_HORZ))) + netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MAXIMIZED_HORZ)); + if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MAXIMIZED_VERT))) + netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MAXIMIZED_VERT)); + } + if (widget()->windowModality() != Qt::NonModal) { + if (!netWmState.contains(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MODAL))) + netWmState.append(QXlibStatic::atom(QXlibStatic::_NET_WM_STATE_MODAL)); + } + + if (!netWmState.isEmpty()) { + XChangeProperty(mScreen->display()->nativeDisplay(), x_window, + QXlibStatic::atom(QXlibStatic::_NET_WM_STATE), XA_ATOM, 32, PropModeReplace, + (unsigned char *) netWmState.data(), netWmState.size()); + } else { + XDeleteProperty(mScreen->display()->nativeDisplay(), x_window, QXlibStatic::atom(QXlibStatic::_NET_WM_STATE)); + } + +//##### only if initializeWindow??? + + if (popup || tooltip) { // popup widget +#ifdef MYX11_DEBUG + qDebug() << "Doing XChangeWindowAttributes for popup" << wsa.override_redirect; +#endif + // set EWMH window types + // setNetWmWindowTypes(); + + wsa.override_redirect = True; + wsa.save_under = True; + XChangeWindowAttributes(mScreen->display()->nativeDisplay(), x_window, CWOverrideRedirect | CWSaveUnder, + &wsa); + } else { +#ifdef MYX11_DEBUG + qDebug() << "Doing XChangeWindowAttributes for non-popup"; +#endif + } + + return flags; +} + +void QXlibWindow::setVisible(bool visible) +{ +#ifdef MYX11_DEBUG + qDebug() << "QTestLiteWindow::setVisible" << visible << hex << x_window; +#endif + if (isTransient(widget())) { + Window parentXWindow = x_window; + if (widget()->parentWidget()) { + QWidget *widgetParent = widget()->parentWidget()->window(); + if (widgetParent && widgetParent->platformWindow()) { + QXlibWindow *parentWidnow = static_cast<QXlibWindow *>(widgetParent->platformWindow()); + parentXWindow = parentWidnow->x_window; + } + } + XSetTransientForHint(mScreen->display()->nativeDisplay(),x_window,parentXWindow); + } + + if (visible) { + //ensure that the window is viewed in correct position. + doSizeHints(); + XMapWindow(mScreen->display()->nativeDisplay(), x_window); + } else { + XUnmapWindow(mScreen->display()->nativeDisplay(), x_window); + } +} + +void QXlibWindow::setCursor(const Cursor &cursor) +{ + XDefineCursor(mScreen->display()->nativeDisplay(), x_window, cursor); + mScreen->display()->flush(); +} + +QPlatformGLContext *QXlibWindow::glContext() const +{ + if (!QApplicationPrivate::platformIntegration()->hasOpenGL()) + return 0; + if (!mGLContext) { + QXlibWindow *that = const_cast<QXlibWindow *>(this); +#if !defined(QT_NO_OPENGL) +#if !defined(QT_OPENGL_ES_2) + that->mGLContext = new QGLXContext(x_window, mScreen,widget()->platformWindowFormat()); +#else + EGLDisplay display = eglGetDisplay(mScreen->display()->nativeDisplay()); + + QPlatformWindowFormat windowFormat = correctColorBuffers(widget()->platformWindowFormat()); + + EGLConfig config = q_configFromQPlatformWindowFormat(display,windowFormat); + QVector<EGLint> eglContextAttrs; + eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); + eglContextAttrs.append(2); + eglContextAttrs.append(EGL_NONE); + + EGLSurface eglSurface = eglCreateWindowSurface(display,config,(EGLNativeWindowType)x_window,0); + that->mGLContext = new QEGLPlatformContext(display, config, eglContextAttrs.data(), eglSurface, EGL_OPENGL_ES_API); +#endif +#endif + } + return mGLContext; +} + +Window QXlibWindow::xWindow() const +{ + return x_window; +} + +GC QXlibWindow::graphicsContext() const +{ + return gc; +} + +void QXlibWindow::doSizeHints() +{ + Q_ASSERT(widget()->testAttribute(Qt::WA_WState_Created)); + XSizeHints s; + s.flags = 0; + QRect g = geometry(); + s.x = g.x(); + s.y = g.y(); + s.width = g.width(); + s.height = g.height(); + s.flags |= USPosition; + s.flags |= PPosition; + s.flags |= USSize; + s.flags |= PSize; + s.flags |= PWinGravity; + s.win_gravity = QApplication::isRightToLeft() ? NorthEastGravity : NorthWestGravity; + XSetWMNormalHints(mScreen->display()->nativeDisplay(), x_window, &s); +} + +QPlatformWindowFormat QXlibWindow::correctColorBuffers(const QPlatformWindowFormat &platformWindowFormat) const +{ + // I have only tested this setup on a dodgy intel setup, where I didn't use standard libs, + // so this might be not what we want to do :) + if ( !(platformWindowFormat.redBufferSize() == -1 && + platformWindowFormat.greenBufferSize() == -1 && + platformWindowFormat.blueBufferSize() == -1)) + return platformWindowFormat; + + QPlatformWindowFormat windowFormat = platformWindowFormat; + if (mScreen->depth() == 16) { + windowFormat.setRedBufferSize(5); + windowFormat.setGreenBufferSize(6); + windowFormat.setBlueBufferSize(5); + } else { + windowFormat.setRedBufferSize(8); + windowFormat.setGreenBufferSize(8); + windowFormat.setBlueBufferSize(8); + } + + return windowFormat; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestlitewindow.h b/src/plugins/platforms/xlib/qxlibwindow.h index dc628f1..08694a5 100644 --- a/src/plugins/platforms/testlite/qtestlitewindow.h +++ b/src/plugins/platforms/xlib/qxlibwindow.h @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -42,77 +42,67 @@ #ifndef QTESTLITEWINDOW_H #define QTESTLITEWINDOW_H +#include "qxlibintegration.h" + #include <QPlatformWindow> -#include <qevent.h> +#include <QEvent> #include <QObject> #include <QImage> -#include <qtimer.h> -#include <QDateTime> - -#include <private/qt_x11_p.h> - -#include <X11/Xlib.h> -#include <X11/Xutil.h> - - - -class QTestLiteIntegration; -class QTestLiteScreen; -class QTestLiteWindowSurface; -class MyX11Cursors; -class QTestLiteWindow; -class MyDisplay : public QObject -{ - Q_OBJECT; -public: - MyDisplay(); - ~MyDisplay(); +struct QXlibMWMHints { + ulong flags, functions, decorations; + long input_mode; + ulong status; +}; - Window rootWindow() { return RootWindow(display, screen); } - unsigned long blackPixel() { return BlackPixel(display, screen); } - unsigned long whitePixel() { return WhitePixel(display, screen); } +enum { + MWM_HINTS_FUNCTIONS = (1L << 0), - bool handleEvent(XEvent *xe); - QImage grabWindow(Window window, int x, int y, int w, int h); + MWM_FUNC_ALL = (1L << 0), + MWM_FUNC_RESIZE = (1L << 1), + MWM_FUNC_MOVE = (1L << 2), + MWM_FUNC_MINIMIZE = (1L << 3), + MWM_FUNC_MAXIMIZE = (1L << 4), + MWM_FUNC_CLOSE = (1L << 5), -public slots: - void eventDispatcher(); + MWM_HINTS_DECORATIONS = (1L << 1), -public: //### - Display * display; - int screen; - int width, height; - int physicalWidth; - int physicalHeight; + MWM_DECOR_ALL = (1L << 0), + MWM_DECOR_BORDER = (1L << 1), + MWM_DECOR_RESIZEH = (1L << 2), + MWM_DECOR_TITLE = (1L << 3), + MWM_DECOR_MENU = (1L << 4), + MWM_DECOR_MINIMIZE = (1L << 5), + MWM_DECOR_MAXIMIZE = (1L << 6), - QList<QTestLiteWindow*> windowList; + MWM_HINTS_INPUT_MODE = (1L << 2), - MyX11Cursors * cursors; + MWM_INPUT_MODELESS = 0L, + MWM_INPUT_PRIMARY_APPLICATION_MODAL = 1L, + MWM_INPUT_FULL_APPLICATION_MODAL = 3L }; -struct MyShmImageInfo; - -class QTestLiteWindow : public QPlatformWindow +class QXlibWindow : public QPlatformWindow { public: - QTestLiteWindow(const QTestLiteIntegration *platformIntegration, - QTestLiteScreen *screen, QWidget *window); - ~QTestLiteWindow(); + QXlibWindow(QWidget *window); + ~QXlibWindow(); void mousePressEvent(XButtonEvent*); void handleMouseEvent(QEvent::Type, XButtonEvent *ev); - void handleKeyEvent(QEvent::Type, void *); void handleCloseEvent(); void handleEnterEvent(); void handleLeaveEvent(); + void handleFocusInEvent(); + void handleFocusOutEvent(); void resizeEvent(XConfigureEvent *configure_event); void paintEvent(); + void requestActivateWindow(); void setGeometry(const QRect &rect); @@ -125,33 +115,31 @@ public: void lower(); void setWindowTitle(const QString &title); - void setCursor(QCursor * cursor); + void setCursor(const Cursor &cursor); QPlatformGLContext *glContext() const; + Window xWindow() const; + GC graphicsContext() const; + +protected: + QVector<Atom> getNetWmState() const; + void setMWMHints(const QXlibMWMHints &mwmhints); + QXlibMWMHints getMWMHints() const; + + void doSizeHints(); + private: - int xpos, ypos; - int width, height; + QPlatformWindowFormat correctColorBuffers(const QPlatformWindowFormat &windowFormat)const; + Window x_window; GC gc; GC createGC(); - Cursor createCursorShape(int cshape); - Cursor createCursorBitmap(QCursor * cursor); - - int currentCursor; - - MyDisplay *xd; - QTestLiteScreen *mScreen; - Qt::WindowFlags window_flags; QPlatformGLContext *mGLContext; - - friend class QTestLiteWindowSurface; // x_window, gc and windowSurface + QXlibScreen *mScreen; + Qt::WindowFlags mWindowFlags; }; - - - - #endif diff --git a/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp b/src/plugins/platforms/xlib/qxlibwindowsurface.cpp index b3232c8..513f10d 100644 --- a/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp +++ b/src/plugins/platforms/xlib/qxlibwindowsurface.cpp @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -39,13 +39,15 @@ ** ****************************************************************************/ -#include "qtestlitewindowsurface.h" -#include "qtestliteintegration.h" +#include "qxlibwindowsurface.h" +#include "qxlibintegration.h" #include <QtCore/qdebug.h> #include <QWindowSystemInterface> -#include "qtestlitewindow.h" +#include "qxlibwindow.h" +#include "qxlibscreen.h" +#include "qxlibdisplay.h" # include <sys/ipc.h> # include <sys/shm.h> @@ -54,9 +56,9 @@ QT_BEGIN_NAMESPACE -struct MyShmImageInfo { - MyShmImageInfo(Display *xdisplay) : image(0), display(xdisplay) {} - ~MyShmImageInfo() { destroy(); } +struct QXlibShmImageInfo { + QXlibShmImageInfo(Display *xdisplay) : image(0), display(xdisplay) {} + ~QXlibShmImageInfo() { destroy(); } void destroy(); @@ -65,11 +67,9 @@ struct MyShmImageInfo { Display *display; }; -//void QTestLiteWindowSurface::flush() - #ifndef DONT_USE_MIT_SHM -void MyShmImageInfo::destroy() +void QXlibShmImageInfo::destroy() { XShmDetach (display, &shminfo); XDestroyImage (image); @@ -78,22 +78,22 @@ void MyShmImageInfo::destroy() } #endif -void QTestLiteWindowSurface::resizeShmImage(int width, int height) +void QXlibWindowSurface::resizeShmImage(int width, int height) { - MyDisplay *xd = xw->xd; #ifdef DONT_USE_MIT_SHM shm_img = QImage(width, height, QImage::Format_RGB32); #else + + QXlibScreen *screen = QXlibScreen::testLiteScreenForWidget(window()); if (image_info) image_info->destroy(); else - image_info = new MyShmImageInfo(xd->display); + image_info = new QXlibShmImageInfo(screen->display()->nativeDisplay()); - Visual *visual = DefaultVisual(xd->display, xd->screen); + Visual *visual = screen->defaultVisual(); - - XImage *image = XShmCreateImage (xd->display, visual, 24, ZPixmap, 0, + XImage *image = XShmCreateImage (screen->display()->nativeDisplay(), visual, 24, ZPixmap, 0, &image_info->shminfo, width, height); @@ -105,7 +105,7 @@ void QTestLiteWindowSurface::resizeShmImage(int width, int height) image_info->image = image; - Status shm_attach_status = XShmAttach(xd->display, &image_info->shminfo); + Status shm_attach_status = XShmAttach(screen->display()->nativeDisplay(), &image_info->shminfo); Q_ASSERT(shm_attach_status == True); @@ -115,65 +115,63 @@ void QTestLiteWindowSurface::resizeShmImage(int width, int height) } -void QTestLiteWindowSurface::resizeBuffer(QSize s) +void QXlibWindowSurface::resizeBuffer(QSize s) { if (shm_img.size() != s) resizeShmImage(s.width(), s.height()); } -QSize QTestLiteWindowSurface::bufferSize() const +QSize QXlibWindowSurface::bufferSize() const { return shm_img.size(); } -QTestLiteWindowSurface::QTestLiteWindowSurface (QTestLiteScreen */*screen*/, QWidget *window) +QXlibWindowSurface::QXlibWindowSurface (QWidget *window) : QWindowSurface(window), painted(false), image_info(0) { - xw = static_cast<QTestLiteWindow*>(window->platformWindow()); + xw = static_cast<QXlibWindow*>(window->platformWindow()); // qDebug() << "QTestLiteWindowSurface::QTestLiteWindowSurface:" << xw->window; } -QTestLiteWindowSurface::~QTestLiteWindowSurface() +QXlibWindowSurface::~QXlibWindowSurface() { delete image_info; } -QPaintDevice *QTestLiteWindowSurface::paintDevice() +QPaintDevice *QXlibWindowSurface::paintDevice() { return &shm_img; } -void QTestLiteWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +void QXlibWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) { Q_UNUSED(widget); Q_UNUSED(region); Q_UNUSED(offset); - // qDebug() << "QTestLiteWindowSurface::flush:" << (long)this; - if (!painted) return; - MyDisplay *xd = xw->xd; - GC gc = xw->gc; - Window window = xw->x_window; + QXlibScreen *screen = QXlibScreen::testLiteScreenForWidget(widget); + GC gc = xw->graphicsContext(); + Window window = xw->xWindow(); #ifdef DONT_USE_MIT_SHM // just convert the image every time... if (!shm_img.isNull()) { - Visual *visual = DefaultVisual(xd->display, xd->screen); + Visual *visual = DefaultVisual(screen->display(), screen->xScreenNumber()); QImage image = shm_img; //img.convertToFormat( - XImage *xi = XCreateImage(xd->display, visual, 24, ZPixmap, + XImage *xi = XCreateImage(screen->display(), visual, 24, ZPixmap, 0, (char *) image.scanLine(0), image.width(), image.height(), 32, image.bytesPerLine()); int x = 0; int y = 0; - /*int r =*/ XPutImage(xd->display, window, gc, xi, 0, 0, x, y, image.width(), image.height()); + /*int r =*/ XPutImage(screen->display(), window, gc, xi, 0, 0, x, y, image.width(), image.height()); xi->data = 0; // QImage owns these bits XDestroyImage(xi); @@ -187,11 +185,11 @@ void QTestLiteWindowSurface::flush(QWidget *widget, const QRegion ®ion, const // We could set send_event to true, and then use the ShmCompletion to synchronize, // but let's do like Qt/11 and just use XSync - XShmPutImage (xd->display, window, gc, image_info->image, 0, 0, + XShmPutImage (screen->display()->nativeDisplay(), window, gc, image_info->image, 0, 0, x, y, image_info->image->width, image_info->image->height, /*send_event*/ False); - XSync(xd->display, False); + screen->display()->sync(); } #endif } @@ -199,7 +197,7 @@ void QTestLiteWindowSurface::flush(QWidget *widget, const QRegion ®ion, const // from qwindowsurface.cpp extern void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset); -bool QTestLiteWindowSurface::scroll(const QRegion &area, int dx, int dy) +bool QXlibWindowSurface::scroll(const QRegion &area, int dx, int dy) { if (shm_img.isNull()) return false; @@ -212,13 +210,13 @@ bool QTestLiteWindowSurface::scroll(const QRegion &area, int dx, int dy) } -void QTestLiteWindowSurface::beginPaint(const QRegion ®ion) +void QXlibWindowSurface::beginPaint(const QRegion ®ion) { Q_UNUSED(region); resizeBuffer(size()); } -void QTestLiteWindowSurface::endPaint(const QRegion ®ion) +void QXlibWindowSurface::endPaint(const QRegion ®ion) { Q_UNUSED(region); painted = true; //there is content in the buffer diff --git a/src/plugins/platforms/testlite/qtestlitewindowsurface.h b/src/plugins/platforms/xlib/qxlibwindowsurface.h index 915e7fe..d46b7b4 100644 --- a/src/plugins/platforms/testlite/qtestlitewindowsurface.h +++ b/src/plugins/platforms/xlib/qxlibwindowsurface.h @@ -1,10 +1,10 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** -** This file is part of the QtOpenVG module of the Qt Toolkit. +** This file is part of the plugins of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage @@ -47,21 +47,19 @@ QT_BEGIN_NAMESPACE -class QTestLiteWindow; -class QTestLiteIntegration; -class QTestLiteScreen; -class MyShmImageInfo; +class QXlibWindow; +class QXlibIntegration; +class QXlibScreen; +class QXlibShmImageInfo; -class QTestLiteWindowSurface : public QWindowSurface +class QXlibWindowSurface : public QWindowSurface { public: - QTestLiteWindowSurface (QTestLiteScreen *screen, QWidget *window); - ~QTestLiteWindowSurface(); + QXlibWindowSurface (QWidget *window); + ~QXlibWindowSurface(); QPaintDevice *paintDevice(); -// void flush(); void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); -// void resize(const QSize &size); bool scroll(const QRegion &area, int dx, int dy); void beginPaint(const QRegion ®ion); @@ -76,9 +74,9 @@ private: void resizeShmImage(int width, int height); QImage shm_img; - MyShmImageInfo *image_info; + QXlibShmImageInfo *image_info; - QTestLiteWindow *xw; + QXlibWindow *xw; }; diff --git a/src/plugins/platforms/xlib/xlib.pro b/src/plugins/platforms/xlib/xlib.pro new file mode 100644 index 0000000..159fdbe --- /dev/null +++ b/src/plugins/platforms/xlib/xlib.pro @@ -0,0 +1,59 @@ +TARGET = qxlib + +include(../../qpluginbase.pri) +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +SOURCES = \ + main.cpp \ + qxlibintegration.cpp \ + qxlibwindowsurface.cpp \ + qxlibwindow.cpp \ + qxlibcursor.cpp \ + qxlibscreen.cpp \ + qxlibkeyboard.cpp \ + qxlibclipboard.cpp \ + qxlibmime.cpp \ + qxlibstatic.cpp \ + qxlibdisplay.cpp + +HEADERS = \ + qxlibintegration.h \ + qxlibwindowsurface.h \ + qxlibwindow.h \ + qxlibcursor.h \ + qxlibscreen.h \ + qxlibkeyboard.h \ + qxlibclipboard.h \ + qxlibmime.h \ + qxlibstatic.h \ + qxlibdisplay.h + +LIBS += -lX11 -lXext + +mac { + LIBS += -L/usr/X11/lib -lz -framework Carbon +} + +include (../fontdatabases/genericunix/genericunix.pri) + +contains(QT_CONFIG, opengl) { + QT += opengl + !contains(QT_CONFIG, opengles2) { + HEADERS += qglxintegration.h + SOURCES += qglxintegration.cpp + } else { # There is no easy way to detect if we'r suppose to use glx or not + HEADERS += \ + ../eglconvenience/qeglplatformcontext.h \ + ../eglconvenience/qeglconvenience.h \ + ../eglconvenience/qxlibeglintegration.h + + SOURCES += \ + ../eglconvenience/qeglplatformcontext.cpp \ + ../eglconvenience/qeglconvenience.cpp \ + ../eglconvenience/qxlibeglintegration.cpp + LIBS += -lEGL + } +} + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target |