diff options
author | Qt Continuous Integration System <qt-info@nokia.com> | 2010-10-29 06:22:14 (GMT) |
---|---|---|
committer | Qt Continuous Integration System <qt-info@nokia.com> | 2010-10-29 06:22:14 (GMT) |
commit | 8943b44c38ee6244c4a5b190c2b35879b1921843 (patch) | |
tree | 71ba80eacd8292f89af2b6c90a1f1f0e7beea455 /src | |
parent | 77819edac505823226c40033e76d2dda0e8b363a (diff) | |
parent | 8b7dad6c1290c3c5f9ce35ea9d13a4b7e6398572 (diff) | |
download | Qt-8943b44c38ee6244c4a5b190c2b35879b1921843.zip Qt-8943b44c38ee6244c4a5b190c2b35879b1921843.tar.gz Qt-8943b44c38ee6244c4a5b190c2b35879b1921843.tar.bz2 |
Merge branch 'staging-master' of scm.dev.nokia.troll.no:qt/qt-lighthouse into master-integration
* 'staging-master' of scm.dev.nokia.troll.no:qt/qt-lighthouse: (388 commits)
Fix the license in files for Lighthouse
Fix typos found by the spellchecking autotest
Add missing QT_MODULE macros.
Fix qt_defaultDpi, but not use Q_DECL_IMPORT but Q_GUI_EXPORT
Compile fix for RVCT 4
Fix QT_BLITTER_RASTEROVERLAY and namespace error
Lighthouse: initial COCOA plugin
Lighthouse on OS X.
Fix QWS generic mac mkspec
actually set egl swap interval
Remove debug code added by 650a0078e2cef43eff107fe8d2505f64a0bfedf0
Update sections if model content changes.
Don't clobber the tty by default
Add touch offset
Jitter removal
Mouse event compression
Add keycodes for some additional multimedia keys
Make it possible to choose some EGLFS configuration options via envvars
use swapInterval=1 by default in EglFS to potentially avoid tearing
Lighthouse: make QFontconfigDatabase not override application font
...
Diffstat (limited to 'src')
275 files changed, 30977 insertions, 184 deletions
diff --git a/src/3rdparty/phonon/gstreamer/devicemanager.cpp b/src/3rdparty/phonon/gstreamer/devicemanager.cpp index c3826eb..518aa85 100644 --- a/src/3rdparty/phonon/gstreamer/devicemanager.cpp +++ b/src/3rdparty/phonon/gstreamer/devicemanager.cpp @@ -22,7 +22,9 @@ #include "videowidget.h" #include "glrenderer.h" #include "widgetrenderer.h" +#ifdef Q_WS_X11 #include "x11renderer.h" +#endif #include "artssink.h" #include "pulsesupport.h" @@ -264,7 +266,7 @@ AbstractRenderer *DeviceManager::createVideoRenderer(VideoWidget *parent) if (m_videoSinkWidget == "software") { return new WidgetRenderer(parent); } -#ifndef Q_WS_QWS +#ifdef Q_WS_X11 else if (m_videoSinkWidget == "xwindow") { return new X11Renderer(parent); } else { diff --git a/src/3rdparty/phonon/gstreamer/videowidget.cpp b/src/3rdparty/phonon/gstreamer/videowidget.cpp index e1f0ec9..a4c6f79 100644 --- a/src/3rdparty/phonon/gstreamer/videowidget.cpp +++ b/src/3rdparty/phonon/gstreamer/videowidget.cpp @@ -31,7 +31,9 @@ #include "glrenderer.h" #include "widgetrenderer.h" +#ifdef Q_WS_X11 #include "x11renderer.h" +#endif #ifndef QT_NO_PHONON_VIDEO QT_BEGIN_NAMESPACE @@ -116,10 +118,12 @@ void VideoWidget::setupVideoBin() GstPad *videopad = gst_element_get_pad (queue, "sink"); gst_element_add_pad (m_videoBin, gst_ghost_pad_new ("sink", videopad)); gst_object_unref (videopad); +#ifndef Q_WS_QPA QWidget *parentWidget = qobject_cast<QWidget*>(parent()); if (parentWidget) parentWidget->winId(); // Due to some existing issues with alien in 4.4, // we must currently force the creation of a parent widget. +#endif m_isValid = true; //initialization ok, accept input } } diff --git a/src/3rdparty/phonon/gstreamer/x11renderer.h b/src/3rdparty/phonon/gstreamer/x11renderer.h index f7140da..8e2ea19 100644 --- a/src/3rdparty/phonon/gstreamer/x11renderer.h +++ b/src/3rdparty/phonon/gstreamer/x11renderer.h @@ -27,8 +27,6 @@ QT_BEGIN_NAMESPACE -#ifndef Q_WS_QWS - class QString; namespace Phonon @@ -61,8 +59,6 @@ private: } } //namespace Phonon::Gstreamer -#endif // Q_WS_QWS - QT_END_NAMESPACE #endif // Phonon_GSTREAMER_X11RENDERER_H diff --git a/src/3rdparty/webkit/WebCore/WebCore.pro b/src/3rdparty/webkit/WebCore/WebCore.pro index 63bde2f..3ccc57f 100644 --- a/src/3rdparty/webkit/WebCore/WebCore.pro +++ b/src/3rdparty/webkit/WebCore/WebCore.pro @@ -56,6 +56,7 @@ TEMPLATE = lib TARGET = QtWebKit contains(QT_CONFIG, embedded):CONFIG += embedded +contains(QT_CONFIG, qpa):CONFIG += embedded CONFIG(standalone_package) { isEmpty(WC_GENERATED_SOURCES_DIR):WC_GENERATED_SOURCES_DIR = $$PWD/generated diff --git a/src/corelib/arch/qatomic_arch.h b/src/corelib/arch/qatomic_arch.h index 00b288b..5106d29 100644 --- a/src/corelib/arch/qatomic_arch.h +++ b/src/corelib/arch/qatomic_arch.h @@ -88,6 +88,8 @@ QT_BEGIN_HEADER # include "QtCore/qatomic_sh.h" #elif defined(QT_ARCH_SH4A) # include "QtCore/qatomic_sh4a.h" +#elif defined(QT_ARCH_NACL) +# include "QtCore/qatomic_generic.h" #else # error "Qt has not been ported to this architecture" #endif diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index b7d6034..349b3d4 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -19,7 +19,14 @@ include(codecs/codecs.pri) include(statemachine/statemachine.pri) include(xml/xml.pri) -mac|darwin:LIBS_PRIVATE += -framework ApplicationServices +!qpa:mac|darwin:LIBS_PRIVATE += -framework ApplicationServices +qpa:mac|darwin { + contains(QT_CONFIG, coreservices) { + LIBS_PRIVATE += -framework CoreServices + } else { + LIBS_PRIVATE += -framework CoreFoundation + } +} mac:lib_bundle:DEFINES += QT_NO_DEBUG_PLUGIN_CHECK win32:DEFINES-=QT_NO_CAST_TO_ASCII diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index ad386a8..47b82ef 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -13,6 +13,10 @@ SOURCES += \ global/qmalloc.cpp \ global/qnumeric.cpp +nacl { + SOURCES += global/qnaclunimplemented.cpp +} + # qlibraryinfo.cpp includes qconfig.cpp INCLUDEPATH += $$QT_BUILD_TREE/src/corelib/global diff --git a/src/corelib/global/qconfig-minimal-system-dependencies.h b/src/corelib/global/qconfig-minimal-system-dependencies.h new file mode 100644 index 0000000..63319b9 --- /dev/null +++ b/src/corelib/global/qconfig-minimal-system-dependencies.h @@ -0,0 +1,371 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore 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$ +** +****************************************************************************/ + +#define QT_FONTS_ARE_RESOURCES + +/* Data structures */ +#ifndef QT_NO_QUUID_STRING +# define QT_NO_QUUID_STRING +#endif +#ifndef QT_NO_STL +# define QT_NO_STL +#endif +#ifndef QT_NO_TEXTDATE +# define QT_NO_TEXTDATE +#endif +#ifndef QT_NO_DATESTRING +# define QT_NO_DATESTRING +#endif + +/* Dialogs */ +#ifndef QT_NO_FILEDIALOG +# define QT_NO_FILEDIALOG +#endif +#ifndef QT_NO_PRINTDIALOG +# define QT_NO_PRINTDIALOG +#endif +#ifndef QT_NO_PRINTPREVIEWDIALOG +# define QT_NO_PRINTPREVIEWDIALOG +#endif + + +/* File I/O */ +#ifndef QT_NO_DOM +# define QT_NO_DOM +#endif +#ifndef QT_NO_FILESYSTEMWATCHER +# define QT_NO_FILESYSTEMWATCHER +#endif +#ifndef QT_NO_FSFILEENGINE +# define QT_NO_FSFILEENGINE +#endif +#ifndef QT_NO_FILESYSTEMMODEL +# define QT_NO_FILESYSTEMMODEL +#endif +#ifndef QT_NO_FILESYSTEMMODEL +# define QT_NO_FILESYSTEMMODEL +#endif +#ifndef QT_NO_PROCESS +# define QT_NO_PROCESS +#endif +#ifndef QT_NO_TEMPORARYFILE +# define QT_NO_TEMPORARYFILE +#endif +#ifndef QT_NO_SETTINGS +# define QT_NO_SETTINGS +#endif +#ifndef QT_NO_LIBRARY +# define QT_NO_LIBRARY +#endif + +/* Fonts */ +#ifndef QT_NO_QWS_QPF2 +# define QT_NO_QWS_QPF2 +#endif + +/* Images */ +#ifndef QT_NO_IMAGEFORMATPLUGIN +# define QT_NO_IMAGEFORMATPLUGIN +#endif +#ifndef QT_NO_IMAGE_HEURISTIC_MASK +# define QT_NO_IMAGE_HEURISTIC_MASK +#endif +#ifndef QT_NO_IMAGE_TEXT +# define QT_NO_IMAGE_TEXT +#endif +#ifndef QT_NO_MOVIE +# define QT_NO_MOVIE +#endif + +/* Internationalization */ +#ifndef QT_NO_BIG_CODECS +# define QT_NO_BIG_CODECS +#endif +#ifndef QT_NO_QWS_INPUTMETHODS +# define QT_NO_QWS_INPUTMETHODS +#endif +#ifndef QT_NO_TEXTCODEC +# define QT_NO_TEXTCODEC +#endif +#ifndef QT_NO_CODECS +# define QT_NO_CODECS +#endif +#ifndef QT_NO_TEXTCODECPLUGIN +# define QT_NO_TEXTCODECPLUGIN +#endif +#ifndef QT_NO_TRANSLATION +# define QT_NO_TRANSLATION +#endif +#ifndef QT_NO_TRANSLATION_UTF8 +# define QT_NO_TRANSLATION_UTF8 +#endif + +/* ItemViews */ + +#ifndef QT_NO_DIRMODEL +# define QT_NO_DIRMODEL +#endif + +/* Kernel */ +#ifndef QT_NO_CLIPBOARD +# define QT_NO_CLIPBOARD +#endif +#ifndef QT_NO_CSSPARSER +# define QT_NO_CSSPARSER +#endif +#ifndef QT_NO_CURSOR +# define QT_NO_CURSOR +#endif +#ifndef QT_NO_DRAGANDDROP +# define QT_NO_DRAGANDDROP +#endif +#ifndef QT_NO_EFFECTS +# define QT_NO_EFFECTS +#endif +#ifndef QT_NO_SESSIONMANAGER +# define QT_NO_SESSIONMANAGER +#endif +#ifndef QT_NO_SHAREDMEMORY +# define QT_NO_SHAREDMEMORY +#endif +#ifndef QT_NO_SOUND +# define QT_NO_SOUND +#endif +#ifndef QT_NO_SYSTEMLOCALE +# define QT_NO_SYSTEMSEMAPHORE +#endif +#ifndef QT_NO_SYSTEMSEMAPHORE +# define QT_NO_SYSTEMSEMAPHORE +#endif +#ifndef QT_NO_TABLETEVENT +# define QT_NO_TABLETEVENT +#endif +#ifndef QT_NO_CRASHHANDLER +# define QT_NO_CRASHHANDLER +#endif +#ifndef QT_NO_CONCURRENT +# define QT_NO_CONCURRENT +#endif +#ifndef QT_NO_XMLSTREAM +# define QT_NO_XMLSTREAM +#endif +#ifndef QT_NO_XMLSTREAMREADER +# define QT_NO_XMLSTREAMREADER +#endif +#ifndef QT_NO_XMLSTREAMWRITER +# define QT_NO_XMLSTREAMWRITER +#endif + +/* Networking */ +#ifndef QT_NO_COP +# define QT_NO_COP +#endif +#ifndef QT_NO_HOSTINFO +# define QT_NO_HOSTINFO +#endif +#ifndef QT_NO_HTTP +# define QT_NO_HTTP +#endif +#ifndef QT_NO_NETWORKPROXY +# define QT_NO_NETWORKPROXY +#endif +#ifndef QT_NO_SOCKS5 +# define QT_NO_SOCKS5 +#endif +#ifndef QT_NO_UDPSOCKET +# define QT_NO_UDPSOCKET +#endif +#ifndef QT_NO_URLINFO +# define QT_NO_URLINFO +#endif +#ifndef QT_NO_FTP +# define QT_NO_FTP +#endif + +/* Painting */ +#ifndef QT_NO_COLORNAMES +# define QT_NO_COLORNAMES +#endif +#ifndef QT_NO_DIRECTPAINTER +# define QT_NO_DIRECTPAINTER +#endif +#ifndef QT_NO_PAINTONSCREEN +# define QT_NO_PAINTONSCREEN +#endif +#ifndef QT_NO_PAINT_DEBUG +# define QT_NO_PAINT_DEBUG +#endif +#ifndef QT_NO_PICTURE +# define QT_NO_PICTURE +#endif +#ifndef QT_NO_PRINTER +# define QT_NO_PRINTER +#endif +#ifndef QT_NO_CUPS +# define QT_NO_CUPS +#endif + +/* Qt for Embedded Linux */ +#ifndef QT_NO_QWSEMBEDWIDGET +# define QT_NO_QWSEMBEDWIDGET +#endif +#ifndef QT_NO_QWS_ALPHA_CURSOR +# define QT_NO_QWS_ALPHA_CURSOR +#endif +#ifndef QT_NO_QWS_CURSOR +# define QT_NO_QWS_CURSOR +#endif +#ifndef QT_NO_QWS_DECORATION_DEFAULT +# define QT_NO_QWS_DECORATION_DEFAULT +#endif +#ifndef QT_NO_QWS_DECORATION_STYLED +# define QT_NO_QWS_DECORATION_STYLED +#endif +#ifndef QT_NO_QWS_DECORATION_WINDOWS +# define QT_NO_QWS_DECORATION_WINDOWS +#endif +#ifndef QT_NO_QWS_MANAGER +# define QT_NO_QWS_MANAGER +#endif +#ifndef QT_NO_QWS_KEYBOARD +# define QT_NO_QWS_KEYBOARD +#endif +#ifndef QT_NO_QWS_MOUSE +# define QT_NO_QWS_MOUSE +#endif +#ifndef QT_NO_QWS_MOUSE_AUTO +# define QT_NO_QWS_MOUSE_AUTO +#endif +#ifndef QT_NO_QWS_MOUSE_MANUAL +# define QT_NO_QWS_MOUSE_MANUAL +#endif +#ifndef QT_NO_QWS_MULTIPROCESS +# define QT_NO_QWS_MULTIPROCESS +#endif +#ifndef QT_NO_QWS_SOUNDSERVER +# define QT_NO_QWS_SOUNDSERVER +#endif +#ifndef QT_NO_SXE +# define QT_NO_SXE +#endif +#ifndef QT_NO_QWS_PROPERTIES +# define QT_NO_QWS_PROPERTIES +#endif +#ifndef QT_NO_QWS_PROXYSCREEN +# define QT_NO_QWS_PROXYSCREEN +#endif +#ifndef QT_NO_QWS_DYNAMICSCREENTRANSFORMATION +# define QT_NO_QWS_DYNAMICSCREENTRANSFORMATION +#endif +#ifndef QT_NO_QWS_LINUXFB +# define QT_NO_QWS_LINUXFB +#endif +#ifndef QT_NO_QWS_MOUSE_PC +# define QT_NO_QWS_MOUSE_PC +#endif +#ifndef QT_NO_QWS_MOUSE_LINUXTP +# define QT_NO_QWS_MOUSE_LINUXTP +#endif +#ifndef QT_NO_QWS_QPF +# define QT_NO_QWS_QPF +#endif + +/* SVG */ +#ifndef QT_NO_SVG +# define QT_NO_SVG +#endif +#ifndef QT_NO_GRAPHICSSVGITEM +# define QT_NO_GRAPHICSSVGITEM +#endif +#ifndef QT_NO_SVGGENERATOR +# define QT_NO_SVGGENERATOR +#endif +#ifndef QT_NO_SVGRENDERER +# define QT_NO_SVGRENDERER +#endif +#ifndef QT_NO_SVGWIDGET +# define QT_NO_SVGWIDGET +#endif + +/* Styles */ +#ifndef QT_NO_STYLE_MOTIF +# define QT_NO_STYLE_MOTIF +#endif +#ifndef QT_NO_STYLE_CDE +# define QT_NO_STYLE_CDE +#endif +#ifndef QT_NO_STYLE_STYLESHEET +# define QT_NO_STYLE_STYLESHEET +#endif +#ifndef QT_NO_STYLE_WINDOWSCE +# define QT_NO_STYLE_WINDOWSCE +#endif +#ifndef QT_NO_STYLE_WINDOWSMOBILE +# define QT_NO_STYLE_WINDOWSMOBILE +#endif +#ifndef QT_NO_STYLE_WINDOWSVISTA +# define QT_NO_STYLE_WINDOWSVISTA +#endif +#ifndef QT_NO_STYLE_WINDOWSXP +# define QT_NO_STYLE_WINDOWSXP +#endif + +/* Utilities */ +#ifndef QT_NO_ACCESSIBILITY +# define QT_NO_ACCESSIBILITY +#endif +#ifndef QT_NO_COMPLETER +# define QT_NO_COMPLETER +#endif +#ifndef QT_NO_DESKTOPSERVICES +# define QT_NO_DESKTOPSERVICES +#endif +#ifndef QT_NO_SCRIPT +# define QT_NO_SCRIPT +#endif +#ifndef QT_NO_SYSTEMTRAYICON +# define QT_NO_SYSTEMTRAYICON +#endif + +/* Windows */ +#ifndef QT_NO_WIN_ACTIVEQT +# define QT_NO_WIN_ACTIVEQT +#endif diff --git a/src/corelib/global/qfeatures.h b/src/corelib/global/qfeatures.h index b606843..9710079 100644 --- a/src/corelib/global/qfeatures.h +++ b/src/corelib/global/qfeatures.h @@ -523,11 +523,6 @@ #define QT_NO_FTP #endif -// Hyper Text Transfer Protocol -#if !defined(QT_NO_HTTP) && (defined(QT_NO_HOSTINFO)) -#define QT_NO_HTTP -#endif - // QInputContext #if !defined(QT_NO_IM) && (defined(QT_NO_LIBRARY)) #define QT_NO_IM @@ -583,6 +578,11 @@ #define QT_NO_GRAPHICSVIEW #endif +// Hyper Text Transfer Protocol +#if !defined(QT_NO_HTTP) && (defined(QT_NO_HOSTINFO) || defined(QT_NO_NETWORKPROXY)) +#define QT_NO_HTTP +#endif + // QMdiArea #if !defined(QT_NO_MDIAREA) && (defined(QT_NO_SCROLLAREA)) #define QT_NO_MDIAREA diff --git a/src/corelib/global/qfeatures.txt b/src/corelib/global/qfeatures.txt index 4d938a9..f07fbd5 100644 --- a/src/corelib/global/qfeatures.txt +++ b/src/corelib/global/qfeatures.txt @@ -1050,7 +1050,7 @@ SeeAlso: ??? Feature: HTTP Description: Supports HTTP file access. Section: Networking -Requires: HOSTINFO +Requires: HOSTINFO NETWORKPROXY Name: Hyper Text Transfer Protocol SeeAlso: ??? diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index e973688..9b597f6 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -74,7 +74,7 @@ # include <envLib.h> #endif -#if defined(Q_CC_MWERKS) && defined(Q_OS_MACX) +#if defined(Q_OS_MACX) && !defined(QT_NO_CORESERVICES) #include <CoreServices/CoreServices.h> #endif @@ -1232,7 +1232,7 @@ bool qSharedBuild() Defined on Mac OS X. - \sa Q_WS_WIN, Q_WS_X11, Q_WS_QWS, Q_WS_S60 + \sa Q_WS_WIN, Q_WS_X11, Q_WS_QWS, Q_WS_QPA, Q_WS_S60 */ /*! @@ -1241,7 +1241,7 @@ bool qSharedBuild() Defined on Windows. - \sa Q_WS_MAC, Q_WS_X11, Q_WS_QWS, Q_WS_S60 + \sa Q_WS_MAC, Q_WS_X11, Q_WS_QWS, Q_WS_QPA, Q_WS_S60 */ /*! @@ -1250,7 +1250,7 @@ bool qSharedBuild() Defined on X11. - \sa Q_WS_MAC, Q_WS_WIN, Q_WS_QWS, Q_WS_S60 + \sa Q_WS_MAC, Q_WS_WIN, Q_WS_QWS, Q_WS_QPA, Q_WS_S60 */ /*! @@ -1259,7 +1259,16 @@ bool qSharedBuild() Defined on Qt for Embedded Linux. - \sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11, Q_WS_S60 + \sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11, Q_WS_QPA, Q_WS_S60 +*/ + +/*! + \macro Q_WS_QPA + \relates <QtGlobal> + + Defined on Qt for Embedded Linux, Lite version. + + \sa Q_WS_MAC, Q_WS_WIN, Q_WS_X11, Q_WS_QWS, Q_WS_S60 */ /*! @@ -1634,7 +1643,7 @@ static const unsigned int qt_one = 1; const int QSysInfo::ByteOrder = ((*((unsigned char *) &qt_one) == 0) ? BigEndian : LittleEndian); #endif -#if !defined(QWS) && defined(Q_OS_MAC) +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) QT_BEGIN_INCLUDE_NAMESPACE #include "private/qcore_mac_p.h" @@ -1688,15 +1697,18 @@ Q_CORE_EXPORT void qt_mac_to_pascal_string(QString s, Str255 str, TextEncoding e Q_CORE_EXPORT QString qt_mac_from_pascal_string(const Str255 pstr) { return QCFString(CFStringCreateWithPascalString(0, pstr, CFStringGetSystemEncoding())); } +#endif //!defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) - +#if !defined(QWS) && defined(Q_OS_MAC) static QSysInfo::MacVersion macVersion() { +#ifndef QT_NO_CORESERVICES SInt32 gestalt_version; if (Gestalt(gestaltSystemVersion, &gestalt_version) == noErr) { return QSysInfo::MacVersion(((gestalt_version & 0x00F0) >> 4) + 2); } +#endif return QSysInfo::MV_Unknown; } const QSysInfo::MacVersion QSysInfo::MacintoshVersion = macVersion(); diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 547ad8d..e71e3b6 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -216,6 +216,8 @@ namespace QT_NAMESPACE {} # define Q_OS_ULTRIX #elif defined(sinix) # define Q_OS_RELIANT +#elif defined(__native_client__) +# define Q_OS_NACL #elif defined(__linux__) || defined(__linux) # define Q_OS_LINUX #elif defined(__FreeBSD__) || defined(__DragonFly__) @@ -284,7 +286,7 @@ namespace QT_NAMESPACE {} # endif #endif -#if defined(Q_OS_MAC64) && !defined(QT_MAC_USE_COCOA) && !defined(QT_BUILD_QMAKE) && !defined(QT_BOOTSTRAPPED) +#if defined(Q_WS_MAC64) && !defined(QT_MAC_USE_COCOA) && !defined(QT_BUILD_QMAKE) && !defined(QT_BOOTSTRAPPED) #error "You are building a 64-bit application, but using a 32-bit version of Qt. Check your build configuration." #endif @@ -822,7 +824,7 @@ namespace QT_NAMESPACE {} # define Q_WS_PM # error "Qt does not work with OS/2 Presentation Manager or Workplace Shell" #elif defined(Q_OS_UNIX) -# if defined(Q_OS_MAC) && !defined(__USE_WS_X11__) && !defined(Q_WS_QWS) +# if defined(Q_OS_MAC) && !defined(__USE_WS_X11__) && !defined(Q_WS_QWS) && !defined(Q_WS_QPA) # define Q_WS_MAC # define Q_WS_MACX # if defined(Q_OS_MAC64) @@ -834,7 +836,7 @@ namespace QT_NAMESPACE {} # if !defined(QT_NO_S60) # define Q_WS_S60 # endif -# elif !defined(Q_WS_QWS) +# elif !defined(Q_WS_QWS) && !defined(Q_WS_QPA) # define Q_WS_X11 # endif #endif @@ -1096,7 +1098,7 @@ redefine to built-in booleans to make autotests work properly */ typedef int QNoImplicitBoolCast; -#if defined(QT_ARCH_ARM) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_MIPS) && (defined(Q_WS_QWS) || defined(Q_OS_WINCE))) || defined(QT_ARCH_SH) || defined(QT_ARCH_SH4A) +#if defined(QT_ARCH_ARM) || defined(QT_ARCH_ARMV6) || defined(QT_ARCH_AVR32) || (defined(QT_ARCH_MIPS) && (defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_WINCE))) || defined(QT_ARCH_SH) || defined(QT_ARCH_SH4A) #define QT_NO_FPU #endif @@ -2649,6 +2651,10 @@ QT_LICENSED_MODULE(DBus) # define QT_NO_PROCESS #endif +#ifdef Q_OS_NACL +#include <QtCore/qnaclunimplemented.h> +#endif + #if defined (__ELF__) # if defined (Q_OS_LINUX) || defined (Q_OS_SOLARIS) || defined (Q_OS_FREEBSD) || defined (Q_OS_OPENBSD) || defined (Q_OS_IRIX) # define Q_OF_ELF diff --git a/src/corelib/global/qnaclunimplemented.cpp b/src/corelib/global/qnaclunimplemented.cpp new file mode 100644 index 0000000..1a89b8df --- /dev/null +++ b/src/corelib/global/qnaclunimplemented.cpp @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore 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 "qnaclunimplemented.h" +#include <pthread.h> +#include <qglobal.h> + +/* + The purpose of this file is to stub out certain functions + that are not provided by the Native Client SDK. This is + done as an alterative to sprinkling the Qt sources with + NACL ifdefs. + + There are two main classes of functions: + + - Functions that are called but can have no effect: + For these we simply give an empty implementation + + - Functions that are referenced in the source code, but + is not/must not be called at run-time: + These we either leave undefined or implement with a + qFatal. + + This is a work in progress. +*/ + +extern "C" { + +void pthread_cleanup_push(void (*)(void *), void *) +{ + +} + +void pthread_cleanup_pop(int) +{ + +} + +int pthread_setcancelstate(int, int *) +{ + return 0; +} + +int pthread_setcanceltype(int, int *) +{ + return 0; +} + +void pthread_testcancel(void) +{ + +} + + +int pthread_cancel(pthread_t) +{ + return 0; +} + +int pthread_attr_setinheritsched(pthread_attr_t *,int) +{ + return 0; +} + + +int pthread_attr_getinheritsched(const pthread_attr_t *, int *) +{ + return 0; +} + +// event dispatcher, select +//struct fd_set; +//struct timeval; + +int fcntl(int, int, ...) +{ + return 0; +} + +int sigaction(int, const struct sigaction *, struct sigaction *) +{ + return 0; +} + +int open(const char *, int, ...) +{ + return 0; +} + +int open64(const char *, int, ...) +{ + return 0; +} + +int access(const char *, int) +{ + return 0; +} + +typedef long off64_t; +off64_t ftello64(void *) +{ + qFatal("ftello64 called"); + return 0; +} + +off64_t lseek64(int, off_t, int) +{ + qFatal("lseek64 called"); + return 0; +} + +} // Extern C + +int select(int, fd_set *, fd_set *, fd_set *, struct timeval *) +{ + return 0; +} diff --git a/src/corelib/global/qnaclunimplemented.h b/src/corelib/global/qnaclunimplemented.h new file mode 100644 index 0000000..2d3d426 --- /dev/null +++ b/src/corelib/global/qnaclunimplemented.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore 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$ +** +****************************************************************************/ + +#ifndef QNACLUNIMPLEMENTED_H +#define QNACLUNIMPLEMENTED_H + +#ifdef Q_OS_NACL + +// pthread +#include <pthread.h> +#define PTHREAD_CANCEL_DISABLE 1 +#define PTHREAD_CANCEL_ENABLE 2 +#define PTHREAD_INHERIT_SCHED 3 + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Core) + +extern "C" { + +void pthread_cleanup_push(void (*handler)(void *), void *arg); +void pthread_cleanup_pop(int execute); + +int pthread_setcancelstate(int state, int *oldstate); +int pthread_setcanceltype(int type, int *oldtype); +void pthread_testcancel(void); +int pthread_cancel(pthread_t thread); + +int pthread_attr_setinheritsched(pthread_attr_t *attr, + int inheritsched); +int pthread_attr_getinheritsched(const pthread_attr_t *attr, + int *inheritsched); + +// event dispatcher, select +//struct fd_set; +//struct timeval; +int fcntl(int fildes, int cmd, ...); +int sigaction(int sig, const struct sigaction * act, struct sigaction * oact); + +typedef long off64_t; +off64_t ftello64(void *stream); +off64_t lseek64(int fildes, off_t offset, int whence); +int open64(const char *path, int oflag, ...); + +} + +int select(int nfds, fd_set * readfds, fd_set * writefds, fd_set * errorfds, struct timeval * timeout); + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif //Q_OS_NACL + +#endif //QNACLUNIMPLEMENTED_H diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index a531009..3ed6291 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -1659,7 +1659,7 @@ public: typedef void *HANDLE; #elif defined(Q_WS_X11) typedef unsigned long HANDLE; -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_QPA) typedef void * HANDLE; #elif defined(Q_OS_SYMBIAN) typedef unsigned long int HANDLE; // equivalent to TUint32 diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 3d964c6..cfb40bc 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -69,7 +69,7 @@ win32 { SOURCES += io/qfsfileengine_iterator_unix.cpp symbian:SOURCES += io/qprocess_symbian.cpp else:SOURCES += io/qprocess_unix.cpp - macx-*: { + !nacl:macx-*: { HEADERS += io/qfilesystemwatcher_fsevents_p.h SOURCES += io/qsettings_mac.cpp io/qfilesystemwatcher_fsevents.cpp } @@ -84,9 +84,11 @@ win32 { io/qfilesystemwatcher_dnotify_p.h } - freebsd-*|macx-*|darwin-*|openbsd-*:{ - SOURCES += io/qfilesystemwatcher_kqueue.cpp - HEADERS += io/qfilesystemwatcher_kqueue_p.h + !nacl { + freebsd-*|macx-*|darwin-*|openbsd-*:{ + SOURCES += io/qfilesystemwatcher_kqueue.cpp + HEADERS += io/qfilesystemwatcher_kqueue_p.h + } } symbian { diff --git a/src/corelib/io/qfilesystemwatcher_fsevents.cpp b/src/corelib/io/qfilesystemwatcher_fsevents.cpp index d3276bd..0f96792 100644 --- a/src/corelib/io/qfilesystemwatcher_fsevents.cpp +++ b/src/corelib/io/qfilesystemwatcher_fsevents.cpp @@ -45,6 +45,8 @@ #include "qfilesystemwatcher.h" #include "qfilesystemwatcher_fsevents_p.h" +#ifndef QT_NO_FILESYSTEMWATCHER + #include <qdebug.h> #include <qfile.h> #include <qdatetime.h> @@ -487,3 +489,4 @@ void QFSEventsFileSystemWatcherEngine::run() } QT_END_NAMESPACE +#endif //QT_NO_FILESYSTEMWATCHER diff --git a/src/corelib/io/qfilesystemwatcher_fsevents_p.h b/src/corelib/io/qfilesystemwatcher_fsevents_p.h index b0462b6..c888c61 100644 --- a/src/corelib/io/qfilesystemwatcher_fsevents_p.h +++ b/src/corelib/io/qfilesystemwatcher_fsevents_p.h @@ -56,6 +56,8 @@ #include "qfilesystemwatcher_p.h" +#ifndef QT_NO_FILESYSTEMWATCHER + #include <QtCore/qmutex.h> #include <QtCore/qwaitcondition.h> #include <QtCore/qthread.h> @@ -123,6 +125,8 @@ private: #endif }; +#endif //QT_NO_FILESYSTEMWATCHER + #endif QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemwatcher_kqueue.cpp b/src/corelib/io/qfilesystemwatcher_kqueue.cpp index 378ad20..7960792 100644 --- a/src/corelib/io/qfilesystemwatcher_kqueue.cpp +++ b/src/corelib/io/qfilesystemwatcher_kqueue.cpp @@ -45,6 +45,8 @@ #include "qfilesystemwatcher_kqueue_p.h" #include "private/qcore_unix_p.h" +#ifndef QT_NO_FILESYSTEMWATCHER + #include <qdebug.h> #include <qfile.h> #include <qsocketnotifier.h> @@ -343,4 +345,6 @@ process_next_event: } } +#endif //QT_NO_FILESYSTEMWATCHER + QT_END_NAMESPACE diff --git a/src/corelib/io/qfilesystemwatcher_kqueue_p.h b/src/corelib/io/qfilesystemwatcher_kqueue_p.h index eda646b..edc20ae 100644 --- a/src/corelib/io/qfilesystemwatcher_kqueue_p.h +++ b/src/corelib/io/qfilesystemwatcher_kqueue_p.h @@ -60,6 +60,7 @@ #include <QtCore/qthread.h> #include <QtCore/qvector.h> +#ifndef QT_NO_FILESYSTEMWATCHER struct kevent; QT_BEGIN_NAMESPACE @@ -92,4 +93,5 @@ private: QT_END_NAMESPACE +#endif //QT_NO_FILESYSTEMWATCHER #endif // FILEWATCHER_KQUEUE_P_H diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 511a1a6..62b9981 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -152,7 +152,7 @@ QString QFSFileEnginePrivate::canonicalized(const QString &path) // ... but Linux with uClibc does not have it #if !defined(__UCLIBC__) char *ret = 0; -#if defined(Q_OS_MAC) +#if defined(Q_OS_MAC) && !defined(QT_NO_CORESERVICES) // Mac OS X 10.5.x doesn't support the realpath(X,0) extension we use here. if (QSysInfo::MacintoshVersion >= QSysInfo::MV_10_6) { ret = realpath(path.toLocal8Bit().constData(), (char*)0); diff --git a/src/corelib/io/qfsfileengine_unix.cpp b/src/corelib/io/qfsfileengine_unix.cpp index f1054c5e..03e7283 100644 --- a/src/corelib/io/qfsfileengine_unix.cpp +++ b/src/corelib/io/qfsfileengine_unix.cpp @@ -739,7 +739,7 @@ static bool _q_isSymbianHidden(const QString &path, bool isDir) } #endif -#if !defined(QWS) && defined(Q_OS_MAC) +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) static bool _q_isMacHidden(const QString &path) { OSErr err = noErr; @@ -824,7 +824,7 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const if (exists && (type & PermsMask)) ret |= d->getPermissions(type); if (type & TypesMask) { -#if !defined(QWS) && defined(Q_OS_MAC) +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) bool foundAlias = false; { FSRef fref; @@ -878,7 +878,7 @@ QAbstractFileEngine::FileFlags QFSFileEngine::fileFlags(FileFlags type) const } else { QString baseName = fileName(BaseName); if ((baseName.size() > 0 && baseName.at(0) == QLatin1Char('.')) -# if !defined(QWS) && defined(Q_OS_MAC) +# if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) || _q_isMacHidden(d->filePath) # if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5 || d->st.st_flags & UF_HIDDEN @@ -1137,7 +1137,7 @@ QString QFSFileEngine::fileName(FileName file) const return ret; } } -#if !defined(QWS) && defined(Q_OS_MAC) +#if !defined(QWS) && !defined(Q_WS_QPA) && defined(Q_OS_MAC) { FSRef fref; if (FSPathMakeRef((const UInt8 *)QFile::encodeName(QDir::cleanPath(d->filePath)).data(), &fref, 0) == noErr) { diff --git a/src/corelib/io/qresource.cpp b/src/corelib/io/qresource.cpp index 929885c..98b1dcc 100644 --- a/src/corelib/io/qresource.cpp +++ b/src/corelib/io/qresource.cpp @@ -580,7 +580,7 @@ QResource::addSearchPath(const QString &path) \obsolete Use QDir::searchPaths() instead. - + Returns the current search path list. This list is consulted when creating a relative resource. @@ -928,7 +928,7 @@ public: } }; -#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) +#if defined(Q_OS_UNIX) && !defined(Q_OS_SYMBIAN) && ! defined (Q_OS_NACL) #define QT_USE_MMAP #endif diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index da296f4..e4fb295 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -1124,7 +1124,7 @@ static void initDefaultPaths(QMutexLocker *locker) if (env == 0) { userPath = homePath; userPath += QLatin1Char('/'); -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) userPath += QLatin1String("Settings"); #else userPath += QLatin1String(".config"); diff --git a/src/corelib/io/qsettings_p.h b/src/corelib/io/qsettings_p.h index ec345be..5ff4d96 100644 --- a/src/corelib/io/qsettings_p.h +++ b/src/corelib/io/qsettings_p.h @@ -70,7 +70,7 @@ QT_BEGIN_NAMESPACE -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) #define QT_QSETTINGS_ALWAYS_CASE_SENSITIVE_AND_FORGET_ORIGINAL_KEY_ORDER #endif diff --git a/src/corelib/kernel/kernel.pri b/src/corelib/kernel/kernel.pri index 1851e04..1e27c31 100644 --- a/src/corelib/kernel/kernel.pri +++ b/src/corelib/kernel/kernel.pri @@ -78,12 +78,12 @@ wince*: { kernel/qfunctions_wince.h } -mac:!embedded { +mac:!embedded:!qpa{ SOURCES += \ kernel/qcoreapplication_mac.cpp } -mac { +mac:!nacl { SOURCES += \ kernel/qcore_mac.cpp } diff --git a/src/corelib/kernel/qcore_mac_p.h b/src/corelib/kernel/qcore_mac_p.h index 9591f08..22b6a36 100644 --- a/src/corelib/kernel/qcore_mac_p.h +++ b/src/corelib/kernel/qcore_mac_p.h @@ -68,7 +68,15 @@ # undef qDebug #endif +#if defined(QT_BUILD_QMAKE) || defined(QT_BOOTSTRAPPED) #include <ApplicationServices/ApplicationServices.h> +#else +#include <CoreFoundation/CoreFoundation.h> +#endif + +#ifndef QT_NO_CORESERVICES +#include <CoreServices/CoreServices.h> +#endif #undef DEBUG #ifdef OLD_DEBUG diff --git a/src/corelib/kernel/qcore_unix.cpp b/src/corelib/kernel/qcore_unix.cpp index e0d92c0..685576b 100644 --- a/src/corelib/kernel/qcore_unix.cpp +++ b/src/corelib/kernel/qcore_unix.cpp @@ -42,7 +42,8 @@ #include "qcore_unix_p.h" #include "qelapsedtimer.h" -#ifndef Q_OS_VXWORKS +#ifdef Q_OS_NACL +#elif !defined (Q_OS_VXWORKS) # if !defined(Q_OS_HPUX) || defined(__ia64) # include <sys/select.h> # endif diff --git a/src/corelib/kernel/qeventdispatcher_unix.cpp b/src/corelib/kernel/qeventdispatcher_unix.cpp index f50994c..b2b9806 100644 --- a/src/corelib/kernel/qeventdispatcher_unix.cpp +++ b/src/corelib/kernel/qeventdispatcher_unix.cpp @@ -112,7 +112,9 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() bool pipefail = false; // initialize the common parts of the event loop -#if defined(Q_OS_INTEGRITY) +#if defined(Q_OS_NACL) + // do nothing. +#elif defined(Q_OS_INTEGRITY) // INTEGRITY doesn't like a "select" on pipes, so use socketpair instead if (socketpair(AF_INET, SOCK_STREAM, PF_INET, thread_pipe) == -1) { perror("QEventDispatcherUNIXPrivate(): Unable to create socket pair"); @@ -157,7 +159,9 @@ QEventDispatcherUNIXPrivate::QEventDispatcherUNIXPrivate() QEventDispatcherUNIXPrivate::~QEventDispatcherUNIXPrivate() { -#if defined(Q_OS_VXWORKS) +#if defined(Q_OS_NACL) + // do nothing. +#elif defined(Q_OS_VXWORKS) close(thread_pipe[0]); char name[20]; @@ -312,7 +316,7 @@ int QEventDispatcherUNIXPrivate::doSelect(QEventLoop::ProcessEventsFlags flags, QTimerInfoList::QTimerInfoList() { -#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) +#if (_POSIX_MONOTONIC_CLOCK-0 <= 0) && !defined(Q_OS_MAC) && !defined(Q_OS_NACL) if (!QElapsedTimer::isMonotonic()) { // not using monotonic timers, initialize the timeChanged() machinery previousTime = qt_gettime(); @@ -364,6 +368,10 @@ timeval qAbs(const timeval &t) */ bool QTimerInfoList::timeChanged(timeval *delta) { +#ifdef Q_OS_NACL + Q_UNUSED(delta) + return false; // Calling "times" crashes. +#endif struct tms unused; clock_t currentTicks = times(&unused); diff --git a/src/corelib/kernel/qeventdispatcher_unix_p.h b/src/corelib/kernel/qeventdispatcher_unix_p.h index 060a163..e1b6b1d 100644 --- a/src/corelib/kernel/qeventdispatcher_unix_p.h +++ b/src/corelib/kernel/qeventdispatcher_unix_p.h @@ -64,7 +64,7 @@ # include <sys/times.h> #else # include <sys/time.h> -# if !defined(Q_OS_HPUX) || defined(__ia64) +# if (!defined(Q_OS_HPUX) || defined(__ia64)) && !defined(Q_OS_NACL) # include <sys/select.h> # endif #endif diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index a44a0e8..daf1a93 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -83,7 +83,9 @@ # define old_qDebug qDebug # undef qDebug # endif +#ifndef QT_NO_CORESERVICES # include <CoreServices/CoreServices.h> +#endif //QT_NO_CORESERVICES # ifdef old_qDebug # undef qDebug @@ -388,7 +390,7 @@ int QThread::idealThreadCount() { int cores = -1; -#if defined(Q_OS_MAC) +#if defined(Q_OS_MAC) && !defined(Q_WS_QPA) // Mac OS X cores = MPProcessorsScheduled(); #elif defined(Q_OS_HPUX) @@ -506,6 +508,7 @@ void QThread::usleep(unsigned long usecs) // Does some magic and calculate the Unix scheduler priorities // sched_policy is IN/OUT: it must be set to a valid policy before calling this function // sched_priority is OUT only +#if defined(Q_OS_DARWIN) || !defined(Q_OS_OPENBSD) && defined(_POSIX_THREAD_PRIORITY_SCHEDULING) && (_POSIX_THREAD_PRIORITY_SCHEDULING-0 >= 0) static bool calculateUnixPriority(int priority, int *sched_policy, int *sched_priority) { #ifdef SCHED_IDLE @@ -533,6 +536,7 @@ static bool calculateUnixPriority(int priority, int *sched_policy, int *sched_pr *sched_priority = prio; return true; } +#endif void QThread::start(Priority priority) { diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index b2fe2da..ac8ccba 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -72,7 +72,12 @@ QT_BEGIN_NAMESPACE -#if defined (Q_OS_WINCE) +#if defined (Q_OS_NACL) +static inline uint detectProcessorFeatures() +{ + return 0; +} +#elif defined (Q_OS_WINCE) static inline uint detectProcessorFeatures() { uint features = 0; diff --git a/src/corelib/tools/tools.pri b/src/corelib/tools/tools.pri index d81ab04..03bb32d 100644 --- a/src/corelib/tools/tools.pri +++ b/src/corelib/tools/tools.pri @@ -83,7 +83,7 @@ SOURCES += \ symbian:SOURCES+=tools/qlocale_symbian.cpp -mac:SOURCES += tools/qelapsedtimer_mac.cpp +!nacl:mac:SOURCES += tools/qelapsedtimer_mac.cpp else:symbian:SOURCES += tools/qelapsedtimer_symbian.cpp else:unix:SOURCES += tools/qelapsedtimer_unix.cpp else:win32:SOURCES += tools/qelapsedtimer_win.cpp diff --git a/src/gui/accessible/accessible.pri b/src/gui/accessible/accessible.pri index ad2fb4c..31362ff 100644 --- a/src/gui/accessible/accessible.pri +++ b/src/gui/accessible/accessible.pri @@ -12,7 +12,7 @@ contains(QT_CONFIG, accessibility) { accessible/qaccessiblewidget.cpp \ accessible/qaccessibleplugin.cpp - mac:!embedded { + mac:!embedded:!qpa { HEADERS += accessible/qaccessible_mac_p.h OBJECTIVE_SOURCES += accessible/qaccessible_mac.mm \ accessible/qaccessible_mac_cocoa.mm diff --git a/src/gui/dialogs/dialogs.pri b/src/gui/dialogs/dialogs.pri index 4e1b9a7..cd8e71a 100644 --- a/src/gui/dialogs/dialogs.pri +++ b/src/gui/dialogs/dialogs.pri @@ -27,7 +27,7 @@ HEADERS += \ dialogs/qwizard.h \ dialogs/qprintpreviewdialog.h -!embedded:mac { +!embedded:!qpa:mac { OBJECTIVE_SOURCES += dialogs/qfiledialog_mac.mm \ dialogs/qfontdialog_mac.mm \ dialogs/qnspanelproxy_mac.mm \ @@ -61,7 +61,7 @@ win32 { !win32-borland:!wince*: LIBS += -lshell32 # the filedialog needs this library } -!mac:!embedded:!symbian:unix { +!mac:!embedded:!symbian:unix|qpa { HEADERS += dialogs/qpagesetupdialog_unix_p.h SOURCES += dialogs/qprintdialog_unix.cpp \ dialogs/qpagesetupdialog_unix.cpp diff --git a/src/gui/dialogs/qfileinfogatherer_p.h b/src/gui/dialogs/qfileinfogatherer_p.h index 8681eb5..b28509b 100644 --- a/src/gui/dialogs/qfileinfogatherer_p.h +++ b/src/gui/dialogs/qfileinfogatherer_p.h @@ -84,10 +84,13 @@ public: && permissions() == fileInfo.permissions(); } +#ifndef QT_NO_FSFILEENGINE bool isCaseSensitive() const { QFSFileEngine fe(mFileInfo.absoluteFilePath()); return fe.caseSensitive(); } +#endif + QFile::Permissions permissions() const { return mFileInfo.permissions(); } diff --git a/src/gui/egl/egl.pri b/src/gui/egl/egl.pri index c6c020d..8e8664c 100644 --- a/src/gui/egl/egl.pri +++ b/src/gui/egl/egl.pri @@ -6,9 +6,21 @@ contains(QT_CONFIG, egl): { egl/qeglcontext_p.h \ egl/qeglproperties_p.h - SOURCES += \ - egl/qegl.cpp \ - egl/qeglproperties.cpp + SOURCES += \ + egl/qegl.cpp \ + egl/qeglproperties.cpp + unix { + !isEmpty(QMAKE_INCDIR_EGL){ + INCLUDEPATH += $$QMAKE_INCDIR_EGL + } + !isEmpty(QMAKE_LIBDIR_EGL){ + for(p, QMAKE_LIBDIR_EGL) { + exists($$p):LIBS += -L$$p + } + } + + !isEmpty(QMAKE_LIBS_EGL): LIBS += $$QMAKE_LIBS_EGL + } wince*: SOURCES += egl/qegl_wince.cpp @@ -16,10 +28,14 @@ contains(QT_CONFIG, egl): { embedded { SOURCES += egl/qegl_qws.cpp } else { - symbian { - SOURCES += egl/qegl_symbian.cpp + qpa { + SOURCES += egl/qegl_qpa.cpp } else { - SOURCES += egl/qegl_x11.cpp + symbian { + SOURCES += egl/qegl_symbian.cpp + } else { + SOURCES += egl/qegl_x11.cpp + } } } } diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index af3b79a..2a82427 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -394,7 +394,7 @@ bool QEglContext::createContext(QEglContext *shareContext, const QEglProperties } } if (ctx == EGL_NO_CONTEXT) { - ctx = eglCreateContext(display(), cfg, 0, contextProps.properties()); + ctx = eglCreateContext(display(), cfg, EGL_NO_CONTEXT, contextProps.properties()); if (ctx == EGL_NO_CONTEXT) { qWarning() << "QEglContext::createContext(): Unable to create EGL context:" << QEgl::errorString(); return false; diff --git a/src/gui/egl/qegl_qpa.cpp b/src/gui/egl/qegl_qpa.cpp new file mode 100644 index 0000000..10caf46 --- /dev/null +++ b/src/gui/egl/qegl_qpa.cpp @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** 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 QtGui 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 <QtGui/qpaintdevice.h> +#include <QtGui/qpixmap.h> +#include <QtGui/qwidget.h> +#include "qeglcontext_p.h" + +#if !defined(QT_NO_EGL) + +#include <QtGui/private/qgraphicssystem_p.h> +#include <QtGui/private/qapplication_p.h> +#include <QtGui/qdesktopwidget.h> + +QT_BEGIN_NAMESPACE + +EGLNativeDisplayType QEgl::nativeDisplay() +{ + return EGLNativeDisplayType(EGL_DEFAULT_DISPLAY); +} + +EGLNativeWindowType QEgl::nativeWindow(QWidget* widget) +{ + return (EGLNativeWindowType)(widget->winId()); +} + +EGLNativePixmapType QEgl::nativePixmap(QPixmap* pixmap) +{ + Q_UNUSED(pixmap); + return 0; +} + +//EGLDisplay QEglContext::display() +//{ +// return eglGetDisplay(EGLNativeDisplayType(EGL_DEFAULT_DISPLAY)); +//} + +static QPlatformScreen *screenForDevice(QPaintDevice *device) +{ + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + + QList<QPlatformScreen *> screens = pi->screens(); + + int screenNumber; + if (device && device->devType() == QInternal::Widget) + screenNumber = qApp->desktop()->screenNumber(static_cast<QWidget *>(device)); + else + screenNumber = 0; + if (screenNumber < 0 || screenNumber >= screens.size()) + return 0; + return screens[screenNumber]; +} + +// Set pixel format and other properties based on a paint device. +void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) +{ + if (!dev) + return; + + // Find the QGLScreen for this paint device. + QPlatformScreen *screen = screenForDevice(dev); + if (!screen) + return; + int devType = dev->devType(); + if (devType == QInternal::Image) + setPixelFormat(static_cast<QImage *>(dev)->format()); + else + setPixelFormat(screen->format()); +} + +QT_END_NAMESPACE + +#endif // !QT_NO_EGL diff --git a/src/gui/embedded/qkbd_defaultmap_qws_p.h b/src/gui/embedded/qkbd_defaultmap_qws_p.h index 16c3459..703dfcd 100644 --- a/src/gui/embedded/qkbd_defaultmap_qws_p.h +++ b/src/gui/embedded/qkbd_defaultmap_qws_p.h @@ -642,7 +642,14 @@ const QWSKeyboard::Mapping QWSKbPrivate::s_keymap_default[] = { { 111, 0xffff, 0x01000007, 0x00, 0x00, 0x0000 }, { 111, 0xffff, 0x01000000, 0x06, 0x08, 0x0200 }, { 111, 0xffff, 0x01000000, 0x0c, 0x08, 0x0200 }, + { 113, 0xffff, 0x01000071, 0x00, 0x00, 0x0000 }, + { 114, 0xffff, 0x01000070, 0x00, 0x00, 0x0000 }, + { 115, 0xffff, 0x01000072, 0x00, 0x00, 0x0000 }, + { 116, 0xffff, 0x0100010b, 0x00, 0x00, 0x0000 }, { 119, 0xffff, 0x01000008, 0x00, 0x00, 0x0000 }, + { 138, 0xffff, 0x01000058, 0x00, 0x00, 0x0000 }, + { 139, 0xffff, 0x01000055, 0x00, 0x00, 0x0000 }, + }; const QWSKeyboard::Composing QWSKbPrivate::s_keycompose_default[] = { diff --git a/src/gui/embedded/qkbd_qws.cpp b/src/gui/embedded/qkbd_qws.cpp index a6c8002..1999ddb 100644 --- a/src/gui/embedded/qkbd_qws.cpp +++ b/src/gui/embedded/qkbd_qws.cpp @@ -48,8 +48,16 @@ #include <QDataStream> #include <QStringList> +#ifdef Q_WS_QWS #include "qwindowsystem_qws.h" #include "qscreen_qws.h" +#endif + +#ifdef Q_WS_QPA +#include <QWindowSystemInterface> +#include <QKeyEvent> +#endif + #include "qtimer.h" #include <stdlib.h> @@ -352,7 +360,15 @@ QWSKeyboardHandler::~QWSKeyboardHandler() void QWSKeyboardHandler::processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers, bool isPress, bool autoRepeat) { +#if defined(Q_WS_QWS) qwsServer->processKeyEvent(unicode, keycode, modifiers, isPress, autoRepeat); +#elif defined(Q_WS_QPA) + QEvent::Type type = isPress ? QEvent::KeyPress : QEvent::KeyRelease; + QString str; + if (unicode != 0xffff) + str = QString(unicode); + QWindowSystemInterface::handleKeyEvent(0, type, keycode, modifiers, str); +#endif } /*! @@ -375,6 +391,7 @@ void QWSKeyboardHandler::processKeyEvent(int unicode, int keycode, Qt::KeyboardM */ int QWSKeyboardHandler::transformDirKey(int key) { +#ifdef Q_WS_QWS static int dir_keyrot = -1; if (dir_keyrot < 0) { // get the rotation @@ -387,6 +404,9 @@ int QWSKeyboardHandler::transformDirKey(int key) } int xf = qt_screen->transformOrientation() + dir_keyrot; return (key-Qt::Key_Left+xf)%4+Qt::Key_Left; +#else + return 0; +#endif } /*! @@ -454,7 +474,7 @@ void QWSKeyboardHandler::endAutoRepeat() Maps \a keycode according to a keymap and sends that key event to the \l{Qt for Embedded Linux} server application. - + Please see the \l{Qt for Embedded Linux Character Input} and the \l {kmap2qmap} documentations for a description on how to create and use keymap files. diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 90b5de5..f7228dc 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -5,7 +5,7 @@ DEFINES += QT_BUILD_GUI_LIB QT_NO_USING_NAMESPACE win32-msvc*|win32-icc:QMAKE_LFLAGS += /BASE:0x65000000 irix-cc*:QMAKE_CXXFLAGS += -no_prelink -ptused -!win32:!embedded:!mac:!symbian:CONFIG += x11 +!win32:!embedded:!qpa:!mac:!symbian:CONFIG += x11 unix:QMAKE_PKGCONFIG_REQUIRES = QtCore diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index f89706c..92ea397 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -23,6 +23,7 @@ HEADERS += \ image/qpictureformatplugin.h \ image/qpixmap.h \ image/qpixmap_raster_p.h \ + image/qpixmap_blitter_p.h \ image/qpixmapcache.h \ image/qpixmapcache_p.h \ image/qpixmapdata_p.h \ @@ -50,6 +51,7 @@ SOURCES += \ image/qiconengineplugin.cpp \ image/qmovie.cpp \ image/qpixmap_raster.cpp \ + image/qpixmap_blitter.cpp \ image/qnativeimage.cpp \ image/qimagepixmapcleanuphooks.cpp @@ -59,6 +61,9 @@ win32 { else:embedded { SOURCES += image/qpixmap_qws.cpp } +else:qpa { + SOURCES += image/qpixmap_qpa.cpp +} else:x11 { HEADERS += image/qpixmap_x11_p.h SOURCES += image/qpixmap_x11.cpp diff --git a/src/gui/image/qimage.h b/src/gui/image/qimage.h index 4fe7da2..003daea 100644 --- a/src/gui/image/qimage.h +++ b/src/gui/image/qimage.h @@ -334,6 +334,7 @@ private: QImageData *d; friend class QRasterPixmapData; + friend class QBlittablePixmapData; friend class QPixmapCacheEntry; friend Q_GUI_EXPORT qint64 qt_image_id(const QImage &image); friend const QVector<QRgb> *qt_image_colortable(const QImage &image); diff --git a/src/gui/image/qnativeimage.cpp b/src/gui/image/qnativeimage.cpp index 5978a1b..0f7872e 100644 --- a/src/gui/image/qnativeimage.cpp +++ b/src/gui/image/qnativeimage.cpp @@ -45,6 +45,9 @@ #include "private/qpaintengine_raster_p.h" +#include "private/qapplication_p.h" +#include "private/qgraphicssystem_p.h" + #if defined(Q_WS_X11) && !defined(QT_NO_MITSHM) #include <qx11info_x11.h> #include <sys/ipc.h> @@ -295,7 +298,11 @@ QNativeImage::~QNativeImage() QImage::Format QNativeImage::systemFormat() { +#ifdef Q_WS_QPA + return QApplicationPrivate::platformIntegration()->screens().at(0)->format(); +#else return QImage::Format_RGB32; +#endif } #endif // platforms diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp index ad07fbd..5383b7c 100644 --- a/src/gui/image/qpixmap.cpp +++ b/src/gui/image/qpixmap.cpp @@ -1964,6 +1964,8 @@ int QPixmap::defaultDepth() return 32; #elif defined(Q_OS_SYMBIAN) return S60->screenDepth; +#elif defined(Q_WS_QPA) + return 32; //LITE: use graphicssystem (we should do that in general) #endif } diff --git a/src/gui/image/qpixmap_blitter.cpp b/src/gui/image/qpixmap_blitter.cpp new file mode 100644 index 0000000..e8a7b89 --- /dev/null +++ b/src/gui/image/qpixmap_blitter.cpp @@ -0,0 +1,311 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qpixmap_blitter_p.h" + +#include <qpainter.h> +#include <qimage.h> + +#include <private/qapplication_p.h> +#include <private/qgraphicssystem_p.h> +#include <private/qblittable_p.h> + +#include <private/qdrawhelper_p.h> + +#ifndef QT_NO_BLITTABLE +QT_BEGIN_NAMESPACE + +static int global_ser_no = 0; + +QBlittablePixmapData::QBlittablePixmapData() + : QPixmapData(QPixmapData::PixmapType,BlitterClass), m_engine(0), m_blittable(0) +#ifdef QT_BLITTER_RASTEROVERLAY + ,m_rasterOverlay(0), m_unmergedCopy(0) +#endif //QT_BLITTER_RASTEROVERLAY +{ + setSerialNumber(++global_ser_no); +} + +QBlittablePixmapData::~QBlittablePixmapData() +{ + delete m_blittable; + delete m_engine; +#ifdef QT_BLITTER_RASTEROVERLAY + delete m_rasterOverlay; + delete m_unmergedCopy; +#endif //QT_BLITTER_RASTEROVERLAY +} + +QBlittable *QBlittablePixmapData::blittable() const +{ + if (!m_blittable) { + QBlittablePixmapData *that = const_cast<QBlittablePixmapData *>(this); + that->m_blittable = this->createBlittable(QSize(w,h)); + } + + return m_blittable; +} + +void QBlittablePixmapData::setBlittable(QBlittable *blittable) +{ + resize(blittable->size().width(),blittable->size().height()); + m_blittable = blittable; +} + +void QBlittablePixmapData::resize(int width, int height) +{ + + delete m_blittable; + m_blittable = 0; + delete m_engine; + m_engine = 0; +#ifdef Q_WS_QPA + d = QApplicationPrivate::platformIntegration()->screens().at(0)->depth(); +#endif + w = width; + h = height; + is_null = (w <= 0 || h <= 0); +} +Q_GUI_EXPORT extern int qt_defaultDpiX(); +Q_GUI_EXPORT extern int qt_defaultDpiY(); + +int QBlittablePixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const +{ + switch (metric) { + case QPaintDevice::PdmWidth: + return w; + case QPaintDevice::PdmHeight: + return h; + case QPaintDevice::PdmWidthMM: + return qRound(w * 25.4 / qt_defaultDpiX()); + case QPaintDevice::PdmHeightMM: + return qRound(h * 25.4 / qt_defaultDpiY()); + case QPaintDevice::PdmDepth: + return 32; + case QPaintDevice::PdmDpiX: // fall-through + case QPaintDevice::PdmPhysicalDpiX: + return qt_defaultDpiX(); + case QPaintDevice::PdmDpiY: // fall-through + case QPaintDevice::PdmPhysicalDpiY: + return qt_defaultDpiY(); + default: + qWarning("QRasterPixmapData::metric(): Unhandled metric type %d", metric); + break; + } + + return 0; +} + +void QBlittablePixmapData::fill(const QColor &color) +{ + //jlind: todo: change when blittables can support non opaque fillRects + if (color.alpha() == 255 && blittable()->capabilities() & QBlittable::SolidRectCapability) { + blittable()->unlock(); + blittable()->fillRect(QRectF(0,0,w,h),color); + }else { + uint pixel; + switch (blittable()->lock()->format()) { + case QImage::Format_ARGB32_Premultiplied: + pixel = PREMUL(color.rgba()); + break; + case QImage::Format_ARGB8565_Premultiplied: + pixel = qargb8565(color.rgba()).rawValue(); + break; + case QImage::Format_ARGB8555_Premultiplied: + pixel = qargb8555(color.rgba()).rawValue(); + break; + case QImage::Format_ARGB6666_Premultiplied: + pixel = qargb6666(color.rgba()).rawValue(); + break; + case QImage::Format_ARGB4444_Premultiplied: + pixel = qargb4444(color.rgba()).rawValue(); + break; + default: + pixel = color.rgba(); + break; + } + //so premultiplied formats are supported and ARGB32 and RGB32 + blittable()->lock()->fill(pixel); + } + +} + +QImage *QBlittablePixmapData::buffer() +{ + return blittable()->lock(); +} + +QImage QBlittablePixmapData::toImage() const +{ + return blittable()->lock()->copy(); +} + +bool QBlittablePixmapData::hasAlphaChannel() const +{ + return blittable()->lock()->hasAlphaChannel(); +} + +void QBlittablePixmapData::fromImage(const QImage &image, + Qt::ImageConversionFlags flags) +{ + resize(image.width(),image.height()); + markRasterOverlay(QRect(0,0,w,h)); + QImage *thisImg = buffer(); + + QImage correctFormatPic = image; + if (correctFormatPic.format() != thisImg->format()) + correctFormatPic = correctFormatPic.convertToFormat(thisImg->format(), flags); + + uchar *mem = thisImg->bits(); + const uchar *bits = correctFormatPic.bits(); + int bytesCopied = 0; + while (bytesCopied < correctFormatPic.byteCount()) { + memcpy(mem,bits,correctFormatPic.bytesPerLine()); + mem += thisImg->bytesPerLine(); + bits += correctFormatPic.bytesPerLine(); + bytesCopied+=correctFormatPic.bytesPerLine(); + } +} + +QPaintEngine *QBlittablePixmapData::paintEngine() const +{ + if (!m_engine) { + QBlittablePixmapData *that = const_cast<QBlittablePixmapData *>(this); + that->m_engine = new QBlitterPaintEngine(that); + } + return m_engine; +} + +#ifdef QT_BLITTER_RASTEROVERLAY + +static bool showRasterOverlay = !qgetenv("QT_BLITTER_RASTEROVERLAY").isEmpty(); + +void QBlittablePixmapData::mergeOverlay() +{ + if (m_unmergedCopy || !showRasterOverlay) + return; + m_unmergedCopy = new QImage(buffer()->copy()); + QPainter p(buffer()); + p.setCompositionMode(QPainter::CompositionMode_SourceOver); + p.drawImage(0,0,*overlay()); + p.end(); +} + +void QBlittablePixmapData::unmergeOverlay() +{ + if (!m_unmergedCopy || !showRasterOverlay) + return; + QPainter p(buffer()); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.drawImage(0,0,*m_unmergedCopy); + p.end(); + + delete m_unmergedCopy; + m_unmergedCopy = 0; +} + +QImage *QBlittablePixmapData::overlay() +{ + if (!m_rasterOverlay|| + m_rasterOverlay->size() != QSize(w,h)){ + m_rasterOverlay = new QImage(w,h,QImage::Format_ARGB32_Premultiplied); + m_rasterOverlay->fill(0x00000000); + uint color = (qrand() % 11)+7; + m_overlayColor = QColor(Qt::GlobalColor(color)); + m_overlayColor.setAlpha(0x88); + + } + return m_rasterOverlay; +} + +void QBlittablePixmapData::markRasterOverlayImpl(const QRectF &rect) +{ + if (!showRasterOverlay) + return; + QRectF transformationRect = clipAndTransformRect(rect); + if(!transformationRect.isEmpty()) { + QPainter p(overlay()); + p.setBrush(m_overlayColor); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(transformationRect,QBrush(m_overlayColor)); + } +} + +void QBlittablePixmapData::unmarkRasterOverlayImpl(const QRectF &rect) +{ + if (!showRasterOverlay) + return; + QRectF transformationRect = clipAndTransformRect(rect); + if (!transformationRect.isEmpty()) { + QPainter p(overlay()); + QColor color(0x00,0x00,0x00,0x00); + p.setBrush(color); + p.setCompositionMode(QPainter::CompositionMode_Source); + p.fillRect(transformationRect,QBrush(color)); + } +} + +QRectF QBlittablePixmapData::clipAndTransformRect(const QRectF &rect) const +{ + QRectF transformationRect = rect; + paintEngine(); + if (m_engine->state()) { + transformationRect = m_engine->state()->matrix.mapRect(rect); + const QClipData *clipData = m_engine->clip(); + if (clipData) { + if (clipData->hasRectClip) { + transformationRect &= clipData->clipRect; + } else if (clipData->hasRegionClip) { + const QVector<QRect> rects = clipData->clipRegion.rects(); + for (int i = 0; i < rects.size(); i++) { + transformationRect &= rects.at(i); + } + } + } + } + return transformationRect; +} + +#endif //QT_BLITTER_RASTEROVERLAY + +QT_END_NAMESPACE + +#endif //QT_NO_BLITTABLE diff --git a/src/gui/image/qpixmap_blitter_p.h b/src/gui/image/qpixmap_blitter_p.h new file mode 100644 index 0000000..55b5618 --- /dev/null +++ b/src/gui/image/qpixmap_blitter_p.h @@ -0,0 +1,166 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ + +#ifndef QPIXMAP_BLITTER_P_H +#define QPIXMAP_BLITTER_P_H + +#include <private/qpixmapdata_p.h> +#include <private/qpaintengine_blitter_p.h> + +#ifndef QT_NO_BLITTABLE +QT_BEGIN_NAMESPACE + +class Q_GUI_EXPORT QBlittablePixmapData : public QPixmapData +{ +// Q_DECLARE_PRIVATE(QBlittablePixmapData); +public: + QBlittablePixmapData(); + ~QBlittablePixmapData(); + + virtual QBlittable *createBlittable(const QSize &size) const = 0; + QBlittable *blittable() const; + void setBlittable(QBlittable *blittable); + + void resize(int width, int height); + int metric(QPaintDevice::PaintDeviceMetric metric) const; + void fill(const QColor &color); + QImage *buffer(); + QImage toImage() const; + bool hasAlphaChannel() const; + void fromImage(const QImage &image, Qt::ImageConversionFlags flags); + + QPaintEngine *paintEngine() const; + + void markRasterOverlay(const QRectF &); + void markRasterOverlay(const QPointF &, const QTextItem &); + void markRasterOverlay(const QVectorPath &); + void markRasterOverlay(const QRect *rects, int rectCount); + void markRasterOverlay(const QRectF *rects, int rectCount); + void unmarkRasterOverlay(const QRectF &); + +#ifdef QT_BLITTER_RASTEROVERLAY + void mergeOverlay(); + void unmergeOverlay(); + QImage *overlay(); + +#endif //QT_BLITTER_RASTEROVERLAY +protected: + QBlitterPaintEngine *m_engine; + QBlittable *m_blittable; + +#ifdef QT_BLITTER_RASTEROVERLAY + QImage *m_rasterOverlay; + QImage *m_unmergedCopy; + QColor m_overlayColor; + + void markRasterOverlayImpl(const QRectF &); + void unmarkRasterOverlayImpl(const QRectF &); + QRectF clipAndTransformRect(const QRectF &) const; +#endif //QT_BLITTER_RASTEROVERLAY + +}; + +inline void QBlittablePixmapData::markRasterOverlay(const QRectF &rect) +{ +#ifdef QT_BLITTER_RASTEROVERLAY + markRasterOverlayImpl(rect); +#else + Q_UNUSED(rect) +#endif +} + +inline void QBlittablePixmapData::markRasterOverlay(const QVectorPath &path) +{ +#ifdef QT_BLITTER_RASTEROVERLAY + markRasterOverlayImpl(path.convertToPainterPath().boundingRect()); +#else + Q_UNUSED(path) +#endif +} + +inline void QBlittablePixmapData::markRasterOverlay(const QPointF &pos, const QTextItem &ti) +{ +#ifdef QT_BLITTER_RASTEROVERLAY + QFontMetricsF fm(ti.font()); + QRectF rect = fm.tightBoundingRect(ti.text()); + rect.moveBottomLeft(pos); + markRasterOverlay(rect); +#else + Q_UNUSED(pos) + Q_UNUSED(ti) +#endif +} + +inline void QBlittablePixmapData::markRasterOverlay(const QRect *rects, int rectCount) +{ +#ifdef QT_BLITTER_RASTEROVERLAY + for (int i = 0; i < rectCount; i++) { + markRasterOverlay(rects[i]); + } +#else + Q_UNUSED(rects) + Q_UNUSED(rectCount) +#endif +} +inline void QBlittablePixmapData::markRasterOverlay(const QRectF *rects, int rectCount) +{ +#ifdef QT_BLITTER_RASTEROVERLAY + for (int i = 0; i < rectCount; i++) { + markRasterOverlay(rects[i]); + } +#else + Q_UNUSED(rects) + Q_UNUSED(rectCount) +#endif +} + +inline void QBlittablePixmapData::unmarkRasterOverlay(const QRectF &rect) +{ +#ifdef QT_BLITTER_RASTEROVERLAY + unmarkRasterOverlayImpl(rect); +#else + Q_UNUSED(rect) +#endif +} + +QT_END_NAMESPACE +#endif // QT_NO_BLITTABLE +#endif // QPIXMAP_BLITTER_P_H diff --git a/src/gui/image/qpixmap_qpa.cpp b/src/gui/image/qpixmap_qpa.cpp new file mode 100644 index 0000000..61be216 --- /dev/null +++ b/src/gui/image/qpixmap_qpa.cpp @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** 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 QtGui 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 <qpixmap.h> +#include <private/qgraphicssystem_p.h> +#include <private/qapplication_p.h> + +QPixmap QPixmap::grabWindow(WId window, int x, int y, int w, int h) +{ + return QApplicationPrivate::platformIntegration()->grabWindow(window, x, y, w, h); +} diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h index ec62b0b..f69eb3d 100644 --- a/src/gui/image/qpixmapdata_p.h +++ b/src/gui/image/qpixmapdata_p.h @@ -75,7 +75,8 @@ public: }; #endif enum ClassId { RasterClass, X11Class, MacClass, DirectFBClass, - OpenGLClass, OpenVGClass, RuntimeClass, CustomClass = 1024 }; + OpenGLClass, OpenVGClass, RuntimeClass, BlitterClass, + CustomClass = 1024 }; QPixmapData(PixelType pixelType, int classId); virtual ~QPixmapData(); diff --git a/src/gui/image/qpixmapdatafactory.cpp b/src/gui/image/qpixmapdatafactory.cpp index 7498a7c..50dad38 100644 --- a/src/gui/image/qpixmapdatafactory.cpp +++ b/src/gui/image/qpixmapdatafactory.cpp @@ -53,6 +53,9 @@ #ifdef Q_WS_MAC # include <private/qpixmap_mac_p.h> #endif +#ifdef Q_WS_QPA +# include <private/qpixmap_raster_p.h> +#endif #ifdef Q_OS_SYMBIAN # include <private/qpixmap_s60_p.h> #endif @@ -82,8 +85,10 @@ QPixmapData* QSimplePixmapDataFactory::create(QPixmapData::PixelType type) return new QRasterPixmapData(type); #elif defined(Q_WS_MAC) return new QMacPixmapData(type); +#elif defined(Q_WS_QPA) + return new QRasterPixmapData(type); #elif defined(Q_OS_SYMBIAN) - return new QS60PixmapData(type); + return new QS60PixmapData(type); #else #error QSimplePixmapDataFactory::create() not implemented #endif diff --git a/src/gui/inputmethod/inputmethod.pri b/src/gui/inputmethod/inputmethod.pri index 02e3e57..d439438 100644 --- a/src/gui/inputmethod/inputmethod.pri +++ b/src/gui/inputmethod/inputmethod.pri @@ -19,7 +19,7 @@ embedded { HEADERS += inputmethod/qwsinputcontext_p.h SOURCES += inputmethod/qwsinputcontext_qws.cpp } -mac:!embedded { +mac:!embedded:!qpa { HEADERS += inputmethod/qmacinputcontext_p.h SOURCES += inputmethod/qmacinputcontext_mac.cpp } diff --git a/src/gui/kernel/kernel.pri b/src/gui/kernel/kernel.pri index 2629d7f..4261e93 100644 --- a/src/gui/kernel/kernel.pri +++ b/src/gui/kernel/kernel.pri @@ -32,8 +32,6 @@ HEADERS += \ kernel/qshortcutmap_p.h \ kernel/qsizepolicy.h \ kernel/qpalette.h \ - kernel/qsound.h \ - kernel/qsound_p.h \ kernel/qstackedlayout.h \ kernel/qtooltip.h \ kernel/qwhatsthis.h \ @@ -50,7 +48,7 @@ HEADERS += \ kernel/qgesturemanager_p.h \ kernel/qsoftkeymanager_p.h \ kernel/qsoftkeymanager_common_p.h \ - kernel/qguiplatformplugin_p.h + kernel/qguiplatformplugin_p.h \ SOURCES += \ kernel/qaction.cpp \ @@ -72,7 +70,6 @@ SOURCES += \ kernel/qpalette.cpp \ kernel/qshortcut.cpp \ kernel/qshortcutmap.cpp \ - kernel/qsound.cpp \ kernel/qstackedlayout.cpp \ kernel/qtooltip.cpp \ kernel/qguivariant.cpp \ @@ -200,7 +197,66 @@ embedded { } } -!embedded:!x11:mac { +!qpa { + HEADERS += \ + kernel/qsound.h \ + kernel/qsound_p.h + + SOURCES += \ + kernel/qsound.cpp +} + +qpa { + HEADERS += \ + kernel/qgenericpluginfactory_qpa.h \ + kernel/qgenericplugin_qpa.h \ + kernel/qeventdispatcher_qpa_p.h \ + kernel/qwindowsysteminterface_qpa.h \ + kernel/qwindowsysteminterface_qpa_p.h \ + kernel/qplatformintegration_qpa.h \ + kernel/qplatformscreen_qpa.h \ + kernel/qplatformintegrationfactory_qpa_p.h \ + kernel/qplatformintegrationplugin_qpa.h \ + kernel/qplatformwindow_qpa.h \ + kernel/qplatformwindowformat_qpa.h \ + kernel/qplatformglcontext_qpa.h \ + kernel/qdesktopwidget_qpa_p.h \ + kernel/qplatformeventloopintegration_qpa.h \ + kernel/qplatformcursor_qpa.h + + SOURCES += \ + kernel/qapplication_qpa.cpp \ + kernel/qclipboard_qpa.cpp \ + kernel/qcursor_qpa.cpp \ + kernel/qdnd_qws.cpp \ + kernel/qdesktopwidget_qpa.cpp \ + kernel/qgenericpluginfactory_qpa.cpp \ + kernel/qgenericplugin_qpa.cpp \ + kernel/qkeymapper_qws.cpp \ + kernel/qwidget_qpa.cpp \ + kernel/qeventdispatcher_qpa.cpp \ + kernel/qwindowsysteminterface_qpa.cpp \ + kernel/qplatformintegration_qpa.cpp \ + kernel/qplatformscreen_qpa.cpp \ + kernel/qplatformintegrationfactory_qpa.cpp \ + kernel/qplatformintegrationplugin_qpa.cpp \ + kernel/qplatformwindow_qpa.cpp \ + kernel/qplatformwindowformat_qpa.cpp \ + kernel/qplatformeventloopintegration_qpa.cpp \ + kernel/qplatformglcontext_qpa.cpp \ + kernel/qplatformcursor_qpa.cpp + + contains(QT_CONFIG, glib) { + SOURCES += \ + kernel/qeventdispatcher_glib_qpa.cpp + HEADERS += \ + kernel/qeventdispatcher_glib_qpa_p.h + QMAKE_CXXFLAGS += $$QT_CFLAGS_GLIB + LIBS_PRIVATE +=$$QT_LIBS_GLIB + } +} + +!embedded:!qpa:!x11:mac { SOURCES += \ kernel/qclipboard_mac.cpp \ kernel/qmime_mac.cpp \ diff --git a/src/gui/kernel/mac.pri b/src/gui/kernel/mac.pri index 1538510..21acd06 100644 --- a/src/gui/kernel/mac.pri +++ b/src/gui/kernel/mac.pri @@ -1,4 +1,4 @@ -!x11:!embedded:mac { +!x11:!embedded:!qpa:mac { LIBS_PRIVATE += -framework Carbon -lz *-mwerks:INCLUDEPATH += compat } diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp index 1284947..d81a3c3 100644 --- a/src/gui/kernel/qapplication.cpp +++ b/src/gui/kernel/qapplication.cpp @@ -450,6 +450,9 @@ QPalette *QApplicationPrivate::sys_pal = 0; // default system palette QPalette *QApplicationPrivate::set_pal = 0; // default palette set by programmer QGraphicsSystem *QApplicationPrivate::graphics_system = 0; // default graphics system +#if defined(Q_WS_QPA) +QPlatformIntegration *QApplicationPrivate::platform_integration = 0; +#endif QString QApplicationPrivate::graphics_system_name; // graphics system id - for delayed initialization bool QApplicationPrivate::runtime_graphics_system = false; @@ -512,7 +515,7 @@ inline bool QApplicationPrivate::isAlien(QWidget *widget) { if (!widget) return false; -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) return !widget->isWindow() # ifdef Q_BACKINGSTORE_SUBSURFACES && !(widget->d_func()->maybeTopData() && widget->d_func()->maybeTopData()->windowSurface) @@ -804,6 +807,7 @@ void QApplicationPrivate::construct( ) { initResources(); + graphics_system_name = QLatin1String(qgetenv("QT_DEFAULT_GRAPHICS_SYSTEM")); qt_is_gui_used = (qt_appType != QApplication::Tty); process_cmdline(); @@ -964,10 +968,11 @@ void QApplicationPrivate::initialize() QWidgetPrivate::mapper = new QWidgetMapper; QWidgetPrivate::allWidgets = new QWidgetSet; -#if !defined(Q_WS_X11) && !defined(Q_WS_QWS) +#if !defined(Q_WS_X11) && !defined(Q_WS_QWS) && !defined(Q_WS_QPA) // initialize the graphics system - on X11 this is initialized inside // qt_init() in qapplication_x11.cpp because of several reasons. // On QWS, the graphics system is set by the QScreen plugin. + // We don't use graphics systems in Qt QPA graphics_system = QGraphicsSystemFactory::create(graphics_system_name); #endif @@ -1633,14 +1638,18 @@ QStyle* QApplication::setStyle(const QString& style) void QApplication::setGraphicsSystem(const QString &system) { -#ifdef QT_GRAPHICSSYSTEM_RUNTIME +#ifdef Q_WS_QPA + Q_UNUSED(system); +#else +# ifdef QT_GRAPHICSSYSTEM_RUNTIME if (QApplicationPrivate::graphics_system_name == QLatin1String("runtime")) { QRuntimeGraphicsSystem *r = static_cast<QRuntimeGraphicsSystem *>(QApplicationPrivate::graphics_system); r->setGraphicsSystem(system); } else -#endif +# endif QApplicationPrivate::graphics_system_name = system; +#endif } /*! @@ -2786,7 +2795,7 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) { // Update cursor for alien/graphics widgets. const bool enterOnAlien = (enter && (isAlien(enter) || enter->testAttribute(Qt::WA_DontShowOnScreen))); -#if defined(Q_WS_X11) +#if defined(Q_WS_X11) || defined(Q_WS_QPA) //Whenever we leave an alien widget on X11, we need to reset its nativeParentWidget()'s cursor. // This is not required on Windows as the cursor is reset on every single mouse move. QWidget *parentOfLeavingCursor = 0; @@ -2810,7 +2819,15 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) { if (!parentOfLeavingCursor->window()->graphicsProxyWidget()) #endif { +#if defined(Q_WS_X11) qt_x11_enforce_cursor(parentOfLeavingCursor,true); +#elif defined(Q_WS_QPA) + if (enter == QApplication::desktop()) { + qt_qpa_set_cursor(enter, true); + } else { + qt_qpa_set_cursor(parentOfLeavingCursor, true); + } +#endif } } #endif @@ -2834,6 +2851,8 @@ void QApplicationPrivate::dispatchEnterLeave(QWidget* enter, QWidget* leave) { qt_x11_enforce_cursor(cursorWidget, true); #elif defined(Q_OS_SYMBIAN) qt_symbian_set_cursor(cursorWidget, true); +#elif defined(Q_WS_QPA) + qt_qpa_set_cursor(cursorWidget, true); #endif } } @@ -3138,7 +3157,7 @@ bool QApplicationPrivate::sendMouseEvent(QWidget *receiver, QMouseEvent *event, return result; } -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_MAC) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA) /* This function should only be called when the widget changes visibility, i.e. when the \a widget is shown, hidden or deleted. This function does nothing @@ -3150,7 +3169,7 @@ extern QWidget *qt_button_down; void QApplicationPrivate::sendSyntheticEnterLeave(QWidget *widget) { #ifndef QT_NO_CURSOR -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) if (!widget || widget->isWindow()) return; #else @@ -6075,6 +6094,8 @@ QPixmap QApplicationPrivate::getPixmapCursor(Qt::CursorShape cshape) default: break; } +#else + Q_UNUSED(cshape); #endif return QPixmap(); } diff --git a/src/gui/kernel/qapplication_p.h b/src/gui/kernel/qapplication_p.h index 636829e..9f675e3 100644 --- a/src/gui/kernel/qapplication_p.h +++ b/src/gui/kernel/qapplication_p.h @@ -65,8 +65,10 @@ #include "QtCore/qhash.h" #include "QtCore/qpointer.h" #include "private/qcoreapplication_p.h" -#include "private/qshortcutmap_p.h" +#include "QtGui/private/qshortcutmap_p.h" #include <private/qthread_p.h> +#include "QtCore/qpoint.h" +#include <QTime> #ifdef Q_WS_QWS #include "QtGui/qscreen_qws.h" #include <private/qgraphicssystem_qws_p.h> @@ -74,6 +76,11 @@ #ifdef Q_OS_SYMBIAN #include <w32std.h> #endif +#ifdef Q_WS_QPA +#include <QWindowSystemInterface> +#include "qwindowsysteminterface_qpa_p.h" +#include "QtGui/qplatformintegration_qpa.h" +#endif QT_BEGIN_NAMESPACE @@ -312,10 +319,18 @@ public: static QString desktopStyleKey(); static QGraphicsSystem *graphicsSystem() -#if !defined(Q_WS_QWS) - { return graphics_system; } -#else +#if defined(Q_WS_QWS) { return QScreen::instance()->graphicsSystem(); } +#else + { return graphics_system; } +#endif + +#if defined(Q_WS_QPA) + static QPlatformIntegration *platformIntegration() + { return platform_integration; } + + static QAbstractEventDispatcher *qt_qpa_core_dispatcher() + { return QCoreApplication::instance()->d_func()->threadData->eventDispatcher; } #endif void createEventDispatcher(); @@ -418,6 +433,9 @@ public: static QGraphicsSystem *graphics_system; static QString graphics_system_name; static bool runtime_graphics_system; +#ifdef Q_WS_QPA + static QPlatformIntegration *platform_integration; +#endif private: static QFont *app_font; // private for a reason! Always use QApplication::font() instead! @@ -476,6 +494,30 @@ public: static bool qt_mac_apply_settings(); #endif +#ifdef Q_WS_QPA + static void processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent *e); + static void processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent *e); + static void processWheelEvent(QWindowSystemInterfacePrivate::WheelEvent *e); + static void processTouchEvent(QWindowSystemInterfacePrivate::TouchEvent *e); + + static void processCloseEvent(QWindowSystemInterfacePrivate::CloseEvent *e); + + static void processGeometryChangeEvent(QWindowSystemInterfacePrivate::GeometryChangeEvent *e); + + static void processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent *e); + static void processLeaveEvent(QWindowSystemInterfacePrivate::LeaveEvent *e); + + static void processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e); + +// static void reportScreenCount(int count); + static void reportScreenCount(QWindowSystemInterfacePrivate::ScreenCountEvent *e); +// static void reportGeometryChange(int screenIndex); + static void reportGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e); +// static void reportAvailableGeometryChange(int screenIndex); + static void reportAvailableGeometryChange(QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e); + +#endif + #ifdef Q_WS_QWS QPointer<QWSManager> last_manager; QWSServerCleaner qwsServerCleaner; @@ -521,7 +563,7 @@ public: void _q_aboutToQuit(); #endif -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA) void sendSyntheticEnterLeave(QWidget *widget); #endif @@ -629,6 +671,8 @@ Q_GUI_EXPORT void qt_translateRawTouchEvent(QWidget *window, extern void qt_x11_enforce_cursor(QWidget *); #elif defined(Q_OS_SYMBIAN) extern void qt_symbian_set_cursor(QWidget *, bool); +#elif defined (Q_WS_QPA) + extern void qt_qpa_set_cursor(QWidget *, bool); #endif QT_END_NAMESPACE diff --git a/src/gui/kernel/qapplication_qpa.cpp b/src/gui/kernel/qapplication_qpa.cpp new file mode 100644 index 0000000..ece035c --- /dev/null +++ b/src/gui/kernel/qapplication_qpa.cpp @@ -0,0 +1,928 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qapplication_p.h" +#include "qcolormap.h" +#include "qpixmapcache.h" +#if !defined(QT_NO_GLIB) +#include "qeventdispatcher_glib_qpa_p.h" +#endif +#include "qeventdispatcher_qpa_p.h" +#ifndef QT_NO_CURSOR +#include "private/qcursor_p.h" +#endif + +#include "private/qwidget_p.h" + +#include "qgenericpluginfactory_qpa.h" +#include "qplatformintegrationfactory_qpa_p.h" +#include <qdesktopwidget.h> + +#include <qinputcontext.h> +#include <QPlatformCursor> +#include <qdebug.h> +#include <QWindowSystemInterface> +#include "qwindowsysteminterface_qpa_p.h" +#include <QPlatformIntegration> + +#include "qdesktopwidget_qpa_p.h" + +QT_BEGIN_NAMESPACE + +static QString appName; +static QString appFont; + +QWidget *qt_button_down = 0; // widget got last button-down + +static bool app_do_modal = false; +extern QWidgetList *qt_modal_stack; // stack of modal widgets + +int qt_last_x = 0; +int qt_last_y = 0; +QPointer<QWidget> qt_last_mouse_receiver = 0; + +static Qt::KeyboardModifiers modifiers = Qt::NoModifier; +static Qt::MouseButtons buttons = Qt::NoButton; +static ulong mousePressTime; +static Qt::MouseButton mousePressButton = Qt::NoButton; +static int mousePressX; +static int mousePressY; +static int mouse_double_click_distance = 5; + +void QApplicationPrivate::processWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *e) +{ + switch(e->type) { + case QWindowSystemInterfacePrivate::Mouse: + QApplicationPrivate::processMouseEvent(static_cast<QWindowSystemInterfacePrivate::MouseEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::Wheel: + QApplicationPrivate::processWheelEvent(static_cast<QWindowSystemInterfacePrivate::WheelEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::Key: + QApplicationPrivate::processKeyEvent(static_cast<QWindowSystemInterfacePrivate::KeyEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::Touch: + QApplicationPrivate::processTouchEvent(static_cast<QWindowSystemInterfacePrivate::TouchEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::GeometryChange: + QApplicationPrivate::processGeometryChangeEvent(static_cast<QWindowSystemInterfacePrivate::GeometryChangeEvent*>(e)); + break; + case QWindowSystemInterfacePrivate::Enter: + QApplicationPrivate::processEnterEvent(static_cast<QWindowSystemInterfacePrivate::EnterEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::Leave: + QApplicationPrivate::processLeaveEvent(static_cast<QWindowSystemInterfacePrivate::LeaveEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::Close: + QApplicationPrivate::processCloseEvent( + static_cast<QWindowSystemInterfacePrivate::CloseEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::ScreenCountChange: + QApplicationPrivate::reportScreenCount( + static_cast<QWindowSystemInterfacePrivate::ScreenCountEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::ScreenGeometry: + QApplicationPrivate::reportGeometryChange( + static_cast<QWindowSystemInterfacePrivate::ScreenGeometryEvent *>(e)); + break; + case QWindowSystemInterfacePrivate::ScreenAvailableGeometry: + QApplicationPrivate::reportAvailableGeometryChange( + static_cast<QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *>(e)); + break; + default: + qWarning() << "Unknown user input event type:" << e->type; + break; + } +} + +QString QApplicationPrivate::appName() const +{ + return QT_PREPEND_NAMESPACE(appName); +} + +void QApplicationPrivate::createEventDispatcher() +{ + Q_Q(QApplication); +#if !defined(QT_NO_GLIB) + if (qgetenv("QT_NO_GLIB").isEmpty() && QEventDispatcherGlib::versionSupported()) + eventDispatcher = new QPAEventDispatcherGlib(q); + else +#endif + eventDispatcher = new QEventDispatcherQPA(q); +} + +static bool qt_try_modal(QWidget *widget, QEvent::Type type) +{ + QWidget * top = 0; + + if (QApplicationPrivate::tryModalHelper(widget, &top)) + return true; + + bool block_event = false; + bool paint_event = false; + + switch (type) { +#if 0 + case QEvent::Focus: + if (!static_cast<QWSFocusEvent*>(event)->simpleData.get_focus) + break; + // drop through +#endif + case QEvent::MouseButtonPress: // disallow mouse/key events + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + case QEvent::KeyPress: + case QEvent::KeyRelease: + block_event = true; + break; + default: + break; + } + + if ((block_event || paint_event) && top->parentWidget() == 0) + top->raise(); + + return !block_event; +} + + + +void QApplicationPrivate::enterModal_sys(QWidget *widget) +{ + if (!qt_modal_stack) + qt_modal_stack = new QWidgetList; + qt_modal_stack->insert(0, widget); + app_do_modal = true; +} + +void QApplicationPrivate::leaveModal_sys(QWidget *widget ) +{ + if (qt_modal_stack && qt_modal_stack->removeAll(widget)) { + if (qt_modal_stack->isEmpty()) { + delete qt_modal_stack; + qt_modal_stack = 0; + } + } + app_do_modal = qt_modal_stack != 0; +} + +bool QApplicationPrivate::modalState() +{ + return app_do_modal; +} + +void QApplicationPrivate::closePopup(QWidget *popup) +{ + Q_Q(QApplication); + if (!popupWidgets) + return; + popupWidgets->removeAll(popup); + +//### +// if (popup == qt_popup_down) { +// qt_button_down = 0; +// qt_popup_down = 0; +// } + + if (QApplicationPrivate::popupWidgets->count() == 0) { // this was the last popup + delete QApplicationPrivate::popupWidgets; + QApplicationPrivate::popupWidgets = 0; + + //### replay mouse event? + + //### transfer/release mouse grab + + //### transfer/release keyboard grab + + //give back focus + + if (active_window) { + if (QWidget *fw = active_window->focusWidget()) { + if (fw != QApplication::focusWidget()) { + fw->setFocus(Qt::PopupFocusReason); + } else { + QFocusEvent e(QEvent::FocusIn, Qt::PopupFocusReason); + q->sendEvent(fw, &e); + } + } + } + + } else { + // A popup was closed, so the previous popup gets the focus. + + QWidget* aw = QApplicationPrivate::popupWidgets->last(); + if (QWidget *fw = aw->focusWidget()) + fw->setFocus(Qt::PopupFocusReason); + + //### regrab the keyboard and mouse in case 'popup' lost the grab + + + } + +} + +static int openPopupCount = 0; +void QApplicationPrivate::openPopup(QWidget *popup) +{ + openPopupCount++; + if (!popupWidgets) { // create list + popupWidgets = new QWidgetList; + + /* only grab if you are the first/parent popup */ + //#### ->grabMouse(popup,true); + //#### ->grabKeyboard(popup,true); + //### popupGrabOk = true; + } + popupWidgets->append(popup); // add to end of list + + // popups are not focus-handled by the window system (the first + // popup grabbed the keyboard), so we have to do that manually: A + // new popup gets the focus + if (popup->focusWidget()) { + popup->focusWidget()->setFocus(Qt::PopupFocusReason); + } else if (popupWidgets->count() == 1) { // this was the first popup + if (QWidget *fw = QApplication::focusWidget()) { + QFocusEvent e(QEvent::FocusOut, Qt::PopupFocusReason); + QApplication::sendEvent(fw, &e); + } + } +} + +void QApplicationPrivate::initializeMultitouch_sys() +{ +} + +void QApplicationPrivate::cleanupMultitouch_sys() +{ +} + +void QApplicationPrivate::initializeWidgetPaletteHash() +{ +} + +void QApplication::setCursorFlashTime(int msecs) +{ + QApplicationPrivate::cursor_flash_time = msecs; +} + +int QApplication::cursorFlashTime() +{ + return QApplicationPrivate::cursor_flash_time; +} + +void QApplication::setDoubleClickInterval(int ms) +{ + QApplicationPrivate::mouse_double_click_time = ms; +} + +int QApplication::doubleClickInterval() +{ + return QApplicationPrivate::mouse_double_click_time; +} + +void QApplication::setKeyboardInputInterval(int ms) +{ + QApplicationPrivate::keyboard_input_time = ms; +} + +int QApplication::keyboardInputInterval() +{ + return QApplicationPrivate::keyboard_input_time; +} + +#ifndef QT_NO_WHEELEVENT +void QApplication::setWheelScrollLines(int lines) +{ + QApplicationPrivate::wheel_scroll_lines = lines; +} + +int QApplication::wheelScrollLines() +{ + return QApplicationPrivate::wheel_scroll_lines; +} +#endif + +void QApplication::setEffectEnabled(Qt::UIEffect effect, bool enable) +{ + switch (effect) { + case Qt::UI_AnimateMenu: + QApplicationPrivate::animate_menu = enable; + break; + case Qt::UI_FadeMenu: + if (enable) + QApplicationPrivate::animate_menu = true; + QApplicationPrivate::fade_menu = enable; + break; + case Qt::UI_AnimateCombo: + QApplicationPrivate::animate_combo = enable; + break; + case Qt::UI_AnimateTooltip: + QApplicationPrivate::animate_tooltip = enable; + break; + case Qt::UI_FadeTooltip: + if (enable) + QApplicationPrivate::animate_tooltip = true; + QApplicationPrivate::fade_tooltip = enable; + break; + case Qt::UI_AnimateToolBox: + QApplicationPrivate::animate_toolbox = enable; + break; + default: + QApplicationPrivate::animate_ui = enable; + break; + } +} + +bool QApplication::isEffectEnabled(Qt::UIEffect effect) +{ + if (QColormap::instance().depth() < 16 || !QApplicationPrivate::animate_ui) + return false; + + switch(effect) { + case Qt::UI_AnimateMenu: + return QApplicationPrivate::animate_menu; + case Qt::UI_FadeMenu: + return QApplicationPrivate::fade_menu; + case Qt::UI_AnimateCombo: + return QApplicationPrivate::animate_combo; + case Qt::UI_AnimateTooltip: + return QApplicationPrivate::animate_tooltip; + case Qt::UI_FadeTooltip: + return QApplicationPrivate::fade_tooltip; + case Qt::UI_AnimateToolBox: + return QApplicationPrivate::animate_toolbox; + default: + return QApplicationPrivate::animate_ui; + } +} + +#ifndef QT_NO_CURSOR +void QApplication::setOverrideCursor(const QCursor &cursor) +{ + qApp->d_func()->cursor_list.prepend(cursor); + qt_qpa_set_cursor(0, false); +} + +void QApplication::restoreOverrideCursor() +{ + if (qApp->d_func()->cursor_list.isEmpty()) + return; + qApp->d_func()->cursor_list.removeFirst(); + qt_qpa_set_cursor(0, false); +} + +#endif// QT_NO_CURSOR + +QWidget *QApplication::topLevelAt(const QPoint &pos) +{ + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + + QList<QPlatformScreen *> screens = pi->screens(); + QList<QPlatformScreen *>::const_iterator screen = screens.constBegin(); + QList<QPlatformScreen *>::const_iterator end = screens.constEnd(); + + // The first screen in a virtual environment should know about all top levels + if (pi->isVirtualDesktop()) { + QWidget *w = (*screen)->topLevelAt(pos); + return w; + } + + while (screen != end) { + if ((*screen)->geometry().contains(pos)) + return (*screen)->topLevelAt(pos); + ++screen; + } + return 0; +} + +void QApplication::beep() +{ +} + +void QApplication::alert(QWidget *, int) +{ +} + +static void init_platform(const QString &name) +{ + QApplicationPrivate::platform_integration = QPlatformIntegrationFactory::create(name); + if (!QApplicationPrivate::platform_integration) { + QStringList keys = QPlatformIntegrationFactory::keys(); + QString fatalMessage = + QString::fromLatin1("Failed to load platform plugin \"%1\". Available platforms are: \n").arg(name); + foreach(QString key, keys) { + fatalMessage.append(key + QString::fromLatin1("\n")); + } + qFatal("%s", fatalMessage.toLocal8Bit().constData()); + + } + +} + + +static void cleanup_platform() +{ + delete QApplicationPrivate::platform_integration; + QApplicationPrivate::platform_integration = 0; +} + +static void init_plugins(const QList<QByteArray> pluginList) +{ + for (int i = 0; i < pluginList.count(); ++i) { + QByteArray pluginSpec = pluginList.at(i); + qDebug() << "init_plugins" << i << pluginSpec; + int colonPos = pluginSpec.indexOf(':'); + QObject *plugin; + if (colonPos < 0) + plugin = QGenericPluginFactory::create(QLatin1String(pluginSpec), QString()); + else + plugin = QGenericPluginFactory::create(QLatin1String(pluginSpec.mid(0, colonPos)), + QLatin1String(pluginSpec.mid(colonPos+1))); + qDebug() << " created" << plugin; + } +} + +#ifndef QT_NO_QWS_INPUTMETHODS +class QDummyInputContext : public QInputContext +{ +public: + explicit QDummyInputContext(QObject* parent = 0) : QInputContext(parent) {} + ~QDummyInputContext() {} + QString identifierName() { return QString(); } + QString language() { return QString(); } + + void reset() {} + bool isComposing() const { return false; } + +}; +#endif // QT_NO_QWS_INPUTMETHODS + +void qt_init(QApplicationPrivate *priv, int type) +{ + Q_UNUSED(type); + + qApp->setAttribute(Qt::AA_DontCreateNativeWidgetSiblings); + char *p; + char **argv = priv->argv; + int argc = priv->argc; + + if (argv && *argv) { //apparently, we allow people to pass 0 on the other platforms + p = strrchr(argv[0], '/'); + appName = QString::fromLocal8Bit(p ? p + 1 : argv[0]); + } + + QList<QByteArray> pluginList; + QString platformName = QLatin1String(qgetenv("QT_QPA_PLATFORM")); + + // Get command line params + + int j = argc ? 1 : 0; + for (int i=1; i<argc; i++) { + if (argv[i] && *argv[i] != '-') { + argv[j++] = argv[i]; + continue; + } + QByteArray arg = argv[i]; + if (arg == "-fn" || arg == "-font") { + if (++i < argc) + appFont = QString::fromLocal8Bit(argv[i]); + } else if (arg == "-platform") { + if (++i < argc) + platformName = QLatin1String(argv[i]); + } else if (arg == "-plugin") { + if (++i < argc) + pluginList << argv[i]; + } else { + argv[j++] = argv[i]; + } + } + + if (j < priv->argc) { + priv->argv[j] = 0; + priv->argc = j; + } + +#if 0 + QByteArray pluginEnv = qgetenv("QT_QPA_PLUGINS"); + if (!pluginEnv.isEmpty()) { + pluginList.append(pluginEnv.split(';')); + } +#endif + + init_platform(platformName); + init_plugins(pluginList); + + QColormap::initialize(); + QFont::initialize(); +#ifndef QT_NO_CURSOR +// QCursorData::initialize(); +#endif + + qApp->setObjectName(appName); + +#ifndef QT_NO_QWS_INPUTMETHODS + qApp->setInputContext(new QDummyInputContext(qApp)); +#endif +} + +void qt_cleanup() +{ + cleanup_platform(); + + QPixmapCache::clear(); +#ifndef QT_NO_CURSOR + QCursorData::cleanup(); +#endif + QFont::cleanup(); + QColormap::cleanup(); + delete QApplicationPrivate::inputContext; + QApplicationPrivate::inputContext = 0; + + QApplicationPrivate::active_window = 0; //### this should not be necessary +} + + +#ifdef QT3_SUPPORT +void QApplication::setMainWidget(QWidget *mainWidget) +{ + QApplicationPrivate::main_widget = mainWidget; + if (QApplicationPrivate::main_widget && windowIcon().isNull() + && QApplicationPrivate::main_widget->testAttribute(Qt::WA_SetWindowIcon)) + setWindowIcon(QApplicationPrivate::main_widget->windowIcon()); +} +#endif + +void QApplicationPrivate::processMouseEvent(QWindowSystemInterfacePrivate::MouseEvent *e) +{ + // qDebug() << "handleMouseEvent" << tlw << ev.pos() << ev.globalPos() << hex << ev.buttons(); + static QWeakPointer<QWidget> implicit_mouse_grabber; + + QEvent::Type type; + // move first + Qt::MouseButtons stateChange = e->buttons ^ buttons; + if (e->globalPos != QPoint(qt_last_x, qt_last_y) && (stateChange != Qt::NoButton)) { + QWindowSystemInterfacePrivate::MouseEvent * newMouseEvent = + new QWindowSystemInterfacePrivate::MouseEvent(e->widget.data(), e->timestamp, e->localPos, e->globalPos, e->buttons); + QWindowSystemInterfacePrivate::windowSystemEventQueue.prepend(newMouseEvent); // just in case the move triggers a new event loop + stateChange = Qt::NoButton; + } + + QWidget * tlw = e->widget.data(); + + QPoint localPoint = e->localPos; + QPoint globalPoint = e->globalPos; + QWidget *mouseWindow = tlw; + + Qt::MouseButton button = Qt::NoButton; + + + if (qt_last_x != globalPoint.x() || qt_last_y != globalPoint.y()) { + type = QEvent::MouseMove; + qt_last_x = globalPoint.x(); + qt_last_y = globalPoint.y(); + if (qAbs(globalPoint.x() - mousePressX) > mouse_double_click_distance|| + qAbs(globalPoint.y() - mousePressY) > mouse_double_click_distance) + mousePressButton = Qt::NoButton; + } + else { // check to see if a new button has been pressed/released + for (int check = Qt::LeftButton; + check <= Qt::XButton2; + check = check << 1) { + if (check & stateChange) { + button = Qt::MouseButton(check); + break; + } + } + if (button == Qt::NoButton) { + // Ignore mouse events that don't change the current state + return; + } + buttons = e->buttons; + if (button & e->buttons) { + if ((e->timestamp - mousePressTime) < static_cast<ulong>(QApplication::doubleClickInterval()) && button == mousePressButton) { + type = QEvent::MouseButtonDblClick; + mousePressButton = Qt::NoButton; + } + else { + type = QEvent::MouseButtonPress; + mousePressTime = e->timestamp; + mousePressButton = button; + mousePressX = qt_last_x; + mousePressY = qt_last_y; + } + } + else + type = QEvent::MouseButtonRelease; + } + + if (self->inPopupMode()) { + //popup mouse handling is magical... + mouseWindow = qApp->activePopupWidget(); + + implicit_mouse_grabber.clear(); + //### how should popup mode and implicit mouse grab interact? + + } else if (tlw && app_do_modal && !qt_try_modal(tlw, QEvent::MouseButtonRelease) ) { + //even if we're blocked by modality, we should deliver the mouse release event.. + //### this code is not completely correct: multiple buttons can be pressed simultaneously + if (!(implicit_mouse_grabber && buttons == Qt::NoButton)) { + //qDebug() << "modal blocked mouse event to" << tlw; + return; + } + } + + // find the tlw if we didn't get it from the plugin + if (!mouseWindow) { + mouseWindow = QApplication::topLevelAt(globalPoint); + } + + if (!mouseWindow && !implicit_mouse_grabber) + mouseWindow = QApplication::desktop(); + + if (mouseWindow && mouseWindow != tlw) { + //we did not get a sensible localPoint from the window system, so let's calculate it + localPoint = mouseWindow->mapFromGlobal(globalPoint); + } + + // which child should have it? + QWidget *mouseWidget = mouseWindow; + if (mouseWindow) { + QWidget *w = mouseWindow->childAt(localPoint); + if (w) { + mouseWidget = w; + } + } + + //handle implicit mouse grab + if (type == QEvent::MouseButtonPress && !implicit_mouse_grabber) { + implicit_mouse_grabber = mouseWidget; + + Q_ASSERT(mouseWindow); + mouseWindow->activateWindow(); //focus + } else if (implicit_mouse_grabber) { + mouseWidget = implicit_mouse_grabber.data(); + mouseWindow = mouseWidget->window(); + if (mouseWindow != tlw) + localPoint = mouseWindow->mapFromGlobal(globalPoint); + } + + Q_ASSERT(mouseWidget); + + //localPoint is local to mouseWindow, but it needs to be local to mouseWidget + localPoint = mouseWidget->mapFrom(mouseWindow, localPoint); + + if (buttons == Qt::NoButton) { + //qDebug() << "resetting mouse grabber"; + implicit_mouse_grabber.clear(); + } + + if (mouseWidget != qt_last_mouse_receiver) { + dispatchEnterLeave(mouseWidget, qt_last_mouse_receiver); + qt_last_mouse_receiver = mouseWidget; + } + + // Remember, we might enter a modal event loop when sending the event, + // so think carefully before adding code below this point. + + // qDebug() << "sending mouse ev." << ev.type() << localPoint << globalPoint << ev.button() << ev.buttons() << mouseWidget << "mouse grabber" << implicit_mouse_grabber; + + QMouseEvent ev(type, localPoint, globalPoint, button, buttons, modifiers); + + QList<QWeakPointer<QPlatformCursor> > cursors = QPlatformCursorPrivate::getInstances(); + foreach (QWeakPointer<QPlatformCursor> cursor, cursors) { + if (cursor) + cursor.data()->pointerEvent(ev); + } + + QApplication::sendSpontaneousEvent(mouseWidget, &ev); +} + + +//### there's a lot of duplicated logic here -- refactoring required! + +void QApplicationPrivate::processWheelEvent(QWindowSystemInterfacePrivate::WheelEvent *e) +{ +// QPoint localPoint = ev.pos(); + QPoint globalPoint = e->globalPos; +// bool trustLocalPoint = !!tlw; //is there something the local point can be local to? + QWidget *mouseWidget; + + qt_last_x = globalPoint.x(); + qt_last_y = globalPoint.y(); + + QWidget *mouseWindow = e->widget.data(); + + // find the tlw if we didn't get it from the plugin + if (!mouseWindow) { + mouseWindow = QApplication::topLevelAt(globalPoint); + } + + if (!mouseWindow) + return; + + mouseWidget = mouseWindow; + + if (app_do_modal && !qt_try_modal(mouseWindow, QEvent::Wheel) ) { + qDebug() << "modal blocked wheel event" << mouseWindow; + return; + } + QPoint p = mouseWindow->mapFromGlobal(globalPoint); + QWidget *w = mouseWindow->childAt(p); + if (w) { + mouseWidget = w; + p = mouseWidget->mapFromGlobal(globalPoint); + } + + QWheelEvent ev(p, globalPoint, e->delta, buttons, modifiers, + e->orient); + QApplication::sendSpontaneousEvent(mouseWidget, &ev); +} + + + +// Remember, Qt convention is: keyboard state is state *before* + +void QApplicationPrivate::processKeyEvent(QWindowSystemInterfacePrivate::KeyEvent *e) +{ + QWidget *focusW = 0; + if (self->inPopupMode()) { + QWidget *popupW = qApp->activePopupWidget(); + focusW = popupW->focusWidget() ? popupW->focusWidget() : popupW; + } + if (!focusW) + focusW = QApplication::focusWidget(); + if (!focusW) { + focusW = e->widget.data(); + } + if (!focusW) + focusW = QApplication::activeWindow(); + + //qDebug() << "handleKeyEvent" << hex << e->key() << e->modifiers() << e->text() << "widget" << focusW; + + if (!focusW) + return; + if (app_do_modal && !qt_try_modal(focusW, e->keyType)) + return; + + modifiers = e->modifiers; + QKeyEvent ev(e->keyType, e->key, e->modifiers, e->unicode, e->repeat, e->repeatCount); + QApplication::sendSpontaneousEvent(focusW, &ev); +} + +void QApplicationPrivate::processEnterEvent(QWindowSystemInterfacePrivate::EnterEvent *e) +{ + QApplicationPrivate::dispatchEnterLeave(e->enter.data(),0); + qt_last_mouse_receiver = e->enter.data(); +} + +void QApplicationPrivate::processLeaveEvent(QWindowSystemInterfacePrivate::LeaveEvent *e) +{ + QApplicationPrivate::dispatchEnterLeave(0,qt_last_mouse_receiver); + + if (e->leave.data() && !e->leave.data()->isAncestorOf(qt_last_mouse_receiver)) //(???) this should not happen + QApplicationPrivate::dispatchEnterLeave(0, e->leave.data()); + qt_last_mouse_receiver = 0; + +} + + +void QApplicationPrivate::processGeometryChangeEvent(QWindowSystemInterfacePrivate::GeometryChangeEvent *e) +{ + if (e->tlw.isNull()) + return; + QWidget *tlw = e->tlw.data(); + if (!tlw->isWindow()) + return; //geo of native child widgets is controlled by lighthouse + //so we already have sent the events; besides this new rect + //is not mapped to parent + + QRect newRect = e->newGeometry; + QRect cr(tlw->geometry()); + bool isResize = cr.size() != newRect.size(); + bool isMove = cr.topLeft() != newRect.topLeft(); + tlw->data->crect = newRect; + if (isResize) { + QResizeEvent e(tlw->data->crect.size(), cr.size()); + QApplication::sendSpontaneousEvent(tlw, &e); + tlw->update(); + } + + if (isMove) { + //### frame geometry + QMoveEvent e(tlw->data->crect.topLeft(), cr.topLeft()); + QApplication::sendSpontaneousEvent(tlw, &e); + } +} + +void QApplicationPrivate::processCloseEvent(QWindowSystemInterfacePrivate::CloseEvent *e) +{ + if (e->topLevel.isNull()) { + //qDebug() << "QApplicationPrivate::processCloseEvent NULL"; + return; + } + e->topLevel.data()->d_func()->close_helper(QWidgetPrivate::CloseWithSpontaneousEvent); +} + +void QApplicationPrivate::processTouchEvent(QWindowSystemInterfacePrivate::TouchEvent *e) +{ + translateRawTouchEvent(e->widget.data(), e->devType, e->points); +} + +void QApplicationPrivate::reportScreenCount(QWindowSystemInterfacePrivate::ScreenCountEvent *e) +{ + // This operation only makes sense after the QApplication constructor runs + if (QCoreApplication::startingUp()) + return; + + QApplication::desktop()->d_func()->updateScreenList(); + // signal anything listening for creation or deletion of screens + QDesktopWidget *desktop = QApplication::desktop(); + emit desktop->screenCountChanged(e->count); +} + +void QApplicationPrivate::reportGeometryChange(QWindowSystemInterfacePrivate::ScreenGeometryEvent *e) +{ + // This operation only makes sense after the QApplication constructor runs + if (QCoreApplication::startingUp()) + return; + + QApplication::desktop()->d_func()->updateScreenList(); + + // signal anything listening for screen geometry changes + QDesktopWidget *desktop = QApplication::desktop(); + emit desktop->resized(e->index); + + // make sure maximized and fullscreen windows are updated + QWidgetList list = QApplication::topLevelWidgets(); + for (int i = list.size() - 1; i >= 0; --i) { + QWidget *w = list.at(i); + if (w->isFullScreen()) + w->d_func()->setFullScreenSize_helper(); + else if (w->isMaximized()) + w->d_func()->setMaxWindowState_helper(); + } +} + +void QApplicationPrivate::reportAvailableGeometryChange( + QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e) +{ + // This operation only makes sense after the QApplication constructor runs + if (QCoreApplication::startingUp()) + return; + + QApplication::desktop()->d_func()->updateScreenList(); + + // signal anything listening for screen geometry changes + QDesktopWidget *desktop = QApplication::desktop(); + emit desktop->workAreaResized(e->index); + + // make sure maximized and fullscreen windows are updated + QWidgetList list = QApplication::topLevelWidgets(); + for (int i = list.size() - 1; i >= 0; --i) { + QWidget *w = list.at(i); + if (w->isFullScreen()) + w->d_func()->setFullScreenSize_helper(); + else if (w->isMaximized()) + w->d_func()->setMaxWindowState_helper(); + } +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qclipboard_qpa.cpp b/src/gui/kernel/qclipboard_qpa.cpp new file mode 100644 index 0000000..92b9e83 --- /dev/null +++ b/src/gui/kernel/qclipboard_qpa.cpp @@ -0,0 +1,163 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qclipboard.h" + +#ifndef QT_NO_CLIPBOARD + +#include "qmimedata.h" +#include "qapplication.h" + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + + +class QClipboardData +{ +public: + QClipboardData(); + ~QClipboardData(); + + void setSource(QMimeData* s) + { + if (s == src) + return; + delete src; + src = s; + } + QMimeData* source() + { return src; } + + void clear(); + +private: + QMimeData* src; +}; + +QClipboardData::QClipboardData() +{ + src = 0; +} + +QClipboardData::~QClipboardData() +{ + delete src; +} + +void QClipboardData::clear() +{ + delete src; + src = 0; +} + + +static QClipboardData *internalCbData = 0; + +static void cleanupClipboardData() +{ + delete internalCbData; + internalCbData = 0; +} + +static QClipboardData *clipboardData() +{ + if (internalCbData == 0) { + internalCbData = new QClipboardData; + qAddPostRoutine(cleanupClipboardData); + } + return internalCbData; +} + + +void QClipboard::clear(Mode mode) +{ + setText(QString(), mode); +} + + +bool QClipboard::event(QEvent *e) +{ + return QObject::event(e); +} + +const QMimeData* QClipboard::mimeData(Mode mode) const +{ + if (mode != Clipboard) return 0; + + QClipboardData *d = clipboardData(); + return d->source(); +} + +void QClipboard::setMimeData(QMimeData* src, Mode mode) +{ + if (mode != Clipboard) return; + + QClipboardData *d = clipboardData(); + + d->setSource(src); + + emitChanged(QClipboard::Clipboard); +} + +bool QClipboard::supportsMode(Mode mode) const +{ + return (mode == Clipboard); +} + +bool QClipboard::ownsMode(Mode mode) const +{ + if (mode == Clipboard) + qWarning("QClipboard::ownsClipboard: UNIMPLEMENTED!"); + return false; +} + +void QClipboard::connectNotify( const char * ) +{ +} + +void QClipboard::ownerDestroyed() +{ +} + +#endif // QT_NO_CLIPBOARD + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qcursor.h b/src/gui/kernel/qcursor.h index ed6b254..62d2f41 100644 --- a/src/gui/kernel/qcursor.h +++ b/src/gui/kernel/qcursor.h @@ -130,7 +130,7 @@ public: static int x11Screen(); #elif defined(Q_WS_MAC) Qt::HANDLE handle() const; -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_QPA) int handle() const; #elif defined(Q_OS_SYMBIAN) Qt::HANDLE handle() const; diff --git a/src/gui/kernel/qcursor_p.h b/src/gui/kernel/qcursor_p.h index 23798b4..bfd6eac 100644 --- a/src/gui/kernel/qcursor_p.h +++ b/src/gui/kernel/qcursor_p.h @@ -91,7 +91,7 @@ public: short hx, hy; #if defined (Q_WS_MAC) int mId; -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_QPA) int id; #endif #if defined (Q_WS_WIN) diff --git a/src/gui/kernel/qcursor_qpa.cpp b/src/gui/kernel/qcursor_qpa.cpp new file mode 100644 index 0000000..a6ae7d3 --- /dev/null +++ b/src/gui/kernel/qcursor_qpa.cpp @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** 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 QtGui 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 <qcursor.h> +#include <private/qcursor_p.h> +#include <qbitmap.h> + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + +#ifndef QT_NO_CURSOR + +static int nextCursorId = Qt::BitmapCursor; + +/***************************************************************************** + Internal QCursorData class + *****************************************************************************/ + +QCursorData::QCursorData(Qt::CursorShape s) + : cshape(s), bm(0), bmm(0), hx(0), hy(0), id(s) +{ + ref = 1; +} + +QCursorData::~QCursorData() +{ + delete bm; + delete bmm; +} + + +/***************************************************************************** + Global cursors + *****************************************************************************/ + +extern QCursorData *qt_cursorTable[Qt::LastCursor + 1]; // qcursor.cpp + +int QCursor::handle() const +{ + return d->id; +} + + +QCursorData *QCursorData::setBitmap(const QBitmap &bitmap, const QBitmap &mask, int hotX, int hotY) +{ + if (!QCursorData::initialized) + QCursorData::initialize(); + if (bitmap.depth() != 1 || mask.depth() != 1 || bitmap.size() != mask.size()) { + qWarning("QCursor: Cannot create bitmap cursor; invalid bitmap(s)"); + QCursorData *c = qt_cursorTable[0]; + c->ref.ref(); + return c; + } + QCursorData *d = new QCursorData; + d->bm = new QBitmap(bitmap); + d->bmm = new QBitmap(mask); + d->cshape = Qt::BitmapCursor; + d->id = ++nextCursorId; + d->hx = hotX >= 0 ? hotX : bitmap.width() / 2; + d->hy = hotY >= 0 ? hotY : bitmap.height() / 2; + + return d; +} + +void QCursorData::update() +{ +} + +#endif //QT_NO_CURSOR + +extern int qt_last_x,qt_last_y; + +QPoint QCursor::pos() +{ + return QPoint(qt_last_x, qt_last_y); +} + +void QCursor::setPos(int x, int y) +{ + // Need to check, since some X servers generate null mouse move + // events, causing looping in applications which call setPos() on + // every mouse move event. + // + if (pos() == QPoint(x, y)) + return; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qdesktopwidget_qpa.cpp b/src/gui/kernel/qdesktopwidget_qpa.cpp new file mode 100644 index 0000000..cff05f5 --- /dev/null +++ b/src/gui/kernel/qdesktopwidget_qpa.cpp @@ -0,0 +1,180 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qdesktopwidget.h" +#include "private/qapplication_p.h" +#include "private/qgraphicssystem_p.h" +#include <QWidget> +#include "private/qwidget_p.h" +#include "private/qdesktopwidget_qpa_p.h" +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + +void QDesktopWidgetPrivate::updateScreenList() +{ + QList<QPlatformScreen *> screenList = QApplicationPrivate::platformIntegration()->screens(); + int targetLength = screenList.length(); + int currentLength = screens.length(); + + // Add or remove screen widgets as necessary + if(currentLength > targetLength) { + QDesktopScreenWidget *screen; + while (currentLength-- > targetLength) { + screen = screens.takeLast(); + delete screen; + } + } + else if (currentLength < targetLength) { + QDesktopScreenWidget *screen; + while (currentLength < targetLength) { + screen = new QDesktopScreenWidget(currentLength++); + screens.append(screen); + } + } + + QRegion virtualGeometry; + bool doVirtualGeometry = QApplicationPrivate::platformIntegration()->isVirtualDesktop(); + + // update the geometry of each screen widget + for (int i = 0; i < screens.length(); i++) { + QRect screenGeometry = screenList.at(i)->geometry(); + screens.at(i)->setGeometry(screenGeometry); + if (doVirtualGeometry) + virtualGeometry += screenGeometry; + } + + virtualScreen.setGeometry(virtualGeometry.boundingRect()); + Q_Q(QDesktopWidget); + q->setGeometry(virtualScreen.geometry()); +} + +QDesktopWidget::QDesktopWidget() + : QWidget(*new QDesktopWidgetPrivate, 0, Qt::Desktop) +{ + Q_D(QDesktopWidget); + setObjectName(QLatin1String("desktop")); + d->updateScreenList(); +} + +QDesktopWidget::~QDesktopWidget() +{ +} + +bool QDesktopWidget::isVirtualDesktop() const +{ + return QApplicationPrivate::platformIntegration()->isVirtualDesktop(); +} + +int QDesktopWidget::primaryScreen() const +{ + return 0; +} + +int QDesktopWidget::numScreens() const +{ + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + return qMax(pi->screens().size(), 1); +} + +QWidget *QDesktopWidget::screen(int screen) +{ + Q_D(QDesktopWidget); + if (QApplicationPrivate::platformIntegration()->isVirtualDesktop()) + return &d->virtualScreen; + if (screen < 0 || screen >= d->screens.length()) + return d->screens.at(0); + return d->screens.at(screen); +} + +const QRect QDesktopWidget::availableGeometry(int screenNo) const +{ + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + QList<QPlatformScreen *> screens = pi->screens(); + if (screenNo == -1) + screenNo = 0; + if (screenNo < 0 || screenNo >= screens.size()) + return QRect(); + else + return screens[screenNo]->availableGeometry(); +} + +const QRect QDesktopWidget::screenGeometry(int screenNo) const +{ + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + QList<QPlatformScreen *> screens = pi->screens(); + if (screenNo == -1) + screenNo = 0; + if (screenNo < 0 || screenNo >= screens.size()) + return QRect(); + else + return screens[screenNo]->geometry(); +} + +int QDesktopWidget::screenNumber(const QWidget *w) const +{ + if (!w) + return 0; + + QRect frame = w->frameGeometry(); + if (!w->isWindow()) + frame.moveTopLeft(w->mapToGlobal(QPoint(0, 0))); + const QPoint midpoint = (frame.topLeft() + frame.bottomRight()) / 2; + return screenNumber(midpoint); +} + +int QDesktopWidget::screenNumber(const QPoint &p) const +{ + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + QList<QPlatformScreen *> screens = pi->screens(); + + for (int i = 0; i < screens.size(); ++i) + if (screens[i]->geometry().contains(p)) + return i; + + return primaryScreen(); //even better would be closest screen +} + +void QDesktopWidget::resizeEvent(QResizeEvent *) +{ +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qdesktopwidget_qpa_p.h b/src/gui/kernel/qdesktopwidget_qpa_p.h new file mode 100644 index 0000000..8bed09d --- /dev/null +++ b/src/gui/kernel/qdesktopwidget_qpa_p.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef QDESKTOPWIDGET_QPA_P_H +#define QDESKTOPWIDGET_QPA_P_H + +#include "QDesktopWidget" +#include "private/qwidget_p.h" + +class QDesktopScreenWidget : public QWidget { + Q_OBJECT +public: + QDesktopScreenWidget(int screenNumber = -1) { setWindowFlags(Qt::Desktop); setVisible(false); d_func()->screenNumber = screenNumber; } +}; + +class QDesktopWidgetPrivate : public QWidgetPrivate { + Q_DECLARE_PUBLIC(QDesktopWidget) + +public: + ~QDesktopWidgetPrivate() {foreach(QDesktopScreenWidget *s, screens) delete s; } + void updateScreenList(); + + QList<QDesktopScreenWidget *> screens; + QDesktopScreenWidget virtualScreen; +}; + +#endif // QDESKTOPWIDGET_QPA_P_H diff --git a/src/gui/kernel/qdnd_p.h b/src/gui/kernel/qdnd_p.h index 033e6a6..598a9de 100644 --- a/src/gui/kernel/qdnd_p.h +++ b/src/gui/kernel/qdnd_p.h @@ -261,11 +261,11 @@ public: #endif private: -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) Qt::DropAction currentActionForOverrideCursor; #endif #ifdef Q_OS_SYMBIAN -#ifndef QT_NO_CURSOR +#ifndef QT_NO_CURSOR QCursor overrideCursor; #endif #endif diff --git a/src/gui/kernel/qeventdispatcher_glib_qpa.cpp b/src/gui/kernel/qeventdispatcher_glib_qpa.cpp new file mode 100644 index 0000000..01d40ca --- /dev/null +++ b/src/gui/kernel/qeventdispatcher_glib_qpa.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore 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 "qeventdispatcher_glib_qpa_p.h" + +#include "qapplication.h" + +#include "qplatformdefs.h" +#include "qapplication.h" + +#include <glib.h> +#include "qapplication_p.h" + +#include <qdebug.h> + +QT_BEGIN_NAMESPACE + +struct GUserEventSource +{ + GSource source; + QPAEventDispatcherGlib *q; +}; + +static gboolean userEventSourcePrepare(GSource *s, gint *timeout) +{ + Q_UNUSED(s) + Q_UNUSED(timeout) + + return QWindowSystemInterfacePrivate::windowSystemEventsQueued() > 0; +} + +static gboolean userEventSourceCheck(GSource *source) +{ + return userEventSourcePrepare(source, 0); +} + +static gboolean userEventSourceDispatch(GSource *s, GSourceFunc, gpointer) +{ + GUserEventSource * source = reinterpret_cast<GUserEventSource *>(s); + + QWindowSystemInterfacePrivate::WindowSystemEvent * event; + while (QWindowSystemInterfacePrivate::windowSystemEventsQueued()) { + event = QWindowSystemInterfacePrivate::getWindowSystemEvent(); + if (!event) + break; + + // send through event filter + if (source->q->filterEvent(event)) { + delete event; + continue; + } + QApplicationPrivate::processWindowSystemEvent(event); + delete event; + } + + return true; +} + + +static GSourceFuncs userEventSourceFuncs = { + userEventSourcePrepare, + userEventSourceCheck, + userEventSourceDispatch, + NULL, + NULL, + NULL +}; + +QPAEventDispatcherGlibPrivate::QPAEventDispatcherGlibPrivate(GMainContext *context) + : QEventDispatcherGlibPrivate(context) +{ + userEventSource = reinterpret_cast<GUserEventSource *>(g_source_new(&userEventSourceFuncs, + sizeof(GUserEventSource))); + userEventSource->q = 0; + g_source_set_can_recurse(&userEventSource->source, true); + g_source_attach(&userEventSource->source, mainContext); +} + + +QPAEventDispatcherGlib::QPAEventDispatcherGlib(QObject *parent) + : QEventDispatcherGlib(*new QPAEventDispatcherGlibPrivate, parent) +{ + Q_D(QPAEventDispatcherGlib); + d->userEventSource->q = this; +} + +QPAEventDispatcherGlib::~QPAEventDispatcherGlib() +{ + Q_D(QPAEventDispatcherGlib); + + g_source_destroy(&d->userEventSource->source); + g_source_unref(&d->userEventSource->source); + d->userEventSource = 0; +} + +bool QPAEventDispatcherGlib::processEvents(QEventLoop::ProcessEventsFlags flags) +{ + static bool init = false; + if (!init) { + if (QApplicationPrivate::platformIntegration()->createEventLoopIntegration()) { + qWarning("Eventloop integration is not supported by the glib event dispatcher"); + qWarning("Use the UNIX event dispatcher by defining environment variable QT_NO_GLIB=1"); + } + init = true; + } + return QEventDispatcherGlib::processEvents(flags); +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qeventdispatcher_glib_qpa_p.h b/src/gui/kernel/qeventdispatcher_glib_qpa_p.h new file mode 100644 index 0000000..1c32ab2 --- /dev/null +++ b/src/gui/kernel/qeventdispatcher_glib_qpa_p.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore 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$ +** +****************************************************************************/ + +#ifndef QEVENTDISPATCHER_GLIB_QPA_P_H +#define QEVENTDISPATCHER_GLIB_QPA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QLibrary class. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/private/qeventdispatcher_glib_p.h> + +typedef struct _GMainContext GMainContext; + +QT_BEGIN_NAMESPACE +class QPAEventDispatcherGlibPrivate; + +class QPAEventDispatcherGlib : public QEventDispatcherGlib +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QPAEventDispatcherGlib) + +public: + explicit QPAEventDispatcherGlib(QObject *parent = 0); + ~QPAEventDispatcherGlib(); + + bool processEvents(QEventLoop::ProcessEventsFlags flags); +}; + +struct GUserEventSource; + +class QPAEventDispatcherGlibPrivate : public QEventDispatcherGlibPrivate +{ + Q_DECLARE_PUBLIC(QPAEventDispatcherGlib) +public: + QPAEventDispatcherGlibPrivate(GMainContext *context = 0); + GUserEventSource *userEventSource; +}; + + +QT_END_NAMESPACE + +#endif // QEVENTDISPATCHER_GLIB_QPA_P_H diff --git a/src/gui/kernel/qeventdispatcher_qpa.cpp b/src/gui/kernel/qeventdispatcher_qpa.cpp new file mode 100644 index 0000000..cb70141 --- /dev/null +++ b/src/gui/kernel/qeventdispatcher_qpa.cpp @@ -0,0 +1,302 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qplatformdefs.h" +#include "qapplication.h" +#include "qeventdispatcher_qpa_p.h" +#include "private/qeventdispatcher_unix_p.h" +#include "qapplication_p.h" +#include "qplatformeventloopintegration_qpa.h" + +#include <QWindowSystemInterface> +#include <QtCore/QElapsedTimer> +#include <QtCore/QAtomicInt> +#include <QtCore/QSemaphore> + +#include <errno.h> + +QT_BEGIN_NAMESPACE + +QT_USE_NAMESPACE + +class Rendezvous +{ +public: + void checkpoint() + { + if (state.testAndSetOrdered(0,1)) { + semaphore.acquire(); + } else if (state.testAndSetAcquire(1,0)) { + semaphore.release(); + } else { + qWarning("Barrier internal error"); + } + } +private: + QSemaphore semaphore; + QAtomicInt state; +}; + +class SelectWorker : public QThread +{ +public: + SelectWorker(QEventDispatcherQPAPrivate *eventDispatcherPrivate) + : QThread(), + m_edPrivate(eventDispatcherPrivate), + m_retVal(0) + { + } + + void setSelectValues(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds) + { + m_nfds = nfds; + m_readfds = readfds; + m_writefds = writefds; + m_exceptfds = exceptfds; + + + } + + int retVal() const { + return m_retVal; + } + +protected: + void run(); + +private: + QEventDispatcherQPAPrivate *m_edPrivate; + int m_retVal; + + int m_nfds; + fd_set *m_readfds, *m_writefds, *m_exceptfds; +}; + +class QEventDispatcherQPAPrivate : public QEventDispatcherUNIXPrivate +{ + Q_DECLARE_PUBLIC(QEventDispatcherQPA) +public: + QEventDispatcherQPAPrivate() + : eventLoopIntegration(0), + barrierBeforeBlocking(0), + barrierReturnValue(0), + selectReturnMutex(0), + selectWorkerNeedsSync(true), + selectWorkerHasResult(false), + m_integrationInitialised(false), + m_hasIntegration(false) + { + + } + + ~QEventDispatcherQPAPrivate() + { + delete selectWorker; + delete eventLoopIntegration; + delete barrierBeforeBlocking; + delete barrierReturnValue; + delete selectReturnMutex; + } + + bool hasIntegration() const + { + if (!m_integrationInitialised) { + QEventDispatcherQPAPrivate *that = const_cast<QEventDispatcherQPAPrivate *>(this); + if (qApp && (qApp->thread() == QThread::currentThread())) { // guiThread + if (QApplicationPrivate::platformIntegration()) { + that->eventLoopIntegration = QApplicationPrivate::platformIntegration()->createEventLoopIntegration(); + if (that->eventLoopIntegration) { + that->selectWorker = new SelectWorker(that); + that->barrierBeforeBlocking = new Rendezvous; + that->barrierReturnValue = new Rendezvous; + that->selectReturnMutex = new QMutex; + that->selectWorker->start(); + that->m_hasIntegration = true; + if (!QElapsedTimer::isMonotonic()) + qWarning("Having eventloop integration without monotonic timers can lead to undefined behaviour"); + } + } + } + that->m_integrationInitialised = true; + } + return m_hasIntegration; + } + + QPlatformEventLoopIntegration *eventLoopIntegration; + Rendezvous *barrierBeforeBlocking; + Rendezvous *barrierReturnValue; + + QMutex *selectReturnMutex; + bool selectWorkerNeedsSync; + bool selectWorkerHasResult; + + SelectWorker *selectWorker; +private: + bool m_integrationInitialised; + bool m_hasIntegration; +}; + +QEventDispatcherQPA::QEventDispatcherQPA(QObject *parent) + : QEventDispatcherUNIX(*new QEventDispatcherQPAPrivate, parent) +{ } + +QEventDispatcherQPA::~QEventDispatcherQPA() +{ } + +bool QEventDispatcherQPA::processEvents(QEventLoop::ProcessEventsFlags flags) +{ + Q_D(QEventDispatcherQPA); + int nevents = 0; + + // handle gui and posted events + d->interrupt = false; + QApplication::sendPostedEvents(); + + while (!d->interrupt) { // also flushes output buffer ###can be optimized + QWindowSystemInterfacePrivate::WindowSystemEvent *event; + if (!(flags & QEventLoop::ExcludeUserInputEvents) + && QWindowSystemInterfacePrivate::windowSystemEventsQueued() > 0) { + // process a pending user input event + event = QWindowSystemInterfacePrivate::getWindowSystemEvent(); + if (!event) + break; + } else { + break; + } + + if (filterEvent(event)) { + delete event; + continue; + } + nevents++; + + QApplicationPrivate::processWindowSystemEvent(event); + delete event; + } + + if (!d->interrupt) { + if (QEventDispatcherUNIX::processEvents(flags)) + return true; + } + return (nevents > 0); +} + +bool QEventDispatcherQPA::hasPendingEvents() +{ + extern uint qGlobalPostedEventsCount(); // from qapplication.cpp + return qGlobalPostedEventsCount() || QWindowSystemInterfacePrivate::windowSystemEventsQueued(); +} + +void QEventDispatcherQPA::registerSocketNotifier(QSocketNotifier *notifier) +{ + Q_D(QEventDispatcherQPA); + QEventDispatcherUNIX::registerSocketNotifier(notifier); + if (d->hasIntegration()) + wakeUp(); + +} + +void QEventDispatcherQPA::unregisterSocketNotifier(QSocketNotifier *notifier) +{ + Q_D(QEventDispatcherQPA); + QEventDispatcherUNIX::unregisterSocketNotifier(notifier); + if (d->hasIntegration()) + wakeUp(); +} + +void QEventDispatcherQPA::flush() +{ + if(qApp) + qApp->sendPostedEvents(); +} + + +int QEventDispatcherQPA::select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + timeval *timeout) +{ + Q_D(QEventDispatcherQPA); + int retVal = 0; + if (d->hasIntegration()) { + qint64 timeoutmsec = 0; + if (timeout) + timeoutmsec = timeout->tv_sec * 1000 + (timeout->tv_usec/1000); + d->selectReturnMutex->lock(); + if (d->selectWorkerNeedsSync) { + if (d->selectWorkerHasResult) { + retVal = d->selectWorker->retVal(); + d->selectWorkerHasResult = false; + + d->selectReturnMutex->unlock(); + d->barrierReturnValue->checkpoint(); + return retVal; + } else { + d->selectWorkerNeedsSync = false; + d->selectWorker->setSelectValues(nfds,readfds, writefds, exceptfds); + d->barrierBeforeBlocking->checkpoint(); + } + } + d->selectReturnMutex->unlock(); + d->eventLoopIntegration->processEvents(timeoutmsec); + retVal = 0; //is 0 if select has not returned + } else { + retVal = QEventDispatcherUNIX::select(nfds, readfds, writefds, exceptfds, timeout); + } + return retVal; +} + +void SelectWorker::run() +{ + while(true) { + m_retVal = 0; + m_edPrivate->barrierBeforeBlocking->checkpoint(); // wait for mainthread + int tmpRet = qt_safe_select(m_nfds,m_readfds,m_writefds,m_exceptfds,0); + m_edPrivate->selectReturnMutex->lock(); + m_edPrivate->eventLoopIntegration->wakeup(); + + m_edPrivate->selectWorkerNeedsSync = true; + m_edPrivate->selectWorkerHasResult = true; + m_retVal = tmpRet; + + m_edPrivate->selectReturnMutex->unlock(); + m_edPrivate->barrierReturnValue->checkpoint(); + } +} +QT_END_NAMESPACE diff --git a/src/gui/kernel/qeventdispatcher_qpa_p.h b/src/gui/kernel/qeventdispatcher_qpa_p.h new file mode 100644 index 0000000..8065c3e --- /dev/null +++ b/src/gui/kernel/qeventdispatcher_qpa_p.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ + +#ifndef QEVENTDISPATCHER_QPA_P_H +#define QEVENTDISPATCHER_QPA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "private/qeventdispatcher_unix_p.h" + +QT_BEGIN_NAMESPACE + +class QEventDispatcherQPAPrivate; + +class QEventDispatcherQPA : public QEventDispatcherUNIX +{ + Q_OBJECT + Q_DECLARE_PRIVATE(QEventDispatcherQPA) + +public: + explicit QEventDispatcherQPA(QObject *parent = 0); + ~QEventDispatcherQPA(); + + bool processEvents(QEventLoop::ProcessEventsFlags flags); + bool hasPendingEvents(); + + void registerSocketNotifier(QSocketNotifier *notifier); + void unregisterSocketNotifier(QSocketNotifier *notifier); + + void flush(); + +protected: + int select(int nfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, + timeval *timeout); +}; + +QT_END_NAMESPACE + +#endif // QEVENTDISPATCHER_QPA_P_H diff --git a/src/gui/kernel/qgenericplugin_qpa.cpp b/src/gui/kernel/qgenericplugin_qpa.cpp new file mode 100644 index 0000000..43d6525 --- /dev/null +++ b/src/gui/kernel/qgenericplugin_qpa.cpp @@ -0,0 +1,112 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qgenericplugin_qpa.h" + +#ifndef QT_NO_LIBRARY + +QT_BEGIN_NAMESPACE + +/*! + \class QGenericPlugin + \ingroup plugins + \ingroup qpa + + \brief The QGenericPlugin class is an abstract base class for + window-system related plugins in Qt QPA. + + Note that this class is only available in \l{Qt QPA}. + + A mouse plugin can be created by subclassing + QGenericPlugin and reimplementing the pure virtual keys() and + create() functions. By exporting the derived class using the + Q_EXPORT_PLUGIN2() macro, The default implementation of the + QGenericPluginFactory class will automatically detect the plugin and + load the driver into the server application at run-time. See \l + {How to Create Qt Plugins} for details. + + \sa QGenericPluginFactory +*/ + +/*! + \fn QStringList QGenericPlugin::keys() const + + Implement this function to return the list of valid keys, i.e. the + drivers supported by this plugin. + + \sa create() +*/ + +/*! + Constructs a plugin with the given \a parent. + + Note that this constructor is invoked automatically by the + Q_EXPORT_PLUGIN2() macro, so there is no need for calling it + explicitly. +*/ +QGenericPlugin::QGenericPlugin(QObject *parent) + : QObject(parent) +{ +} + +/*! + Destroys the plugin. + + Note that Qt destroys a plugin automatically when it is no longer + used, so there is no need for calling the destructor explicitly. +*/ +QGenericPlugin::~QGenericPlugin() +{ +} + +/*! + \fn QObject* QGenericPlugin::create(const QString &key, const QString& specification) + + Implement this function to create a driver matching the type + specified by the given \a key and \a specification parameters. Note that + keys are case-insensitive. + + \sa keys() +*/ + +QT_END_NAMESPACE + +#endif // QT_NO_LIBRARY diff --git a/src/gui/kernel/qgenericplugin_qpa.h b/src/gui/kernel/qgenericplugin_qpa.h new file mode 100644 index 0000000..e1792cd --- /dev/null +++ b/src/gui/kernel/qgenericplugin_qpa.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QGENERICPLUGIN_QPA_H +#define QGENERICPLUGIN_QPA_H + +#include <QtCore/qplugin.h> +#include <QtCore/qfactoryinterface.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +#ifndef QT_NO_LIBRARY + +//class QGenericObject; ????? + + struct Q_GUI_EXPORT QGenericPluginFactoryInterface : public QFactoryInterface +{ + virtual QObject* create(const QString &name, const QString &spec) = 0; +}; + +#define QGenericPluginFactoryInterface_iid "com.trolltech.Qt.QGenericPluginFactoryInterface" +Q_DECLARE_INTERFACE(QGenericPluginFactoryInterface, QGenericPluginFactoryInterface_iid) + +class Q_GUI_EXPORT QGenericPlugin : public QObject, public QGenericPluginFactoryInterface +{ + Q_OBJECT + Q_INTERFACES(QGenericPluginFactoryInterface:QFactoryInterface) +public: + explicit QGenericPlugin(QObject *parent = 0); + ~QGenericPlugin(); + + virtual QStringList keys() const = 0; + virtual QObject* create(const QString& name, const QString &spec) = 0; +}; + +#endif // QT_NO_LIBRARY + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGENERICPLUGIN_QPA_H diff --git a/src/gui/kernel/qgenericpluginfactory_qpa.cpp b/src/gui/kernel/qgenericpluginfactory_qpa.cpp new file mode 100644 index 0000000..abc575a --- /dev/null +++ b/src/gui/kernel/qgenericpluginfactory_qpa.cpp @@ -0,0 +1,115 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qgenericpluginfactory_qpa.h" + +#include "qapplication.h" +#include "private/qfactoryloader_p.h" +#include "qgenericplugin_qpa.h" +#include "qdebug.h" + +QT_BEGIN_NAMESPACE + +#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL) +#ifndef QT_NO_LIBRARY + +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, + (QGenericPluginFactoryInterface_iid, + QLatin1String("/generic"), Qt::CaseInsensitive)) + +#endif //QT_NO_LIBRARY +#endif //QT_MAKEDLL + +/*! + \class QGenericPluginFactory + \ingroup qpa + + \brief The QGenericPluginFactory class creates window-system + related plugin drivers in Qt QPA. + + Note that this class is only available in \l{Qt QPA}. + + + \sa QGenericPlugin +*/ + +/*! + Creates the driver specified by \a key, using the given \a specification. + + Note that the keys are case-insensitive. + + \sa keys() +*/ +QObject *QGenericPluginFactory::create(const QString& key, const QString &specification) +{ + QString driver = key.toLower(); + +#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL) +#ifndef QT_NO_LIBRARY + if (QGenericPluginFactoryInterface *factory = qobject_cast<QGenericPluginFactoryInterface*>(loader()->instance(driver))) + return factory->create(driver, specification); +#endif +#endif + return 0; +} + +/*! + Returns the list of valid keys, i.e. the available mouse drivers. + + \sa create() +*/ +QStringList QGenericPluginFactory::keys() +{ + QStringList list; + +#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL) +#ifndef QT_NO_LIBRARY + QStringList plugins = loader()->keys(); + for (int i = 0; i < plugins.size(); ++i) { + if (!list.contains(plugins.at(i))) + list += plugins.at(i); + } +#endif //QT_NO_LIBRARY +#endif //QT_MAKEDLL + return list; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qgenericpluginfactory_qpa.h b/src/gui/kernel/qgenericpluginfactory_qpa.h new file mode 100644 index 0000000..59eac38 --- /dev/null +++ b/src/gui/kernel/qgenericpluginfactory_qpa.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QGENERICPLUGINFACTORY_QPA_H +#define QGENERICPLUGINFACTORY_QPA_H + +#include <QtCore/qstringlist.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QString; +class QObject; + +class Q_GUI_EXPORT QGenericPluginFactory +{ +public: + static QStringList keys(); + static QObject *create(const QString&, const QString &); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGENERICPLUGINFACTORY_QPA_H diff --git a/src/gui/kernel/qguiplatformplugin.cpp b/src/gui/kernel/qguiplatformplugin.cpp index 2dd251b..98b9c4a 100644 --- a/src/gui/kernel/qguiplatformplugin.cpp +++ b/src/gui/kernel/qguiplatformplugin.cpp @@ -152,7 +152,7 @@ QString QGuiPlatformPlugin::styleName() return QLatin1String("Windows"); // default style for Symbian without S60 #elif defined(Q_WS_X11) && defined(Q_OS_IRIX) return QLatin1String("SGI"); // default style for X11 on IRIX -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_QPA) return QLatin1String("Plastique"); // default style for X11 and small devices #elif defined(Q_WS_MAC) return QLatin1String("Macintosh"); // default style for all Mac's diff --git a/src/gui/kernel/qplatformcursor_qpa.cpp b/src/gui/kernel/qplatformcursor_qpa.cpp new file mode 100644 index 0000000..ac557b9 --- /dev/null +++ b/src/gui/kernel/qplatformcursor_qpa.cpp @@ -0,0 +1,660 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qplatformcursor_qpa.h" + +#include <QWidget> +#include <QPainter> +#include <QBitmap> +#include <QApplication> + +#include <QDebug> + +QT_BEGIN_NAMESPACE + +QList <QWeakPointer<QPlatformCursor> > QPlatformCursorPrivate::instances; + +/*! + \class QGraphicsSystemCursor + + \brief The QGraphicsSystemCursor class provides information about + pointer device events (movement, buttons), and requests to change + the currently displayed cursor. + + Note that QGraphicsSystemCursor does not include any graphics for + display. An application that sets a QCursor may provide its own + graphics. + + \sa QGraphicsSystemCursorImage +*/ + +/*! + \fn virtual void QGraphicsSystemCursor::pointerEvent(const QMouseEvent & event) + + This method is called by Qt whenever a QMouseEvent is generated by the + underlying pointer input. \a event is a reference to the QMouseEvent in + question. A default do-nothing implementation is provided. + + \sa QApplicationPrivate::handleMouseEvent() +*/ + +/*! + \fn virtual void QGraphicsSystemCursor::changeCursor(QCursor * widgetCursor, QWidget * widget) + + \brief This method is called by Qt whenever the cursor graphic should be changed. + + Implementation of this method is mandatory for a subclass of QGraphicsSystemCursor. + + \a widgetCursor is a pointer to the QCursor that should be displayed. + + \a widget is a pointer to the widget currently displayed at QCursor::pos(). Note + that this may be 0 if the current position is not occupied by a displayed widget. + + \sa QApplicationPrivate::handleMouseEvent(), QCursor::pos() +*/ + +/*! + \fn QGraphicsSystemCursor::QGraphicsSystemCursor() + + \brief Constructs a QGraphicsSystemCursor +*/ +QPlatformCursor::QPlatformCursor(QPlatformScreen *scr ) + : screen(scr) +{ + QPlatformCursorPrivate::instances.append(this); +} + +// End of display and pointer event handling code +// Beginning of built-in cursor graphics +// from src/gui/embedded/QGraphicsSystemCursorImage_qws.cpp + +/*! + \class QGraphicsSystemCursorImage + + \brief The QGraphicsSystemCursorImage class provides a set of graphics + intended to be used as cursors. + + \sa QGraphicsSystemCursor +*/ + +static QPlatformCursorImage *systemCursorTable[Qt::LastCursor+1]; +static bool systemCursorTableInit = false; + +// 16 x 16 +static const uchar cur_arrow_bits[] = { + 0x07, 0x00, 0x39, 0x00, 0xc1, 0x01, 0x02, 0x0e, 0x02, 0x10, 0x02, 0x08, + 0x04, 0x04, 0x04, 0x02, 0x04, 0x04, 0x88, 0x08, 0x48, 0x11, 0x28, 0x22, + 0x10, 0x44, 0x00, 0x28, 0x00, 0x10, 0x00, 0x00 }; +static const uchar mcur_arrow_bits[] = { + 0x07, 0x00, 0x3f, 0x00, 0xff, 0x01, 0xfe, 0x0f, 0xfe, 0x1f, 0xfe, 0x0f, + 0xfc, 0x07, 0xfc, 0x03, 0xfc, 0x07, 0xf8, 0x0f, 0x78, 0x1f, 0x38, 0x3e, + 0x10, 0x7c, 0x00, 0x38, 0x00, 0x10, 0x00, 0x00 }; + +static const unsigned char cur_up_arrow_bits[] = { + 0x80, 0x00, 0x40, 0x01, 0x40, 0x01, 0x20, 0x02, 0x20, 0x02, 0x10, 0x04, + 0x10, 0x04, 0x08, 0x08, 0x78, 0x0f, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, + 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0xc0, 0x01}; +static const unsigned char mcur_up_arrow_bits[] = { + 0x80, 0x00, 0xc0, 0x01, 0xc0, 0x01, 0xe0, 0x03, 0xe0, 0x03, 0xf0, 0x07, + 0xf0, 0x07, 0xf8, 0x0f, 0xf8, 0x0f, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, + 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01}; + +static const unsigned char cur_cross_bits[] = { + 0xc0, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, + 0x7f, 0x7f, 0x01, 0x40, 0x7f, 0x7f, 0x40, 0x01, 0x40, 0x01, 0x40, 0x01, + 0x40, 0x01, 0x40, 0x01, 0xc0, 0x01, 0x00, 0x00}; +static const unsigned char mcur_cross_bits[] = { + 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, + 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, + 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0x00, 0x00}; + +static const uchar cur_ibeam_bits[] = { + 0x00, 0x00, 0xe0, 0x03, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, + 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, + 0x80, 0x00, 0xe0, 0x03, 0x00, 0x00, 0x00, 0x00 }; +static const uchar mcur_ibeam_bits[] = { + 0xf0, 0x07, 0xf0, 0x07, 0xf0, 0x07, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, + 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, 0xc0, 0x01, + 0xf0, 0x07, 0xf0, 0x07, 0xf0, 0x07, 0x00, 0x00 }; + +static const uchar cur_ver_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x80, 0x01, 0xc0, 0x03, 0xe0, 0x07, 0xf0, 0x0f, + 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0x80, 0x01, 0xf0, 0x0f, + 0xe0, 0x07, 0xc0, 0x03, 0x80, 0x01, 0x00, 0x00 }; +static const uchar mcur_ver_bits[] = { + 0x00, 0x00, 0x80, 0x03, 0xc0, 0x07, 0xe0, 0x0f, 0xf0, 0x1f, 0xf8, 0x3f, + 0xfc, 0x7f, 0xc0, 0x07, 0xc0, 0x07, 0xc0, 0x07, 0xfc, 0x7f, 0xf8, 0x3f, + 0xf0, 0x1f, 0xe0, 0x0f, 0xc0, 0x07, 0x80, 0x03 }; + +static const uchar cur_hor_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x08, 0x30, 0x18, + 0x38, 0x38, 0xfc, 0x7f, 0xfc, 0x7f, 0x38, 0x38, 0x30, 0x18, 0x20, 0x08, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar mcur_hor_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x40, 0x04, 0x60, 0x0c, 0x70, 0x1c, 0x78, 0x3c, + 0xfc, 0x7f, 0xfe, 0xff, 0xfe, 0xff, 0xfe, 0xff, 0xfc, 0x7f, 0x78, 0x3c, + 0x70, 0x1c, 0x60, 0x0c, 0x40, 0x04, 0x00, 0x00 }; +static const uchar cur_bdiag_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x3e, 0x00, 0x3c, 0x00, 0x3e, + 0x00, 0x37, 0x88, 0x23, 0xd8, 0x01, 0xf8, 0x00, 0x78, 0x00, 0xf8, 0x00, + 0xf8, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar mcur_bdiag_bits[] = { + 0x00, 0x00, 0xc0, 0x7f, 0x80, 0x7f, 0x00, 0x7f, 0x00, 0x7e, 0x04, 0x7f, + 0x8c, 0x7f, 0xdc, 0x77, 0xfc, 0x63, 0xfc, 0x41, 0xfc, 0x00, 0xfc, 0x01, + 0xfc, 0x03, 0xfc, 0x07, 0x00, 0x00, 0x00, 0x00 }; +static const uchar cur_fdiag_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x01, 0xf8, 0x00, 0x78, 0x00, + 0xf8, 0x00, 0xd8, 0x01, 0x88, 0x23, 0x00, 0x37, 0x00, 0x3e, 0x00, 0x3c, + 0x00, 0x3e, 0x00, 0x3f, 0x00, 0x00, 0x00, 0x00 }; +static const uchar mcur_fdiag_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0xfc, 0x07, 0xfc, 0x03, 0xfc, 0x01, 0xfc, 0x00, + 0xfc, 0x41, 0xfc, 0x63, 0xdc, 0x77, 0x8c, 0x7f, 0x04, 0x7f, 0x00, 0x7e, + 0x00, 0x7f, 0x80, 0x7f, 0xc0, 0x7f, 0x00, 0x00 }; + +// 20 x 20 +static const uchar forbidden_bits[] = { + 0x00,0x00,0x00,0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xf0,0x00,0x38,0xc0,0x01, + 0x7c,0x80,0x03,0xec,0x00,0x03,0xce,0x01,0x07,0x86,0x03,0x06,0x06,0x07,0x06, + 0x06,0x0e,0x06,0x06,0x1c,0x06,0x0e,0x38,0x07,0x0c,0x70,0x03,0x1c,0xe0,0x03, + 0x38,0xc0,0x01,0xf0,0xe0,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00,0x00,0x00,0x00 }; + +static const uchar forbiddenm_bits[] = { + 0x80,0x1f,0x00,0xe0,0x7f,0x00,0xf0,0xff,0x00,0xf8,0xff,0x01,0xfc,0xf0,0x03, + 0xfe,0xc0,0x07,0xfe,0x81,0x07,0xff,0x83,0x0f,0xcf,0x07,0x0f,0x8f,0x0f,0x0f, + 0x0f,0x1f,0x0f,0x0f,0x3e,0x0f,0x1f,0xfc,0x0f,0x1e,0xf8,0x07,0x3e,0xf0,0x07, + 0xfc,0xe0,0x03,0xf8,0xff,0x01,0xf0,0xff,0x00,0xe0,0x7f,0x00,0x80,0x1f,0x00}; + +// 32 x 32 +static const uchar wait_data_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, + 0x00, 0x04, 0x40, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x08, 0x20, 0x00, + 0x00, 0x08, 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, 0x00, 0x08, 0x20, 0x00, + 0x00, 0x50, 0x15, 0x00, 0x00, 0xa0, 0x0a, 0x00, 0x00, 0x40, 0x05, 0x00, + 0x00, 0x80, 0x02, 0x00, 0x00, 0x40, 0x04, 0x00, 0x00, 0x20, 0x08, 0x00, + 0x00, 0x10, 0x10, 0x00, 0x00, 0x08, 0x21, 0x00, 0x00, 0x88, 0x22, 0x00, + 0x00, 0x48, 0x25, 0x00, 0x00, 0xa8, 0x2a, 0x00, 0x00, 0xfc, 0x7f, 0x00, + 0x00, 0x04, 0x40, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar wait_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xfc, 0x7f, 0x00, + 0x00, 0xfc, 0x7f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0xf8, 0x3f, 0x00, + 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00, + 0x00, 0xf0, 0x1f, 0x00, 0x00, 0xe0, 0x0f, 0x00, 0x00, 0xc0, 0x07, 0x00, + 0x00, 0x80, 0x03, 0x00, 0x00, 0xc0, 0x07, 0x00, 0x00, 0xe0, 0x0f, 0x00, + 0x00, 0xf0, 0x1f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00, + 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x7f, 0x00, + 0x00, 0xfc, 0x7f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +static const uchar hsplit_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, + 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, + 0x00, 0x41, 0x82, 0x00, 0x80, 0x41, 0x82, 0x01, 0xc0, 0x7f, 0xfe, 0x03, + 0x80, 0x41, 0x82, 0x01, 0x00, 0x41, 0x82, 0x00, 0x00, 0x40, 0x02, 0x00, + 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, + 0x00, 0x40, 0x02, 0x00, 0x00, 0x40, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar hsplitm_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, + 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe3, 0xc7, 0x00, + 0x80, 0xe3, 0xc7, 0x01, 0xc0, 0xff, 0xff, 0x03, 0xe0, 0xff, 0xff, 0x07, + 0xc0, 0xff, 0xff, 0x03, 0x80, 0xe3, 0xc7, 0x01, 0x00, 0xe3, 0xc7, 0x00, + 0x00, 0xe2, 0x47, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, + 0x00, 0xe0, 0x07, 0x00, 0x00, 0xe0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar vsplit_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x7f, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar vsplitm_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00, + 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, + 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, 0x80, 0xff, 0xff, 0x00, + 0x80, 0xff, 0xff, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc0, 0x01, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00, + 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar phand_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0xfe, 0x01, 0x00, 0x00, 0x01, 0x02, 0x00, 0x00, + 0x7e, 0x04, 0x00, 0x00, 0x08, 0x08, 0x00, 0x00, 0x70, 0x08, 0x00, 0x00, + 0x08, 0x08, 0x00, 0x00, 0x70, 0x14, 0x00, 0x00, 0x08, 0x22, 0x00, 0x00, + 0x30, 0x41, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0x40, 0x12, 0x00, 0x00, + 0x80, 0x08, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar phandm_bits[] = { + 0xfe, 0x01, 0x00, 0x00, 0xff, 0x03, 0x00, 0x00, 0xff, 0x07, 0x00, 0x00, + 0xff, 0x0f, 0x00, 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xf8, 0x1f, 0x00, 0x00, + 0xfc, 0x1f, 0x00, 0x00, 0xf8, 0x3f, 0x00, 0x00, 0xfc, 0x7f, 0x00, 0x00, + 0xf8, 0xff, 0x00, 0x00, 0xf0, 0x7f, 0x00, 0x00, 0xe0, 0x3f, 0x00, 0x00, + 0xc0, 0x1f, 0x00, 0x00, 0x80, 0x0f, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, + 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +static const uchar size_all_data_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x81, 0x40, 0x00, 0x80, 0x81, 0xc0, 0x00, + 0xc0, 0xff, 0xff, 0x01, 0x80, 0x81, 0xc0, 0x00, 0x00, 0x81, 0x40, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xc0, 0x01, 0x00, + 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const uchar size_all_mask_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x00, 0xe0, 0x03, 0x00, 0x00, 0xf0, 0x07, 0x00, + 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xc0, 0x01, 0x00, 0x00, 0xc2, 0x21, 0x00, + 0x00, 0xc3, 0x61, 0x00, 0x80, 0xc3, 0xe1, 0x00, 0xc0, 0xff, 0xff, 0x01, + 0xe0, 0xff, 0xff, 0x03, 0xc0, 0xff, 0xff, 0x01, 0x80, 0xc3, 0xe1, 0x00, + 0x00, 0xc3, 0x61, 0x00, 0x00, 0xc2, 0x21, 0x00, 0x00, 0xc0, 0x01, 0x00, + 0x00, 0xf8, 0x0f, 0x00, 0x00, 0xf0, 0x07, 0x00, 0x00, 0xe0, 0x03, 0x00, + 0x00, 0xc0, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + +static const uchar whatsthis_bits[] = { + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0xf0, 0x07, 0x00, + 0x09, 0x18, 0x0e, 0x00, 0x11, 0x1c, 0x0e, 0x00, 0x21, 0x1c, 0x0e, 0x00, + 0x41, 0x1c, 0x0e, 0x00, 0x81, 0x1c, 0x0e, 0x00, 0x01, 0x01, 0x07, 0x00, + 0x01, 0x82, 0x03, 0x00, 0xc1, 0xc7, 0x01, 0x00, 0x49, 0xc0, 0x01, 0x00, + 0x95, 0xc0, 0x01, 0x00, 0x93, 0xc0, 0x01, 0x00, 0x21, 0x01, 0x00, 0x00, + 0x20, 0xc1, 0x01, 0x00, 0x40, 0xc2, 0x01, 0x00, 0x40, 0x02, 0x00, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; +static const uchar whatsthism_bits[] = { + 0x01, 0x00, 0x00, 0x00, 0x03, 0xf0, 0x07, 0x00, 0x07, 0xf8, 0x0f, 0x00, + 0x0f, 0xfc, 0x1f, 0x00, 0x1f, 0x3e, 0x1f, 0x00, 0x3f, 0x3e, 0x1f, 0x00, + 0x7f, 0x3e, 0x1f, 0x00, 0xff, 0x3e, 0x1f, 0x00, 0xff, 0x9d, 0x0f, 0x00, + 0xff, 0xc3, 0x07, 0x00, 0xff, 0xe7, 0x03, 0x00, 0x7f, 0xe0, 0x03, 0x00, + 0xf7, 0xe0, 0x03, 0x00, 0xf3, 0xe0, 0x03, 0x00, 0xe1, 0xe1, 0x03, 0x00, + 0xe0, 0xe1, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00, 0xc0, 0xe3, 0x03, 0x00, + 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; + +static const uchar busy_bits[] = { + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, + 0x09, 0x00, 0x00, 0x00, 0x11, 0x00, 0x00, 0x00, 0x21, 0x00, 0x00, 0x00, + 0x41, 0xe0, 0xff, 0x00, 0x81, 0x20, 0x80, 0x00, 0x01, 0xe1, 0xff, 0x00, + 0x01, 0x42, 0x40, 0x00, 0xc1, 0x47, 0x40, 0x00, 0x49, 0x40, 0x55, 0x00, + 0x95, 0x80, 0x2a, 0x00, 0x93, 0x00, 0x15, 0x00, 0x21, 0x01, 0x0a, 0x00, + 0x20, 0x01, 0x11, 0x00, 0x40, 0x82, 0x20, 0x00, 0x40, 0x42, 0x44, 0x00, + 0x80, 0x41, 0x4a, 0x00, 0x00, 0x40, 0x55, 0x00, 0x00, 0xe0, 0xff, 0x00, + 0x00, 0x20, 0x80, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; +static const uchar busym_bits[] = { + 0x01, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, + 0x0f, 0x00, 0x00, 0x00, 0x1f, 0x00, 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, + 0x7f, 0xe0, 0xff, 0x00, 0xff, 0xe0, 0xff, 0x00, 0xff, 0xe1, 0xff, 0x00, + 0xff, 0xc3, 0x7f, 0x00, 0xff, 0xc7, 0x7f, 0x00, 0x7f, 0xc0, 0x7f, 0x00, + 0xf7, 0x80, 0x3f, 0x00, 0xf3, 0x00, 0x1f, 0x00, 0xe1, 0x01, 0x0e, 0x00, + 0xe0, 0x01, 0x1f, 0x00, 0xc0, 0x83, 0x3f, 0x00, 0xc0, 0xc3, 0x7f, 0x00, + 0x80, 0xc1, 0x7f, 0x00, 0x00, 0xc0, 0x7f, 0x00, 0x00, 0xe0, 0xff, 0x00, + 0x00, 0xe0, 0xff, 0x00, 0x00, 0xe0, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + +// 16 x 16 +static const uchar openhand_bits[] = { + 0x80,0x01,0x58,0x0e,0x64,0x12,0x64,0x52,0x48,0xb2,0x48,0x92, + 0x16,0x90,0x19,0x80,0x11,0x40,0x02,0x40,0x04,0x40,0x04,0x20, + 0x08,0x20,0x10,0x10,0x20,0x10,0x00,0x00}; +static const uchar openhandm_bits[] = { + 0x80,0x01,0xd8,0x0f,0xfc,0x1f,0xfc,0x5f,0xf8,0xff,0xf8,0xff, + 0xfe,0xff,0xff,0xff,0xff,0x7f,0xfe,0x7f,0xfc,0x7f,0xfc,0x3f, + 0xf8,0x3f,0xf0,0x1f,0xe0,0x1f,0x00,0x00}; +static const uchar closedhand_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0x48,0x32,0x08,0x50, + 0x10,0x40,0x18,0x40,0x04,0x40,0x04,0x20,0x08,0x20,0x10,0x10, + 0x20,0x10,0x20,0x10,0x00,0x00,0x00,0x00}; +static const uchar closedhandm_bits[] = { + 0x00,0x00,0x00,0x00,0x00,0x00,0xb0,0x0d,0xf8,0x3f,0xf8,0x7f, + 0xf0,0x7f,0xf8,0x7f,0xfc,0x7f,0xfc,0x3f,0xf8,0x3f,0xf0,0x1f, + 0xe0,0x1f,0xe0,0x1f,0x00,0x00,0x00,0x00}; + +void QPlatformCursorImage::createSystemCursor(int id) +{ + if (!systemCursorTableInit) { + for (int i = 0; i <= Qt::LastCursor; i++) + systemCursorTable[i] = 0; + systemCursorTableInit = true; + } + switch (id) { + // 16x16 cursors + case Qt::ArrowCursor: + systemCursorTable[Qt::ArrowCursor] = + new QPlatformCursorImage(cur_arrow_bits, mcur_arrow_bits, 16, 16, 0, 0); + break; + + case Qt::UpArrowCursor: + systemCursorTable[Qt::UpArrowCursor] = + new QPlatformCursorImage(cur_up_arrow_bits, mcur_up_arrow_bits, 16, 16, 7, 0); + break; + + case Qt::CrossCursor: + systemCursorTable[Qt::CrossCursor] = + new QPlatformCursorImage(cur_cross_bits, mcur_cross_bits, 16, 16, 7, 7); + break; + + case Qt::IBeamCursor: + systemCursorTable[Qt::IBeamCursor] = + new QPlatformCursorImage(cur_ibeam_bits, mcur_ibeam_bits, 16, 16, 7, 7); + break; + + case Qt::SizeVerCursor: + systemCursorTable[Qt::SizeVerCursor] = + new QPlatformCursorImage(cur_ver_bits, mcur_ver_bits, 16, 16, 7, 7); + break; + + case Qt::SizeHorCursor: + systemCursorTable[Qt::SizeHorCursor] = + new QPlatformCursorImage(cur_hor_bits, mcur_hor_bits, 16, 16, 7, 7); + break; + + case Qt::SizeBDiagCursor: + systemCursorTable[Qt::SizeBDiagCursor] = + new QPlatformCursorImage(cur_bdiag_bits, mcur_bdiag_bits, 16, 16, 7, 7); + break; + + case Qt::SizeFDiagCursor: + systemCursorTable[Qt::SizeFDiagCursor] = + new QPlatformCursorImage(cur_fdiag_bits, mcur_fdiag_bits, 16, 16, 7, 7); + break; + + case Qt::BlankCursor: + systemCursorTable[Qt::BlankCursor] = + new QPlatformCursorImage(0, 0, 0, 0, 0, 0); + break; + + // 20x20 cursors + case Qt::ForbiddenCursor: + systemCursorTable[Qt::ForbiddenCursor] = + new QPlatformCursorImage(forbidden_bits, forbiddenm_bits, 20, 20, 10, 10); + break; + + // 32x32 cursors + case Qt::WaitCursor: + systemCursorTable[Qt::WaitCursor] = + new QPlatformCursorImage(wait_data_bits, wait_mask_bits, 32, 32, 15, 15); + break; + + case Qt::SplitVCursor: + systemCursorTable[Qt::SplitVCursor] = + new QPlatformCursorImage(vsplit_bits, vsplitm_bits, 32, 32, 15, 15); + break; + + case Qt::SplitHCursor: + systemCursorTable[Qt::SplitHCursor] = + new QPlatformCursorImage(hsplit_bits, hsplitm_bits, 32, 32, 15, 15); + break; + + case Qt::SizeAllCursor: + systemCursorTable[Qt::SizeAllCursor] = + new QPlatformCursorImage(size_all_data_bits, size_all_mask_bits, 32, 32, 15, 15); + break; + + case Qt::PointingHandCursor: + systemCursorTable[Qt::PointingHandCursor] = + new QPlatformCursorImage(phand_bits, phandm_bits, 32, 32, 0, 0); + break; + + case Qt::WhatsThisCursor: + systemCursorTable[Qt::WhatsThisCursor] = + new QPlatformCursorImage(whatsthis_bits, whatsthism_bits, 32, 32, 0, 0); + break; + case Qt::BusyCursor: + systemCursorTable[Qt::BusyCursor] = + new QPlatformCursorImage(busy_bits, busym_bits, 32, 32, 0, 0); + break; + + case Qt::OpenHandCursor: + systemCursorTable[Qt::OpenHandCursor] = + new QPlatformCursorImage(openhand_bits, openhandm_bits, 16, 16, 8, 8); + break; + case Qt::ClosedHandCursor: + systemCursorTable[Qt::ClosedHandCursor] = + new QPlatformCursorImage(closedhand_bits, closedhandm_bits, 16, 16, 8, 8); + break; + default: + qWarning("Unknown system cursor %d", id); + } +} + +/*! + \fn void QGraphicsSystemCursorImage::set(Qt::CursorShape id) + + \brief Calling this method sets the cursor image to the specified shape + + \a id is one of the defined Qt::CursorShape values. + + If id is invalid, Qt::BitmapCursor, or unknown by the implementation, + Qt::ArrowCursor is used instead. +*/ + +void QPlatformCursorImage::set(Qt::CursorShape id) +{ + QPlatformCursorImage *cursor = 0; + if (id >= 0 && id <= Qt::LastCursor) { + if (!systemCursorTable[id]) + createSystemCursor(id); + cursor = systemCursorTable[id]; + } + + if (cursor == 0) { + if (!systemCursorTable[Qt::ArrowCursor]) + createSystemCursor(Qt::ArrowCursor); + cursor = systemCursorTable[Qt::ArrowCursor]; + } + cursorImage = cursor->cursorImage; + hot = cursor->hot; +} + +/*! + \fn void QGraphicsSystemCursorImage::set(const QImage * image, int hx, int hy) + + \brief Set the cursor image to the specified QImage, with the hotsport at (hx, hy) + + \a image A pointer to a QImage + + \a hx The x coordinate of the cursor's hotspot + + \a hy the y coordinate of the cursor's hotspot +*/ + +void QPlatformCursorImage::set(const QImage &image, int hx, int hy) +{ + hot.setX(hx); + hot.setY(hy); + cursorImage = image; +} + +/*! + \fn void QGraphicsSystemCursorImage::set(const uchar *data, const uchar *mask, int width, int height, int hx, int hy) + + \brief set the cursor image to the graphic represented by the combination of data, mask, + width, and height + + \a data The pixel data of the graphic + + \a mask Mask data for the graphic. pixels in data with a corresponding mask bit of 0 are not drawn + + \a width The width of the graphic in pixels + + \a height The height of the graphic in pixels + + \a hx The X hotspot of the cursor graphic + + \a hy The Y hotspot of the cursor graphic +*/ +void QPlatformCursorImage::set(const uchar *data, const uchar *mask, + int width, int height, int hx, int hy) +{ + hot.setX(hx); + hot.setY(hy); + + cursorImage = QImage(width,height, QImage::Format_Indexed8); + + if (!width || !height || !data || !mask || cursorImage.isNull()) + return; + + cursorImage.setNumColors(3); + cursorImage.setColor(0, 0xff000000); + cursorImage.setColor(1, 0xffffffff); + cursorImage.setColor(2, 0x00000000); + + int bytesPerLine = (width + 7) / 8; + int p = 0; + int d, m; + + int x = -1, w = 0; + + uchar *cursor_data = cursorImage.bits(); + int bpl = cursorImage.bytesPerLine(); + for (int i = 0; i < height; i++) + { + for (int j = 0; j < bytesPerLine; j++, data++, mask++) + { + for (int b = 0; b < 8 && j*8+b < width; b++) + { + d = *data & (1 << b); + m = *mask & (1 << b); + if (d && m) p = 0; + else if (!d && m) p = 1; + else p = 2; + cursor_data[j*8+b] = p; + + // calc region + if (x < 0 && m) + x = j*8+b; + else if (x >= 0 && !m) { + x = -1; + w = 0; + } + if (m) + w++; + } + } + if (x >= 0) { + x = -1; + w = 0; + } + cursor_data += bpl; + } + +} + +/*! + \fn QGraphicsSystemCursorImage::QGraphicsSystemCursorImage(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY) + + \brief set the cursor image to the graphic represented by the combination of data, mask, + width, and height + + \a data The pixel data of the graphic + + \a mask Mask data for the graphic. pixels in data with a corresponding mask bit of 0 are not drawn + + \a width The width of the graphic in pixels + + \a height The height of the graphic in pixels + + \a hotX The X hotspot of the cursor graphic + + \a hotY The Y hotspot of the cursor graphic + + \sa set +*/ + +/*! + \fn QImage *QGraphicsSystemCursorImage::image() + + \brief Return the cursor graphic as a pointer to a QImage +*/ + +/*! + \fn QPoint QGraphicsSystemCursorImage::hotspot() + + \brief Return the cursor's hotspot +*/ + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformcursor_qpa.h b/src/gui/kernel/qplatformcursor_qpa.h new file mode 100644 index 0000000..71d0e87 --- /dev/null +++ b/src/gui/kernel/qplatformcursor_qpa.h @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#ifndef QGRAPHICSSYSTEMCURSOR_H +#define QGRAPHICSSYSTEMCURSOR_H + +#include <QtCore/QList> +#include <QtGui/QImage> +#include <QtGui/QMouseEvent> +#include <QtCore/QWeakPointer> +#include <QtCore/QObject> +#include <QtGui/QPlatformScreen> +#include <QtGui/QCursor> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +// Cursor graphics management +class Q_GUI_EXPORT QPlatformCursorImage { +public: + QPlatformCursorImage(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY) + { set(data, mask, width, height, hotX, hotY); } + QImage * image() { return &cursorImage; } + QPoint hotspot() { return hot; } + void set(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY); + void set(const QImage &image, int hx, int hy); + void set(Qt::CursorShape); +private: + static void createSystemCursor(int id); + QImage cursorImage; + QPoint hot; +}; + +class QPlatformCursor; + +class QPlatformCursorPrivate { +public: + static QList<QWeakPointer<QPlatformCursor> > getInstances() { return instances; } + static QList<QWeakPointer<QPlatformCursor> > instances; +}; + +class Q_GUI_EXPORT QPlatformCursor : public QObject { +public: + QPlatformCursor(QPlatformScreen *); + + // input methods + virtual void pointerEvent(const QMouseEvent & event) { Q_UNUSED(event); } + virtual void changeCursor(QCursor * widgetCursor, QWidget * widget) = 0; + +protected: + QPlatformScreen* screen; // Where to request an update + +private: + Q_DECLARE_PRIVATE(QPlatformCursor); + friend void qt_qpa_set_cursor(QWidget * w, bool force); + friend class QApplicationPrivate; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QGRAPHICSSYSTEMCURSOR_H diff --git a/src/gui/kernel/qplatformeventloopintegration_qpa.cpp b/src/gui/kernel/qplatformeventloopintegration_qpa.cpp new file mode 100644 index 0000000..8bdba5e --- /dev/null +++ b/src/gui/kernel/qplatformeventloopintegration_qpa.cpp @@ -0,0 +1,41 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ + diff --git a/src/gui/kernel/qplatformeventloopintegration_qpa.h b/src/gui/kernel/qplatformeventloopintegration_qpa.h new file mode 100644 index 0000000..a06fecf --- /dev/null +++ b/src/gui/kernel/qplatformeventloopintegration_qpa.h @@ -0,0 +1,64 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMEVENTLOOPINTEGRATION_QPA_H +#define QPLATFORMEVENTLOOPINTEGRATION_QPA_H + +#include <QtCore/qglobal.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QPlatformEventLoopIntegration +{ +public: + virtual void processEvents( qint64 msec ) = 0; + virtual void wakeup() = 0; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMEVENTLOOPINTEGRATION_QPA_H diff --git a/src/gui/kernel/qplatformglcontext_qpa.cpp b/src/gui/kernel/qplatformglcontext_qpa.cpp new file mode 100644 index 0000000..36db2b0 --- /dev/null +++ b/src/gui/kernel/qplatformglcontext_qpa.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenGL 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 "qplatformglcontext_qpa.h" + +QPlatformGLContext::~QPlatformGLContext() +{ } + +static QPlatformGLContext *staticSharedContext = 0; + +void QPlatformGLContext::setDefaultSharedContext(QPlatformGLContext *sharedContext) +{ + staticSharedContext = sharedContext; +} + +QPlatformGLContext *QPlatformGLContext::defaultSharedContext() +{ + return staticSharedContext; +} diff --git a/src/gui/kernel/qplatformglcontext_qpa.h b/src/gui/kernel/qplatformglcontext_qpa.h new file mode 100644 index 0000000..ed41723 --- /dev/null +++ b/src/gui/kernel/qplatformglcontext_qpa.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenGL 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$ +** +****************************************************************************/ + +#ifndef QPLATFORM_GL_CONTEXT_H +#define QPLATFORM_GL_CONTEXT_H + +#include <QtCore/qnamespace.h> +#include <QtGui/QPlatformWindowFormat> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class Q_OPENGL_EXPORT QPlatformGLContext +{ +public: + virtual ~QPlatformGLContext(); + + virtual void makeCurrent() = 0; + virtual void doneCurrent() = 0; + virtual void swapBuffers() = 0; + virtual void* getProcAddress(const QString& procName) = 0; + + virtual QPlatformWindowFormat platformWindowFormat() const = 0; + + static QPlatformGLContext *defaultSharedContext(); + +protected: + + static void setDefaultSharedContext(QPlatformGLContext *sharedContext); + +}; + +QT_END_NAMESPACE + +QT_END_HEADER + + +#endif // QPLATFORM_GL_INTEGRATION_P_H diff --git a/src/gui/kernel/qplatformintegration_qpa.cpp b/src/gui/kernel/qplatformintegration_qpa.cpp new file mode 100644 index 0000000..e2a493d --- /dev/null +++ b/src/gui/kernel/qplatformintegration_qpa.cpp @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qplatformintegration_qpa.h" + +#include <QtGui/QPlatformFontDatabase> + +QT_BEGIN_NAMESPACE + +QPixmap QPlatformIntegration::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(); +} + +QPlatformEventLoopIntegration *QPlatformIntegration::createEventLoopIntegration() const +{ + return 0; +} + +bool QPlatformIntegration::hasOpenGL() const +{ + return false; +} + +QPlatformFontDatabase *QPlatformIntegration::fontDatabase() const +{ + static QPlatformFontDatabase *db = 0; + if (!db) { + db = new QPlatformFontDatabase; + } + return db; +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformintegration_qpa.h b/src/gui/kernel/qplatformintegration_qpa.h new file mode 100644 index 0000000..b1f4e5f --- /dev/null +++ b/src/gui/kernel/qplatformintegration_qpa.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMINTEGRATION_H +#define QPLATFORMINTEGRATION_H + +#include <QtGui/qwindowdefs.h> +#include <QtGui/private/qwindowsurface_p.h> +#include <QtGui/private/qpixmapdata_p.h> +#include <QtGui/qplatformscreen_qpa.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QPlatformWindow; +class QWindowSurface; +class QBlittable; +class QWidget; +class QPlatformEventLoopIntegration; +class QPlatformFontDatabase; + +class Q_GUI_EXPORT QPlatformIntegration +{ +public: + virtual ~QPlatformIntegration() { } + +// GraphicsSystem functions + virtual QPixmapData *createPixmapData(QPixmapData::PixelType type) const = 0; + virtual QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const = 0; + virtual QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const = 0; + virtual void moveToScreen(QWidget *window, int screen) {Q_UNUSED(window); Q_UNUSED(screen);} + +// Window System functions + virtual QList<QPlatformScreen *> screens() const = 0; + virtual bool isVirtualDesktop() { return false; } + virtual QPixmap grabWindow(WId window, int x, int y, int width, int height) const; + +//Fontdatabase integration. + virtual QPlatformFontDatabase *fontDatabase() const; + +// Experimental in mainthread eventloop integration +// This should only be used if it is only possible to do window system event processing in +// the gui thread. All of the functions in QWindowSystemInterface are thread safe. + virtual QPlatformEventLoopIntegration *createEventLoopIntegration() const; + +//jl:XXX should it be hasGLContext and do we need it at all? + virtual bool hasOpenGL() const; + + +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMINTEGRATION_H diff --git a/src/gui/kernel/qplatformintegrationfactory_qpa.cpp b/src/gui/kernel/qplatformintegrationfactory_qpa.cpp new file mode 100644 index 0000000..9122e1a --- /dev/null +++ b/src/gui/kernel/qplatformintegrationfactory_qpa.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qplatformintegrationfactory_qpa_p.h" +#include <QPlatformIntegrationPlugin> +#include "private/qfactoryloader_p.h" +#include "qmutex.h" + +#include "qapplication.h" +#include "qdebug.h" + +QT_BEGIN_NAMESPACE + +#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, + (QPlatformIntegrationFactoryInterface_iid, QLatin1String("/platforms"), Qt::CaseInsensitive)) +#endif + +QPlatformIntegration *QPlatformIntegrationFactory::create(const QString& key) +{ + QPlatformIntegration *ret = 0; + QStringList paramList = key.split(QLatin1Char(':')); + QString platform = paramList.takeFirst().toLower(); + +#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) + if (QPlatformIntegrationFactoryInterface *factory = qobject_cast<QPlatformIntegrationFactoryInterface*>(loader()->instance(platform))) + ret = factory->create(platform, paramList); +#endif + + return ret; +} + +/*! + Returns the list of valid keys, i.e. the keys this factory can + create styles for. + + \sa create() +*/ +QStringList QPlatformIntegrationFactory::keys() +{ +#if !defined(QT_NO_LIBRARY) && !defined(QT_NO_SETTINGS) + QStringList list = loader()->keys(); +#else + QStringList list; +#endif + return list; +} + +QT_END_NAMESPACE + diff --git a/src/gui/kernel/qplatformintegrationfactory_qpa_p.h b/src/gui/kernel/qplatformintegrationfactory_qpa_p.h new file mode 100644 index 0000000..ba02d2c --- /dev/null +++ b/src/gui/kernel/qplatformintegrationfactory_qpa_p.h @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMINTEGRATIONFACTORY_H +#define QPLATFORMINTEGRATIONFACTORY_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qstringlist.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QPlatformIntegration; + +class QPlatformIntegrationFactory +{ +public: + static QStringList keys(); + static QPlatformIntegration *create(const QString&); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMINTEGRATIONFACTORY_H + diff --git a/src/gui/kernel/qplatformintegrationplugin_qpa.cpp b/src/gui/kernel/qplatformintegrationplugin_qpa.cpp new file mode 100644 index 0000000..3bf2474 --- /dev/null +++ b/src/gui/kernel/qplatformintegrationplugin_qpa.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qplatformintegrationplugin_qpa.h" + +QT_BEGIN_NAMESPACE + +QPlatformIntegrationPlugin::QPlatformIntegrationPlugin(QObject *parent) + : QObject(parent) +{ +} + +QPlatformIntegrationPlugin::~QPlatformIntegrationPlugin() +{ +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qplatformintegrationplugin_qpa.h b/src/gui/kernel/qplatformintegrationplugin_qpa.h new file mode 100644 index 0000000..9c37cf7 --- /dev/null +++ b/src/gui/kernel/qplatformintegrationplugin_qpa.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMINTEGRATIONPLUGIN_H +#define QPLATFORMINTEGRATIONPLUGIN_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qplugin.h> +#include <QtCore/qfactoryinterface.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QPlatformIntegration; + +struct QPlatformIntegrationFactoryInterface : public QFactoryInterface +{ + virtual QPlatformIntegration *create(const QString &key, const QStringList ¶mList) = 0; +}; + +#define QPlatformIntegrationFactoryInterface_iid "com.nokia.Qt.QPlatformIntegrationFactoryInterface" + +Q_DECLARE_INTERFACE(QPlatformIntegrationFactoryInterface, QPlatformIntegrationFactoryInterface_iid) + +class Q_GUI_EXPORT QPlatformIntegrationPlugin : public QObject, public QPlatformIntegrationFactoryInterface +{ + Q_OBJECT + Q_INTERFACES(QPlatformIntegrationFactoryInterface:QFactoryInterface) +public: + explicit QPlatformIntegrationPlugin(QObject *parent = 0); + ~QPlatformIntegrationPlugin(); + + virtual QStringList keys() const = 0; + virtual QPlatformIntegration *create(const QString &key, const QStringList ¶mList) = 0; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMINTEGRATIONPLUGIN_H diff --git a/src/gui/kernel/qplatformscreen_qpa.cpp b/src/gui/kernel/qplatformscreen_qpa.cpp new file mode 100644 index 0000000..478d2d6 --- /dev/null +++ b/src/gui/kernel/qplatformscreen_qpa.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qplatformscreen_qpa.h" +#include <QtGui/qapplication.h> +#include <QtGui/qdesktopwidget.h> + +QWidget *QPlatformScreen::topLevelAt(const QPoint & pos) const +{ + QWidgetList list = QApplication::topLevelWidgets(); + for (int i = list.size()-1; i >= 0; --i) { + QWidget *w = list[i]; + //### mask is ignored + if (w != QApplication::desktop() && w->isVisible() && w->geometry().contains(pos)) + return w; + } + + return 0; +} + +QSize QPlatformScreen::physicalSize() const +{ + static const int dpi = 100; + int width = geometry().width() / dpi * qreal(25.4) ; + int height = geometry().height() / dpi * qreal(25.4) ; + return QSize(width,height); +} + diff --git a/src/gui/kernel/qplatformscreen_qpa.h b/src/gui/kernel/qplatformscreen_qpa.h new file mode 100644 index 0000000..1704f0f --- /dev/null +++ b/src/gui/kernel/qplatformscreen_qpa.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMSCREEN_H +#define QPLATFORMSCREEN_H + +#include <QtCore/qmetatype.h> +#include <QtCore/qnamespace.h> +#include <QtCore/qcoreevent.h> +#include <QtCore/qvariant.h> +#include <QtCore/qrect.h> +#include <QtCore/qobject.h> + +#include <QtGui/qcursor.h> +#include <QtGui/qimage.h> +#include <QtGui/qwidget.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class Q_GUI_EXPORT QPlatformScreen : public QObject +{ + Q_OBJECT +public: + virtual ~QPlatformScreen() { } + + virtual QRect geometry() const = 0; + virtual QRect availableGeometry() const {return geometry();} + virtual int depth() const = 0; + virtual QImage::Format format() const = 0; + virtual QSize physicalSize() const; + virtual void setDirty(const QRect &) {} + virtual QWidget *topLevelAt(const QPoint &point) const; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMSCREEN_H diff --git a/src/gui/kernel/qplatformwindow_qpa.cpp b/src/gui/kernel/qplatformwindow_qpa.cpp new file mode 100644 index 0000000..9d722d8 --- /dev/null +++ b/src/gui/kernel/qplatformwindow_qpa.cpp @@ -0,0 +1,129 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qplatformwindow_qpa.h" + +#include <QtGui/qwidget.h> + +class QPlatformWindowPrivate +{ + QWidget *tlw; + QRect rect; + Qt::WindowFlags flags; + friend class QPlatformWindow; +}; + +QPlatformWindow::QPlatformWindow(QWidget *tlw) + : d_ptr(new QPlatformWindowPrivate) +{ + Q_D(QPlatformWindow); + d->tlw = tlw; + tlw->setPlatformWindow(this); +} + +QPlatformWindow::~QPlatformWindow() +{ +} + +QWidget *QPlatformWindow::widget() const +{ + Q_D(const QPlatformWindow); + return d->tlw; +} + +void QPlatformWindow::setGeometry(const QRect &rect) +{ + Q_D(QPlatformWindow); + d->rect = rect; +} + +QRect QPlatformWindow::geometry() const +{ + Q_D(const QPlatformWindow); + return d->rect; +} + +/*! +Reimplemented in subclasses to show the surface if \a visible is \c true, and hide it if \a visible is \c false. +*/ +void QPlatformWindow::setVisible(bool visible) +{ + Q_UNUSED(visible); +} +/*! +Requests setting the window flags of this surface to \a type. Returns the actual flags set. +*/ +Qt::WindowFlags QPlatformWindow::setWindowFlags(Qt::WindowFlags flags) +{ + Q_D(QPlatformWindow); + d->flags = flags; + return flags; +} + +/*! + Returns the effective window flags for this surface. +*/ +Qt::WindowFlags QPlatformWindow::windowFlags() const +{ + Q_D(const QPlatformWindow); + return d->flags; +} + +WId QPlatformWindow::winId() const { return WId(0); } + +void QPlatformWindow::setParent(const QPlatformWindow *) { qWarning("This plugin does not support setParent!"); } + +void QPlatformWindow::setWindowTitle(const QString &) {} + +void QPlatformWindow::raise() { qWarning("This plugin does not support raise()"); } + +void QPlatformWindow::lower() { qWarning("This plugin does not support lower()"); } + +void QPlatformWindow::setOpacity(qreal level) +{ + Q_UNUSED(level); + qWarning("This plugin does not support setting window opacity"); +} + +QPlatformGLContext *QPlatformWindow::glContext() const +{ + return 0; +} diff --git a/src/gui/kernel/qplatformwindow_qpa.h b/src/gui/kernel/qplatformwindow_qpa.h new file mode 100644 index 0000000..6dfba05 --- /dev/null +++ b/src/gui/kernel/qplatformwindow_qpa.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ +#ifndef QPLATFORMWINDOW_H +#define QPLATFORMWINDOW_H + + +#include <QtCore/qscopedpointer.h> +#include <QtCore/qrect.h> +#include <QtCore/qstring.h> +#include <QtGui/qwindowdefs.h> + + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QPlatformWindowPrivate; +class QWidget; +class QPlatformGLContext; + +class Q_GUI_EXPORT QPlatformWindow +{ + Q_DECLARE_PRIVATE(QPlatformWindow); +public: + QPlatformWindow(QWidget *tlw); + virtual ~QPlatformWindow(); + + QWidget *widget() const; + virtual void setGeometry(const QRect &rect); + virtual QRect geometry() const; + + virtual void setVisible(bool visible); + virtual Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags); + virtual Qt::WindowFlags windowFlags() const; + virtual WId winId() const; + virtual void setParent(const QPlatformWindow *window); + + virtual void setWindowTitle(const QString &); + virtual void raise(); + virtual void lower(); + + virtual void setOpacity(qreal level); + + virtual QPlatformGLContext *glContext() const; +protected: + QScopedPointer<QPlatformWindowPrivate> d_ptr; +private: + Q_DISABLE_COPY(QPlatformWindow); +}; + +QT_END_NAMESPACE + +QT_END_HEADER +#endif //QPLATFORMWINDOW_H diff --git a/src/gui/kernel/qplatformwindowformat_qpa.cpp b/src/gui/kernel/qplatformwindowformat_qpa.cpp new file mode 100644 index 0000000..d497e85 --- /dev/null +++ b/src/gui/kernel/qplatformwindowformat_qpa.cpp @@ -0,0 +1,1012 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qplatformwindowformat_qpa.h" + +#include <QtCore/QDebug> + +Q_GLOBAL_STATIC(QPlatformWindowFormat, q_platformwindow_default_format); + +class QPlatformWindowFormatPrivate +{ +public: + QPlatformWindowFormatPrivate() + : ref(1) + , opts(QPlatformWindowFormat::DoubleBuffer | QPlatformWindowFormat::DepthBuffer + | QPlatformWindowFormat::Rgba | QPlatformWindowFormat::DirectRendering + | QPlatformWindowFormat::StencilBuffer | QPlatformWindowFormat::DeprecatedFunctions + | QPlatformWindowFormat::UseDefaultSharedContext) + , depthSize(-1) + , accumSize(-1) + , stencilSize(-1) + , redSize(-1) + , greenSize(-1) + , blueSize(-1) + , alphaSize(-1) + , numSamples(-1) + , swapInterval(-1) + , windowApi(QPlatformWindowFormat::Raster) + , sharedContext(0) + { + } + + QPlatformWindowFormatPrivate(const QPlatformWindowFormatPrivate *other) + : ref(1), + opts(other->opts), + depthSize(other->depthSize), + accumSize(other->accumSize), + stencilSize(other->stencilSize), + redSize(other->redSize), + greenSize(other->greenSize), + blueSize(other->blueSize), + alphaSize(other->alphaSize), + numSamples(other->numSamples), + swapInterval(other->swapInterval), + windowApi(other->windowApi), + sharedContext(other->sharedContext) + { + } + QAtomicInt ref; + QPlatformWindowFormat::FormatOptions opts; + int depthSize; + int accumSize; + int stencilSize; + int redSize; + int greenSize; + int blueSize; + int alphaSize; + int numSamples; + int swapInterval; + QPlatformWindowFormat::WindowApi windowApi; + QPlatformGLContext *sharedContext; +}; + +/*! + \class QPlatformWindowFormat + \brief The QPlatformWindowFormat class specifies the display format of an OpenGL + rendering context. + + \ingroup painting-3D + + A display format has several characteristics: + \list + \i \link setDoubleBuffer() Double or single buffering.\endlink + \i \link setDepth() Depth buffer.\endlink + \i \link setRgba() RGBA or color index mode.\endlink + \i \link setAlpha() Alpha channel.\endlink + \i \link setAccum() Accumulation buffer.\endlink + \i \link setStencil() Stencil buffer.\endlink + \i \link setStereo() Stereo buffers.\endlink + \i \link setDirectRendering() Direct rendering.\endlink + \i \link setOverlay() Presence of an overlay.\endlink + \i \link setPlane() Plane of an overlay.\endlink + \i \link setSampleBuffers() Multisample buffers.\endlink + \endlist + + You can also specify preferred bit depths for the color buffer, + depth buffer, alpha buffer, accumulation buffer and the stencil + buffer with the functions: setRedBufferSize(), setGreenBufferSize(), + setBlueBufferSize(), setDepthBufferSize(), setAlphaBufferSize(), + setAccumBufferSize() and setStencilBufferSize(). + + Note that even if you specify that you prefer a 32 bit depth + buffer (e.g. with setDepthBufferSize(32)), the format that is + chosen may not have a 32 bit depth buffer, even if there is a + format available with a 32 bit depth buffer. The main reason for + this is how the system dependant picking algorithms work on the + different platforms, and some format options may have higher + precedence than others. + + You create and tell a QPlatformWindowFormat object what rendering options you + want from an OpenGL rendering context. + + OpenGL drivers or accelerated hardware may or may not support + advanced features such as alpha channel or stereographic viewing. + If you request some features that the driver/hardware does not + provide when you create a QGLWidget, you will get a rendering + context with the nearest subset of features. + + There are different ways to define the display characteristics of + a rendering context. One is to create a QPlatformWindowFormat and make it the + default for the entire application: + \snippet doc/src/snippets/code/src_opengl_qgl.cpp 0 + + Or you can specify the desired format when creating an object of + your QGLWidget subclass: + \snippet doc/src/snippets/code/src_opengl_qgl.cpp 1 + + After the widget has been created, you can find out which of the + requested features the system was able to provide: + \snippet doc/src/snippets/code/src_opengl_qgl.cpp 2 + + \legalese + OpenGL is a trademark of Silicon Graphics, Inc. in the + United States and other countries. + \endlegalese + + \sa QGLContext, QGLWidget +*/ + +/*! + Constructs a QPlatformWindowFormat object with the following default settings: + \list + \i \link setDoubleBuffer() Double buffer:\endlink Enabled. + \i \link setDepth() Depth buffer:\endlink Enabled. + \i \link setRgba() RGBA:\endlink Enabled (i.e., color index disabled). + \i \link setAlpha() Alpha channel:\endlink Disabled. + \i \link setAccum() Accumulator buffer:\endlink Disabled. + \i \link setStencil() Stencil buffer:\endlink Enabled. + \i \link setStereo() Stereo:\endlink Disabled. + \i \link setDirectRendering() Direct rendering:\endlink Enabled. + \i \link setOverlay() Overlay:\endlink Disabled. + \i \link setPlane() Plane:\endlink 0 (i.e., normal plane). + \i \link setSampleBuffers() Multisample buffers:\endlink Disabled. + \endlist +*/ + +QPlatformWindowFormat::QPlatformWindowFormat() +{ + d = new QPlatformWindowFormatPrivate; +} + + +/*! + Creates a QPlatformWindowFormat object that is a copy of the current + defaultFormat(). + + If \a options is not 0, the default format is modified by the + specified format options. The \a options parameter should be + QGL::FormatOption values OR'ed together. + + This constructor makes it easy to specify a certain desired format + in classes derived from QGLWidget, for example: + \snippet doc/src/snippets/code/src_opengl_qgl.cpp 3 + + Note that there are QGL::FormatOption values to turn format settings + both on and off, e.g. QGL::DepthBuffer and QGL::NoDepthBuffer, + QGL::DirectRendering and QGL::IndirectRendering, etc. + + The \a plane parameter defaults to 0 and is the plane which this + format should be associated with. Not all OpenGL implementations + supports overlay/underlay rendering planes. + + \sa defaultFormat(), setOption(), setPlane() +*/ + +QPlatformWindowFormat::QPlatformWindowFormat(QPlatformWindowFormat::FormatOptions options) +{ + d = new QPlatformWindowFormatPrivate; + QPlatformWindowFormat::FormatOptions newOpts = options; + d->opts = defaultFormat().d->opts; + d->opts |= (newOpts & 0xffff); + d->opts &= ~(newOpts >> 16); +} + +/*! + \internal +*/ +void QPlatformWindowFormat::detach() +{ + if (d->ref != 1) { + QPlatformWindowFormatPrivate *newd = new QPlatformWindowFormatPrivate(d); + if (!d->ref.deref()) + delete d; + d = newd; + } +} + +/*! + Constructs a copy of \a other. +*/ + +QPlatformWindowFormat::QPlatformWindowFormat(const QPlatformWindowFormat &other) +{ + d = other.d; + d->ref.ref(); +} + +/*! + Assigns \a other to this object. +*/ + +QPlatformWindowFormat &QPlatformWindowFormat::operator=(const QPlatformWindowFormat &other) +{ + if (d != other.d) { + other.d->ref.ref(); + if (!d->ref.deref()) + delete d; + d = other.d; + } + return *this; +} + +/*! + Destroys the QPlatformWindowFormat. +*/ +QPlatformWindowFormat::~QPlatformWindowFormat() +{ + if (!d->ref.deref()) + delete d; +} + +/*! + \fn bool QPlatformWindowFormat::doubleBuffer() const + + Returns true if double buffering is enabled; otherwise returns + false. Double buffering is enabled by default. + + \sa setDoubleBuffer() +*/ + +/*! + If \a enable is true sets double buffering; otherwise sets single + buffering. + + Double buffering is enabled by default. + + Double buffering is a technique where graphics are rendered on an + off-screen buffer and not directly to the screen. When the drawing + has been completed, the program calls a swapBuffers() function to + exchange the screen contents with the buffer. The result is + flicker-free drawing and often better performance. + + \sa doubleBuffer(), QGLContext::swapBuffers(), + QGLWidget::swapBuffers() +*/ + +void QPlatformWindowFormat::setDoubleBuffer(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::DoubleBuffer : QPlatformWindowFormat::SingleBuffer); +} + + +/*! + \fn bool QPlatformWindowFormat::depth() const + + Returns true if the depth buffer is enabled; otherwise returns + false. The depth buffer is enabled by default. + + \sa setDepth(), setDepthBufferSize() +*/ + +/*! + If \a enable is true enables the depth buffer; otherwise disables + the depth buffer. + + The depth buffer is enabled by default. + + The purpose of a depth buffer (or Z-buffering) is to remove hidden + surfaces. Pixels are assigned Z values based on the distance to + the viewer. A pixel with a high Z value is closer to the viewer + than a pixel with a low Z value. This information is used to + decide whether to draw a pixel or not. + + \sa depth(), setDepthBufferSize() +*/ + +void QPlatformWindowFormat::setDepth(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::DepthBuffer : QPlatformWindowFormat::NoDepthBuffer); +} + + +/*! + \fn bool QPlatformWindowFormat::rgba() const + + Returns true if RGBA color mode is set. Returns false if color + index mode is set. The default color mode is RGBA. + + \sa setRgba() +*/ + +/*! + If \a enable is true sets RGBA mode. If \a enable is false sets + color index mode. + + The default color mode is RGBA. + + RGBA is the preferred mode for most OpenGL applications. In RGBA + color mode you specify colors as red + green + blue + alpha + quadruplets. + + In color index mode you specify an index into a color lookup + table. + + \sa rgba() +*/ + +void QPlatformWindowFormat::setRgba(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::Rgba : QPlatformWindowFormat::ColorIndex); +} + + +/*! + \fn bool QPlatformWindowFormat::alpha() const + + Returns true if the alpha buffer in the framebuffer is enabled; + otherwise returns false. The alpha buffer is disabled by default. + + \sa setAlpha(), setAlphaBufferSize() +*/ + +/*! + If \a enable is true enables the alpha buffer; otherwise disables + the alpha buffer. + + The alpha buffer is disabled by default. + + The alpha buffer is typically used for implementing transparency + or translucency. The A in RGBA specifies the transparency of a + pixel. + + \sa alpha(), setAlphaBufferSize() +*/ + +void QPlatformWindowFormat::setAlpha(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::AlphaChannel : QPlatformWindowFormat::NoAlphaChannel); +} + + +/*! + \fn bool QPlatformWindowFormat::accum() const + + Returns true if the accumulation buffer is enabled; otherwise + returns false. The accumulation buffer is disabled by default. + + \sa setAccum(), setAccumBufferSize() +*/ + +/*! + If \a enable is true enables the accumulation buffer; otherwise + disables the accumulation buffer. + + The accumulation buffer is disabled by default. + + The accumulation buffer is used to create blur effects and + multiple exposures. + + \sa accum(), setAccumBufferSize() +*/ + +void QPlatformWindowFormat::setAccum(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::AccumBuffer : QPlatformWindowFormat::NoAccumBuffer); +} + + +/*! + \fn bool QPlatformWindowFormat::stencil() const + + Returns true if the stencil buffer is enabled; otherwise returns + false. The stencil buffer is enabled by default. + + \sa setStencil(), setStencilBufferSize() +*/ + +/*! + If \a enable is true enables the stencil buffer; otherwise + disables the stencil buffer. + + The stencil buffer is enabled by default. + + The stencil buffer masks certain parts of the drawing area so that + masked parts are not drawn on. + + \sa stencil(), setStencilBufferSize() +*/ + +void QPlatformWindowFormat::setStencil(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::StencilBuffer: QPlatformWindowFormat::NoStencilBuffer); +} + + +/*! + \fn bool QPlatformWindowFormat::stereo() const + + Returns true if stereo buffering is enabled; otherwise returns + false. Stereo buffering is disabled by default. + + \sa setStereo() +*/ + +/*! + If \a enable is true enables stereo buffering; otherwise disables + stereo buffering. + + Stereo buffering is disabled by default. + + Stereo buffering provides extra color buffers to generate left-eye + and right-eye images. + + \sa stereo() +*/ + +void QPlatformWindowFormat::setStereo(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::StereoBuffers : QPlatformWindowFormat::NoStereoBuffers); +} + + +/*! + \fn bool QPlatformWindowFormat::directRendering() const + + Returns true if direct rendering is enabled; otherwise returns + false. + + Direct rendering is enabled by default. + + \sa setDirectRendering() +*/ + +/*! + If \a enable is true enables direct rendering; otherwise disables + direct rendering. + + Direct rendering is enabled by default. + + Enabling this option will make OpenGL bypass the underlying window + system and render directly from hardware to the screen, if this is + supported by the system. + + \sa directRendering() +*/ + +void QPlatformWindowFormat::setDirectRendering(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::DirectRendering : QPlatformWindowFormat::IndirectRendering); +} + +/*! + \fn bool QPlatformWindowFormat::sampleBuffers() const + + Returns true if multisample buffer support is enabled; otherwise + returns false. + + The multisample buffer is disabled by default. + + \sa setSampleBuffers() +*/ + +/*! + If \a enable is true, a GL context with multisample buffer support + is picked; otherwise ignored. + + \sa sampleBuffers(), setSamples(), samples() +*/ +void QPlatformWindowFormat::setSampleBuffers(bool enable) +{ + setOption(enable ? QPlatformWindowFormat::SampleBuffers : QPlatformWindowFormat::NoSampleBuffers); +} + +void QPlatformWindowFormat::setUseDefaultSharedContext(bool enable) +{ + if (enable) { + setOption(QPlatformWindowFormat::UseDefaultSharedContext); + d->sharedContext = 0; + } else { + setOption(QPlatformWindowFormat::NoDefaultSharedContext); + } +} + +/*! + Returns the number of samples per pixel when multisampling is + enabled. By default, the highest number of samples that is + available is used. + + \sa setSampleBuffers(), sampleBuffers(), setSamples() +*/ +int QPlatformWindowFormat::samples() const +{ + return d->numSamples; +} + +/*! + Set the preferred number of samples per pixel when multisampling + is enabled to \a numSamples. By default, the highest number of + samples available is used. + + \sa setSampleBuffers(), sampleBuffers(), samples() +*/ +void QPlatformWindowFormat::setSamples(int numSamples) +{ + detach(); + if (numSamples < 0) { + qWarning("QPlatformWindowFormat::setSamples: Cannot have negative number of samples per pixel %d", numSamples); + return; + } + d->numSamples = numSamples; + setSampleBuffers(numSamples > 0); +} + +/*! + \since 4.2 + + Set the preferred swap interval. This can be used to sync the GL + drawing into a system window to the vertical refresh of the screen. + Setting an \a interval value of 0 will turn the vertical refresh syncing + off, any value higher than 0 will turn the vertical syncing on. + + Under Windows and under X11, where the \c{WGL_EXT_swap_control} + and \c{GLX_SGI_video_sync} extensions are used, the \a interval + parameter can be used to set the minimum number of video frames + that are displayed before a buffer swap will occur. In effect, + setting the \a interval to 10, means there will be 10 vertical + retraces between every buffer swap. + + Under Windows the \c{WGL_EXT_swap_control} extension has to be present, + and under X11 the \c{GLX_SGI_video_sync} extension has to be present. +*/ +void QPlatformWindowFormat::setSwapInterval(int interval) +{ + detach(); + d->swapInterval = interval; +} + +/*! + \since 4.2 + + Returns the currently set swap interval. -1 is returned if setting + the swap interval isn't supported in the system GL implementation. +*/ +int QPlatformWindowFormat::swapInterval() const +{ + return d->swapInterval; +} + +void QPlatformWindowFormat::setWindowApi(QPlatformWindowFormat::WindowApi api) +{ + detach(); + d->windowApi = api; +} + +QPlatformWindowFormat::WindowApi QPlatformWindowFormat::windowApi() const +{ + return d->windowApi; +} + +void QPlatformWindowFormat::setSharedContext(QPlatformGLContext *context) +{ + setUseDefaultSharedContext(false); + d->sharedContext = context; +} + +QPlatformGLContext *QPlatformWindowFormat::sharedGLContext() const +{ + return d->sharedContext; +} + +///*! +// \fn bool QPlatformWindowFormat::hasOverlay() const + +// Returns true if overlay plane is enabled; otherwise returns false. + +// Overlay is disabled by default. + +// \sa setOverlay() +//*/ + +///*! +// If \a enable is true enables an overlay plane; otherwise disables +// the overlay plane. + +// Enabling the overlay plane will cause QGLWidget to create an +// additional context in an overlay plane. See the QGLWidget +// documentation for further information. + +// \sa hasOverlay() +//*/ + +//void QPlatformWindowFormat::setOverlay(bool enable) +//{ +// setOption(enable ? QPlatformWindowFormat::HasOverlay : QPlatformWindowFormat::NoOverlay); +//} + +/*! + Sets the format option to \a opt. + + \sa testOption() +*/ + +void QPlatformWindowFormat::setOption(QPlatformWindowFormat::FormatOptions opt) +{ + detach(); + if (opt & 0xffff) + d->opts |= opt; + else + d->opts &= ~(opt >> 16); +} + + + +/*! + Returns true if format option \a opt is set; otherwise returns false. + + \sa setOption() +*/ + +bool QPlatformWindowFormat::testOption(QPlatformWindowFormat::FormatOptions opt) const +{ + if (opt & 0xffff) + return (d->opts & opt) != 0; + else + return (d->opts & (opt >> 16)) == 0; +} + +/*! + Set the minimum depth buffer size to \a size. + + \sa depthBufferSize(), setDepth(), depth() +*/ +void QPlatformWindowFormat::setDepthBufferSize(int size) +{ + detach(); + if (size < 0) { + qWarning("QPlatformWindowFormat::setDepthBufferSize: Cannot set negative depth buffer size %d", size); + return; + } + d->depthSize = size; + setDepth(size > 0); +} + +/*! + Returns the depth buffer size. + + \sa depth(), setDepth(), setDepthBufferSize() +*/ +int QPlatformWindowFormat::depthBufferSize() const +{ + return d->depthSize; +} + +/*! + \since 4.2 + + Set the preferred red buffer size to \a size. + + \sa setGreenBufferSize(), setBlueBufferSize(), setAlphaBufferSize() +*/ +void QPlatformWindowFormat::setRedBufferSize(int size) +{ + detach(); + if (size < 0) { + qWarning("QPlatformWindowFormat::setRedBufferSize: Cannot set negative red buffer size %d", size); + return; + } + d->redSize = size; +} + +/*! + \since 4.2 + + Returns the red buffer size. + + \sa setRedBufferSize() +*/ +int QPlatformWindowFormat::redBufferSize() const +{ + return d->redSize; +} + +/*! + \since 4.2 + + Set the preferred green buffer size to \a size. + + \sa setRedBufferSize(), setBlueBufferSize(), setAlphaBufferSize() +*/ +void QPlatformWindowFormat::setGreenBufferSize(int size) +{ + detach(); + if (size < 0) { + qWarning("QPlatformWindowFormat::setGreenBufferSize: Cannot set negative green buffer size %d", size); + return; + } + d->greenSize = size; +} + +/*! + \since 4.2 + + Returns the green buffer size. + + \sa setGreenBufferSize() +*/ +int QPlatformWindowFormat::greenBufferSize() const +{ + return d->greenSize; +} + +/*! + \since 4.2 + + Set the preferred blue buffer size to \a size. + + \sa setRedBufferSize(), setGreenBufferSize(), setAlphaBufferSize() +*/ +void QPlatformWindowFormat::setBlueBufferSize(int size) +{ + detach(); + if (size < 0) { + qWarning("QPlatformWindowFormat::setBlueBufferSize: Cannot set negative blue buffer size %d", size); + return; + } + d->blueSize = size; +} + +/*! + \since 4.2 + + Returns the blue buffer size. + + \sa setBlueBufferSize() +*/ +int QPlatformWindowFormat::blueBufferSize() const +{ + return d->blueSize; +} + +/*! + Set the preferred alpha buffer size to \a size. + This function implicitly enables the alpha channel. + + \sa setRedBufferSize(), setGreenBufferSize(), alphaBufferSize() +*/ +void QPlatformWindowFormat::setAlphaBufferSize(int size) +{ + detach(); + if (size < 0) { + qWarning("QPlatformWindowFormat::setAlphaBufferSize: Cannot set negative alpha buffer size %d", size); + return; + } + d->alphaSize = size; + setAlpha(size > 0); +} + +/*! + Returns the alpha buffer size. + + \sa alpha(), setAlpha(), setAlphaBufferSize() +*/ +int QPlatformWindowFormat::alphaBufferSize() const +{ + return d->alphaSize; +} + +/*! + Set the preferred accumulation buffer size, where \a size is the + bit depth for each RGBA component. + + \sa accum(), setAccum(), accumBufferSize() +*/ +void QPlatformWindowFormat::setAccumBufferSize(int size) +{ + detach(); + if (size < 0) { + qWarning("QPlatformWindowFormat::setAccumBufferSize: Cannot set negative accumulate buffer size %d", size); + return; + } + d->accumSize = size; + setAccum(size > 0); +} + +/*! + Returns the accumulation buffer size. + + \sa setAccumBufferSize(), accum(), setAccum() +*/ +int QPlatformWindowFormat::accumBufferSize() const +{ + return d->accumSize; +} + +/*! + Set the preferred stencil buffer size to \a size. + + \sa stencilBufferSize(), setStencil(), stencil() +*/ +void QPlatformWindowFormat::setStencilBufferSize(int size) +{ + detach(); + if (size < 0) { + qWarning("QPlatformWindowFormat::setStencilBufferSize: Cannot set negative stencil buffer size %d", size); + return; + } + d->stencilSize = size; + setStencil(size > 0); +} + +/*! + Returns the stencil buffer size. + + \sa stencil(), setStencil(), setStencilBufferSize() +*/ +int QPlatformWindowFormat::stencilBufferSize() const +{ + return d->stencilSize; +} + +/*! + Returns the default QPlatformWindowFormat for the application. All QGLWidget + objects that are created use this format unless another format is + specified, e.g. when they are constructed. + + If no special default format has been set using + setDefaultFormat(), the default format is the same as that created + with QPlatformWindowFormat(). + + \sa setDefaultFormat() +*/ + +QPlatformWindowFormat QPlatformWindowFormat::defaultFormat() +{ + return *q_platformwindow_default_format(); +} + +/*! + Sets a new default QPlatformWindowFormat for the application to \a f. For + example, to set single buffering as the default instead of double + buffering, your main() might contain code like this: + \snippet doc/src/snippets/code/src_opengl_qgl.cpp 4 + + \sa defaultFormat() +*/ + +void QPlatformWindowFormat::setDefaultFormat(const QPlatformWindowFormat &f) +{ + *q_platformwindow_default_format() = f; +} + + +/*! + Returns the default QPlatformWindowFormat for overlay contexts. + + The default overlay format is: + \list + \i \link setDoubleBuffer() Double buffer:\endlink Disabled. + \i \link setDepth() Depth buffer:\endlink Disabled. + \i \link setRgba() RGBA:\endlink Disabled (i.e., color index enabled). + \i \link setAlpha() Alpha channel:\endlink Disabled. + \i \link setAccum() Accumulator buffer:\endlink Disabled. + \i \link setStencil() Stencil buffer:\endlink Disabled. + \i \link setStereo() Stereo:\endlink Disabled. + \i \link setDirectRendering() Direct rendering:\endlink Enabled. + \i \link setOverlay() Overlay:\endlink Disabled. + \i \link setSampleBuffers() Multisample buffers:\endlink Disabled. + \i \link setPlane() Plane:\endlink 1 (i.e., first overlay plane). + \endlist + + \sa setDefaultFormat() +*/ + +//QPlatformWindowFormat QPlatformWindowFormat::defaultOverlayFormat() +//{ +// return *defaultOverlayFormatInstance(); +//} + +///*! +// Sets a new default QPlatformWindowFormat for overlay contexts to \a f. This +// format is used whenever a QGLWidget is created with a format that +// hasOverlay() enabled. + +// For example, to get a double buffered overlay context (if +// available), use code like this: + +// \snippet doc/src/snippets/code/src_opengl_qgl.cpp 5 + +// As usual, you can find out after widget creation whether the +// underlying OpenGL system was able to provide the requested +// specification: + +// \snippet doc/src/snippets/code/src_opengl_qgl.cpp 6 + +// \sa defaultOverlayFormat() +//*/ + +//void QPlatformWindowFormat::setDefaultOverlayFormat(const QPlatformWindowFormat &f) +//{ +// QPlatformWindowFormat *defaultFormat = defaultOverlayFormatInstance(); +// *defaultFormat = f; +// // Make sure the user doesn't request that the overlays themselves +// // have overlays, since it is unlikely that the system supports +// // infinitely many planes... +// defaultFormat->setOverlay(false); +//} + + +/*! + Returns true if all the options of the two QPlatformWindowFormat objects + \a a and \a b are equal; otherwise returns false. + + \relates QPlatformWindowFormat +*/ + +bool operator==(const QPlatformWindowFormat& a, const QPlatformWindowFormat& b) +{ + return (a.d == b.d) || ((int) a.d->opts == (int) b.d->opts + && a.d->alphaSize == b.d->alphaSize + && a.d->accumSize == b.d->accumSize + && a.d->stencilSize == b.d->stencilSize + && a.d->depthSize == b.d->depthSize + && a.d->redSize == b.d->redSize + && a.d->greenSize == b.d->greenSize + && a.d->blueSize == b.d->blueSize + && a.d->numSamples == b.d->numSamples + && a.d->swapInterval == b.d->swapInterval + && a.d->windowApi == b.d->windowApi); +} + + +/*! + Returns false if all the options of the two QPlatformWindowFormat objects + \a a and \a b are equal; otherwise returns true. + + \relates QPlatformWindowFormat +*/ + +bool operator!=(const QPlatformWindowFormat& a, const QPlatformWindowFormat& b) +{ + return !(a == b); +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug dbg, const QPlatformWindowFormat &f) +{ + const QPlatformWindowFormatPrivate * const d = f.d; + + dbg.nospace() << "QGLFormat(" + << "options " << d->opts + << ", depthBufferSize " << d->depthSize + << ", accumBufferSize " << d->accumSize + << ", stencilBufferSize " << d->stencilSize + << ", redBufferSize " << d->redSize + << ", greenBufferSize " << d->greenSize + << ", blueBufferSize " << d->blueSize + << ", alphaBufferSize " << d->alphaSize + << ", samples " << d->numSamples + << ", swapInterval " << d->swapInterval + << ')'; + + return dbg.space(); +} +#endif diff --git a/src/gui/kernel/qplatformwindowformat_qpa.h b/src/gui/kernel/qplatformwindowformat_qpa.h new file mode 100644 index 0000000..63df76a --- /dev/null +++ b/src/gui/kernel/qplatformwindowformat_qpa.h @@ -0,0 +1,241 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ +#ifndef QPLATFORMWINDOWFORMAT_QPA_H +#define QPLATFORMWINDOWFORMAT_QPA_H + +#include <QtGui/QPlatformWindow> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QPlatformWindowFormatPrivate; + +class Q_GUI_EXPORT QPlatformWindowFormat +{ +public: + enum FormatOption { + DoubleBuffer = 0x0001, + DepthBuffer = 0x0002, + Rgba = 0x0004, + AlphaChannel = 0x0008, + AccumBuffer = 0x0010, + StencilBuffer = 0x0020, + StereoBuffers = 0x0040, + DirectRendering = 0x0080, + HasOverlay = 0x0100, + SampleBuffers = 0x0200, + DeprecatedFunctions = 0x0400, + UseDefaultSharedContext = 0x0800, + SingleBuffer = DoubleBuffer << 16, + NoDepthBuffer = DepthBuffer << 16, + ColorIndex = Rgba << 16, + NoAlphaChannel = AlphaChannel << 16, + NoAccumBuffer = AccumBuffer << 16, + NoStencilBuffer = StencilBuffer << 16, + NoStereoBuffers = StereoBuffers << 16, + IndirectRendering = DirectRendering << 16, + NoOverlay = HasOverlay << 16, + NoSampleBuffers = SampleBuffers << 16, + NoDeprecatedFunctions = DeprecatedFunctions << 16, + NoDefaultSharedContext = UseDefaultSharedContext << 16 + + }; + Q_DECLARE_FLAGS(FormatOptions, FormatOption) + + enum WindowApi { + Raster, + OpenGL, + OpenVG + }; + + QPlatformWindowFormat(); + QPlatformWindowFormat(FormatOptions options); + QPlatformWindowFormat(const QPlatformWindowFormat &other); + QPlatformWindowFormat &operator=(const QPlatformWindowFormat &other); + ~QPlatformWindowFormat(); + + void setDepthBufferSize(int size); + int depthBufferSize() const; + + void setAccumBufferSize(int size); + int accumBufferSize() const; + + void setRedBufferSize(int size); + int redBufferSize() const; + + void setGreenBufferSize(int size); + int greenBufferSize() const; + + void setBlueBufferSize(int size); + int blueBufferSize() const; + + void setAlphaBufferSize(int size); + int alphaBufferSize() const; + + void setStencilBufferSize(int size); + int stencilBufferSize() const; + + void setSampleBuffers(bool enable); + bool sampleBuffers() const; + + void setSamples(int numSamples); + int samples() const; + + void setSwapInterval(int interval); + int swapInterval() const; + + void setWindowApi(QPlatformWindowFormat::WindowApi api); + WindowApi windowApi() const; + + void setSharedContext(QPlatformGLContext *context); + QPlatformGLContext *sharedGLContext() const; + + bool doubleBuffer() const; + void setDoubleBuffer(bool enable); + bool depth() const; + void setDepth(bool enable); + bool rgba() const; + void setRgba(bool enable); + bool alpha() const; + void setAlpha(bool enable); + bool accum() const; + void setAccum(bool enable); + bool stencil() const; + void setStencil(bool enable); + bool stereo() const; + void setStereo(bool enable); + bool directRendering() const; + void setDirectRendering(bool enable); + bool useDefaultSharedContext() const; + void setUseDefaultSharedContext(bool enable); +// bool hasOverlay() const; +// void setOverlay(bool enable); + + void setOption(QPlatformWindowFormat::FormatOptions opt); + bool testOption(QPlatformWindowFormat::FormatOptions opt) const; + + static QPlatformWindowFormat defaultFormat(); + static void setDefaultFormat(const QPlatformWindowFormat& f); + +private: + QPlatformWindowFormatPrivate *d; + + void detach(); + + friend Q_GUI_EXPORT bool operator==(const QPlatformWindowFormat&, const QPlatformWindowFormat&); + friend Q_GUI_EXPORT bool operator!=(const QPlatformWindowFormat&, const QPlatformWindowFormat&); +#ifndef QT_NO_DEBUG_STREAM + friend Q_GUI_EXPORT QDebug operator<<(QDebug, const QPlatformWindowFormat &); +#endif +}; + +Q_GUI_EXPORT bool operator==(const QPlatformWindowFormat&, const QPlatformWindowFormat&); +Q_GUI_EXPORT bool operator!=(const QPlatformWindowFormat&, const QPlatformWindowFormat&); + +#ifndef QT_NO_DEBUG_STREAM +Q_OPENGL_EXPORT QDebug operator<<(QDebug, const QPlatformWindowFormat &); +#endif + +Q_DECLARE_OPERATORS_FOR_FLAGS(QPlatformWindowFormat::FormatOptions) + +inline bool QPlatformWindowFormat::doubleBuffer() const +{ + return testOption(QPlatformWindowFormat::DoubleBuffer); +} + +inline bool QPlatformWindowFormat::depth() const +{ + return testOption(QPlatformWindowFormat::DepthBuffer); +} + +inline bool QPlatformWindowFormat::rgba() const +{ + return testOption(QPlatformWindowFormat::Rgba); +} + +inline bool QPlatformWindowFormat::alpha() const +{ + return testOption(QPlatformWindowFormat::AlphaChannel); +} + +inline bool QPlatformWindowFormat::accum() const +{ + return testOption(QPlatformWindowFormat::AccumBuffer); +} + +inline bool QPlatformWindowFormat::stencil() const +{ + return testOption(QPlatformWindowFormat::StencilBuffer); +} + +inline bool QPlatformWindowFormat::stereo() const +{ + return testOption(QPlatformWindowFormat::StereoBuffers); +} + +inline bool QPlatformWindowFormat::directRendering() const +{ + return testOption(QPlatformWindowFormat::DirectRendering); +} + +//inline bool QPlatformWindowFormat::hasOverlay() const +//{ +// return testOption(QPlatformWindowFormat::HasOverlay); +//} + +inline bool QPlatformWindowFormat::sampleBuffers() const +{ + return testOption(QPlatformWindowFormat::SampleBuffers); +} + +inline bool QPlatformWindowFormat::useDefaultSharedContext() const +{ + return testOption(QPlatformWindowFormat::UseDefaultSharedContext); +} + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif //QPLATFORMWINDOWFORMAT_QPA_H diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp index b05f0d02..25450ce 100644 --- a/src/gui/kernel/qwidget.cpp +++ b/src/gui/kernel/qwidget.cpp @@ -76,6 +76,9 @@ # include "qpaintengine.h" // for PorterDuff # include "private/qwindowsurface_qws_p.h" #endif +#if defined(Q_WS_QPA) +#include "qplatformwindow_qpa.h" +#endif #include "qpainter.h" #include "qtooltip.h" #include "qwhatsthis.h" @@ -300,6 +303,8 @@ QWidgetPrivate::QWidgetPrivate(int version) , hasAlienChildren(0) , window_event(0) , qd_hd(0) +#elif defined (Q_WS_QPA) + , screenNumber(0) #endif { if (!qApp) { @@ -1270,6 +1275,12 @@ void QWidgetPrivate::init(QWidget *parentWidget, Qt::WindowFlags f) // programmer specified desktop widget xinfo = desktopWidget->d_func()->xinfo; } +#elif defined(Q_WS_QPA) + if (desktopWidget) { + int screen = desktopWidget->d_func()->screenNumber; + QPlatformIntegration *platform = QApplicationPrivate::platformIntegration(); + platform->moveToScreen(q, screen); + } #else Q_UNUSED(desktopWidget); #endif @@ -1401,6 +1412,7 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow) flags |= Qt::Window; } +#ifndef Q_WS_QPA if (QWidget *parent = parentWidget()) { #ifdef Q_WS_MAC if (testAttribute(Qt::WA_NativeWindow) == false) @@ -1421,6 +1433,7 @@ void QWidget::create(WId window, bool initializeWindow, bool destroyOldWindow) return; } } +#endif //Q_WS_QPA #ifdef QT3_SUPPORT if (flags & Qt::WStaticContents) @@ -1579,13 +1592,13 @@ QWidget::~QWidget() } } -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) +#if defined(Q_WS_WIN) || defined(Q_WS_X11)|| defined(Q_WS_MAC) else if (!internalWinId() && isVisible()) { qApp->d_func()->sendSyntheticEnterLeave(this); -#ifdef Q_WS_QWS - } else if (isVisible()) { + } +#elif defined(Q_WS_QWS) || defined(Q_WS_QPA) + else if (isVisible()) { qApp->d_func()->sendSyntheticEnterLeave(this); -#endif } #endif @@ -1718,6 +1731,10 @@ void QWidgetPrivate::createTLExtra() static int count = 0; qDebug() << "tlextra" << ++count; #endif +#if defined(Q_WS_QPA) + x->platformWindow = 0; + x->platformWindowFormat = QPlatformWindowFormat::defaultFormat(); +#endif } } @@ -2452,7 +2469,9 @@ WId QWidget::winId() const qDebug() << "QWidget::winId: creating native window for" << this; #endif QWidget *that = const_cast<QWidget*>(this); +#ifndef Q_WS_QPA that->setAttribute(Qt::WA_NativeWindow); +#endif that->d_func()->createWinId(); return that->data->winid; } @@ -2469,6 +2488,7 @@ void QWidgetPrivate::createWinId(WId winid) #endif const bool forceNativeWindow = q->testAttribute(Qt::WA_NativeWindow); if (!q->testAttribute(Qt::WA_WState_Created) || (forceNativeWindow && !q->internalWinId())) { +#ifndef Q_WS_QPA if (!q->isWindow()) { QWidget *parent = q->parentWidget(); QWidgetPrivate *pd = parent->d_func(); @@ -2496,6 +2516,11 @@ void QWidgetPrivate::createWinId(WId winid) } else { q->create(); } +#else + Q_UNUSED(winid); + q->create(); +#endif //Q_WS_QPA + } } @@ -5492,7 +5517,7 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP //actually send the paint event QPaintEvent e(toBePainted); QCoreApplication::sendSpontaneousEvent(q, &e); -#if !defined(Q_WS_QWS) +#if !defined(Q_WS_QWS) && !defined(Q_WS_QPA) if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow())) backingStore->markDirtyOnScreen(toBePainted, q, offset); #endif @@ -7530,7 +7555,7 @@ void QWidgetPrivate::hide_helper() // next bit tries to move the focus if the focus widget is now // hidden. if (wasVisible) { -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA) qApp->d_func()->sendSyntheticEnterLeave(q); #endif @@ -7662,7 +7687,7 @@ void QWidget::setVisible(bool visible) d->show_helper(); -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA) qApp->d_func()->sendSyntheticEnterLeave(this); #endif } @@ -7794,7 +7819,7 @@ void QWidgetPrivate::hideChildren(bool spontaneous) widget->d_func()->hide_sys(); } } -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined (Q_WS_QWS) || defined(Q_WS_MAC) || defined(Q_WS_QPA) qApp->d_func()->sendSyntheticEnterLeave(widget); #endif #ifndef QT_NO_ACCESSIBILITY @@ -10572,7 +10597,6 @@ void QWidget::setAttribute(Qt::WidgetAttribute attribute, bool on) Q_ASSERT_X(sizeof(d->high_attributes)*8 >= (Qt::WA_AttributeCount - sizeof(uint)*8), "QWidget::setAttribute(WidgetAttribute, bool)", "QWidgetPrivate::high_attributes[] too small to contain all attributes in WidgetAttribute"); - #ifdef Q_WS_WIN // ### Don't use PaintOnScreen+paintEngine() to do native painting in 5.0 if (attribute == Qt::WA_PaintOnScreen && on && !inherits("QGLWidget")) { diff --git a/src/gui/kernel/qwidget.h b/src/gui/kernel/qwidget.h index 81b3618..eea7cca 100644 --- a/src/gui/kernel/qwidget.h +++ b/src/gui/kernel/qwidget.h @@ -56,6 +56,10 @@ #include <QtGui/qcursor.h> #include <QtGui/qkeysequence.h> +#ifdef Q_WS_QPA //should this go somewhere else? +#include <QtGui/qplatformwindowformat_qpa.h> +#endif + #ifdef QT_INCLUDE_COMPAT #include <QtGui/qevent.h> #endif @@ -94,6 +98,7 @@ class QHideEvent; class QInputContext; class QIcon; class QWindowSurface; +class QPlatformWindow; class QLocale; class QGraphicsProxyWidget; class QGraphicsEffect; @@ -629,6 +634,16 @@ public: void setWindowSurface(QWindowSurface *surface); QWindowSurface *windowSurface() const; +#if defined(Q_WS_QPA) + void setPlatformWindow(QPlatformWindow *window); + QPlatformWindow *platformWindow() const; + + void setPlatformWindowFormat(const QPlatformWindowFormat &format); + QPlatformWindowFormat platformWindowFormat() const; + + friend class QDesktopScreenWidget; +#endif + Q_SIGNALS: void customContextMenuRequested(const QPoint &pos); diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h index 2d0bd85..4b35238 100644 --- a/src/gui/kernel/qwidget_p.h +++ b/src/gui/kernel/qwidget_p.h @@ -102,6 +102,9 @@ class QWSManager; #if defined(Q_WS_MAC) class QCoreGraphicsPaintEnginePrivate; #endif +#if defined(Q_WS_QPA) +class QPlatformWindow; +#endif class QPaintEngine; class QPixmap; class QWidgetBackingStore; @@ -226,6 +229,9 @@ struct QTLWExtra { #endif #elif defined(Q_OS_SYMBIAN) uint inExpose : 1; // Prevents drawing recursion +#elif defined(Q_WS_QPA) + QPlatformWindow *platformWindow; + QPlatformWindowFormat platformWindowFormat; #endif }; @@ -878,6 +884,14 @@ public: void updateCursor() const; #endif QScreen* getScreen() const; +#elif defined(Q_WS_QPA) + void setMaxWindowState_helper(); + void setFullScreenSize_helper(); + + int screenNumber; // screen the widget should be displayed on +#ifndef QT_NO_CURSOR + void updateCursor() const; +#endif #elif defined(Q_OS_SYMBIAN) // <--------------------------------------------------------- SYMBIAN static QWidget *mouseGrabber; static QWidget *keyboardGrabber; diff --git a/src/gui/kernel/qwidget_qpa.cpp b/src/gui/kernel/qwidget_qpa.cpp new file mode 100644 index 0000000..ac8b37d --- /dev/null +++ b/src/gui/kernel/qwidget_qpa.cpp @@ -0,0 +1,895 @@ +/**************************************************************************** +** +** 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 QtGui 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 "QtGui/qwidget.h" +#include "QtGui/qevent.h" +#include "QtGui/qapplication.h" +#include "QtGui/private/qbackingstore_p.h" +#include "QtGui/private/qwidget_p.h" +#include "QtGui/private/qgraphicssystem_p.h" +#include "QtGui/private/qapplication_p.h" +#include "QtGui/qdesktopwidget.h" +#include "QtGui/qplatformwindow_qpa.h" + +#include <QtGui/QPlatformCursor> + +QT_BEGIN_NAMESPACE +static QPlatformScreen *qt_screenForWidget(const QWidget *w); + +void q_createNativeChildrenAndSetParent(QPlatformWindow *parentWindow, const QWidget *parentWidget) +{ + QObjectList children = parentWidget->children(); + for (int i = 0; i < children.size(); i++) { + if (children.at(i)->isWidgetType()) { + const QWidget *childWidget = qobject_cast<const QWidget *>(children.at(i)); + if (childWidget) { // should not be necessary + if (childWidget->testAttribute(Qt::WA_NativeWindow)) { + if (!childWidget->platformWindow()) + childWidget->winId(); + } + if (childWidget->platformWindow()) { + childWidget->platformWindow()->setParent(parentWindow); + } else { + q_createNativeChildrenAndSetParent(parentWindow,childWidget); + } + } + } + } + +} + +void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyOldWindow) +{ + Q_Q(QWidget); + + Q_UNUSED(window); + Q_UNUSED(initializeWindow); + Q_UNUSED(destroyOldWindow); + + Qt::WindowFlags flags = data.window_flags; + + if ((!q->testAttribute(Qt::WA_NativeWindow) && !q->isWindow()) || q->windowType() == Qt::Desktop ) + return; // we only care about real toplevels + + QWindowSurface *surface = q->windowSurface(); + QPlatformWindow *platformWindow = q->platformWindow(); + + if (!platformWindow) { + platformWindow = QApplicationPrivate::platformIntegration()->createPlatformWindow(q); + } + Q_ASSERT(platformWindow); + + if (!surface) { + surface = QApplicationPrivate::platformIntegration()->createWindowSurface(q,platformWindow->winId()); + } + + data.window_flags = q->platformWindow()->setWindowFlags(data.window_flags); + + setWinId(q->platformWindow()->winId()); + + //first check children. and create them if necessary + q_createNativeChildrenAndSetParent(q->platformWindow(),q); + + //if we we have a parent, then set correct parent; + if (!q->isWindow()) { + if (QWidget *nativeParent = q->nativeParentWidget()) { + if (nativeParent->platformWindow()) { + platformWindow->setParent(nativeParent->platformWindow()); + } + } + } + + QApplicationPrivate::platformIntegration()->moveToScreen(q, screenNumber); +// qDebug() << "create_sys" << q << q->internalWinId(); +} + +void QWidget::destroy(bool destroyWindow, bool destroySubWindows) +{ + Q_D(QWidget); + + if ((windowType() == Qt::Popup)) + qApp->d_func()->closePopup(this); + + //### we don't have proper focus event handling yet + if (this == QApplicationPrivate::active_window) + QApplication::setActiveWindow(0); + + if (windowType() != Qt::Desktop) { + if (destroySubWindows) { + QObjectList childList(children()); + for (int i = 0; i < childList.size(); i++) { + QWidget *widget = qobject_cast<QWidget *>(childList.at(i)); + if (widget && widget->testAttribute(Qt::WA_NativeWindow)) { + if (widget->platformWindow()) { + widget->destroy(); + } + } + } + } + if (destroyWindow) { + d->deleteTLSysExtra(); + } else { + if (parentWidget() && parentWidget()->testAttribute(Qt::WA_WState_Created)) { + d->hide_sys(); + } + } + } +} + +void QWidgetPrivate::setParent_sys(QWidget *newparent, Qt::WindowFlags f) +{ + Q_Q(QWidget); + + // QWidget *oldParent = q->parentWidget(); + Qt::WindowFlags oldFlags = data.window_flags; + + int targetScreen = -1; + // Handle a request to move the widget to a particular screen + if (newparent && newparent->windowType() == Qt::Desktop) { + // make sure the widget is created on the same screen as the + // programmer specified desktop widget + + // get the desktop's screen number + targetScreen = newparent->d_func()->screenNumber; + newparent = 0; + } + + if (parent != newparent) { + QObjectPrivate::setParent_helper(newparent); //### why does this have to be done in the _sys function??? + if (q->platformWindow() && newparent) { + QWidget * parentWithWindow = newparent->platformWindow()? newparent : newparent->nativeParentWidget(); + if (parentWithWindow && parentWithWindow->platformWindow()) { + q->platformWindow()->setParent(parentWithWindow->platformWindow()); + } + } + + } + + if (!newparent) { + f |= Qt::Window; + if (targetScreen == -1) { + if (parent) + targetScreen = qobject_cast<QWidget *>(parent)->d_func()->screenNumber; + } + } + + bool explicitlyHidden = q->testAttribute(Qt::WA_WState_Hidden) && q->testAttribute(Qt::WA_WState_ExplicitShowHide); + + // Reparenting toplevel to child + if (!(f&Qt::Window) && (oldFlags&Qt::Window) && !q->testAttribute(Qt::WA_NativeWindow)) { + //qDebug() << "setParent_sys() change from toplevel"; + q->destroy(); + } + + data.window_flags = f; + q->setAttribute(Qt::WA_WState_Created, false); + q->setAttribute(Qt::WA_WState_Visible, false); + q->setAttribute(Qt::WA_WState_Hidden, false); + + if (f & Qt::Window) { + //qDebug() << "setParent_sys" << q << newparent << hex << f; + if (QPlatformWindow *window = q->platformWindow()) + data.window_flags = window->setWindowFlags(data.window_flags); + } + + // Reparenting child to toplevel + if ((f&Qt::Window) && !(oldFlags&Qt::Window)) { + //qDebug() << "setParent_sys() change to toplevel"; + q->create(); //### too early: this ought to happen at show() time + } + + + if (q->isWindow() || (!newparent || newparent->isVisible()) || explicitlyHidden) + q->setAttribute(Qt::WA_WState_Hidden); + q->setAttribute(Qt::WA_WState_ExplicitShowHide, explicitlyHidden); + + // move the window to the selected screen + if (!newparent && targetScreen != -1) { + screenNumber = targetScreen; + // only if it is already created + if (q->testAttribute(Qt::WA_WState_Created)) { + QPlatformIntegration *platform = QApplicationPrivate::platformIntegration(); + platform->moveToScreen(q, targetScreen); + } + } +} + +QPoint QWidget::mapToGlobal(const QPoint &pos) const +{ + int x=pos.x(), y=pos.y(); + const QWidget* w = this; + while (w) { + x += w->data->crect.x(); + y += w->data->crect.y(); + w = w->isWindow() ? 0 : w->parentWidget(); + } + return QPoint(x, y); +} + +QPoint QWidget::mapFromGlobal(const QPoint &pos) const +{ + int x=pos.x(), y=pos.y(); + const QWidget* w = this; + while (w) { + x -= w->data->crect.x(); + y -= w->data->crect.y(); + w = w->isWindow() ? 0 : w->parentWidget(); + } + return QPoint(x, y); +} + +void QWidgetPrivate::updateSystemBackground() {} + +#ifndef QT_NO_CURSOR +void QWidgetPrivate::setCursor_sys(const QCursor &cursor) +{ + Q_UNUSED(cursor); + Q_Q(QWidget); + if (q->isVisible()) + qt_qpa_set_cursor(q, false); +} + +void QWidgetPrivate::unsetCursor_sys() +{ + Q_Q(QWidget); + if (q->isVisible()) + qt_qpa_set_cursor(q, false); +} + +void QWidgetPrivate::updateCursor() const +{ + // XXX +} + +#endif //QT_NO_CURSOR + +void QWidgetPrivate::setWindowTitle_sys(const QString &caption) +{ + Q_Q(QWidget); + if (!q->isWindow()) + return; + + if (QPlatformWindow *window = q->platformWindow()) + window->setWindowTitle(caption); + +} + +void QWidgetPrivate::setWindowIcon_sys(bool /*forceReset*/) +{ +} + +void QWidgetPrivate::setWindowIconText_sys(const QString &iconText) +{ + Q_UNUSED(iconText); +} + +QWidget *qt_pressGrab = 0; +QWidget *qt_mouseGrb = 0; +static QWidget *keyboardGrb = 0; + +void QWidget::grabMouse() +{ + if (qt_mouseGrb) + qt_mouseGrb->releaseMouse(); + + // XXX + //qwsDisplay()->grabMouse(this,true); + + qt_mouseGrb = this; + qt_pressGrab = 0; +} + +#ifndef QT_NO_CURSOR +void QWidget::grabMouse(const QCursor &cursor) +{ + Q_UNUSED(cursor); + + if (qt_mouseGrb) + qt_mouseGrb->releaseMouse(); + + // XXX + //qwsDisplay()->grabMouse(this,true); + //qwsDisplay()->selectCursor(this, cursor.handle()); + qt_mouseGrb = this; + qt_pressGrab = 0; +} +#endif + +void QWidget::releaseMouse() +{ + if (qt_mouseGrb == this) { + // XXX + //qwsDisplay()->grabMouse(this,false); + qt_mouseGrb = 0; + } +} + +void QWidget::grabKeyboard() +{ + if (keyboardGrb) + keyboardGrb->releaseKeyboard(); + // XXX + //qwsDisplay()->grabKeyboard(this, true); + keyboardGrb = this; +} + +void QWidget::releaseKeyboard() +{ + if (keyboardGrb == this) { + // XXX + //qwsDisplay()->grabKeyboard(this, false); + keyboardGrb = 0; + } +} + +QWidget *QWidget::mouseGrabber() +{ + if (qt_mouseGrb) + return qt_mouseGrb; + return qt_pressGrab; +} + +QWidget *QWidget::keyboardGrabber() +{ + return keyboardGrb; +} + +void QWidget::activateWindow() +{ + // XXX +// qDebug() << "QWidget::activateWindow" << this; + QApplication::setActiveWindow(this); //##### +} + +void QWidgetPrivate::show_sys() +{ + Q_Q(QWidget); + q->setAttribute(Qt::WA_Mapped); + if (q->testAttribute(Qt::WA_DontShowOnScreen)) { + invalidateBuffer(q->rect()); + return; + } + + QApplication::postEvent(q, new QUpdateLaterEvent(q->rect())); + + QPlatformWindow *window = q->platformWindow(); + if (window) { + const QRect geomRect = q->geometry(); + const QRect windowRect = window->geometry(); + if (windowRect != geomRect) { + window->setGeometry(geomRect); + } + if (q->isWindow()) { + if (QWindowSurface *surface = q->windowSurface()) { + if (windowRect.size() != geomRect.size()) { + surface->resize(geomRect.size()); + } + } + + if (window) + window->setVisible(true); + + if (q->windowType() != Qt::Popup && q->windowType() != Qt::ToolTip && !(q->windowFlags() & Qt::X11BypassWindowManagerHint)) + q->activateWindow(); //### + } + } +} + + +void QWidgetPrivate::hide_sys() +{ + Q_Q(QWidget); + q->setAttribute(Qt::WA_Mapped, false); + if (!q->isWindow()) { + QWidget *p = q->parentWidget(); + if (p &&p->isVisible()) { + invalidateBuffer(q->rect()); + } + return; + } + if (QPlatformWindow *window = q->platformWindow()) { + window->setVisible(false); + } + + //### we don't yet have proper focus event handling + if (q == QApplicationPrivate::active_window) + QApplication::setActiveWindow(0); + +} + +void QWidgetPrivate::setMaxWindowState_helper() +{ + setFullScreenSize_helper(); //### decoration size +} + +void QWidgetPrivate::setFullScreenSize_helper() +{ + Q_Q(QWidget); + + const uint old_state = data.in_set_window_state; + data.in_set_window_state = 1; + + const QRect screen = qApp->desktop()->screenGeometry(qApp->desktop()->screenNumber(q)); + q->move(screen.topLeft()); + q->resize(screen.size()); + + data.in_set_window_state = old_state; +} + +static Qt::WindowStates effectiveState(Qt::WindowStates state) + { + if (state & Qt::WindowMinimized) + return Qt::WindowMinimized; + else if (state & Qt::WindowFullScreen) + return Qt::WindowFullScreen; + else if (state & Qt::WindowMaximized) + return Qt::WindowMaximized; + return Qt::WindowNoState; + } + +void QWidget::setWindowState(Qt::WindowStates newstate) +{ + Q_D(QWidget); + Qt::WindowStates oldstate = windowState(); + if (oldstate == newstate) + return; + if (isWindow() && !testAttribute(Qt::WA_WState_Created)) + create(); + + data->window_state = newstate; + data->in_set_window_state = 1; + bool needShow = false; + Qt::WindowStates newEffectiveState = effectiveState(newstate); + Qt::WindowStates oldEffectiveState = effectiveState(oldstate); + if (isWindow() && newEffectiveState != oldEffectiveState) { + d->createTLExtra(); + if (oldEffectiveState == Qt::WindowNoState) { //normal + d->topData()->normalGeometry = geometry(); + } else if (oldEffectiveState == Qt::WindowFullScreen) { + setParent(0, d->topData()->savedFlags); + needShow = true; + } else if (oldEffectiveState == Qt::WindowMinimized) { + needShow = true; + } + + if (newEffectiveState == Qt::WindowMinimized) { + //### not ideal... + hide(); + needShow = false; + } else if (newEffectiveState == Qt::WindowFullScreen) { + d->topData()->savedFlags = windowFlags(); + setParent(0, Qt::FramelessWindowHint | (windowFlags() & Qt::WindowStaysOnTopHint)); + d->setFullScreenSize_helper(); + raise(); + needShow = true; + } else if (newEffectiveState == Qt::WindowMaximized) { + createWinId(); + d->setMaxWindowState_helper(); + } else { //normal + QRect r = d->topData()->normalGeometry; + if (r.width() >= 0) { + d->topData()->normalGeometry = QRect(0,0,-1,-1); + setGeometry(r); + } + } + } + data->in_set_window_state = 0; + + if (needShow) + show(); + + if (newstate & Qt::WindowActive) + activateWindow(); + + QWindowStateChangeEvent e(oldstate); + QApplication::sendEvent(this, &e); +} + +void QWidgetPrivate::setFocus_sys() +{ + +} + +void QWidgetPrivate::raise_sys() +{ + Q_Q(QWidget); + if (q->isWindow()) { + q->platformWindow()->raise(); + } +} + +void QWidgetPrivate::lower_sys() +{ + Q_Q(QWidget); + if (q->isWindow()) { + Q_ASSERT(q->testAttribute(Qt::WA_WState_Created)); + q->platformWindow()->lower(); + } else if (QWidget *p = q->parentWidget()) { + setDirtyOpaqueRegion(); + p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); + } +} + +void QWidgetPrivate::stackUnder_sys(QWidget*) +{ + Q_Q(QWidget); + if (QWidget *p = q->parentWidget()) { + setDirtyOpaqueRegion(); + p->d_func()->invalidateBuffer(effectiveRectFor(q->geometry())); + } +} + +void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) +{ + Q_Q(QWidget); + if (extra) { // any size restrictions? + w = qMin(w,extra->maxw); + h = qMin(h,extra->maxh); + w = qMax(w,extra->minw); + h = qMax(h,extra->minh); + } + + QPoint oldp = q->geometry().topLeft(); + QSize olds = q->size(); + QRect r(x, y, w, h); + + bool isResize = olds != r.size(); + isMove = oldp != r.topLeft(); //### why do we have isMove as a parameter? + + + // We only care about stuff that changes the geometry, or may + // cause the window manager to change its state + if (r.size() == olds && oldp == r.topLeft()) + return; + + if (!data.in_set_window_state) { + q->data->window_state &= ~Qt::WindowMaximized; + q->data->window_state &= ~Qt::WindowFullScreen; + if (q->isWindow()) + topData()->normalGeometry = QRect(0, 0, -1, -1); + } + + QPoint oldPos = q->pos(); + data.crect = r; + + if (q->isVisible()) { + if (q->platformWindow()) { + if (q->isWindow()) { + q->platformWindow()->setGeometry(q->frameGeometry()); + } else { + QPoint posInNativeParent = q->mapTo(q->nativeParentWidget(),QPoint()); + q->platformWindow()->setGeometry(QRect(posInNativeParent,r.size())); + } + const QWidgetBackingStore *bs = maybeBackingStore(); + if (bs->windowSurface) { + if (isResize) + bs->windowSurface->resize(r.size()); + } + } else { + if (isMove && !isResize) + moveRect(QRect(oldPos, olds), x - oldPos.x(), y - oldPos.y()); + else + invalidateBuffer_resizeHelper(oldPos, olds); + } + + if (isMove) { + QMoveEvent e(q->pos(), oldPos); + QApplication::sendEvent(q, &e); + } + if (isResize) { + QResizeEvent e(r.size(), olds); + QApplication::sendEvent(q, &e); + if (q->platformWindow()) + q->update(); + } + } else { // not visible + if (isMove && q->pos() != oldPos) + q->setAttribute(Qt::WA_PendingMoveEvent, true); + if (isResize) + q->setAttribute(Qt::WA_PendingResizeEvent, true); + } + +} + +void QWidgetPrivate::setConstraints_sys() +{ +} + +void QWidgetPrivate::scroll_sys(int dx, int dy) +{ + Q_Q(QWidget); + scrollChildren(dx, dy); + scrollRect(q->rect(), dx, dy); +} + +void QWidgetPrivate::scroll_sys(int dx, int dy, const QRect &r) +{ + scrollRect(r, dx, dy); +} + +static QPlatformScreen *qt_screenForWidget(const QWidget *w) +{ + if (!w) + return 0; + QRect frame = w->frameGeometry(); + if (!w->isWindow()) + frame.moveTopLeft(w->mapToGlobal(QPoint(0, 0))); + const QPoint p = (frame.topLeft() + frame.bottomRight()) / 2; + + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + QList<QPlatformScreen *> screens = pi->screens(); + + for (int i = 0; i < screens.size(); ++i) { + if (screens[i]->geometry().contains(p)) + return screens[i]; + } + + // Assume screen zero if we have it. + if (!screens.isEmpty()) + return screens[0]; + else + qWarning("qt_screenForWidget: no screens"); + + return 0; +} + +int QWidget::metric(PaintDeviceMetric m) const +{ + Q_D(const QWidget); + + QPlatformScreen *screen = qt_screenForWidget(this); + if (!screen) { + if (m == PdmDpiX || m == PdmDpiY) + return 72; + return QPaintDevice::metric(m); + } + int val; + if (m == PdmWidth) { + val = data->crect.width(); + } else if (m == PdmWidthMM) { + val = data->crect.width() * screen->physicalSize().width() / screen->geometry().width(); + } else if (m == PdmHeight) { + val = data->crect.height(); + } else if (m == PdmHeightMM) { + val = data->crect.height() * screen->physicalSize().height() / screen->geometry().height(); + } else if (m == PdmDepth) { + return screen->depth(); + } else if (m == PdmDpiX || m == PdmPhysicalDpiX) { + if (d->extra && d->extra->customDpiX) + return d->extra->customDpiX; + else if (d->parent) + return static_cast<QWidget *>(d->parent)->metric(m); + return qRound(screen->geometry().width() / double(screen->physicalSize().width() / 25.4)); + } else if (m == PdmDpiY || m == PdmPhysicalDpiY) { + if (d->extra && d->extra->customDpiY) + return d->extra->customDpiY; + else if (d->parent) + return static_cast<QWidget *>(d->parent)->metric(m); + return qRound(screen->geometry().height() / double(screen->physicalSize().height() / 25.4)); + } else { + val = QPaintDevice::metric(m);// XXX + } + return val; +} + +/*! + \preliminary + + Sets the window to be the \a window specified. + The QWidget takes ownership of the \a surface. +*/ +void QWidget::setPlatformWindow(QPlatformWindow *window) +{ + Q_D(QWidget); + + QTLWExtra *topData = d->topData(); + if (topData->platformWindow == window) + return; + + delete topData->platformWindow; + topData->platformWindow = window; +} + +/*! + \preliminary + + Returns the QPlatformWindow this widget will be drawn into. +*/ +QPlatformWindow *QWidget::platformWindow() const +{ + Q_D(const QWidget); + QTLWExtra *extra = d->maybeTopData(); + if (extra && extra->platformWindow) + return extra->platformWindow; + + return 0; +} + +void QWidget::setPlatformWindowFormat(const QPlatformWindowFormat &format) +{ + if (isWindow() || testAttribute(Qt::WA_NativeWindow)) { + Q_D(QWidget); + QTLWExtra *topData = d->topData(); + topData->platformWindowFormat = format; + if (testAttribute(Qt::WA_WState_Created)) { + bool wasVisible = testAttribute(Qt::WA_WState_Visible); + destroy(); + d->create_sys(0,true,true); + if (wasVisible) + topData->platformWindow->setVisible(true); + } + } +} + +QPlatformWindowFormat QWidget::platformWindowFormat() const +{ + Q_D(const QWidget); + + QTLWExtra *extra = d->maybeTopData(); + if (extra){ + return extra->platformWindowFormat; + } else { + return QPlatformWindowFormat::defaultFormat(); + } +} + +void QWidgetPrivate::createSysExtra() +{ +} + +void QWidgetPrivate::deleteSysExtra() +{ + +} + +void QWidgetPrivate::createTLSysExtra() +{ +} + +void QWidgetPrivate::deleteTLSysExtra() +{ + if (extra && extra->topextra) { + delete extra->topextra->platformWindow; + extra->topextra->platformWindow = 0; + extra->topextra->backingStore.destroy(); + } +} + +void QWidgetPrivate::registerDropSite(bool on) +{ + Q_UNUSED(on); +} + +void QWidgetPrivate::setMask_sys(const QRegion ®ion) +{ + Q_UNUSED(region); + // XXX +} + +void QWidgetPrivate::updateFrameStrut() +{ + // XXX +} + +void QWidgetPrivate::setWindowOpacity_sys(qreal level) +{ + Q_Q(QWidget); + q->platformWindow()->setOpacity(level); +} + +void QWidgetPrivate::setWSGeometry(bool dontShow, const QRect &oldRect) +{ + Q_UNUSED(dontShow); + Q_UNUSED(oldRect); + // XXX +} + +QPaintEngine *QWidget::paintEngine() const +{ + qWarning("QWidget::paintEngine: Should no longer be called"); + return 0; //##### @@@ +} + +QWindowSurface *QWidgetPrivate::createDefaultWindowSurface_sys() +{ + Q_Q(QWidget); + return QApplicationPrivate::platformIntegration()->createWindowSurface(q,0); +} + +void QWidgetPrivate::setModal_sys() +{ +} + +#ifndef QT_NO_CURSOR +void qt_qpa_set_cursor(QWidget * w, bool force) +{ + static QCursor arrowCursor(Qt::ArrowCursor); + static QPointer<QWidget> lastUnderMouse = 0; + + QCursor * override = QApplication::overrideCursor(); + + if (override && w != 0) + return; + + QWidget *cursorWidget; + QCursor cursorCursor; + + do { + if (w == 0) { + if (override) { + cursorCursor = *override; + cursorWidget = QApplication::topLevelAt(QCursor::pos()); + break; + } + w = QApplication::widgetAt(QCursor::pos()); + if (w == 0) // clear the override cursor while over empty space + w = QApplication::desktop(); + } else if (force) { + lastUnderMouse = w; + } else if (w->testAttribute(Qt::WA_WState_Created) && lastUnderMouse + && lastUnderMouse->effectiveWinId() == w->effectiveWinId()) { + w = lastUnderMouse; + } + if (w == QApplication::desktop() && !override) { + cursorCursor = arrowCursor; + cursorWidget = w; + break; + } + + QWidget * curWin = QApplication::activeWindow(); + if (!curWin && w && w->internalWinId()) + return; + QWidget* cW = w && !w->internalWinId() ? w : curWin; + + if (!cW || cW->window() != w->window() || + !cW->isVisible() || !cW->underMouse() || override) + return; + + cursorCursor = w->cursor(); + cursorWidget = w; + } while (0); + foreach (QWeakPointer<QPlatformCursor> cursor, QPlatformCursorPrivate::getInstances()) + if (cursor) + cursor.data()->changeCursor(&cursorCursor, cursorWidget); +} +#endif //QT_NO_CURSOR + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qwindowdefs.h b/src/gui/kernel/qwindowdefs.h index a721c7d..1dc7203 100644 --- a/src/gui/kernel/qwindowdefs.h +++ b/src/gui/kernel/qwindowdefs.h @@ -131,6 +131,12 @@ QT_END_HEADER #endif // Q_WS_QWS +#if defined(Q_WS_QPA) + +typedef unsigned long WId; + +#endif // Q_WS_QPA + #if defined(Q_OS_SYMBIAN) class CCoeControl; typedef CCoeControl * WId; diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.cpp b/src/gui/kernel/qwindowsysteminterface_qpa.cpp new file mode 100644 index 0000000..bb29cbf --- /dev/null +++ b/src/gui/kernel/qwindowsysteminterface_qpa.cpp @@ -0,0 +1,255 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qwindowsysteminterface_qpa.h" +#include "qwindowsysteminterface_qpa_p.h" +#include "qapplication_p.h" +#include <QAbstractEventDispatcher> + +QT_BEGIN_NAMESPACE + + +QTime QWindowSystemInterfacePrivate::eventTime; + +//------------------------------------------------------------ +// +// Callback functions for plugins: +// + +QList<QWindowSystemInterfacePrivate::WindowSystemEvent *> QWindowSystemInterfacePrivate::windowSystemEventQueue; +QMutex QWindowSystemInterfacePrivate::queueMutex; + +extern QPointer<QWidget> qt_last_mouse_receiver; + + +void QWindowSystemInterface::handleEnterEvent(QWidget *tlw) +{ + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + return; + + QWindowSystemInterfacePrivate::EnterEvent *e = new QWindowSystemInterfacePrivate::EnterEvent(tlw); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); + } +} + +void QWindowSystemInterface::handleLeaveEvent(QWidget *tlw) +{ + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + return; + } + QWindowSystemInterfacePrivate::LeaveEvent *e = new QWindowSystemInterfacePrivate::LeaveEvent(tlw); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +void QWindowSystemInterface::handleGeometryChange(QWidget *tlw, const QRect &newRect) +{ + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + return; + } + QWindowSystemInterfacePrivate::GeometryChangeEvent *e = new QWindowSystemInterfacePrivate::GeometryChangeEvent(tlw,newRect); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + + +void QWindowSystemInterface::handleCloseEvent(QWidget *tlw) +{ + if (tlw) { + QWindowSystemInterfacePrivate::CloseEvent *e = + new QWindowSystemInterfacePrivate::CloseEvent(tlw); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); + } +} + +/*! + +\a tlw == 0 means that \a ev is in global coords only + + +*/ +void QWindowSystemInterface::handleMouseEvent(QWidget *w, const QPoint & local, const QPoint & global, Qt::MouseButtons b) { + unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); + handleMouseEvent(w, time, local, global, b); +} + +void QWindowSystemInterface::handleMouseEvent(QWidget *tlw, ulong timestamp, const QPoint & local, const QPoint & global, Qt::MouseButtons b) +{ + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + tlw = 0; + } + QWindowSystemInterfacePrivate::MouseEvent * e = + new QWindowSystemInterfacePrivate::MouseEvent(tlw, timestamp, local, global, b); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +void QWindowSystemInterface::handleKeyEvent(QWidget *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) { + unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); + handleKeyEvent(w, time, t, k, mods, text, autorep, count); +} + +void QWindowSystemInterface::handleKeyEvent(QWidget *tlw, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text, bool autorep, ushort count) +{ + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + tlw = 0; + } + + QWindowSystemInterfacePrivate::KeyEvent * e = + new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, t, k, mods, text, autorep, count); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +void QWindowSystemInterface::handleWheelEvent(QWidget *w, const QPoint & local, const QPoint & global, int d, Qt::Orientation o) { + unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); + handleWheelEvent(w, time, local, global, d, o); +} + +void QWindowSystemInterface::handleWheelEvent(QWidget *tlw, ulong timestamp, const QPoint & local, const QPoint & global, int d, Qt::Orientation o) +{ + if (tlw) { + QWidgetData *data = qt_qwidget_data(tlw); + if (data->in_destructor) + tlw = 0; + } + + QWindowSystemInterfacePrivate::WheelEvent *e = + new QWindowSystemInterfacePrivate::WheelEvent(tlw, timestamp, local, global, d, o); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +int QWindowSystemInterfacePrivate::windowSystemEventsQueued() +{ + queueMutex.lock(); + int ret = windowSystemEventQueue.count(); + queueMutex.unlock(); + return ret; +} + +QWindowSystemInterfacePrivate::WindowSystemEvent * QWindowSystemInterfacePrivate::getWindowSystemEvent() +{ + queueMutex.lock(); + QWindowSystemInterfacePrivate::WindowSystemEvent *ret; + if (windowSystemEventQueue.isEmpty()) + ret = 0; + else + ret = windowSystemEventQueue.takeFirst(); + queueMutex.unlock(); + return ret; +} + +void QWindowSystemInterfacePrivate::queueWindowSystemEvent(QWindowSystemInterfacePrivate::WindowSystemEvent *ev) +{ + queueMutex.lock(); + windowSystemEventQueue.append(ev); + queueMutex.unlock(); + + QAbstractEventDispatcher *dispatcher = QApplicationPrivate::qt_qpa_core_dispatcher(); + if (dispatcher) + dispatcher->wakeUp(); +} + +void QWindowSystemInterface::handleTouchEvent(QWidget *w, QEvent::Type type, QTouchEvent::DeviceType devType, const QList<struct TouchPoint> &points) { + unsigned long time = QWindowSystemInterfacePrivate::eventTime.elapsed(); + handleTouchEvent(w, time, type, devType, points); +} + +void QWindowSystemInterface::handleTouchEvent(QWidget *tlw, ulong timestamp, QEvent::Type type, QTouchEvent::DeviceType devType, const QList<struct TouchPoint> &points) +{ + if (!points.size()) // Touch events must have at least one point + return; + + QList<QTouchEvent::TouchPoint> touchPoints; + Qt::TouchPointStates states; + QTouchEvent::TouchPoint p; + + QList<struct TouchPoint>::const_iterator point = points.constBegin(); + QList<struct TouchPoint>::const_iterator end = points.constEnd(); + while (point != end) { + p.setId(point->id); + p.setPressure(point->pressure); + states |= point->state; + Qt::TouchPointStates state = point->state; + if (point->isPrimary) { + state |= Qt::TouchPointPrimary; + } + p.setState(state); + p.setRect(point->area); + p.setScreenPos(point->area.center()); + p.setNormalizedPos(point->normalPosition); + + touchPoints.append(p); + ++point; + } + + QWindowSystemInterfacePrivate::TouchEvent *e = + new QWindowSystemInterfacePrivate::TouchEvent(tlw, timestamp, type, devType, touchPoints); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +void QWindowSystemInterface::handleScreenGeometryChange(int screenIndex) +{ + QWindowSystemInterfacePrivate::ScreenGeometryEvent *e = + new QWindowSystemInterfacePrivate::ScreenGeometryEvent(screenIndex); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +void QWindowSystemInterface::handleScreenAvailableGeometryChange(int screenIndex) +{ + QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent *e = + new QWindowSystemInterfacePrivate::ScreenAvailableGeometryEvent(screenIndex); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +void QWindowSystemInterface::handleScreenCountChange(int count) +{ + QWindowSystemInterfacePrivate::ScreenCountEvent *e = + new QWindowSystemInterfacePrivate::ScreenCountEvent(count); + QWindowSystemInterfacePrivate::queueWindowSystemEvent(e); +} + +QT_END_NAMESPACE diff --git a/src/gui/kernel/qwindowsysteminterface_qpa.h b/src/gui/kernel/qwindowsysteminterface_qpa.h new file mode 100644 index 0000000..1c79f2a --- /dev/null +++ b/src/gui/kernel/qwindowsysteminterface_qpa.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ +#ifndef QWINDOWSYSTEMINTERFACE_H +#define QWINDOWSYSTEMINTERFACE_H + +#include <QtCore/QTime> +#include <QtGui/qwindowdefs.h> +#include <QtCore/QEvent> +#include <QtGui/QWidget> +#include <QtCore/QWeakPointer> +#include <QtCore/QMutex> +#include <QtGui/QTouchEvent> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class Q_GUI_EXPORT QWindowSystemInterface +{ +public: + static void handleMouseEvent(QWidget *w, const QPoint & local, const QPoint & global, Qt::MouseButtons b); + static void handleMouseEvent(QWidget *w, ulong timestamp, const QPoint & local, const QPoint & global, Qt::MouseButtons b); + + static void handleKeyEvent(QWidget *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); + static void handleKeyEvent(QWidget *w, ulong timestamp, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1); + + static void handleWheelEvent(QWidget *w, const QPoint & local, const QPoint & global, int d, Qt::Orientation o); + static void handleWheelEvent(QWidget *w, ulong timestamp, const QPoint & local, const QPoint & global, int d, Qt::Orientation o); + + struct TouchPoint { + int id; // for application use + bool isPrimary; // for application use + QPointF normalPosition; // touch device coordinates, (0 to 1, 0 to 1) + QRectF area; // the touched area, centered at position in screen coordinates + qreal pressure; // 0 to 1 + Qt::TouchPointState state; //Qt::TouchPoint{Pressed|Moved|Stationary|Released} + }; + + static void handleTouchEvent(QWidget *w, QEvent::Type type, QTouchEvent::DeviceType devType, const QList<struct TouchPoint> &points); + static void handleTouchEvent(QWidget *w, ulong timestamp, QEvent::Type type, QTouchEvent::DeviceType devType, const QList<struct TouchPoint> &points); + + static void handleGeometryChange(QWidget *w, const QRect &newRect); + static void handleCloseEvent(QWidget *w); + static void handleEnterEvent(QWidget *w); + static void handleLeaveEvent(QWidget *w); + + // Changes to the screen + static void handleScreenGeometryChange(int screenIndex); + static void handleScreenAvailableGeometryChange(int screenIndex); + static void handleScreenCountChange(int count); +}; + +QT_END_NAMESPACE +QT_END_HEADER +#endif // QWINDOWSYSTEMINTERFACE_H diff --git a/src/gui/kernel/qwindowsysteminterface_qpa_p.h b/src/gui/kernel/qwindowsysteminterface_qpa_p.h new file mode 100644 index 0000000..78e1f33 --- /dev/null +++ b/src/gui/kernel/qwindowsysteminterface_qpa_p.h @@ -0,0 +1,189 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ +#ifndef QWINDOWSYSTEMINTERFACE_QPA_P_H +#define QWINDOWSYSTEMINTERFACE_QPA_P_H + +#include "qwindowsysteminterface_qpa.h" + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QWindowSystemInterfacePrivate { +public: + enum EventType { + Close, + GeometryChange, + Enter, + Leave, + Mouse, + Wheel, + Key, + Touch, + ScreenGeometry, + ScreenAvailableGeometry, + ScreenCountChange + }; + + class WindowSystemEvent { + public: + WindowSystemEvent(EventType t) + : type(t) { } + EventType type; + }; + + class CloseEvent : public WindowSystemEvent { + public: + CloseEvent(QWidget *tlw) + : WindowSystemEvent(Close), topLevel(tlw) { } + QWeakPointer<QWidget> topLevel; + }; + + class GeometryChangeEvent : public WindowSystemEvent { + public: + GeometryChangeEvent(QWidget *tlw, const QRect &newGeometry) + : WindowSystemEvent(GeometryChange), tlw(tlw), newGeometry(newGeometry) + { } + QWeakPointer<QWidget> tlw; + QRect newGeometry; + }; + + class EnterEvent : public WindowSystemEvent { + public: + EnterEvent(QWidget *enter) + : WindowSystemEvent(Enter), enter(enter) + { } + QWeakPointer<QWidget> enter; + }; + + class LeaveEvent : public WindowSystemEvent { + public: + LeaveEvent(QWidget *leave) + : WindowSystemEvent(Leave), leave(leave) + { } + QWeakPointer<QWidget> leave; + }; + + class UserEvent : public WindowSystemEvent { + public: + UserEvent(QWidget * w, ulong time, EventType t) + : WindowSystemEvent(t), widget(w), timestamp(time) { } + QWeakPointer<QWidget> widget; + unsigned long timestamp; + }; + + class MouseEvent : public UserEvent { + public: + MouseEvent(QWidget * w, ulong time, const QPoint & local, const QPoint & global, Qt::MouseButtons b) + : UserEvent(w, time, Mouse), localPos(local), globalPos(global), buttons(b) { } + QPoint localPos; + QPoint globalPos; + Qt::MouseButtons buttons; + }; + + class WheelEvent : public UserEvent { + public: + WheelEvent(QWidget *w, ulong time, const QPoint & local, const QPoint & global, int d, Qt::Orientation o) + : UserEvent(w, time, Wheel), delta(d), localPos(local), globalPos(global), orient(o) { } + int delta; + QPoint localPos; + QPoint globalPos; + Qt::Orientation orient; + }; + + class KeyEvent : public UserEvent { + public: + KeyEvent(QWidget *w, ulong time, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString & text = QString(), bool autorep = false, ushort count = 1) + :UserEvent(w, time, Key), key(k), unicode(text), repeat(autorep), + repeatCount(count), modifiers(mods), keyType(t) { } + int key; + QString unicode; + bool repeat; + ushort repeatCount; + Qt::KeyboardModifiers modifiers; + QEvent::Type keyType; + }; + + class TouchEvent : public UserEvent { + public: + TouchEvent(QWidget *w, ulong time, QEvent::Type t, QTouchEvent::DeviceType d, const QList<QTouchEvent::TouchPoint> &p) + :UserEvent(w, time, Touch), devType(d), points(p), touchType(t) { } + QTouchEvent::DeviceType devType; + QList<QTouchEvent::TouchPoint> points; + QEvent::Type touchType; + + }; + + class ScreenCountEvent : public WindowSystemEvent { + public: + ScreenCountEvent (int count) + : WindowSystemEvent(ScreenCountChange) , count(count) { } + int count; + }; + + class ScreenGeometryEvent : public WindowSystemEvent { + public: + ScreenGeometryEvent(int index) + : WindowSystemEvent(ScreenGeometry), index(index) { } + int index; + }; + + class ScreenAvailableGeometryEvent : public WindowSystemEvent { + public: + ScreenAvailableGeometryEvent(int index) + : WindowSystemEvent(ScreenAvailableGeometry), index(index) { } + int index; + }; + + static QList<WindowSystemEvent *> windowSystemEventQueue; + static QMutex queueMutex; + + static int windowSystemEventsQueued(); + static WindowSystemEvent * getWindowSystemEvent(); + static void queueWindowSystemEvent(WindowSystemEvent *ev); + + static QTime eventTime; +}; + +QT_END_HEADER +QT_END_NAMESPACE + +#endif // QWINDOWSYSTEMINTERFACE_QPA_P_H diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri index 9ad4648..099619c 100644 --- a/src/gui/painting/painting.pri +++ b/src/gui/painting/painting.pri @@ -87,14 +87,18 @@ SOURCES += \ painting/qpaintengine_raster.cpp \ painting/qdrawhelper.cpp \ painting/qimagescale.cpp \ - painting/qgrayraster.c + painting/qgrayraster.c \ + painting/qpaintengine_blitter.cpp \ + painting/qblittable.cpp \ HEADERS += \ painting/qpaintengine_raster_p.h \ painting/qdrawhelper_p.h \ painting/qblendfunctions_p.h \ painting/qrasterdefs_p.h \ - painting/qgrayraster_p.h + painting/qgrayraster_p.h \ + painting/qpaintengine_blitter_p.h \ + painting/qblittable_p.h \ win32 { HEADERS += painting/qprintengine_win_p.h @@ -115,20 +119,20 @@ embedded { SOURCES += \ painting/qgraphicssystem_qws.cpp \ -} else { +} else: if(!qpa) { HEADERS += \ painting/qgraphicssystem_raster_p.h \ painting/qgraphicssystem_runtime_p.h \ painting/qgraphicssystemfactory_p.h \ painting/qgraphicssystemplugin_p.h \ - painting/qwindowsurface_raster_p.h \ + painting/qwindowsurface_raster_p.h SOURCES += \ painting/qgraphicssystem_raster.cpp \ painting/qgraphicssystem_runtime.cpp \ painting/qgraphicssystemfactory.cpp \ painting/qgraphicssystemplugin.cpp \ - painting/qwindowsurface_raster.cpp \ + painting/qwindowsurface_raster.cpp } unix:x11 { @@ -141,7 +145,7 @@ unix:x11 { painting/qpaintengine_x11.cpp } -!embedded:!x11:mac { +!embedded:!qpa:!x11:mac { HEADERS += \ painting/qpaintengine_mac_p.h \ painting/qgraphicssystem_mac_p.h \ @@ -157,14 +161,14 @@ unix:x11 { painting/qprintengine_mac.mm \ } -unix:!mac:!symbian { +unix:!mac:!symbian|qpa { HEADERS += \ painting/qprinterinfo_unix_p.h SOURCES += \ painting/qprinterinfo_unix.cpp } -win32|x11|mac|embedded|symbian { +win32|x11|mac|embedded|qpa|symbian { SOURCES += painting/qbackingstore.cpp HEADERS += painting/qbackingstore_p.h } @@ -181,6 +185,12 @@ embedded { painting/qpaintdevice_qws.cpp } +qpa { + SOURCES += \ + painting/qcolormap_qpa.cpp \ + painting/qpaintdevice_qpa.cpp +} + symbian { SOURCES += \ painting/qpaintengine_s60.cpp \ @@ -191,7 +201,7 @@ symbian { painting/qpaintengine_s60_p.h } -x11|embedded { +x11|embedded|qpa { contains(QT_CONFIG,qtopia) { DEFINES += QT_NO_CUPS QT_NO_LPR } else { @@ -221,7 +231,7 @@ x11 { SOURCES += painting/qwindowsurface_x11.cpp } -mac { +!embedded:!qpa:mac { HEADERS += painting/qwindowsurface_mac_p.h SOURCES += painting/qwindowsurface_mac.cpp } diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp index ac9b994..dc7b808 100644 --- a/src/gui/painting/qbackingstore.cpp +++ b/src/gui/painting/qbackingstore.cpp @@ -98,6 +98,21 @@ static inline void qt_flush(QWidget *widget, const QRegion ®ion, QWindowSurfa QWidgetBackingStore::showYellowThing(widget, region, flushUpdate * 10, false); #endif + //The performance hit by doing this should be negligible. However, be aware that + //using this FPS when you have > 1 windowsurface can give you inaccurate FPS + static bool fpsDebug = qgetenv("QT_DEBUG_FPS").toInt(); + if (fpsDebug) { + static QTime time = QTime::currentTime(); + static int frames = 0; + + frames++; + + if(time.elapsed() > 5000) { + double fps = double(frames * 1000) /time.restart(); + fprintf(stderr,"FPS: %.1f\n",fps); + frames = 0; + } + } if (widget != tlw) windowSurface->flush(widget, region, tlwOffset + widget->mapTo(tlw, QPoint())); else @@ -271,7 +286,11 @@ bool QWidgetBackingStore::bltRect(const QRect &rect, int dx, int dy, QWidget *wi void QWidgetBackingStore::releaseBuffer() { if (windowSurface) +#if defined(Q_WS_QPA) + windowSurface->resize(QSize()); +#else windowSurface->setGeometry(QRect()); +#endif #ifdef Q_BACKINGSTORE_SUBSURFACES for (int i = 0; i < subSurfaces.size(); ++i) subSurfaces.at(i)->setGeometry(QRect()); @@ -401,7 +420,11 @@ QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const { const bool widgetDirty = widget && widget != tlw; const QRect tlwRect(topLevelRect()); +#if defined(Q_WS_QPA) + const QRect surfaceGeometry(tlwRect.topLeft(), windowSurface->size()); +#else const QRect surfaceGeometry(windowSurface->geometry()); +#endif if (fullUpdatePending || (surfaceGeometry != tlwRect && surfaceGeometry.size() != tlwRect.size())) { if (widgetDirty) { const QRect dirtyTlwRect = QRect(QPoint(), tlwRect.size()); @@ -452,7 +475,11 @@ QRegion QWidgetBackingStore::dirtyRegion(QWidget *widget) const QRegion QWidgetBackingStore::staticContents(QWidget *parent, const QRect &withinClipRect) const { if (!parent && tlw->testAttribute(Qt::WA_StaticContents)) { +#if defined(Q_WS_QPA) + const QSize surfaceGeometry(windowSurface->size()); +#else const QRect surfaceGeometry(windowSurface->geometry()); +#endif QRect surfaceRect(0, 0, surfaceGeometry.width(), surfaceGeometry.height()); if (!withinClipRect.isEmpty()) surfaceRect &= withinClipRect; @@ -720,9 +747,8 @@ void QWidgetBackingStore::markDirtyOnScreen(const QRegion ®ion, QWidget *widg } // Alien widgets. - if (!widget->internalWinId()) { - QWidget *nativeParent = widget->nativeParentWidget(); - // Alien widgets with the top-level as the native parent (common case). + if (!widget->internalWinId() && !widget->isWindow()) { + QWidget *nativeParent = widget->nativeParentWidget(); // Alien widgets with the top-level as the native parent (common case). if (nativeParent == tlw) { if (!widget->testAttribute(Qt::WA_WState_InPaintEvent)) dirtyOnScreen += region.translated(topLevelOffset); @@ -1152,12 +1178,16 @@ void QWidgetBackingStore::sync() return; } - const bool inTopLevelResize = tlwExtra->inTopLevelResize; const bool updatesDisabled = !tlw->updatesEnabled(); - const QRect tlwRect(topLevelRect()); - const QRect surfaceGeometry(windowSurface->geometry()); bool repaintAllWidgets = false; + const bool inTopLevelResize = tlwExtra->inTopLevelResize; + const QRect tlwRect(topLevelRect()); +#ifdef Q_WS_QPA + const QRect surfaceGeometry(tlwRect.topLeft(), windowSurface->size()); +#else + const QRect surfaceGeometry(windowSurface->geometry()); +#endif if ((fullUpdatePending || inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) && !updatesDisabled) { if (hasStaticContents()) { // Repaint existing dirty area and newly visible area. @@ -1177,8 +1207,13 @@ void QWidgetBackingStore::sync() } } +#ifdef Q_WS_QPA + if (inTopLevelResize || surfaceGeometry.size() != tlwRect.size()) + windowSurface->resize(tlwRect.size()); +#else if (inTopLevelResize || surfaceGeometry != tlwRect) windowSurface->setGeometry(tlwRect); +#endif if (updatesDisabled) return; diff --git a/src/gui/painting/qblittable.cpp b/src/gui/painting/qblittable.cpp new file mode 100644 index 0000000..f4b84a9 --- /dev/null +++ b/src/gui/painting/qblittable.cpp @@ -0,0 +1,105 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qblittable_p.h" + +#ifndef QT_NO_BLITTABLE +QT_BEGIN_NAMESPACE + +class QBlittablePrivate +{ +public: + QBlittablePrivate(const QSize &size, QBlittable::Capabilities caps) + : caps(caps), m_size(size), locked(false), cachedImg(0) + {} + QBlittable::Capabilities caps; + QSize m_size; + bool locked; + QImage *cachedImg; +}; + + +QBlittable::QBlittable(const QSize &size, Capabilities caps) + : d_ptr(new QBlittablePrivate(size,caps)) +{ +} + +QBlittable::~QBlittable() +{ + delete d_ptr; +} + + +QBlittable::Capabilities QBlittable::capabilities() const +{ + Q_D(const QBlittable); + return d->caps; +} + +QSize QBlittable::size() const +{ + Q_D(const QBlittable); + return d->m_size; +} + +QImage *QBlittable::lock() +{ + Q_D(QBlittable); + if (!d->locked) { + d->cachedImg = doLock(); + d->locked = true; + } + + return d->cachedImg; +} + +void QBlittable::unlock() +{ + Q_D(QBlittable); + if (d->locked) { + doUnlock(); + d->locked = false; + } +} + +QT_END_NAMESPACE +#endif //QT_NO_BLITTABLE + diff --git a/src/gui/painting/qblittable_p.h b/src/gui/painting/qblittable_p.h new file mode 100644 index 0000000..cb56cb2 --- /dev/null +++ b/src/gui/painting/qblittable_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ + +#ifndef QBLITTABLE_P_H +#define QBLITTABLE_P_H + +#include <QtCore/qsize.h> +#include <QtGui/private/qpixmap_blitter_p.h> + + +#ifndef QT_NO_BLITTABLE +QT_BEGIN_NAMESPACE + +class QImage; +class QBlittablePrivate; + +class Q_GUI_EXPORT QBlittable +{ + Q_DECLARE_PRIVATE(QBlittable); +public: + enum Capability { + + SolidRectCapability = 0x0001, + SourcePixmapCapability = 0x0002, + SourceOverPixmapCapability = 0x0004, + SourceOverScaledPixmapCapability = 0x0008, + + // Internal ones + OutlineCapability = 0x0001000, + }; + Q_DECLARE_FLAGS (Capabilities, Capability); + + QBlittable(const QSize &size, Capabilities caps); + virtual ~QBlittable(); + + Capabilities capabilities() const; + QSize size() const; + + virtual void fillRect(const QRectF &rect, const QColor &color) = 0; + virtual void drawPixmap(const QRectF &rect, const QPixmap &pixmap, const QRectF &subrect) = 0; + + QImage *lock(); + void unlock(); + +protected: + virtual QImage *doLock() = 0; + virtual void doUnlock() = 0; + QBlittablePrivate *d_ptr; +}; + +QT_END_NAMESPACE +#endif //QT_NO_BLITTABLE +#endif //QBLITTABLE_P_H diff --git a/src/gui/painting/qcolormap_qpa.cpp b/src/gui/painting/qcolormap_qpa.cpp new file mode 100644 index 0000000..1f4fea8 --- /dev/null +++ b/src/gui/painting/qcolormap_qpa.cpp @@ -0,0 +1,231 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qcolormap.h" +#include "qcolor.h" +#include "qpaintdevice.h" +#include "private/qapplication_p.h" +#include "private/qgraphicssystem_p.h" + +QT_BEGIN_NAMESPACE + +class QColormapPrivate +{ +public: + inline QColormapPrivate() + : ref(1), mode(QColormap::Direct), depth(0), numcolors(0) + { } + + QAtomicInt ref; + + QColormap::Mode mode; + int depth; + int numcolors; +}; + +static QColormapPrivate *screenMap = 0; + +void QColormap::initialize() +{ + screenMap = new QColormapPrivate; + + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + QList<QPlatformScreen*> screens = pi->screens(); + + screenMap->depth = screens[0]->depth(); + if (screenMap->depth < 8) { + screenMap->mode = QColormap::Indexed; + screenMap->numcolors = 256; + } else { + screenMap->mode = QColormap::Direct; + screenMap->numcolors = -1; + } +} + +void QColormap::cleanup() +{ + delete screenMap; + screenMap = 0; +} + +QColormap QColormap::instance(int /*screen*/) +{ + return QColormap(); +} + +QColormap::QColormap() + : d(screenMap) +{ d->ref.ref(); } + +QColormap::QColormap(const QColormap &colormap) + :d (colormap.d) +{ d->ref.ref(); } + +QColormap::~QColormap() +{ + if (!d->ref.deref()) + delete d; +} + +QColormap::Mode QColormap::mode() const +{ return d->mode; } + + +int QColormap::depth() const +{ return d->depth; } + + +int QColormap::size() const +{ + return d->numcolors; +} + +#ifndef QT_QWS_DEPTH16_RGB +#define QT_QWS_DEPTH16_RGB 565 +#endif +static const int qt_rbits = (QT_QWS_DEPTH16_RGB/100); +static const int qt_gbits = (QT_QWS_DEPTH16_RGB/10%10); +static const int qt_bbits = (QT_QWS_DEPTH16_RGB%10); +static const int qt_red_shift = qt_bbits+qt_gbits-(8-qt_rbits); +static const int qt_green_shift = qt_bbits-(8-qt_gbits); +static const int qt_neg_blue_shift = 8-qt_bbits; +static const int qt_blue_mask = (1<<qt_bbits)-1; +static const int qt_green_mask = (1<<(qt_gbits+qt_bbits))-(1<<qt_bbits); +static const int qt_red_mask = (1<<(qt_rbits+qt_gbits+qt_bbits))-(1<<(qt_gbits+qt_bbits)); + +static const int qt_red_rounding_shift = qt_red_shift + qt_rbits; +static const int qt_green_rounding_shift = qt_green_shift + qt_gbits; +static const int qt_blue_rounding_shift = qt_bbits - qt_neg_blue_shift; + +inline ushort qt_convRgbTo16(QRgb c) +{ + const int tr = qRed(c) << qt_red_shift; + const int tg = qGreen(c) << qt_green_shift; + const int tb = qBlue(c) >> qt_neg_blue_shift; + + return (tb & qt_blue_mask) | (tg & qt_green_mask) | (tr & qt_red_mask); +} + +inline QRgb qt_conv16ToRgb(ushort c) +{ + const int r=(c & qt_red_mask); + const int g=(c & qt_green_mask); + const int b=(c & qt_blue_mask); + const int tr = r >> qt_red_shift | r >> qt_red_rounding_shift; + const int tg = g >> qt_green_shift | g >> qt_green_rounding_shift; + const int tb = b << qt_neg_blue_shift | b >> qt_blue_rounding_shift; + + return qRgb(tr,tg,tb); +} + +uint QColormap::pixel(const QColor &color) const +{ + QRgb rgb = color.rgba(); + if (d->mode == QColormap::Direct) { + switch(d->depth) { + case 16: + return qt_convRgbTo16(rgb); + case 24: + case 32: + { + const int r = qRed(rgb); + const int g = qGreen(rgb); + const int b = qBlue(rgb); + const int red_shift = 16; + const int green_shift = 8; + const int red_mask = 0xff0000; + const int green_mask = 0x00ff00; + const int blue_mask = 0x0000ff; + const int tg = g << green_shift; +#ifdef QT_QWS_DEPTH_32_BGR + if (qt_screen->pixelType() == QScreen::BGRPixel) { + const int tb = b << red_shift; + return 0xff000000 | (r & blue_mask) | (tg & green_mask) | (tb & red_mask); + } +#endif + const int tr = r << red_shift; + return 0xff000000 | (b & blue_mask) | (tg & green_mask) | (tr & red_mask); + } + } + } + //XXX + //return qt_screen->alloc(qRed(rgb), qGreen(rgb), qBlue(rgb)); + return 0; +} + +const QColor QColormap::colorAt(uint pixel) const +{ + if (d->mode == Direct) { + if (d->depth == 16) { + pixel = qt_conv16ToRgb(pixel); + } + const int red_shift = 16; + const int green_shift = 8; + const int red_mask = 0xff0000; + const int green_mask = 0x00ff00; + const int blue_mask = 0x0000ff; +#ifdef QT_QWS_DEPTH_32_BGR + if (qt_screen->pixelType() == QScreen::BGRPixel) { + return QColor((pixel & blue_mask), + (pixel & green_mask) >> green_shift, + (pixel & red_mask) >> red_shift); + } +#endif + return QColor((pixel & red_mask) >> red_shift, + (pixel & green_mask) >> green_shift, + (pixel & blue_mask)); + } +#if 0 // XXX + Q_ASSERT_X(int(pixel) < qt_screen->numCols(), "QColormap::colorAt", "pixel out of bounds of palette"); + return QColor(qt_screen->clut()[pixel]); +#endif + return QColor(); +} + +const QVector<QColor> QColormap::colormap() const +{ + return QVector<QColor>(); +} + +QColormap &QColormap::operator=(const QColormap &colormap) +{ qAtomicAssign(d, colormap.d); return *this; } + +QT_END_NAMESPACE diff --git a/src/gui/painting/qgraphicssystem.cpp b/src/gui/painting/qgraphicssystem.cpp index f06e309..f594136 100644 --- a/src/gui/painting/qgraphicssystem.cpp +++ b/src/gui/painting/qgraphicssystem.cpp @@ -50,6 +50,9 @@ #ifdef Q_WS_MAC # include <private/qpixmap_mac_p.h> #endif +#ifdef Q_WS_QPA +# include <QtGui/private/qapplication_p.h> +#endif #ifdef Q_OS_SYMBIAN # include <private/qpixmap_s60_p.h> #endif @@ -71,8 +74,10 @@ QPixmapData *QGraphicsSystem::createDefaultPixmapData(QPixmapData::PixelType typ return new QRasterPixmapData(type); #elif defined(Q_WS_MAC) return new QMacPixmapData(type); +#elif defined(Q_WS_QPA) + return QApplicationPrivate::platformIntegration()->createPixmapData(type); #elif defined(Q_OS_SYMBIAN) - return new QS60PixmapData(type); + return new QS60PixmapData(type); #elif !defined(Q_WS_QWS) #error QGraphicsSystem::createDefaultPixmapData() not implemented #endif diff --git a/src/gui/painting/qgraphicssystem_p.h b/src/gui/painting/qgraphicssystem_p.h index 1211505..a75ea61 100644 --- a/src/gui/painting/qgraphicssystem_p.h +++ b/src/gui/painting/qgraphicssystem_p.h @@ -55,10 +55,14 @@ #include "private/qpixmapdata_p.h" #include "private/qwindowsurface_p.h" +#include "private/qpaintengine_blitter_p.h" + +#include <qdebug.h> QT_BEGIN_NAMESPACE class QPixmapFilter; +class QBlittable; class Q_GUI_EXPORT QGraphicsSystem { @@ -67,7 +71,7 @@ public: virtual QPixmapData *createPixmapData(QPixmapData *origin); virtual QWindowSurface *createWindowSurface(QWidget *widget) const = 0; - virtual ~QGraphicsSystem() = 0; + virtual ~QGraphicsSystem(); //### Remove this & change qpixmap.cpp & qbitmap.cpp once every platform is gaurenteed // to have a graphics system. diff --git a/src/gui/painting/qpaintdevice.cpp b/src/gui/painting/qpaintdevice.cpp index 4169df0..cde7bfa 100644 --- a/src/gui/painting/qpaintdevice.cpp +++ b/src/gui/painting/qpaintdevice.cpp @@ -59,11 +59,13 @@ QPaintDevice::~QPaintDevice() } +#ifndef Q_WS_QPA int QPaintDevice::metric(PaintDeviceMetric) const { qWarning("QPaintDevice::metrics: Device has no metric information"); return 0; } +#endif Q_GUI_EXPORT int qt_paint_device_metric(const QPaintDevice *device, QPaintDevice::PaintDeviceMetric metric) { diff --git a/src/gui/painting/qpaintdevice_qpa.cpp b/src/gui/painting/qpaintdevice_qpa.cpp new file mode 100644 index 0000000..0d1ca92 --- /dev/null +++ b/src/gui/painting/qpaintdevice_qpa.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qpaintdevice.h" +#include "qpainter.h" +#include "qwidget.h" +#include "qbitmap.h" +#include "qapplication.h" + +QT_BEGIN_NAMESPACE + +extern void qt_painter_removePaintDevice(QPaintDevice *); //qpainter.cpp + +int QPaintDevice::metric(PaintDeviceMetric m) const +{ + qWarning("QPaintDevice::metrics: Device has no metric information"); + if (m == PdmDpiX) { + return 72; + } else if (m == PdmDpiY) { + return 72; + } else if (m == PdmNumColors) { + // FIXME: does this need to be a real value? + return 256; + } else { + qDebug("Unrecognised metric %d!",m); + return 0; + } +} + +QT_END_NAMESPACE diff --git a/src/gui/painting/qpaintengine.h b/src/gui/painting/qpaintengine.h index b860012..ee9b457 100644 --- a/src/gui/painting/qpaintengine.h +++ b/src/gui/painting/qpaintengine.h @@ -213,6 +213,7 @@ public: OpenVG, OpenGL2, PaintBuffer, + Blitter, User = 50, // first user type id MaxUser = 100 // last user type id @@ -270,6 +271,9 @@ private: friend class QtopiaPrintEnginePrivate; friend class QProxyFontEngine; #endif +#ifdef Q_WS_QPA + friend class QFontEngineQPA; +#endif friend class QPainter; friend class QPainterPrivate; friend class QWidget; diff --git a/src/gui/painting/qpaintengine_blitter.cpp b/src/gui/painting/qpaintengine_blitter.cpp new file mode 100644 index 0000000..2e8d9dd --- /dev/null +++ b/src/gui/painting/qpaintengine_blitter.cpp @@ -0,0 +1,663 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "private/qpaintengine_blitter_p.h" + +#include "private/qblittable_p.h" +#include "private/qpaintengine_raster_p.h" +#include "private/qpainter_p.h" +#include "private/qapplication_p.h" +#include "private/qpixmap_blitter_p.h" + +#ifndef QT_NO_BLITTABLE +QT_BEGIN_NAMESPACE + +#define STATE_XFORM_SCALE 0x00000001 +#define STATE_XFORM_COMPLEX 0x00000002 + +#define STATE_BRUSH_PATTERN 0x00000010 +#define STATE_BRUSH_ALPHA 0x00000020 + +#define STATE_PEN_ENABLED 0x00000100 + +#define STATE_ANTIALIASING 0x00001000 +#define STATE_ALPHA 0x00002000 +#define STATE_BLENDING_COMPLEX 0x00004000 + +#define STATE_CLIPSYS_COMPLEX 0x00010000 +#define STATE_CLIP_COMPLEX 0x00020000 + + +static inline void updateStateBits(uint *state, uint mask, bool on) +{ + *state = on ? (*state | mask) : (*state & ~mask); +} + +static inline bool checkStateAgainstMask(uint state, uint mask) +{ + return !state || (state & mask && !(state & ~mask)); +} + +class CapabilitiesToStateMask +{ +public: + CapabilitiesToStateMask(QBlittable::Capabilities capabilities) + : m_capabilities(capabilities), + fillRectMask(0), + drawRectMask(0), + drawPixmapMask(0), + capabillitiesState(0) + { + if (capabilities & QBlittable::SolidRectCapability) { + setFillRectMask(); + } + if (capabilities & QBlittable::SourcePixmapCapability) { + setSourcePixmapMask(); + } + if (capabilities & QBlittable::SourceOverPixmapCapability) { + setSourceOverPixmapMask(); + } + if (capabilities & QBlittable::SourceOverScaledPixmapCapability) { + setSourceOverScaledPixmapMask(); + } + } + + inline bool canBlitterFillRect() const + { + return checkStateAgainstMask(capabillitiesState,fillRectMask); + } + + inline bool canBlitterDrawRectMask() const + { + return checkStateAgainstMask(capabillitiesState,drawRectMask); + } + + bool canBlitterDrawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) const + { + if (pm.pixmapData()->classId() != QPixmapData::BlitterClass) + return false; + if (checkStateAgainstMask(capabillitiesState,drawPixmapMask)) { + if (m_capabilities & (QBlittable::SourceOverPixmapCapability + | QBlittable::SourceOverScaledPixmapCapability)) { + if (r.size() != sr.size()) { + return m_capabilities & QBlittable::SourceOverScaledPixmapCapability; + } else { + return m_capabilities & QBlittable::SourceOverPixmapCapability; + } + } + if ((m_capabilities & QBlittable::SourcePixmapCapability) && r.size() == sr.size() && !pm.hasAlphaChannel()) { + return m_capabilities & QBlittable::SourcePixmapCapability; + } + } + return false; + } + + inline void updateState(uint mask, bool on) { + updateStateBits(&capabillitiesState,mask,on); + } + +public: + + void setFillRectMask() { + updateStateBits(&fillRectMask, STATE_XFORM_SCALE, false); + updateStateBits(&fillRectMask, STATE_XFORM_COMPLEX, false); + + updateStateBits(&fillRectMask, STATE_BRUSH_PATTERN, false); + updateStateBits(&fillRectMask, STATE_BRUSH_ALPHA, false); + + updateStateBits(&fillRectMask, STATE_PEN_ENABLED, true); + + //Sub-pixel aliasing should not be sent to the blitter + updateStateBits(&fillRectMask, STATE_ANTIALIASING, true); + updateStateBits(&fillRectMask, STATE_ALPHA, false); + updateStateBits(&fillRectMask, STATE_BLENDING_COMPLEX, false); + + updateStateBits(&fillRectMask, STATE_CLIPSYS_COMPLEX, false); + updateStateBits(&fillRectMask, STATE_CLIP_COMPLEX, false); + } + + void setSourcePixmapMask() { + updateStateBits(&drawPixmapMask, STATE_XFORM_SCALE, true); + updateStateBits(&drawPixmapMask, STATE_XFORM_COMPLEX, false); + + updateStateBits(&drawPixmapMask, STATE_BRUSH_PATTERN, true); + updateStateBits(&drawPixmapMask, STATE_BRUSH_ALPHA, false); + + updateStateBits(&drawPixmapMask, STATE_PEN_ENABLED, true); + + updateStateBits(&drawPixmapMask, STATE_ANTIALIASING, true); + updateStateBits(&drawPixmapMask, STATE_ALPHA, false); + updateStateBits(&drawPixmapMask, STATE_BLENDING_COMPLEX, false); + + updateStateBits(&drawPixmapMask, STATE_CLIPSYS_COMPLEX, false); + updateStateBits(&drawPixmapMask, STATE_CLIP_COMPLEX, false); + } + + void setSourceOverPixmapMask() { + setSourcePixmapMask(); + } + + void setSourceOverScaledPixmapMask() { + setSourceOverPixmapMask(); + updateStateBits(&drawRectMask, STATE_XFORM_SCALE, true); + } + + QBlittable::Capabilities m_capabilities; + uint fillRectMask; + uint drawRectMask; + uint drawPixmapMask; + uint capabillitiesState; +}; + +class QBlitterPaintEnginePrivate : public QPaintEngineExPrivate +{ + Q_DECLARE_PUBLIC(QBlitterPaintEngine); +public: + QBlitterPaintEnginePrivate(QBlittablePixmapData *p) + : QPaintEngineExPrivate(), + pmData(p), + isBlitterLocked(false), + hasXForm(false) + + { + raster = new QRasterPaintEngine(p->buffer()); + capabillities = new CapabilitiesToStateMask(pmData->blittable()->capabilities()); + } + + inline void lock() { + if (!isBlitterLocked) { + raster->d_func()->rasterBuffer->prepare(pmData->blittable()->lock()); + isBlitterLocked = true; + } + } + + inline void unlock() { + if (isBlitterLocked) { + pmData->blittable()->unlock(); + isBlitterLocked = false; + } + } + + void fillRect(const QRectF &rect, const QColor &color) { + Q_Q(QBlitterPaintEngine); + pmData->unmarkRasterOverlay(rect); + QRectF targetRect = rect; + if (hasXForm) { + targetRect = q->state()->matrix.mapRect(rect); + } + const QClipData *clipData = q->clip(); + if (clipData) { + if (clipData->hasRectClip) { + unlock(); + pmData->blittable()->fillRect(targetRect & clipData->clipRect, color); + } else if (clipData->hasRegionClip) { + QVector<QRect> rects = clipData->clipRegion.rects(); + for ( int i = 0; i < rects.size(); i++ ) { + QRect intersectRect = rects.at(i).intersected(targetRect.toRect()); + if (!intersectRect.isEmpty()) { + unlock(); + pmData->blittable()->fillRect(intersectRect,color); + } + } + } + } else { + if (targetRect.x() >= 0 && targetRect.y() >= 0 + && targetRect.width() <= raster->paintDevice()->width() + && targetRect.height() <= raster->paintDevice()->height()) { + unlock(); + pmData->blittable()->fillRect(targetRect,color); + } else { + QRectF deviceRect(0,0,raster->paintDevice()->width(), raster->paintDevice()->height()); + unlock(); + pmData->blittable()->fillRect(deviceRect&targetRect,color); + } + } + } + + void clipAndDrawPixmap(const QRectF &clip, const QRectF &target, const QPixmap &pm, const QRectF &sr) { + QRectF intersectedRect = clip.intersected(target); + if (intersectedRect.isEmpty()) + return; + QRectF source = sr; + if(intersectedRect.size() != target.size()) { + qreal deltaTop = target.top() - intersectedRect.top(); + qreal deltaLeft = target.left() - intersectedRect.left(); + qreal deltaBottom = target.bottom() - intersectedRect.bottom(); + qreal deltaRight = target.right() - intersectedRect.right(); + source.adjust(-deltaLeft,-deltaTop,-deltaRight,-deltaBottom); + } + pmData->unmarkRasterOverlay(intersectedRect); + pmData->blittable()->drawPixmap(intersectedRect, pm, source); + } + + void updateClip() { + Q_Q(QBlitterPaintEngine); + const QClipData *clip = q->clip(); + bool complex = clip && !(clip->hasRectClip || clip->hasRegionClip); + capabillities->updateState(STATE_CLIP_COMPLEX, complex); + } + + void systemStateChanged() { + raster->d_func()->systemStateChanged(); + } + + QRasterPaintEngine *raster; + + QBlittablePixmapData *pmData; + bool isBlitterLocked; + + CapabilitiesToStateMask *capabillities; + + uint hasXForm; +}; + +QBlitterPaintEngine::QBlitterPaintEngine(QBlittablePixmapData *p) + : QPaintEngineEx(*(new QBlitterPaintEnginePrivate(p))) +{ +} + +QBlitterPaintEngine::~QBlitterPaintEngine() +{ +} + +QPainterState *QBlitterPaintEngine::createState(QPainterState *orig) const +{ + Q_D(const QBlitterPaintEngine); + return d->raster->createState(orig); +} + +bool QBlitterPaintEngine::begin(QPaintDevice *pdev) +{ + Q_D(QBlitterPaintEngine); + + setActive(true); + bool ok = d->raster->begin(pdev); +#ifdef QT_BLITTER_RASTEROVERLAY + d->pmData->unmergeOverlay(); +#endif + return ok; +} + + +bool QBlitterPaintEngine::end() +{ + Q_D(QBlitterPaintEngine); + + setActive(false); +#ifdef QT_BLITTER_RASTEROVERLAY + d->pmData->mergeOverlay(); +#endif + return d->raster->end(); +} + + +void QBlitterPaintEngine::fill(const QVectorPath &path, const QBrush &brush) +{ + Q_D(QBlitterPaintEngine); + if (path.shape() == QVectorPath::RectangleHint) { + QRectF rect(((QPointF *) path.points())[0], ((QPointF *) path.points())[2]); + fillRect(rect, brush); + } else { + d->lock(); + d->pmData->markRasterOverlay(path); + d->raster->fill(path, brush); + } +} + +void QBlitterPaintEngine::fillRect(const QRectF &rect, const QColor &color) +{ + Q_D(QBlitterPaintEngine); + if (d->capabillities->canBlitterFillRect() && color.alpha() == 0xff) { + d->fillRect(rect, color); + } else { + d->lock(); + d->pmData->markRasterOverlay(rect); + d->raster->fillRect(rect, color); + } +} + +void QBlitterPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) +{ + if(rect.size().isEmpty()) + return; + + Q_D(QBlitterPaintEngine); + + if (qbrush_style(brush) == Qt::SolidPattern + && qbrush_color(brush).alpha() == 0xff + && d->capabillities->canBlitterFillRect()) + { + d->fillRect(rect, qbrush_color(brush)); + }else if (brush.style() == Qt::TexturePattern + && d->capabillities->canBlitterDrawPixmap(rect,brush.texture(),rect)) + { + bool rectIsFilled = false; + QRectF transformedRect = state()->matrix.mapRect(rect); + qreal x = transformedRect.x(); + qreal y = transformedRect.y(); + QPixmap pm = brush.texture(); + d->unlock(); + int srcX = int(rect.x() - state()->brushOrigin.x()) % pm.width(); + if (srcX < 0) + srcX = pm.width() + srcX; + const int startX = srcX; + int srcY = int(rect.y() - state()->brushOrigin.y()) % pm.height(); + if (srcY < 0) + srcY = pm.height() + srcY; + while (!rectIsFilled) { + qreal blitWidth = (pm.width() ) - srcX; + qreal blitHeight = (pm.height() ) - srcY; + if (x + blitWidth > transformedRect.right()) + blitWidth = transformedRect.right() -x; + if (y + blitHeight > transformedRect.bottom()) + blitHeight = transformedRect.bottom() - y; + const QClipData *clipData = clip(); + if (clipData->hasRectClip) { + QRect targetRect = QRect(x,y,blitWidth,blitHeight).intersected(clipData->clipRect); + if (targetRect.isValid()) { + int tmpSrcX = srcX + (targetRect.x() - x); + int tmpSrcY = srcY + (targetRect.y() - y); + QRect srcRect(tmpSrcX,tmpSrcY,targetRect.width(),targetRect.height()); + d->pmData->blittable()->drawPixmap(targetRect,pm,srcRect); + } + } else if (clipData->hasRegionClip) { + QVector<QRect> clipRects = clipData->clipRegion.rects(); + QRect unclippedTargetRect(x,y,blitWidth,blitHeight); + QRegion intersectedRects = clipData->clipRegion.intersected(unclippedTargetRect); + + for ( int i = 0; i < intersectedRects.rects().size(); i++ ) { + QRect targetRect = intersectedRects.rects().at(i); + if (!targetRect.isValid() || targetRect.isEmpty()) + continue; + int tmpSrcX = srcX + (targetRect.x() - x); + int tmpSrcY = srcY + (targetRect.y() - y); + QRect srcRect(tmpSrcX,tmpSrcY,targetRect.width(),targetRect.height()); + d->pmData->blittable()->drawPixmap(targetRect,pm,srcRect); + } + } + x+=blitWidth; + if (x>=transformedRect.right()) { + x = transformedRect.x(); + srcX = startX; + srcY = 0; + y+=blitHeight; + if (y>=transformedRect.bottom()) + rectIsFilled = true; + } else + srcX = 0; + } + } else { + d->lock(); + d->pmData->markRasterOverlay(rect); + d->raster->fillRect(rect, brush); + } + +} + +void QBlitterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->pmData->markRasterOverlay(path); + d->raster->stroke(path, pen); +} + +void QBlitterPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->raster->clip(path, op); + d->updateClip(); +} +void QBlitterPaintEngine::clip(const QRect &rect, Qt::ClipOperation op){ + Q_D(QBlitterPaintEngine); + d->lock(); + d->raster->clip(rect,op); + d->updateClip(); +} +void QBlitterPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->raster->clip(region,op); + d->updateClip(); +} + +void QBlitterPaintEngine::clipEnabledChanged() +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->raster->clipEnabledChanged(); +} + +void QBlitterPaintEngine::penChanged() +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->raster->penChanged(); + d->capabillities->updateState(STATE_PEN_ENABLED,qpen_style(state()->pen) != Qt::NoPen); +} + +void QBlitterPaintEngine::brushChanged() +{ + Q_D(QBlitterPaintEngine); + d->raster->brushChanged(); + + bool solid = qbrush_style(state()->brush) == Qt::SolidPattern; + + d->capabillities->updateState(STATE_BRUSH_PATTERN, !solid); + d->capabillities->updateState(STATE_BRUSH_ALPHA, + qbrush_color(state()->brush).alpha() < 255); +} + +void QBlitterPaintEngine::brushOriginChanged() +{ + Q_D(QBlitterPaintEngine); + d->raster->brushOriginChanged(); +} + +void QBlitterPaintEngine::opacityChanged() +{ + Q_D(QBlitterPaintEngine); + d->raster->opacityChanged(); + + bool translucent = state()->opacity < 1; + d->capabillities->updateState(STATE_ALPHA,translucent); +} + +void QBlitterPaintEngine::compositionModeChanged() +{ + Q_D(QBlitterPaintEngine); + d->raster->compositionModeChanged(); + + bool nonTrivial = state()->composition_mode != QPainter::CompositionMode_SourceOver + && state()->composition_mode != QPainter::CompositionMode_Source; + + d->capabillities->updateState(STATE_BLENDING_COMPLEX,nonTrivial); +} + +void QBlitterPaintEngine::renderHintsChanged() +{ + Q_D(QBlitterPaintEngine); + d->raster->renderHintsChanged(); + + bool aa = state()->renderHints & QPainter::Antialiasing; + d->capabillities->updateState(STATE_ANTIALIASING, aa); + +} + +void QBlitterPaintEngine::transformChanged() +{ + Q_D(QBlitterPaintEngine); + d->raster->transformChanged(); + + QTransform::TransformationType type = state()->matrix.type(); + + d->capabillities->updateState(STATE_XFORM_COMPLEX, type > QTransform::TxScale); + d->capabillities->updateState(STATE_XFORM_SCALE, type > QTransform::TxTranslate); + + d->hasXForm = type >= QTransform::TxTranslate; + +} + +void QBlitterPaintEngine::drawRects(const QRect *rects, int rectCount) +{ + Q_D(QBlitterPaintEngine); + if (d->capabillities->canBlitterDrawRectMask()) { + for (int i=0; i<rectCount; ++i) { + d->fillRect(rects[i], qbrush_color(state()->brush)); + } + } else { + d->pmData->markRasterOverlay(rects,rectCount); + QPaintEngineEx::drawRects(rects, rectCount); + } +} + +void QBlitterPaintEngine::drawRects(const QRectF *rects, int rectCount) +{ + Q_D(QBlitterPaintEngine); + if (d->capabillities->canBlitterDrawRectMask()) { + for (int i=0; i<rectCount; ++i) { + d->fillRect(rects[i], qbrush_color(state()->brush)); + } + } else { + d->pmData->markRasterOverlay(rects,rectCount); + QPaintEngineEx::drawRects(rects, rectCount); + } +} + +void QBlitterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) +{ + Q_D(QBlitterPaintEngine); + if (d->capabillities->canBlitterDrawPixmap(r,pm,sr)) { + + d->unlock(); + QRectF targetRect = r; + if (d->hasXForm) { + targetRect = state()->matrix.mapRect(r); + } + const QClipData *clipData = clip(); + if (clipData) { + if (clipData->hasRectClip) { + d->clipAndDrawPixmap(clipData->clipRect,targetRect,pm,sr); + }else if (clipData->hasRegionClip) { + QVector<QRect>rects = clipData->clipRegion.rects(); + for (int i = 0; i<rects.size(); i++) { + d->clipAndDrawPixmap(rects.at(i),targetRect,pm,sr); + } + } + } else { + QRectF deviceRect(0,0,d->raster->paintDevice()->width(), d->raster->paintDevice()->height()); + d->clipAndDrawPixmap(deviceRect,targetRect,pm,sr); + } + }else { + d->lock(); + d->pmData->markRasterOverlay(r); + d->raster->drawPixmap(r, pm, sr); + } +} + +void QBlitterPaintEngine::drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, + Qt::ImageConversionFlags flags) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->pmData->markRasterOverlay(r); + d->raster->drawImage(r, pm, sr, flags); +} + + +void QBlitterPaintEngine::drawTextItem(const QPointF &pos, const QTextItem &ti) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->raster->drawTextItem(pos, ti); + d->pmData->markRasterOverlay(pos,ti); +} + +void QBlitterPaintEngine::drawStaticTextItem(QStaticTextItem *sti) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->raster->drawStaticTextItem(sti); + +//#### d->pmData->markRasterOverlay(sti); + qWarning("not implemented: markRasterOverlay for QStaticTextItem"); + +} + + +void QBlitterPaintEngine::drawEllipse(const QRectF &r) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + d->pmData->markRasterOverlay(r); + d->raster->drawEllipse(r); +} + +void QBlitterPaintEngine::setState(QPainterState *s) +{ + Q_D(QBlitterPaintEngine); + d->lock(); + QPaintEngineEx::setState(s); + d->raster->setState(s); + + clipEnabledChanged(); + penChanged(); + brushChanged(); + brushOriginChanged(); + opacityChanged(); + compositionModeChanged(); + renderHintsChanged(); + transformChanged(); + + d->updateClip(); +} + +inline QRasterPaintEngine *QBlitterPaintEngine::raster() const +{ + Q_D(const QBlitterPaintEngine); + return d->raster; +} + +QT_END_NAMESPACE +#endif //QT_NO_BLITTABLE + diff --git a/src/gui/painting/qpaintengine_blitter_p.h b/src/gui/painting/qpaintengine_blitter_p.h new file mode 100644 index 0000000..c8aa536 --- /dev/null +++ b/src/gui/painting/qpaintengine_blitter_p.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ + +#ifndef QPAINTENGINE_BLITTER_P_H +#define QPAINTENGINE_BLITTER_P_H + +#include "private/qpaintengineex_p.h" +#include "private/qpaintengine_raster_p.h" + +#ifndef QT_NO_BLITTABLE +QT_BEGIN_NAMESPACE + +class QBlitterPaintEnginePrivate; +class QBlittablePixmapData; +class QBlittable; + +class Q_GUI_EXPORT QBlitterPaintEngine : public QPaintEngineEx +{ + Q_DECLARE_PRIVATE(QBlitterPaintEngine); +public: + QBlitterPaintEngine(QBlittablePixmapData *p); + ~QBlitterPaintEngine(); + + virtual QPainterState *createState(QPainterState *orig) const; + + virtual QPaintEngine::Type type() const { return Blitter; } + + virtual bool begin(QPaintDevice *pdev); + virtual bool end(); + + virtual void fill(const QVectorPath &path, const QBrush &brush); + virtual void stroke(const QVectorPath &path, const QPen &pen); + + virtual void clip(const QVectorPath &path, Qt::ClipOperation op); + virtual void clip(const QRect &rect, Qt::ClipOperation op); + virtual void clip(const QRegion ®ion, Qt::ClipOperation op); + + virtual void clipEnabledChanged(); + virtual void penChanged(); + virtual void brushChanged(); + virtual void brushOriginChanged(); + virtual void opacityChanged(); + virtual void compositionModeChanged(); + virtual void renderHintsChanged(); + virtual void transformChanged(); + + virtual void fillRect(const QRectF &rect, const QBrush &brush); + virtual void fillRect(const QRectF &rect, const QColor &color); + + virtual void drawRects(const QRect *rects, int rectCount); + virtual void drawRects(const QRectF *rects, int rectCount); + + virtual void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr); + + virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, Qt::ImageConversionFlags flags); + + virtual void drawTextItem(const QPointF &pos, const QTextItem &ti); + virtual void drawStaticTextItem(QStaticTextItem *); + + virtual void drawEllipse(const QRectF &r); + + virtual void setState(QPainterState *s); + + inline QPainterState *state() { return raster()->state(); } + inline const QPainterState *state() const { const QPainterState *state = raster()->state(); return state;} + inline const QClipData *clip(){return raster()->d_func()->clip();} + +private: + QRasterPaintEngine *raster() const; +}; + +QT_END_NAMESPACE +#endif //QT_NO_BLITTABLE +#endif // QPAINTENGINE_BLITTER_P_H + diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index d0a0d79..1690e67 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -95,6 +95,8 @@ # include <private/qabstractfontengine_p.h> #elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) # include <private/qfontengine_s60_p.h> +#elif defined(Q_WS_QPA) +# include <private/qfontengine_ft_p.h> #endif #if defined(Q_WS_WIN64) @@ -440,7 +442,7 @@ bool QRasterPaintEngine::begin(QPaintDevice *device) if (device->devType() == QInternal::Pixmap) { QPixmap *pixmap = static_cast<QPixmap *>(device); QPixmapData *pd = pixmap->pixmapData(); - if (pd->classId() == QPixmapData::RasterClass) + if (pd->classId() == QPixmapData::RasterClass || pd->classId() == QPixmapData::BlitterClass) d->device = pd->buffer(); } else { d->device = device; @@ -3381,6 +3383,33 @@ void QRasterPaintEngine::drawTextItem(const QPointF &p, const QTextItem &textIte } #endif // Q_WS_QWS +#ifdef Q_WS_QPA + if (s->matrix.type() < QTransform::TxScale) { + + QVarLengthArray<QFixedPoint> positions; + QVarLengthArray<glyph_t> glyphs; + QTransform matrix = state()->transform(); + + qreal _x = qFloor(p.x()); + qreal _y = qFloor(p.y()); + matrix.translate(_x, _y); + + fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions); + if (glyphs.size() == 0) + return; + + for(int i = 0; i < glyphs.size(); i++) { + QImage img = fontEngine->alphaMapForGlyph(glyphs[i]); + glyph_metrics_t metrics = fontEngine->boundingBox(glyphs[i]); + alphaPenBlt(img.bits(), img.bytesPerLine(), img.depth(), + qRound(positions[i].x + metrics.x), + qRound(positions[i].y + metrics.y), + img.width(), img.height()); + } + return; + } +#endif //Q_WS_QPA + #if (defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) #if defined(Q_WS_QWS) && !defined(QT_NO_QWS_QPF2) diff --git a/src/gui/painting/qpaintengine_raster_p.h b/src/gui/painting/qpaintengine_raster_p.h index 1016f8d..fd635e6 100644 --- a/src/gui/painting/qpaintengine_raster_p.h +++ b/src/gui/painting/qpaintengine_raster_p.h @@ -254,6 +254,8 @@ protected: QRasterPaintEngine(QRasterPaintEnginePrivate &d, QPaintDevice *); private: friend struct QSpanData; + friend class QBlitterPaintEngine; + friend class QBlitterPaintEnginePrivate; void init(); void fillRect(const QRectF &rect, QSpanData *data); diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp index ba5d164..45af03a 100644 --- a/src/gui/painting/qpdf.cpp +++ b/src/gui/painting/qpdf.cpp @@ -915,7 +915,6 @@ const char *QPdf::paperSizeToString(QPrinter::PaperSize paperSize) return psToStr[paperSize]; } - // -------------------------- base engine, shared code between PS and PDF ----------------------- QPdfBaseEngine::QPdfBaseEngine(QPdfBaseEnginePrivate &dd, PaintEngineFeatures f) diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp index 3412f9b..c5d5dc9 100644 --- a/src/gui/painting/qregion.cpp +++ b/src/gui/painting/qregion.cpp @@ -1620,7 +1620,7 @@ QT_END_INCLUDE_NAMESPACE QT_BEGIN_INCLUDE_NAMESPACE # include "qregion_win.cpp" QT_END_INCLUDE_NAMESPACE -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_QPA) static QRegionPrivate qrp; QRegion::QRegionData QRegion::shared_empty = {Q_BASIC_ATOMIC_INITIALIZER(1), &qrp}; #endif @@ -4231,7 +4231,7 @@ QRect QRegion::boundingRect() const Returns true if \a rect is guaranteed to be fully contained in \a region. A false return value does not guarantee the opposite. */ -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) Q_GUI_EXPORT #endif bool qt_region_strictContains(const QRegion ®ion, const QRect &rect) diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h index 378f753..91d82e0 100644 --- a/src/gui/painting/qregion.h +++ b/src/gui/painting/qregion.h @@ -59,7 +59,7 @@ QT_MODULE(Gui) template <class T> class QVector; class QVariant; -#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) struct QRegionPrivate; #endif @@ -166,7 +166,7 @@ public: #endif HIMutableShapeRef toHIMutableShape() const; static QRegion fromHIShapeRef(HIShapeRef shape); -#elif defined(Q_WS_QWS) +#elif defined(Q_WS_QWS) || defined(Q_WS_QPA) inline void *handle() const { return d->qt_rgn; } #endif #endif @@ -206,7 +206,7 @@ private: #elif defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA) mutable RgnHandle unused; // Here for binary compatibility reasons. ### Qt 5 remove. #endif -#if defined(Q_WS_QWS) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) QRegionPrivate *qt_rgn; #endif }; diff --git a/src/gui/painting/qwindowsurface.cpp b/src/gui/painting/qwindowsurface.cpp index 8cf3977..e9eb9c5 100644 --- a/src/gui/painting/qwindowsurface.cpp +++ b/src/gui/painting/qwindowsurface.cpp @@ -58,7 +58,11 @@ public: } QWidget *window; +#if !defined(Q_WS_QPA) QRect geometry; +#else + QSize size; +#endif //Q_WS_QPA QRegion staticContents; QList<QImage*> bufferImages; uint staticContentsSupport : 1; @@ -153,6 +157,7 @@ void QWindowSurface::endPaint(const QRegion &) d_ptr->bufferImages.clear(); } +#if !defined(Q_WS_QPA) /*! Sets the currently allocated area to be the given \a rect. @@ -173,6 +178,17 @@ QRect QWindowSurface::geometry() const { return d_ptr->geometry; } +#else +void QWindowSurface::resize(const QSize &size) +{ + d_ptr->size = size; +} + +QSize QWindowSurface::size() const +{ + return d_ptr->size; +} +#endif //Q_WS_QPA /*! Scrolls the given \a area \a dx pixels to the right and \a dy @@ -329,7 +345,13 @@ void QWindowSurface::setPartialUpdateSupport(bool enable) d_ptr->partialUpdateSupport = enable; } -void qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset) +#ifdef Q_WS_QPA +#define Q_EXPORT_SCROLLRECT Q_GUI_EXPORT +#else +#define Q_EXPORT_SCROLLRECT +#endif + +void Q_EXPORT_SCROLLRECT qt_scrollRectInImage(QImage &img, const QRect &rect, const QPoint &offset) { // make sure we don't detach uchar *mem = const_cast<uchar*>(const_cast<const QImage &>(img).bits()); diff --git a/src/gui/painting/qwindowsurface_p.h b/src/gui/painting/qwindowsurface_p.h index ab84527..82100c3 100644 --- a/src/gui/painting/qwindowsurface_p.h +++ b/src/gui/painting/qwindowsurface_p.h @@ -63,6 +63,7 @@ class QRect; class QPoint; class QImage; class QWindowSurfacePrivate; +class QPlatformWindow; class Q_GUI_EXPORT QWindowSurface { @@ -79,8 +80,14 @@ public: // can be larger than just the offset from the top-level widget as there may also be window // decorations which are painted into the window surface. virtual void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) = 0; +#if !defined(Q_WS_QPA) virtual void setGeometry(const QRect &rect); QRect geometry() const; +#else + virtual void resize(const QSize &size); + QSize size() const; + inline QRect geometry() const { return QRect(QPoint(), size()); } //### cleanup before Qt 5 +#endif virtual bool scroll(const QRegion &area, int dx, int dy); diff --git a/src/gui/styles/styles.pri b/src/gui/styles/styles.pri index b22a908..b6eeec9 100644 --- a/src/gui/styles/styles.pri +++ b/src/gui/styles/styles.pri @@ -35,7 +35,7 @@ contains( styles, all ) { styles = mac windows windowsxp windowsvista } -x11|embedded|!macx-*:styles -= mac +x11|embedded|qpa|!macx-*:styles -= mac x11{ QMAKE_CXXFLAGS += $$QT_CFLAGS_QGTKSTYLE diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 3fe98e1..bdba10d 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -75,6 +75,10 @@ #ifdef Q_OS_SYMBIAN #include <private/qt_s60_p.h> #endif +#ifdef Q_WS_QPA +#include <QtGui/qplatformscreen_qpa.h> +#include <QtGui/private/qapplication_p.h> +#endif #include <QMutexLocker> @@ -172,6 +176,17 @@ Q_GUI_EXPORT int qt_defaultDpiX() if (!subScreens.isEmpty()) screen = subScreens.at(0); dpi = qRound(screen->width() / (screen->physicalWidth() / qreal(25.4))); +#elif defined(Q_WS_QPA) + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + if (pi) { + QPlatformScreen *screen = QApplicationPrivate::platformIntegration()->screens().at(0); + const QSize screenSize = screen->geometry().size(); + const QSize physicalSize = screen->physicalSize(); + dpi = qRound(screenSize.width() / (physicalSize.width() / qreal(25.4))); + } else { + //PI has not been initialised, or it is being initialised. Give a default dpi + dpi = 100; + } #elif defined(Q_OS_SYMBIAN) dpi = S60->defaultDpiX; #endif // Q_WS_X11 @@ -200,6 +215,17 @@ Q_GUI_EXPORT int qt_defaultDpiY() if (!subScreens.isEmpty()) screen = subScreens.at(0); dpi = qRound(screen->height() / (screen->physicalHeight() / qreal(25.4))); +#elif defined(Q_WS_QPA) + QPlatformIntegration *pi = QApplicationPrivate::platformIntegration(); + if (pi) { + QPlatformScreen *screen = QApplicationPrivate::platformIntegration()->screens().at(0); + const QSize screenSize = screen->geometry().size(); + const QSize physicalSize = screen->physicalSize(); + dpi = qRound(screenSize.height() / (physicalSize.height() / qreal(25.4))); + } else { + //PI has not been initialised, or it is being initialised. Give a default dpi + dpi = 100; + } #elif defined(Q_OS_SYMBIAN) dpi = S60->defaultDpiY; #endif // Q_WS_X11 diff --git a/src/gui/text/qfont_qpa.cpp b/src/gui/text/qfont_qpa.cpp new file mode 100644 index 0000000..5fed18b --- /dev/null +++ b/src/gui/text/qfont_qpa.cpp @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 <QtGui/private/qapplication_p.h> +#include <QtGui/QPlatformFontDatabase> + +QT_BEGIN_NAMESPACE + +void QFont::initialize() +{ + QApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase(); +} + +void QFont::cleanup() +{ + QFontCache::cleanup(); +} + + +/***************************************************************************** + QFont member functions + *****************************************************************************/ + +Qt::HANDLE QFont::handle() const +{ + return 0; +} + +QString QFont::rawName() const +{ + return QLatin1String("unknown"); +} + +void QFont::setRawName(const QString &) +{ +} + +QString QFont::defaultFamily() const +{ + QString familyName; + switch(d->request.styleHint) { + case QFont::Times: + familyName = QString::fromLatin1("times"); + case QFont::Courier: + case QFont::Monospace: + familyName = QString::fromLatin1("monospace"); + case QFont::Decorative: + familyName = QString::fromLatin1("old english"); + case QFont::Helvetica: + case QFont::System: + default: + familyName = QString::fromLatin1("helvetica"); + } + + QStringList list = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(familyName,QFont::StyleNormal,QUnicodeTables::Common); + if (list.size()) { + familyName = list.at(0); + } + return familyName; +} + +QString QFont::lastResortFamily() const +{ + return QString::fromLatin1("helvetica"); +} + +QString QFont::lastResortFont() const +{ + qFatal("QFont::lastResortFont: Cannot find any reasonable font"); + // Shut compiler up + return QString(); +} + + +QT_END_NAMESPACE + diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 9ed09c2..bae2a20 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -50,13 +50,19 @@ #include "private/qunicodetables_p.h" #include "qfontengine_p.h" +#ifdef Q_WS_QPA +#include <QtGui/private/qapplication_p.h> +#include <QtGui/qplatformfontdatabase_qpa.h> +#include "qabstractfileengine.h" +#endif + #ifdef Q_WS_X11 #include <locale.h> #endif #include <stdlib.h> #include <limits.h> -#if (defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) +#if (defined(Q_WS_QWS)|| defined(Q_OS_SYMBIAN)) && !defined(QT_NO_FREETYPE) # include <ft2build.h> # include FT_TRUETYPE_TABLES_H #endif @@ -139,7 +145,7 @@ struct QtFontEncoding uchar pitch : 8; }; -struct QtFontSize +struct QtFontSize { #ifdef Q_WS_X11 QtFontEncoding *encodings; @@ -147,10 +153,14 @@ struct QtFontSize uint yres = 0, uint avgwidth = 0, bool add = false); unsigned short count : 16; #endif // Q_WS_X11 + #if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) QByteArray fileName; int fileIndex; -#endif // defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#endif // defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QPA) + void *handle; +#endif unsigned short pixelSize : 16; }; @@ -226,7 +236,7 @@ struct QtFontStyle delete [] weightName; delete [] setwidthName; #endif -#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) while (count) { // bitfield count-- in while condition does not work correctly in mwccsym2 count--; @@ -236,6 +246,12 @@ struct QtFontStyle #if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) pixelSizes[count].fileName.~QByteArray(); #endif +#if defined (Q_WS_QPA) + QPlatformIntegration *integration = QApplicationPrivate::platformIntegration(); + if (integration) { //on shut down there will be some that we don't release. + integration->fontDatabase()->releaseHandle(pixelSizes[count].handle); + } +#endif } #endif free(pixelSizes); @@ -251,7 +267,7 @@ struct QtFontStyle const char *weightName; const char *setwidthName; #endif // Q_WS_X11 -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) bool antialiased; #endif @@ -301,6 +317,9 @@ QtFontSize *QtFontStyle::pixelSize(unsigned short size, bool add) new (&pixelSizes[count].fileName) QByteArray; pixelSizes[count].fileIndex = 0; #endif +#if defined(Q_WS_QPA) + pixelSizes[count].handle = 0; +#endif return pixelSizes + (count++); } @@ -357,7 +376,7 @@ QtFontStyle *QtFontFoundry::style(const QtFontStyle::Key &key, bool create) } -struct QtFontFamily +struct QtFontFamily { enum WritingSystemStatus { Unknown = 0, @@ -383,9 +402,12 @@ struct QtFontFamily fixedPitchComputed(false), #endif name(n), count(0), foundries(0) -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) , bogusWritingSystems(false) #endif +#if defined(Q_WS_QPA) + , askedForFallback(false) +#endif { memset(writingSystems, 0, sizeof(writingSystems)); } @@ -423,10 +445,13 @@ struct QtFontFamily int count; QtFontFoundry **foundries; -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) bool bogusWritingSystems; QStringList fallbackFamilies; #endif +#if defined (Q_WS_QPA) + bool askedForFallback; +#endif unsigned char writingSystems[QFontDatabase::WritingSystemsCount]; QtFontFoundry *foundry(const QString &f, bool = false); @@ -471,6 +496,7 @@ QtFontFoundry *QtFontFamily::foundry(const QString &f, bool create) // ### copied to tools/makeqpf/qpf2.cpp #if (defined(Q_WS_QWS) && !defined(QT_NO_FREETYPE)) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || (defined(Q_WS_MAC) && !defined(QT_MAC_USE_COCOA)) + // see the Unicode subset bitfields in the MSDN docs static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = { // Any, @@ -663,7 +689,7 @@ public: bool loadFromCache(const QString &fontPath); void addQPF2File(const QByteArray &file); #endif // Q_WS_QWS -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) +#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) void addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize, const QByteArray &file, int fileIndex, bool antialiased, @@ -674,10 +700,12 @@ public: #endif #if defined(Q_WS_QWS) QDataStream *stream; - QStringList fallbackFamilies; #elif defined(Q_OS_SYMBIAN) && defined(QT_NO_FREETYPE) const QSymbianFontDatabaseExtras *symbianExtras; #endif +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) + QStringList fallbackFamilies; +#endif }; void QFontDatabasePrivate::invalidate() @@ -726,7 +754,7 @@ QtFontFamily *QFontDatabasePrivate::family(const QString &f, bool create) return families[pos]; } -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) +#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) && !defined(QT_NO_FREETYPE) void QFontDatabasePrivate::addFont(const QString &familyname, const char *foundryname, int weight, bool italic, int pixelSize, const QByteArray &file, int fileIndex, bool antialiased, const QList<QFontDatabase::WritingSystem> &writingSystems) @@ -959,7 +987,7 @@ static void match(int script, const QFontDef &request, const QString &family_name, const QString &foundry_name, int force_encoding_id, QtFontDesc *desc, const QList<int> &blacklistedFamilies = QList<int>(), bool forceXLFD=false); -#if defined(Q_WS_X11) || defined(Q_WS_QWS) +#if defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDef *fontDef) { fontDef->family = desc.family->name; @@ -988,7 +1016,7 @@ static void initFontDef(const QtFontDesc &desc, const QFontDef &request, QFontDe #endif #endif -#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_X11) || defined(Q_WS_WIN) || defined(Q_OS_SYMBIAN) || defined(Q_WS_QPA) static void getEngineData(const QFontPrivate *d, const QFontCache::Key &key) { // look for the requested font in the engine data cache @@ -1049,6 +1077,8 @@ QT_BEGIN_INCLUDE_NAMESPACE # include "qfontdatabase_win.cpp" #elif defined(Q_WS_QWS) # include "qfontdatabase_qws.cpp" +#elif defined(Q_WS_QPA) +# include "qfontdatabase_qpa.cpp" #elif defined(Q_OS_SYMBIAN) # include "qfontdatabase_s60.cpp" #endif @@ -1334,6 +1364,7 @@ static void match(int script, const QFontDef &request, styleKey.stretch = request.stretch; char pitch = request.ignorePitch ? '*' : request.fixedPitch ? 'm' : 'p'; + FM_DEBUG("QFontDatabase::match\n" " request:\n" " family: %s [%s], script: %d\n" @@ -2481,7 +2512,7 @@ void QFontDatabase::createDatabase() { initializeDb(); } // used from qfontengine_ft.cpp -QByteArray qt_fontdata_from_index(int index) +Q_GUI_EXPORT QByteArray qt_fontdata_from_index(int index) { QMutexLocker locker(fontDatabaseMutex()); return privateDb()->applicationFonts.value(index).data; diff --git a/src/gui/text/qfontdatabase.h b/src/gui/text/qfontdatabase.h index 719242c..f31c19c 100644 --- a/src/gui/text/qfontdatabase.h +++ b/src/gui/text/qfontdatabase.h @@ -152,7 +152,7 @@ public: private: static void createDatabase(); static void parseFontName(const QString &name, QString &foundry, QString &family); -#if defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) static QFontEngine *findFont(int script, const QFontPrivate *fp, const QFontDef &request); #endif static void load(const QFontPrivate *d, int script); @@ -167,6 +167,7 @@ private: friend class QFontEngineMultiXLFD; friend class QFontEngineMultiQWS; friend class QFontEngineMultiS60; + friend class QFontEngineMultiQPA; QFontDatabasePrivate *d; }; diff --git a/src/gui/text/qfontdatabase_qpa.cpp b/src/gui/text/qfontdatabase_qpa.cpp new file mode 100644 index 0000000..19ce1be --- /dev/null +++ b/src/gui/text/qfontdatabase_qpa.cpp @@ -0,0 +1,393 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qlibraryinfo.h" +#include <QtCore/qsettings.h> + +#include "qfontengine_qpa_p.h" +#include "qplatformdefs.h" + +#include <QtGui/private/qapplication_p.h> +#include <QtGui/qplatformfontdatabase_qpa.h> + +#include <QtCore/qmath.h> + +QT_BEGIN_NAMESPACE + +Q_GUI_EXPORT void qt_registerFont(const QString &familyName, const QString &foundryname, int weight, + QFont::Style style, int stretch, bool antialiased, bool scalable, int pixelSize, + const QSupportedWritingSystems &writingSystems, void *handle) +{ + QFontDatabasePrivate *d = privateDb(); + // qDebug() << "Adding font" << familyname << weight << italic << pixelSize << file << fileIndex << antialiased; + QtFontStyle::Key styleKey; + styleKey.style = style; + styleKey.weight = weight; + styleKey.stretch = stretch; + QtFontFamily *f = d->family(familyName, true); + + for (int i = 0; i < QFontDatabase::WritingSystemsCount; ++i) { + if (writingSystems.supported(QFontDatabase::WritingSystem(i))) { + f->writingSystems[i] = QtFontFamily::Supported; + } else { + f->writingSystems[i] = QtFontFamily::Unsupported; + } + } + + QtFontFoundry *foundry = f->foundry(foundryname, true); + QtFontStyle *fontStyle = foundry->style(styleKey, true); + fontStyle->smoothScalable = scalable; + fontStyle->antialiased = antialiased; + QtFontSize *size = fontStyle->pixelSize(pixelSize?pixelSize:SMOOTH_SCALABLE, true); + size->handle = handle; +} + +static QStringList fallbackFamilies(const QString &family, const QFont::Style &style, const QUnicodeTables::Script &script) +{ + QStringList retList = QApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,script); + QFontDatabasePrivate *db = privateDb(); + + QStringList::iterator i; + for (i = retList.begin(); i != retList.end(); ++i) { + bool contains = false; + for (int j = 0; j < db->count; j++) { + QtFontFamily *qtFamily = db->families[j]; + if (!(i->compare(qtFamily->name,Qt::CaseInsensitive))) { + contains = true; + break; + } + } + if (!contains) { + i = retList.erase(i); + i--; + } + } + return retList; +} + +static void initializeDb() +{ + static int initialized = false; + + if (!initialized) { + //init by asking for the platformfontdb for the first time :) + QApplicationPrivate::platformIntegration()->fontDatabase()->populateFontDatabase(); + initialized = true; + } +} + +#ifndef QT_NO_SETTINGS +// called from qapplication_qws.cpp +void qt_applyFontDatabaseSettings(const QSettings &settings) +{ + initializeDb(); + QFontDatabasePrivate *db = privateDb(); + for (int i = 0; i < db->count; ++i) { + QtFontFamily *family = db->families[i]; + if (settings.contains(family->name)) + family->fallbackFamilies = settings.value(family->name).toStringList(); + } + + if (settings.contains(QLatin1String("Global Fallbacks"))) + db->fallbackFamilies = settings.value(QLatin1String("Global Fallbacks")).toStringList(); +} +#endif // QT_NO_SETTINGS + +static inline void load(const QString & = QString(), int = -1) +{ + initializeDb(); +} + +static +QFontEngine *loadSingleEngine(int script, + const QFontDef &request, + QtFontFoundry *foundry, + QtFontStyle *style, QtFontSize *size) +{ + Q_UNUSED(foundry); + + Q_ASSERT(size); + int pixelSize = size->pixelSize; + if (!pixelSize || (style->smoothScalable && pixelSize == SMOOTH_SCALABLE)) + pixelSize = request.pixelSize; + + QFontDef def = request; + def.pixelSize = pixelSize; + + QFontCache::Key key(def,script); + QFontEngine *engine = QFontCache::instance()->findEngine(key); + if (!engine) { + QPlatformFontDatabase *pfdb = QApplicationPrivate::platformIntegration()->fontDatabase(); + if (size->handle) { + engine = pfdb->fontEngine(def,QUnicodeTables::Script(script),size->handle); + if (engine) { + QFontCache::Key key(def,script); + QFontCache::instance()->instance()->insertEngine(key,engine); + } + } + + } + return engine; +} + +static +QFontEngine *loadEngine(int script, const QFontDef &request, + QtFontFamily *family, QtFontFoundry *foundry, + QtFontStyle *style, QtFontSize *size) +{ + + QFontEngine *engine = loadSingleEngine(script, request, foundry, style, size); + //make sure that the db has all fallback families + if (engine + && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol ) { + + if (family && !family->askedForFallback) { + family->fallbackFamilies = fallbackFamilies(family->name,QFont::Style(style->key.style),QUnicodeTables::Script(script)); + + family->askedForFallback = true; + } + + QStringList fallbacks = privateDb()->fallbackFamilies; + if (family && !family->fallbackFamilies.isEmpty()) + fallbacks = family->fallbackFamilies; + + engine = new QFontEngineMultiQPA(engine, script, fallbacks); + } + + return engine; +} + +static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt) +{ + QFontDatabasePrivate *db = privateDb(); + + fnt->families = QApplicationPrivate::platformIntegration()->fontDatabase()->addApplicationFont(fnt->data,fnt->fileName); + + db->reregisterAppFonts = true; +} + +bool QFontDatabase::removeApplicationFont(int handle) +{ + QMutexLocker locker(fontDatabaseMutex()); + + QFontDatabasePrivate *db = privateDb(); + if (handle < 0 || handle >= db->applicationFonts.count()) + return false; + + db->applicationFonts[handle] = QFontDatabasePrivate::ApplicationFont(); + + db->reregisterAppFonts = true; + db->invalidate(); + return true; +} + +bool QFontDatabase::removeAllApplicationFonts() +{ + QMutexLocker locker(fontDatabaseMutex()); + + QFontDatabasePrivate *db = privateDb(); + if (db->applicationFonts.isEmpty()) + return false; + + db->applicationFonts.clear(); + db->invalidate(); + return true; +} + +bool QFontDatabase::supportsThreadedFontRendering() +{ + return true; +} + +/*! + \internal +*/ +QFontEngine * +QFontDatabase::findFont(int script, const QFontPrivate *fp, + const QFontDef &request) +{ + QMutexLocker locker(fontDatabaseMutex()); + + const int force_encoding_id = -1; + + if (!privateDb()->count) + initializeDb(); + + QFontEngine *engine; + QFontCache::Key key(request, script); + engine = QFontCache::instance()->findEngine(key); + if (engine) { + qDebug() << "Cache hit level 1"; + return engine; + } + + QString family_name, foundry_name; + + parseFontName(request.family, foundry_name, family_name); + + if (qt_enable_test_font && request.family == QLatin1String("__Qt__Box__Engine__")) { + engine =new QTestFontEngine(request.pixelSize); + engine->fontDef = request; + } + + QtFontDesc desc; + match(script, request, family_name, foundry_name, force_encoding_id, &desc); + if (desc.family != 0 && desc.foundry != 0 && desc.style != 0) { + engine = loadEngine(script, request, desc.family, desc.foundry, desc.style, desc.size); + } else { + FM_DEBUG(" NO MATCH FOUND\n"); + } + + if (engine) { + initFontDef(desc, request, &engine->fontDef); + + if (fp) { + QFontDef def = request; + if (def.family.isEmpty()) { + def.family = fp->request.family; + def.family = def.family.left(def.family.indexOf(QLatin1Char(','))); + } + } + } + + if (!engine) { + if (!request.family.isEmpty()) { + QStringList fallbacks = fallbackFamilies(request.family,QFont::Style(request.style),QUnicodeTables::Script(script)); + for (int i = 0; i < fallbacks.size(); i++) { + QFontDef def = request; + def.family = fallbacks.at(i); + QFontCache::Key key(def,script); + engine = QFontCache::instance()->findEngine(key); + if (!engine) { + QtFontDesc desc; + match(script, def, def.family, QLatin1String(""), 0, &desc); + if (desc.family == 0 && desc.foundry == 0 && desc.style == 0) { + continue; + } + engine = loadEngine(script, def, desc.family, desc.foundry, desc.style, desc.size); + if (engine) { + initFontDef(desc, def, &engine->fontDef); + break; + } + } + } + } + + if (!engine) + engine = new QFontEngineBox(request.pixelSize); + + FM_DEBUG("returning box engine"); + } + + if (fp && fp->dpi > 0) { + engine->fontDef.pointSize = qreal(double((engine->fontDef.pixelSize * 72) / fp->dpi)); + } else { + engine->fontDef.pointSize = request.pointSize; + } + + return engine; +} + +void QFontDatabase::load(const QFontPrivate *d, int script) +{ + QFontDef req = d->request; + + if (req.pixelSize == -1) { + req.pixelSize = floor(((req.pointSize * d->dpi) / 72) * 100 + 0.5) / 100; + req.pixelSize = qRound(req.pixelSize); + } + if (req.pointSize < 0) + req.pointSize = req.pixelSize*72.0/d->dpi; + if (req.weight == 0) + req.weight = QFont::Normal; + if (req.stretch == 0) + req.stretch = 100; + + QFontCache::Key key(req, script); + + if (!d->engineData) + getEngineData(d, key); + + // the cached engineData could have already loaded the engine we want + if (d->engineData->engines[script]) + return; + + QFontEngine *fe = QFontCache::instance()->findEngine(key); + + // list of families to try + QStringList family_list; + + if (!req.family.isEmpty()) { + family_list = familyList(req); + + // add the default family + QString defaultFamily = QApplication::font().family(); + if (! family_list.contains(defaultFamily)) + family_list << defaultFamily; + + } + + // null family means find the first font matching the specified script + family_list << QString(); + + QStringList::ConstIterator it = family_list.constBegin(), end = family_list.constEnd(); + for (; !fe && it != end; ++it) { + req.family = *it; + + fe = QFontDatabase::findFont(script, d, req); + if (fe && (fe->type()==QFontEngine::Box) && !req.family.isEmpty()) + fe = 0; + } + + if (fe->symbol || (d->request.styleStrategy & QFont::NoFontMerging)) { + for (int i = 0; i < QUnicodeTables::ScriptCount; ++i) { + if (!d->engineData->engines[i]) { + d->engineData->engines[i] = fe; + fe->ref.ref(); + } + } + } else { + d->engineData->engines[script] = fe; + fe->ref.ref(); + } +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qfontdatabase_qws.cpp b/src/gui/text/qfontdatabase_qws.cpp index a3d8d65..09fb07c 100644 --- a/src/gui/text/qfontdatabase_qws.cpp +++ b/src/gui/text/qfontdatabase_qws.cpp @@ -40,8 +40,10 @@ ****************************************************************************/ #include "qdir.h" +#if defined(Q_WS_QWS) #include "qscreen_qws.h" //so we can check for rotation #include "qwindowsystem_qws.h" +#endif #include "qlibraryinfo.h" #include "qabstractfileengine.h" #include <QtCore/qsettings.h> @@ -153,7 +155,11 @@ extern QString qws_fontCacheDir(); #ifndef QT_FONTS_ARE_RESOURCES bool QFontDatabasePrivate::loadFromCache(const QString &fontPath) { +#ifdef Q_WS_QWS const bool weAreTheServer = QWSServer::instance(); +#else + const bool weAreTheServer = true; // assume single-process +#endif QString fontDirFile = fontPath + QLatin1String("/fontdir"); @@ -382,12 +388,14 @@ static void initializeDb() } #endif +#ifndef QT_NO_QWS_QPF2 QDir dir(fontpath, QLatin1String("*.qpf2")); for (int i = 0; i < int(dir.count()); ++i) { const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i])); //qDebug() << "looking at" << file; db->addQPF2File(file); } +#endif #endif //QT_FONTS_ARE_RESOURCES @@ -688,6 +696,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, { QScopedPointer<QFontEngine> engine(loadSingleEngine(script, fp, request, family, foundry, style, size)); +#ifndef QT_NO_QWS_QPF if (!engine.isNull() && script == QUnicodeTables::Common && !(request.styleStrategy & QFont::NoFontMerging) && !engine->symbol) { @@ -701,6 +710,7 @@ QFontEngine *loadEngine(int script, const QFontPrivate *fp, engine.take(); engine.reset(fe); } +#endif return engine.take(); } diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index be346e9..f73b816 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -494,7 +494,7 @@ static void collectSingleContour(qreal x0, qreal y0, uint *grid, int x, int y, i path->closeSubpath(); } -void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path) +Q_GUI_EXPORT void qt_addBitmapToPath(qreal x0, qreal y0, const uchar *image_data, int bpl, int w, int h, QPainterPath *path) { uint *grid = new uint[(w+1)*(h+1)]; // set up edges @@ -753,7 +753,7 @@ QFontEngineGlyphCache *QFontEngine::glyphCache(void *key, QFontEngineGlyphCache: return 0; } -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) static inline QFixed kerning(int left, int right, const QFontEngine::KernPair *pairs, int numPairs) { uint left_right = (left << 16) + right; @@ -1197,7 +1197,7 @@ glyph_metrics_t QFontEngineBox::boundingBox(const QGlyphLayout &glyphs) return overall; } -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) void QFontEngineBox::draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &ti) { if (!ti.glyphs.numGlyphs) diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 6991143..81e2594 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -723,7 +723,7 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format) metrics = face->size->metrics; -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) /* TrueType fonts with embedded bitmaps may have a bitmap font specific ascent/descent in the EBLC table. There is no direct public API @@ -755,6 +755,11 @@ bool QFontEngineFT::init(FaceId faceId, bool antialias, GlyphFormat format) return true; } +void QFontEngineFT::setDefaultHintStyle(HintStyle style) +{ + default_hint_style = style; +} + QFontEngineFT::Glyph *QFontEngineFT::loadGlyphMetrics(QGlyphSet *set, uint glyph, GlyphFormat format) const { Glyph *g = set->getGlyph(glyph); diff --git a/src/gui/text/qfontengine_ft_p.h b/src/gui/text/qfontengine_ft_p.h index 1a1cadb..f0f7153 100644 --- a/src/gui/text/qfontengine_ft_p.h +++ b/src/gui/text/qfontengine_ft_p.h @@ -277,6 +277,14 @@ private: virtual HB_Error getPointInOutline(HB_Glyph glyph, int flags, hb_uint32 point, HB_Fixed *xpos, HB_Fixed *ypos, hb_uint32 *nPoints); + enum HintStyle { + HintNone, + HintLight, + HintMedium, + HintFull + }; + + void setDefaultHintStyle(HintStyle style); protected: void freeGlyphSets(); @@ -288,12 +296,6 @@ protected: QFreetypeFace *freetype; int default_load_flags; - enum HintStyle { - HintNone, - HintLight, - HintMedium, - HintFull - }; HintStyle default_hint_style; diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index cd3b488..6d6daaa 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -177,7 +177,7 @@ public: virtual void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const {} virtual void doKerning(QGlyphLayout *, QTextEngine::ShaperFlags) const; -#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN) +#if !defined(Q_WS_X11) && !defined(Q_WS_WIN) && !defined(Q_WS_MAC) && !defined(Q_OS_SYMBIAN) && !defined(Q_WS_QPA) virtual void draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &si) = 0; #endif virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, @@ -255,7 +255,7 @@ public: bool symbol; mutable HB_FontRec hbFont; mutable HB_Face hbFace; -#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_WIN) || defined(Q_WS_X11) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) struct KernPair { uint left_right; QFixed adjust; diff --git a/src/gui/text/qfontengine_qpa.cpp b/src/gui/text/qfontengine_qpa.cpp new file mode 100644 index 0000000..cccbc92 --- /dev/null +++ b/src/gui/text/qfontengine_qpa.cpp @@ -0,0 +1,691 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qfontengine_qpa_p.h" + +#include <QtCore/QFile> +#include <QtCore/QFileInfo> +#include <QtCore/QDir> +#include <QtCore/QBuffer> + +#include <QtGui/private/qapplication_p.h> +#include <QtGui/QPlatformFontDatabase> +#include <QtGui/private/qpaintengine_raster_p.h> + +QT_BEGIN_NAMESPACE + +//#define DEBUG_HEADER +//#define DEBUG_FONTENGINE + +static QFontEngineQPA::TagType tagTypes[QFontEngineQPA::NumTags] = { + QFontEngineQPA::StringType, // FontName + QFontEngineQPA::StringType, // FileName + QFontEngineQPA::UInt32Type, // FileIndex + QFontEngineQPA::UInt32Type, // FontRevision + QFontEngineQPA::StringType, // FreeText + QFontEngineQPA::FixedType, // Ascent + QFontEngineQPA::FixedType, // Descent + QFontEngineQPA::FixedType, // Leading + QFontEngineQPA::FixedType, // XHeight + QFontEngineQPA::FixedType, // AverageCharWidth + QFontEngineQPA::FixedType, // MaxCharWidth + QFontEngineQPA::FixedType, // LineThickness + QFontEngineQPA::FixedType, // MinLeftBearing + QFontEngineQPA::FixedType, // MinRightBearing + QFontEngineQPA::FixedType, // UnderlinePosition + QFontEngineQPA::UInt8Type, // GlyphFormat + QFontEngineQPA::UInt8Type, // PixelSize + QFontEngineQPA::UInt8Type, // Weight + QFontEngineQPA::UInt8Type, // Style + QFontEngineQPA::StringType, // EndOfHeader + QFontEngineQPA::BitFieldType// WritingSystems +}; + + +#if defined(DEBUG_HEADER) +# define DEBUG_VERIFY qDebug +#else +# define DEBUG_VERIFY if (0) qDebug +#endif + +#define READ_VERIFY(type, variable) \ + if (tagPtr + sizeof(type) > endPtr) { \ + DEBUG_VERIFY() << "read verify failed in line" << __LINE__; \ + return 0; \ + } \ + variable = qFromBigEndian<type>(tagPtr); \ + DEBUG_VERIFY() << "read value" << variable << "of type " #type; \ + tagPtr += sizeof(type) + +template <typename T> +T readValue(const uchar *&data) +{ + T value = qFromBigEndian<T>(data); + data += sizeof(T); + return value; +} + +#define VERIFY(condition) \ + if (!(condition)) { \ + DEBUG_VERIFY() << "condition " #condition " failed in line" << __LINE__; \ + return 0; \ + } + +#define VERIFY_TAG(condition) \ + if (!(condition)) { \ + DEBUG_VERIFY() << "verifying tag condition " #condition " failed in line" << __LINE__ << "with tag" << tag; \ + return 0; \ + } + +static inline const uchar *verifyTag(const uchar *tagPtr, const uchar *endPtr) +{ + quint16 tag, length; + READ_VERIFY(quint16, tag); + READ_VERIFY(quint16, length); + if (tag == QFontEngineQPA::Tag_EndOfHeader) + return endPtr; + if (tag < QFontEngineQPA::NumTags) { + switch (tagTypes[tag]) { + case QFontEngineQPA::BitFieldType: + case QFontEngineQPA::StringType: + // can't do anything... + break; + case QFontEngineQPA::UInt32Type: + VERIFY_TAG(length == sizeof(quint32)); + break; + case QFontEngineQPA::FixedType: + VERIFY_TAG(length == sizeof(quint32)); + break; + case QFontEngineQPA::UInt8Type: + VERIFY_TAG(length == sizeof(quint8)); + break; + } +#if defined(DEBUG_HEADER) + if (length == 1) + qDebug() << "tag data" << hex << *tagPtr; + else if (length == 4) + qDebug() << "tag data" << hex << tagPtr[0] << tagPtr[1] << tagPtr[2] << tagPtr[3]; +#endif + } + return tagPtr + length; +} + +const QFontEngineQPA::Glyph *QFontEngineQPA::findGlyph(glyph_t g) const +{ + if (!g || g >= glyphMapEntries) + return 0; + const quint32 *gmapPtr = reinterpret_cast<const quint32 *>(fontData + glyphMapOffset); + quint32 glyphPos = qFromBigEndian<quint32>(gmapPtr[g]); + if (glyphPos > glyphDataSize) { + if (glyphPos == 0xffffffff) + return 0; +#if defined(DEBUG_FONTENGINE) + qDebug() << "glyph" << g << "outside of glyphData, remapping font file"; +#endif + if (glyphPos > glyphDataSize) + return 0; + } + return reinterpret_cast<const Glyph *>(fontData + glyphDataOffset + glyphPos); +} + +bool QFontEngineQPA::verifyHeader(const uchar *data, int size) +{ + VERIFY(size >= int(sizeof(Header))); + const Header *header = reinterpret_cast<const Header *>(data); + if (header->magic[0] != 'Q' + || header->magic[1] != 'P' + || header->magic[2] != 'F' + || header->magic[3] != '2') + return false; + + VERIFY(header->majorVersion <= CurrentMajorVersion); + const quint16 dataSize = qFromBigEndian<quint16>(header->dataSize); + VERIFY(size >= int(sizeof(Header)) + dataSize); + + const uchar *tagPtr = data + sizeof(Header); + const uchar *tagEndPtr = tagPtr + dataSize; + while (tagPtr < tagEndPtr - 3) { + tagPtr = verifyTag(tagPtr, tagEndPtr); + VERIFY(tagPtr); + } + + VERIFY(tagPtr <= tagEndPtr); + return true; +} + +QVariant QFontEngineQPA::extractHeaderField(const uchar *data, HeaderTag requestedTag) +{ + const Header *header = reinterpret_cast<const Header *>(data); + const uchar *tagPtr = data + sizeof(Header); + const uchar *endPtr = tagPtr + qFromBigEndian<quint16>(header->dataSize); + while (tagPtr < endPtr - 3) { + quint16 tag = readValue<quint16>(tagPtr); + quint16 length = readValue<quint16>(tagPtr); + if (tag == requestedTag) { + switch (tagTypes[requestedTag]) { + case StringType: + return QVariant(QString::fromUtf8(reinterpret_cast<const char *>(tagPtr), length)); + case UInt32Type: + return QVariant(readValue<quint32>(tagPtr)); + case UInt8Type: + return QVariant(uint(*tagPtr)); + case FixedType: + return QVariant(QFixed::fromFixed(readValue<quint32>(tagPtr)).toReal()); + case BitFieldType: + return QVariant(QByteArray(reinterpret_cast<const char *>(tagPtr), length)); + } + return QVariant(); + } else if (tag == Tag_EndOfHeader) { + break; + } + tagPtr += length; + } + + return QVariant(); +} + + + +static inline unsigned int getChar(const QChar *str, int &i, const int len) +{ + unsigned int uc = str[i].unicode(); + if (uc >= 0xd800 && uc < 0xdc00 && i < len-1) { + uint low = str[i+1].unicode(); + if (low >= 0xdc00 && low < 0xe000) { + uc = (uc - 0xd800)*0x400 + (low - 0xdc00) + 0x10000; + ++i; + } + } + return uc; +} + +QFontEngineQPA::QFontEngineQPA(const QFontDef &def, const QByteArray &data) + : fontData(reinterpret_cast<const uchar *>(data.constData())), dataSize(data.size()) +{ + fontDef = def; + cache_cost = 100; + externalCMap = 0; + cmapOffset = 0; + cmapSize = 0; + glyphMapOffset = 0; + glyphMapEntries = 0; + glyphDataOffset = 0; + glyphDataSize = 0; + kerning_pairs_loaded = false; + readOnly = true; + +#if defined(DEBUG_FONTENGINE) + qDebug() << "QFontEngineQPA::QFontEngineQPA( fd =" << fd << ", renderingFontEngine =" << renderingFontEngine << ')'; +#endif + + if (!verifyHeader(fontData, dataSize)) { +#if defined(DEBUG_FONTENGINE) + qDebug() << "verifyHeader failed!"; +#endif + return; + } + + const Header *header = reinterpret_cast<const Header *>(fontData); + + readOnly = (header->lock == 0xffffffff); + + const uchar *imgData = fontData + sizeof(Header) + qFromBigEndian<quint16>(header->dataSize); + const uchar *endPtr = fontData + dataSize; + while (imgData <= endPtr - 8) { + quint16 blockTag = readValue<quint16>(imgData); + imgData += 2; // skip padding + quint32 blockSize = readValue<quint32>(imgData); + + if (blockTag == CMapBlock) { + cmapOffset = imgData - fontData; + cmapSize = blockSize; + } else if (blockTag == GMapBlock) { + glyphMapOffset = imgData - fontData; + glyphMapEntries = blockSize / 4; + } else if (blockTag == GlyphBlock) { + glyphDataOffset = imgData - fontData; + glyphDataSize = blockSize; + } + + imgData += blockSize; + } + + face_id.filename = QFile::encodeName(extractHeaderField(fontData, Tag_FileName).toString()); + face_id.index = extractHeaderField(fontData, Tag_FileIndex).toInt(); + + // get the real cmap + if (cmapOffset) { + int tableSize = cmapSize; + const uchar *cmapPtr = getCMap(fontData + cmapOffset, tableSize, &symbol, &cmapSize); + if (cmapPtr) + cmapOffset = cmapPtr - fontData; + else + cmapOffset = 0; + } else if (externalCMap) { + int tableSize = cmapSize; + externalCMap = getCMap(externalCMap, tableSize, &symbol, &cmapSize); + } + + // verify all the positions in the glyphMap + if (glyphMapOffset) { + const quint32 *gmapPtr = reinterpret_cast<const quint32 *>(fontData + glyphMapOffset); + for (uint i = 0; i < glyphMapEntries; ++i) { + quint32 glyphDataPos = qFromBigEndian<quint32>(gmapPtr[i]); + if (glyphDataPos == 0xffffffff) + continue; + if (glyphDataPos >= glyphDataSize) { + // error + glyphMapOffset = 0; + glyphMapEntries = 0; + break; + } + } + } + +#if defined(DEBUG_FONTENGINE) + if (!isValid()) + qDebug() << "fontData" << fontData << "dataSize" << dataSize + << "externalCMap" << externalCMap << "cmapOffset" << cmapOffset + << "glyphMapOffset" << glyphMapOffset << "glyphDataOffset" << glyphDataOffset + << "fd" << fd << "glyphDataSize" << glyphDataSize; +#endif +} + +QFontEngineQPA::~QFontEngineQPA() +{ +} + +bool QFontEngineQPA::getSfntTableData(uint tag, uchar *buffer, uint *length) const +{ + Q_UNUSED(tag); + Q_UNUSED(buffer); + *length = 0; + return false; +} + +bool QFontEngineQPA::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const +{ + if (*nglyphs < len) { + *nglyphs = len; + return false; + } + +#if defined(DEBUG_FONTENGINE) + QSet<QChar> seenGlyphs; +#endif + + const uchar *cmap = externalCMap ? externalCMap : (fontData + cmapOffset); + + bool mirrored = flags & QTextEngine::RightToLeft; + int glyph_pos = 0; + if (symbol) { + for (int i = 0; i < len; ++i) { + unsigned int uc = getChar(str, i, len); + if (mirrored) + uc = QChar::mirroredChar(uc); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); + if(!glyphs->glyphs[glyph_pos] && uc < 0x100) + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc + 0xf000); + ++glyph_pos; + } + } else { + for (int i = 0; i < len; ++i) { + unsigned int uc = getChar(str, i, len); + if (mirrored) + uc = QChar::mirroredChar(uc); + glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, uc); +#if 0 && defined(DEBUG_FONTENGINE) + QChar c(uc); + if (!findGlyph(glyphs[glyph_pos].glyph) && !seenGlyphs.contains(c)) + qDebug() << "glyph for character" << c << '/' << hex << uc << "is" << dec << glyphs[glyph_pos].glyph; + + seenGlyphs.insert(c); +#endif + ++glyph_pos; + } + } + + *nglyphs = glyph_pos; + glyphs->numGlyphs = glyph_pos; + recalcAdvances(glyphs, flags); + return true; +} + +void QFontEngineQPA::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFlags) const +{ + for (int i = 0; i < glyphs->numGlyphs; ++i) { + const Glyph *g = findGlyph(glyphs->glyphs[i]); + if (!g) { + glyphs->glyphs[i] = 0; + continue; + } + glyphs->advances_x[i] = g->advance; + glyphs->advances_y[i] = 0; + } +} + +QImage QFontEngineQPA::alphaMapForGlyph(glyph_t g) +{ + const Glyph *glyph = findGlyph(g); + if (!glyph) + return QImage(); + + const uchar *bits = ((const uchar *) glyph) + sizeof(Glyph); + + QImage image(bits,glyph->width, glyph->height, glyph->bytesPerLine, QImage::Format_Indexed8); + + return image; +} + +void QFontEngineQPA::addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) +{ + addBitmapFontToPath(x, y, glyphs, path, flags); +} + +glyph_metrics_t QFontEngineQPA::boundingBox(const QGlyphLayout &glyphs) +{ + glyph_metrics_t overall; + // initialize with line height, we get the same behaviour on all platforms + overall.y = -ascent(); + overall.height = ascent() + descent() + 1; + + QFixed ymax = 0; + QFixed xmax = 0; + for (int i = 0; i < glyphs.numGlyphs; i++) { + const Glyph *g = findGlyph(glyphs.glyphs[i]); + if (!g) + continue; + + QFixed x = overall.xoff + glyphs.offsets[i].x + g->x; + QFixed y = overall.yoff + glyphs.offsets[i].y + g->y; + overall.x = qMin(overall.x, x); + overall.y = qMin(overall.y, y); + xmax = qMax(xmax, x + g->width); + ymax = qMax(ymax, y + g->height); + overall.xoff += g->advance; + } + overall.height = qMax(overall.height, ymax - overall.y); + overall.width = xmax - overall.x; + + return overall; +} + +glyph_metrics_t QFontEngineQPA::boundingBox(glyph_t glyph) +{ + glyph_metrics_t overall; + const Glyph *g = findGlyph(glyph); + if (!g) + return overall; + overall.x = g->x; + overall.y = g->y; + overall.width = g->width; + overall.height = g->height; + overall.xoff = g->advance; + return overall; +} + +QFixed QFontEngineQPA::ascent() const +{ + return QFixed::fromReal(extractHeaderField(fontData, Tag_Ascent).value<qreal>()); +} + +QFixed QFontEngineQPA::descent() const +{ + return QFixed::fromReal(extractHeaderField(fontData, Tag_Descent).value<qreal>()); +} + +QFixed QFontEngineQPA::leading() const +{ + return QFixed::fromReal(extractHeaderField(fontData, Tag_Leading).value<qreal>()); +} + +qreal QFontEngineQPA::maxCharWidth() const +{ + return extractHeaderField(fontData, Tag_MaxCharWidth).value<qreal>(); +} + +qreal QFontEngineQPA::minLeftBearing() const +{ + return extractHeaderField(fontData, Tag_MinLeftBearing).value<qreal>(); +} + +qreal QFontEngineQPA::minRightBearing() const +{ + return extractHeaderField(fontData, Tag_MinRightBearing).value<qreal>(); +} + +QFixed QFontEngineQPA::underlinePosition() const +{ + return QFixed::fromReal(extractHeaderField(fontData, Tag_UnderlinePosition).value<qreal>()); +} + +QFixed QFontEngineQPA::lineThickness() const +{ + return QFixed::fromReal(extractHeaderField(fontData, Tag_LineThickness).value<qreal>()); +} + +QFontEngine::Type QFontEngineQPA::type() const +{ + return QFontEngine::QPF2; +} + +bool QFontEngineQPA::canRender(const QChar *string, int len) +{ + const uchar *cmap = externalCMap ? externalCMap : (fontData + cmapOffset); + + if (symbol) { + for (int i = 0; i < len; ++i) { + unsigned int uc = getChar(string, i, len); + glyph_t g = getTrueTypeGlyphIndex(cmap, uc); + if(!g && uc < 0x100) + g = getTrueTypeGlyphIndex(cmap, uc + 0xf000); + if (!g) + return false; + } + } else { + for (int i = 0; i < len; ++i) { + unsigned int uc = getChar(string, i, len); + if (!getTrueTypeGlyphIndex(cmap, uc)) + return false; + } + } + return true; +} + +bool QFontEngineQPA::isValid() const +{ + return fontData && dataSize && (cmapOffset || externalCMap) + && glyphMapOffset && glyphDataOffset && glyphDataSize > 0; +} + +void QPAGenerator::generate() +{ + writeHeader(); + writeGMap(); + writeBlock(QFontEngineQPA::GlyphBlock, QByteArray()); + + dev->seek(4); // position of header.lock + writeUInt32(0); +} + +void QPAGenerator::writeHeader() +{ + QFontEngineQPA::Header header; + + header.magic[0] = 'Q'; + header.magic[1] = 'P'; + header.magic[2] = 'F'; + header.magic[3] = '2'; + header.lock = 1; + header.majorVersion = QFontEngineQPA::CurrentMajorVersion; + header.minorVersion = QFontEngineQPA::CurrentMinorVersion; + header.dataSize = 0; + dev->write((const char *)&header, sizeof(header)); + + writeTaggedString(QFontEngineQPA::Tag_FontName, fe->fontDef.family.toUtf8()); + + QFontEngine::FaceId face = fe->faceId(); + writeTaggedString(QFontEngineQPA::Tag_FileName, face.filename); + writeTaggedUInt32(QFontEngineQPA::Tag_FileIndex, face.index); + + { + uchar data[4]; + uint len = 4; + bool ok = fe->getSfntTableData(MAKE_TAG('h', 'e', 'a', 'd'), data, &len); + if (ok) { + const quint32 revision = qFromBigEndian<quint32>(data); + writeTaggedUInt32(QFontEngineQPA::Tag_FontRevision, revision); + } + } + + writeTaggedQFixed(QFontEngineQPA::Tag_Ascent, fe->ascent()); + writeTaggedQFixed(QFontEngineQPA::Tag_Descent, fe->descent()); + writeTaggedQFixed(QFontEngineQPA::Tag_Leading, fe->leading()); + writeTaggedQFixed(QFontEngineQPA::Tag_XHeight, fe->xHeight()); + writeTaggedQFixed(QFontEngineQPA::Tag_AverageCharWidth, fe->averageCharWidth()); + writeTaggedQFixed(QFontEngineQPA::Tag_MaxCharWidth, QFixed::fromReal(fe->maxCharWidth())); + writeTaggedQFixed(QFontEngineQPA::Tag_LineThickness, fe->lineThickness()); + writeTaggedQFixed(QFontEngineQPA::Tag_MinLeftBearing, QFixed::fromReal(fe->minLeftBearing())); + writeTaggedQFixed(QFontEngineQPA::Tag_MinRightBearing, QFixed::fromReal(fe->minRightBearing())); + writeTaggedQFixed(QFontEngineQPA::Tag_UnderlinePosition, fe->underlinePosition()); + writeTaggedUInt8(QFontEngineQPA::Tag_PixelSize, fe->fontDef.pixelSize); + writeTaggedUInt8(QFontEngineQPA::Tag_Weight, fe->fontDef.weight); + writeTaggedUInt8(QFontEngineQPA::Tag_Style, fe->fontDef.style); + + writeTaggedUInt8(QFontEngineQPA::Tag_GlyphFormat, QFontEngineQPA::AlphamapGlyphs); + + writeTaggedString(QFontEngineQPA::Tag_EndOfHeader, QByteArray()); + align4(); + + const quint64 size = dev->pos(); + header.dataSize = qToBigEndian<quint16>(size - sizeof(header)); + dev->seek(0); + dev->write((const char *)&header, sizeof(header)); + dev->seek(size); +} + +void QPAGenerator::writeGMap() +{ + const quint16 glyphCount = fe->glyphCount(); + + writeUInt16(QFontEngineQPA::GMapBlock); + writeUInt16(0); // padding + writeUInt32(glyphCount * 4); + + QByteArray &buffer = dev->buffer(); + const int numBytes = glyphCount * sizeof(quint32); + qint64 pos = buffer.size(); + buffer.resize(pos + numBytes); + qMemSet(buffer.data() + pos, 0xff, numBytes); + dev->seek(pos + numBytes); +} + +void QPAGenerator::writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &data) +{ + writeUInt16(tag); + writeUInt16(0); // padding + const int padSize = ((data.size() + 3) / 4) * 4 - data.size(); + writeUInt32(data.size() + padSize); + dev->write(data); + for (int i = 0; i < padSize; ++i) + writeUInt8(0); +} + +void QPAGenerator::writeTaggedString(QFontEngineQPA::HeaderTag tag, const QByteArray &string) +{ + writeUInt16(tag); + writeUInt16(string.length()); + dev->write(string); +} + +void QPAGenerator::writeTaggedUInt32(QFontEngineQPA::HeaderTag tag, quint32 value) +{ + writeUInt16(tag); + writeUInt16(sizeof(value)); + writeUInt32(value); +} + +void QPAGenerator::writeTaggedUInt8(QFontEngineQPA::HeaderTag tag, quint8 value) +{ + writeUInt16(tag); + writeUInt16(sizeof(value)); + writeUInt8(value); +} + +void QPAGenerator::writeTaggedQFixed(QFontEngineQPA::HeaderTag tag, QFixed value) +{ + writeUInt16(tag); + writeUInt16(sizeof(quint32)); + writeUInt32(value.value()); +} + + +/* + Creates a new multi QPA engine. + + This function takes ownership of the QFontEngine, increasing it's refcount. +*/ +QFontEngineMultiQPA::QFontEngineMultiQPA(QFontEngine *fe, int _script, const QStringList &fallbacks) + : QFontEngineMulti(fallbacks.size() + 1), + fallbackFamilies(fallbacks), script(_script) +{ + engines[0] = fe; + fe->ref.ref(); + fontDef = engines[0]->fontDef; +} + +void QFontEngineMultiQPA::loadEngine(int at) +{ + Q_ASSERT(at < engines.size()); + Q_ASSERT(engines.at(at) == 0); + + QFontDef request = fontDef; + request.styleStrategy |= QFont::NoFontMerging; + request.family = fallbackFamilies.at(at-1); + engines[at] = QFontDatabase::findFont(script, + /*fontprivate*/0, + request); + Q_ASSERT(engines[at]); + engines[at]->ref.ref(); + engines[at]->fontDef = request; +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qfontengine_qpa_p.h b/src/gui/text/qfontengine_qpa_p.h new file mode 100644 index 0000000..467fca6 --- /dev/null +++ b/src/gui/text/qfontengine_qpa_p.h @@ -0,0 +1,262 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ + +#ifndef QFONTENGINE_QPA_P_H +#define QFONTENGINE_QPA_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// +#include <QtCore/qconfig.h> +#include <QtCore/qglobal.h> +#include <QtCore/qendian.h> +#include <QtCore/QBuffer> + +#include "qfontengine_p.h" + +#include <QtCore/QFile> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QFontEngine; +class QFreetypeFace; +class QBuffer; + +class Q_GUI_EXPORT QFontEngineQPA : public QFontEngine +{ +public: + // if you add new tags please make sure to update the tables in + // qpfutil.cpp and tools/makeqpf/qpf2.cpp + enum HeaderTag { + Tag_FontName, // 0 string + Tag_FileName, // 1 string + Tag_FileIndex, // 2 quint32 + Tag_FontRevision, // 3 quint32 + Tag_FreeText, // 4 string + Tag_Ascent, // 5 QFixed + Tag_Descent, // 6 QFixed + Tag_Leading, // 7 QFixed + Tag_XHeight, // 8 QFixed + Tag_AverageCharWidth, // 9 QFixed + Tag_MaxCharWidth, // 10 QFixed + Tag_LineThickness, // 11 QFixed + Tag_MinLeftBearing, // 12 QFixed + Tag_MinRightBearing, // 13 QFixed + Tag_UnderlinePosition, // 14 QFixed + Tag_GlyphFormat, // 15 quint8 + Tag_PixelSize, // 16 quint8 + Tag_Weight, // 17 quint8 + Tag_Style, // 18 quint8 + Tag_EndOfHeader, // 19 string + Tag_WritingSystems, // 20 bitfield + + NumTags + }; + + enum TagType { + StringType, + FixedType, + UInt8Type, + UInt32Type, + BitFieldType + }; + + struct Tag + { + quint16 tag; + quint16 size; + }; + + enum GlyphFormat { + BitmapGlyphs = 1, + AlphamapGlyphs = 8 + }; + + enum { + CurrentMajorVersion = 2, + CurrentMinorVersion = 0 + }; + + // The CMap is identical to the TrueType CMap table format + // The GMap table is a normal array with the total number of + // covered glyphs in the TrueType font + enum BlockTag { + CMapBlock, + GMapBlock, + GlyphBlock + }; + + struct Q_PACKED Header + { + char magic[4]; // 'QPF2' + quint32 lock; // values: 0 = unlocked, 0xffffffff = read-only, otherwise qws client id of locking process + quint8 majorVersion; + quint8 minorVersion; + quint16 dataSize; + }; + + struct Q_PACKED Block + { + quint16 tag; + quint16 pad; + quint32 dataSize; + }; + + struct Q_PACKED Glyph + { + quint8 width; + quint8 height; + quint8 bytesPerLine; + qint8 x; + qint8 y; + qint8 advance; + }; + + QFontEngineQPA(const QFontDef &def, const QByteArray &data); + ~QFontEngineQPA(); + + FaceId faceId() const { return face_id; } + bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; + + bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QTextEngine::ShaperFlags flags) const; + void recalcAdvances(QGlyphLayout *, QTextEngine::ShaperFlags) const; + + void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags); + QImage alphaMapForGlyph(glyph_t t); + + glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); + glyph_metrics_t boundingBox(glyph_t glyph); + + QFixed ascent() const; + QFixed descent() const; + QFixed leading() const; + qreal maxCharWidth() const; + qreal minLeftBearing() const; + qreal minRightBearing() const; + QFixed underlinePosition() const; + QFixed lineThickness() const; + + Type type() const; + + bool canRender(const QChar *string, int len); + inline const char *name() const { return "QPF2"; } + + virtual int glyphCount() const { return glyphMapEntries; } + + bool isValid() const; + + const Glyph *findGlyph(glyph_t g) const; + + static bool verifyHeader(const uchar *data, int size); + static QVariant extractHeaderField(const uchar *data, HeaderTag tag); + +private: + + const uchar *fontData; + int dataSize; + const uchar *externalCMap; + quint32 cmapOffset; + int cmapSize; + quint32 glyphMapOffset; + quint32 glyphMapEntries; + quint32 glyphDataOffset; + quint32 glyphDataSize; + QString internalFileName; + QString encodedFileName; + bool readOnly; + + FaceId face_id; + QByteArray freetypeCMapTable; + mutable bool kerning_pairs_loaded; +}; + +struct QPAGenerator +{ + QPAGenerator(QBuffer *device, QFontEngine *engine) + : dev(device), fe(engine) {} + + void generate(); + void writeHeader(); + void writeGMap(); + void writeBlock(QFontEngineQPA::BlockTag tag, const QByteArray &data); + + void writeTaggedString(QFontEngineQPA::HeaderTag tag, const QByteArray &string); + void writeTaggedUInt32(QFontEngineQPA::HeaderTag tag, quint32 value); + void writeTaggedUInt8(QFontEngineQPA::HeaderTag tag, quint8 value); + void writeTaggedQFixed(QFontEngineQPA::HeaderTag tag, QFixed value); + + void writeUInt16(quint16 value) { value = qToBigEndian(value); dev->write((const char *)&value, sizeof(value)); } + void writeUInt32(quint32 value) { value = qToBigEndian(value); dev->write((const char *)&value, sizeof(value)); } + void writeUInt8(quint8 value) { dev->write((const char *)&value, sizeof(value)); } + void writeInt8(qint8 value) { dev->write((const char *)&value, sizeof(value)); } + + void align4() { while (dev->pos() & 3) { dev->putChar('\0'); } } + + QBuffer *dev; + QFontEngine *fe; +}; + +class QFontEngineMultiQPA : public QFontEngineMulti +{ +public: + QFontEngineMultiQPA(QFontEngine *fe, int script, const QStringList &fallbacks); + + void loadEngine(int at); + +private: + QStringList fallbackFamilies; + int script; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QFONTENGINE_QPA_P_H diff --git a/src/gui/text/qplatformfontdatabase_qpa.cpp b/src/gui/text/qplatformfontdatabase_qpa.cpp new file mode 100644 index 0000000..370c921 --- /dev/null +++ b/src/gui/text/qplatformfontdatabase_qpa.cpp @@ -0,0 +1,241 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qplatformfontdatabase_qpa.h" +#include <QtGui/private/qfontengine_p.h> +#include <QtGui/private/qfontengine_qpa_p.h> +#include <QtCore/QLibraryInfo> +#include <QtCore/QDir> + +QT_BEGIN_NAMESPACE + +extern void qt_registerFont(const QString &familyname, const QString &foundryname, int weight, + QFont::Style style, int stretch, bool antialiased,bool scalable, int pixelSize, + const QSupportedWritingSystems &writingSystems, void *hanlde); + +void QPlatformFontDatabase::registerQPF2Font(const QByteArray &dataArray, void *handle) +{ + if (dataArray.size() == 0) + return; + + const uchar *data = reinterpret_cast<const uchar *>(dataArray.constData()); + if (QFontEngineQPA::verifyHeader(data, dataArray.size())) { + QString fontName = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_FontName).toString(); + int pixelSize = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_PixelSize).toInt(); + QVariant weight = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Weight); + QVariant style = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_Style); + QByteArray writingSystemBits = QFontEngineQPA::extractHeaderField(data, QFontEngineQPA::Tag_WritingSystems).toByteArray(); + + if (!fontName.isEmpty() && pixelSize) { + int fontWeight = 50; + if (weight.type() == QVariant::Int || weight.type() == QVariant::UInt) + fontWeight = weight.toInt(); + + QFont::Style fontStyle = static_cast<QFont::Style>(style.toInt()); + + QSupportedWritingSystems writingSystems; + for (int i = 0; i < writingSystemBits.count(); ++i) { + uchar currentByte = writingSystemBits.at(i); + for (int j = 0; j < 8; ++j) { + if (currentByte & 1) + writingSystems.setSupported(QFontDatabase::WritingSystem(i * 8 + j)); + currentByte >>= 1; + } + } + + registerFont(fontName,QString(),fontWeight,fontStyle,100,true,false,pixelSize,writingSystems,handle); + } + } else { + qDebug() << "header verification of QPF2 font failed. maybe it is corrupt?"; + } +} + +void QPlatformFontDatabase::registerFont(const QString &familyname, const QString &foundryname, int weight, + QFont::Style style, int stretch, bool antialiased, bool scalable, int pixelSize, + const QSupportedWritingSystems &writingSystems, void *usrPtr) +{ + if (scalable) + pixelSize = 0; + qt_registerFont(familyname,foundryname,weight,style,stretch,antialiased,scalable,pixelSize,writingSystems,usrPtr); +} + +class QWritingSystemsPrivate +{ +public: + QWritingSystemsPrivate() + : ref(1) + , vector(QFontDatabase::WritingSystemsCount,false) + { + } + + QWritingSystemsPrivate(const QWritingSystemsPrivate *other) + : ref(1) + , vector(other->vector) + { + } + + QAtomicInt ref; + QVector<bool> vector; +}; + +QSupportedWritingSystems::QSupportedWritingSystems() +{ + d = new QWritingSystemsPrivate; +} + +QSupportedWritingSystems::QSupportedWritingSystems(const QSupportedWritingSystems &other) +{ + d = other.d; + d->ref.ref(); +} + +QSupportedWritingSystems &QSupportedWritingSystems::operator=(const QSupportedWritingSystems &other) +{ + if (d != other.d) { + other.d->ref.ref(); + if (!d->ref.deref()) + delete d; + d = other.d; + } + return *this; +} + +QSupportedWritingSystems::~QSupportedWritingSystems() +{ + if (!d->ref.deref()) + delete d; +} + +void QSupportedWritingSystems::detach() +{ + if (d->ref != 1) { + QWritingSystemsPrivate *newd = new QWritingSystemsPrivate(d); + if (!d->ref.deref()) + delete d; + d = newd; + } +} + +void QSupportedWritingSystems::setSupported(QFontDatabase::WritingSystem writingSystem, bool support) +{ + detach(); + d->vector[writingSystem] = support; +} + +bool QSupportedWritingSystems::supported(QFontDatabase::WritingSystem writingSystem) const +{ + return d->vector.at(writingSystem); +} + +void QPlatformFontDatabase::populateFontDatabase() +{ + QString fontpath = fontDir(); + + if(!QFile::exists(fontpath)) { + qFatal("QFontDatabase: Cannot find font directory %s - is Qt installed correctly?", + qPrintable(fontpath)); + } + + QDir dir(fontpath); + dir.setNameFilters(QStringList() << QLatin1String("*.qpf2")); + dir.refresh(); + for (int i = 0; i < int(dir.count()); ++i) { + const QByteArray fileName = QFile::encodeName(dir.absoluteFilePath(dir[i])); + QFile file(QString::fromLocal8Bit(fileName)); + if (file.open(QFile::ReadOnly)) { + const QByteArray fileData = file.readAll(); + QByteArray *fileDataPtr = new QByteArray(fileData); + registerQPF2Font(fileData, fileDataPtr); + } + } +} + +QFontEngine *QPlatformFontDatabase::fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle) +{ + Q_UNUSED(script); + Q_UNUSED(handle); + QByteArray *fileDataPtr = static_cast<QByteArray *>(handle); + QFontEngineQPA *engine = new QFontEngineQPA(fontDef,*fileDataPtr); + qDebug() << fontDef.pixelSize << fontDef.weight << fontDef.style << fontDef.stretch << fontDef.styleHint << fontDef.styleStrategy << fontDef.family << script; + return engine; +} + +QStringList QPlatformFontDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const +{ + Q_UNUSED(family); + Q_UNUSED(style); + Q_UNUSED(script); + return QStringList(); +} + +/*! + Adds an application font. Returns a list of family names, or an empty list if the font could + not be added +*/ +QStringList QPlatformFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) +{ + Q_UNUSED(fontData); + Q_UNUSED(fileName); + + qWarning("This plugin does not support application fonts"); + return QStringList(); +} + +void QPlatformFontDatabase::releaseHandle(void *handle) +{ + QByteArray *fileDataPtr = static_cast<QByteArray *>(handle); + delete fileDataPtr; +} + +QString QPlatformFontDatabase::fontDir() const +{ + QString fontpath = QString::fromLocal8Bit(qgetenv("QT_QPA_FONTDIR")); + if (fontpath.isEmpty()) { +#ifndef QT_NO_SETTINGS + fontpath = QLibraryInfo::location(QLibraryInfo::LibrariesPath); + fontpath += QLatin1String("/fonts"); +#endif + } + + return fontpath; +} + +QT_END_NAMESPACE diff --git a/src/gui/text/qplatformfontdatabase_qpa.h b/src/gui/text/qplatformfontdatabase_qpa.h new file mode 100644 index 0000000..75b0a18 --- /dev/null +++ b/src/gui/text/qplatformfontdatabase_qpa.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMFONTDATABASE_QPA_H +#define QPLATFORMFONTDATABASE_QPA_H + +#include <QtCore/qconfig.h> +#include <QtCore/QString> +#include <QtCore/QStringList> +#include <QtCore/QList> +#include <QtGui/QFontDatabase> +#include <QtGui/private/qfont_p.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +QT_MODULE(Gui) + +class QWritingSystemsPrivate; + +class Q_GUI_EXPORT QSupportedWritingSystems +{ +public: + + QSupportedWritingSystems(); + QSupportedWritingSystems(const QSupportedWritingSystems &other); + QSupportedWritingSystems &operator=(const QSupportedWritingSystems &other); + ~QSupportedWritingSystems(); + + void setSupported(QFontDatabase::WritingSystem, bool supported = true); + bool supported(QFontDatabase::WritingSystem) const; + +private: + void detach(); + + QWritingSystemsPrivate *d; + + friend Q_GUI_EXPORT bool operator==(const QSupportedWritingSystems &, const QSupportedWritingSystems &); + friend Q_GUI_EXPORT bool operator!=(const QSupportedWritingSystems &, const QSupportedWritingSystems &); +}; + +Q_GUI_EXPORT bool operator==(const QSupportedWritingSystems &, const QSupportedWritingSystems &); +Q_GUI_EXPORT bool operator!=(const QSupportedWritingSystems &, const QSupportedWritingSystems &); + +class QFontRequestPrivate; + +class Q_GUI_EXPORT QPlatformFontDatabase +{ +public: + virtual void populateFontDatabase(); + virtual QFontEngine *fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *handle); + virtual QStringList fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const; + virtual QStringList addApplicationFont(const QByteArray &fontData, const QString &fileName); + virtual void releaseHandle(void *handle); + + virtual QString fontDir() const; + + //callback + static void registerQPF2Font(const QByteArray &dataArray, void *handle); + static void registerFont(const QString &familyname, const QString &foundryname, int weight, + QFont::Style style, int stetch, bool antialiased, bool scalable, int pixelSize, + const QSupportedWritingSystems &writingSystems, void *handle); +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QPLATFORMFONTDATABASE_QPA_H diff --git a/src/gui/text/text.pri b/src/gui/text/text.pri index 102df4d..0040b54 100644 --- a/src/gui/text/text.pri +++ b/src/gui/text/text.pri @@ -25,7 +25,7 @@ HEADERS += \ text/qabstracttextdocumentlayout.h \ text/qtextdocumentlayout_p.h \ text/qtextcursor.h \ - text/qtextcursor_p.h \ + text/qtextcursor_p.h \ text/qtextdocumentfragment.h \ text/qtextdocumentfragment_p.h \ text/qtextimagehandler_p.h \ @@ -92,7 +92,7 @@ unix:x11 { text/qfontengine_ft.cpp } -!embedded:!x11:mac { +!embedded:!qpa:!x11:mac { SOURCES += \ text/qfont_mac.cpp OBJECTIVE_SOURCES += text/qfontengine_mac.mm @@ -113,6 +113,19 @@ embedded { DEFINES += QT_NO_FONTCONFIG } +qpa { + SOURCES += \ + text/qfont_qpa.cpp \ + text/qfontengine_qpa.cpp \ + text/qplatformfontdatabase_qpa.cpp + + HEADERS += \ + text/qplatformfontdatabase_qpa.h + + DEFINES += QT_NO_FONTCONFIG + DEFINES += QT_NO_FREETYPE +} + symbian { SOURCES += \ text/qfont_s60.cpp @@ -132,6 +145,7 @@ symbian { } } +!qpa { contains(QT_CONFIG, freetype) { SOURCES += \ ../3rdparty/freetype/src/base/ftbase.c \ @@ -205,6 +219,7 @@ contains(QT_CONFIG, freetype) { contains(QT_CONFIG, fontconfig) { CONFIG += opentype } +}#!qpa DEFINES += QT_NO_OPENTYPE INCLUDEPATH += ../3rdparty/harfbuzz/src diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp index 8b36b32..39a160e 100644 --- a/src/gui/util/qdesktopservices.cpp +++ b/src/gui/util/qdesktopservices.cpp @@ -45,7 +45,7 @@ #include <qdebug.h> -#if defined(Q_WS_QWS) +#if defined(Q_WS_QWS) || defined(Q_WS_QPA) #include "qdesktopservices_qws.cpp" #elif defined(Q_WS_X11) #include "qdesktopservices_x11.cpp" diff --git a/src/gui/util/util.pri b/src/gui/util/util.pri index bea520e..af6218a 100644 --- a/src/gui/util/util.pri +++ b/src/gui/util/util.pri @@ -33,12 +33,12 @@ unix:x11 { util/qsystemtrayicon_x11.cpp } -embedded { +embedded|qpa { SOURCES += \ util/qsystemtrayicon_qws.cpp } -!embedded:!x11:mac { +!embedded:!qpa:!x11:mac { OBJECTIVE_SOURCES += util/qsystemtrayicon_mac.mm } diff --git a/src/gui/widgets/qlinecontrol.cpp b/src/gui/widgets/qlinecontrol.cpp index f338f40..a283da6 100644 --- a/src/gui/widgets/qlinecontrol.cpp +++ b/src/gui/widgets/qlinecontrol.cpp @@ -112,7 +112,7 @@ void QLineControl::updateDisplayText(bool forceUpdate) Copies the currently selected text into the clipboard using the given \a mode. - + \note If the echo mode is set to a mode other than Normal then copy will not work. This is to prevent using copy as a method of bypassing password features of the line control. @@ -486,7 +486,7 @@ void QLineControl::processInputMethodEvent(QInputMethodEvent *event) /*! \internal - Draws the display text for the line control using the given + Draws the display text for the line control using the given \a painter, \a clip, and \a offset. Which aspects of the display text are drawn is specified by the given \a flags. diff --git a/src/gui/widgets/widgets.pri b/src/gui/widgets/widgets.pri index 937b8d6..669b838 100644 --- a/src/gui/widgets/widgets.pri +++ b/src/gui/widgets/widgets.pri @@ -144,7 +144,7 @@ SOURCES += \ widgets/qplaintextedit.cpp \ widgets/qprintpreviewwidget.cpp -!embedded:mac { +!embedded:!qpa:mac { HEADERS += widgets/qmacnativewidget_mac.h \ widgets/qmaccocoaviewcontainer_mac.h OBJECTIVE_HEADERS += widgets/qcocoatoolbardelegate_mac_p.h \ diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index c7ca4bc..682e620 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -11,7 +11,7 @@ unix:QMAKE_PKGCONFIG_REQUIRES = QtCore QtGui include(../qbase.pri) -!win32:!embedded:!mac:!symbian:CONFIG += x11 +!win32:!embedded:!mac:!symbian:!qpa:CONFIG += x11 contains(QT_CONFIG, opengl):CONFIG += opengl contains(QT_CONFIG, opengles1):CONFIG += opengles1 contains(QT_CONFIG, opengles2):CONFIG += opengles2 @@ -79,6 +79,11 @@ SOURCES += qgl.cpp \ } +qpa { + SOURCES += qgl_qpa.cpp \ + qglpixelbuffer_stub.cpp +} + x11 { contains(QT_CONFIG, egl) { SOURCES += qgl_x11egl.cpp \ diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 41677c4..f316db6 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -93,12 +93,15 @@ #include "qlibrary.h" #include <qmutex.h> +#ifdef QT_OPENGL_ES +#include <EGL/egl.h> +#endif // #define QT_GL_CONTEXT_RESOURCE_DEBUG QT_BEGIN_NAMESPACE -#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) QGLExtensionFuncs QGLContextPrivate::qt_extensionFuncs; #endif @@ -1406,6 +1409,10 @@ QGLFormat::OpenGLVersionFlags QGLFormat::openGLVersionFlags() } } +#ifdef Q_WS_QPA + hasOpenGL(); // ### I have no idea why this is needed here, but it makes things work for testlite +#endif + QString versionString(QLatin1String(reinterpret_cast<const char*>(glGetString(GL_VERSION)))); OpenGLVersionFlags versionFlags = qOpenGLVersionFlagsFromString(versionString); if (currentCtx) { @@ -1678,7 +1685,10 @@ void QGLContextPrivate::init(QPaintDevice *dev, const QGLFormat &format) # endif vi = 0; #endif -#ifndef QT_NO_EGL +#if defined(Q_WS_QPA) + platformContext = 0; +#endif +#if !defined(QT_NO_EGL) ownsEglContext = false; eglContext = 0; eglSurface = EGL_NO_SURFACE; @@ -2268,7 +2278,7 @@ static void convertToGLFormatHelper(QImage &dst, const QImage &img, GLenum textu } } -#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) QGLExtensionFuncs& QGLContextPrivate::extensionFuncs(const QGLContext *) { return qt_extensionFuncs; @@ -4189,7 +4199,7 @@ void QGLWidget::resizeOverlayGL(int, int) /*! \fn bool QGLWidget::event(QEvent *e) \reimp */ -#if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS) +#if !defined(Q_OS_WINCE) && !defined(Q_WS_QWS) && !defined(Q_WS_QPA) bool QGLWidget::event(QEvent *e) { Q_D(QGLWidget); @@ -5435,7 +5445,7 @@ void QGLWidgetPrivate::initContext(QGLContext *context, const QGLWidget* shareWi glcx = new QGLContext(QGLFormat::defaultFormat(), q); } -#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) +#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_WS_QPA) Q_GLOBAL_STATIC(QString, qt_gl_lib_name) Q_OPENGL_EXPORT void qt_set_gl_library_name(const QString& name) diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index cf239f4..8c7f15c 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -68,6 +68,10 @@ #include <QtGui/private/qegl_p.h> #endif +#if defined(Q_WS_QPA) +#include <QtGui/QPlatformGLContext> +#endif + QT_BEGIN_NAMESPACE class QGLContext; @@ -161,7 +165,7 @@ class QGLWidgetPrivate : public QWidgetPrivate public: QGLWidgetPrivate() : QWidgetPrivate() , disable_clear_on_painter_begin(false) -#ifdef Q_WS_QWS +#if defined(Q_WS_QWS) , wsurf(0) #endif #if defined(Q_WS_X11) && !defined(QT_NO_EGL) @@ -360,11 +364,14 @@ public: Qt::HANDLE threadId; #endif #ifndef QT_NO_EGL - uint ownsEglContext : 1; QEglContext *eglContext; EGLSurface eglSurface; void destroyEglSurfaceForDevice(); EGLSurface eglSurfaceForDevice() const; +#endif + +#if defined(Q_WS_QPA) + QPlatformGLContext *platformContext; #elif defined(Q_WS_X11) || defined(Q_WS_MAC) void* cx; #endif @@ -406,6 +413,10 @@ public: uint workaround_brokenTextureFromPixmap : 1; uint workaround_brokenTextureFromPixmap_init : 1; +#ifndef QT_NO_EGL + uint ownsEglContext : 1; +#endif + QPaintDevice *paintDevice; QColor transpColor; QGLContext *q_ptr; @@ -428,7 +439,7 @@ public: static inline QGLExtensionFuncs& extensionFuncs(const QGLContext *ctx) { return ctx->d_ptr->group->extensionFuncs(); } #endif -#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_OS_SYMBIAN) +#if defined(Q_WS_X11) || defined(Q_WS_MAC) || defined(Q_WS_QWS) || defined(Q_WS_QPA) || defined(Q_OS_SYMBIAN) static Q_OPENGL_EXPORT QGLExtensionFuncs qt_extensionFuncs; static Q_OPENGL_EXPORT QGLExtensionFuncs& extensionFuncs(const QGLContext *); #endif diff --git a/src/opengl/qgl_qpa.cpp b/src/opengl/qgl_qpa.cpp new file mode 100644 index 0000000..49c0860 --- /dev/null +++ b/src/opengl/qgl_qpa.cpp @@ -0,0 +1,345 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenGL 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 <QApplication> +#include <QtGui/private/qapplication_p.h> +#include <QPixmap> +#include <QDebug> + +#include <QtGui/private/qapplication_p.h> +#include <QtGui/QPlatformWindow> + +#include "qgl.h" +#include "qgl_p.h" + +QT_BEGIN_NAMESPACE + +static QGLFormat qt_platformwindowformat_to_glformat(const QPlatformWindowFormat &format) +{ + QGLFormat retFormat; + retFormat.setAccum(format.accum()); + if (format.accumBufferSize() >= 0) + retFormat.setAccumBufferSize(format.accumBufferSize()); + retFormat.setAlpha(format.alpha()); + if (format.alphaBufferSize() >= 0) + retFormat.setAlphaBufferSize(format.alphaBufferSize()); + if (format.blueBufferSize() >= 0) + retFormat.setBlueBufferSize(format.blueBufferSize()); + retFormat.setDepth(format.depth()); + if (format.depthBufferSize() >= 0) + retFormat.setDepthBufferSize(format.depthBufferSize()); + retFormat.setDirectRendering(format.directRendering()); + retFormat.setDoubleBuffer(format.doubleBuffer()); + if (format.greenBufferSize() >= 0) + retFormat.setGreenBufferSize(format.greenBufferSize()); + if (format.redBufferSize() >= 0) + retFormat.setRedBufferSize(format.redBufferSize()); + retFormat.setRgba(format.rgba()); + retFormat.setSampleBuffers(format.sampleBuffers()); + retFormat.setSamples(format.sampleBuffers()); + retFormat.setStencil(format.stencil()); + if (format.stencilBufferSize() >= 0) + retFormat.setStencilBufferSize(format.stencilBufferSize()); + retFormat.setStereo(format.stereo()); + retFormat.setSwapInterval(format.swapInterval()); + return retFormat; +} + +static QPlatformWindowFormat qt_glformat_to_platformwindowformat(const QGLFormat &format) +{ + QPlatformWindowFormat retFormat; + retFormat.setAccum(format.accum()); + if (format.accumBufferSize() >= 0) + retFormat.setAccumBufferSize(format.accumBufferSize()); + retFormat.setAlpha(format.alpha()); + if (format.alphaBufferSize() >= 0) + retFormat.setAlphaBufferSize(format.alphaBufferSize()); + if (format.blueBufferSize() >= 0) + retFormat.setBlueBufferSize(format.blueBufferSize()); + retFormat.setDepth(format.depth()); + if (format.depthBufferSize() >= 0) + retFormat.setDepthBufferSize(format.depthBufferSize()); + retFormat.setDirectRendering(format.directRendering()); + retFormat.setDoubleBuffer(format.doubleBuffer()); + if (format.greenBufferSize() >= 0) + retFormat.setGreenBufferSize(format.greenBufferSize()); + if (format.redBufferSize() >= 0) + retFormat.setRedBufferSize(format.redBufferSize()); + retFormat.setRgba(format.rgba()); + retFormat.setSampleBuffers(format.sampleBuffers()); + if (format.samples() >= 0) + retFormat.setSamples(format.samples()); + retFormat.setStencil(format.stencil()); + if (format.stencilBufferSize() >= 0) + retFormat.setStencilBufferSize(format.stencilBufferSize()); + retFormat.setStereo(format.stereo()); + retFormat.setSwapInterval(format.swapInterval()); + return retFormat; +} + +bool QGLFormat::hasOpenGL() +{ + return QApplicationPrivate::platformIntegration()->hasOpenGL(); +} + +bool QGLContext::chooseContext(const QGLContext* shareContext) +{ + Q_D(QGLContext); + if (!d->paintDevice || d->paintDevice->devType() != QInternal::Widget) { + d->valid = false; + }else { + QWidget *widget = static_cast<QWidget *>(d->paintDevice); + if (!widget->platformWindow()){ + QGLFormat glformat = format(); + QPlatformWindowFormat winFormat = qt_glformat_to_platformwindowformat(glformat); + if (shareContext) { + winFormat.setSharedContext(shareContext->d_func()->platformContext); + } + winFormat.setWindowApi(QPlatformWindowFormat::OpenGL); + widget->setPlatformWindowFormat(winFormat); + widget->winId();//make window + } + d->platformContext = widget->platformWindow()->glContext(); + Q_ASSERT(d->platformContext); + d->glFormat = qt_platformwindowformat_to_glformat(d->platformContext->platformWindowFormat()); + d->valid =(bool) d->platformContext; + } + + return d->valid; +} + +void QGLContext::reset() +{ + Q_D(QGLContext); + if (!d->valid) + return; + d->cleanup(); + + d->crWin = false; + d->sharing = false; + d->valid = false; + d->transpColor = QColor(); + d->initDone = false; + QGLContextGroup::removeShare(this); +} + +void QGLContext::makeCurrent() +{ + Q_D(QGLContext); + d->platformContext->makeCurrent(); + QGLContextPrivate::setCurrentContext(this); +} + +void QGLContext::doneCurrent() +{ + Q_D(QGLContext); + d->platformContext->doneCurrent(); + QGLContextPrivate::setCurrentContext(0); +} + +void QGLContext::swapBuffers() const +{ + Q_D(const QGLContext); + d->platformContext->swapBuffers(); +} + +void *QGLContext::getProcAddress(const QString &procName) const +{ + Q_D(const QGLContext); + return d->platformContext->getProcAddress(procName); +} + +void QGLWidget::setContext(QGLContext *context, + const QGLContext* shareContext, + bool deleteOldContext) +{ + Q_D(QGLWidget); + if (context == 0) { + qWarning("QGLWidget::setContext: Cannot set null context"); + return; + } + if (!context->deviceIsPixmap() && context->device() != this) { + qWarning("QGLWidget::setContext: Context must refer to this widget"); + return; + } + + QGLContext* oldcx = d->glcx; + d->glcx = context; + + if (!d->glcx->isValid()) + d->glcx->create(shareContext ? shareContext : oldcx); + + if (deleteOldContext) + delete oldcx; +} + +void QGLWidgetPrivate::init(QGLContext *context, const QGLWidget *shareWidget) +{ + initContext(context, shareWidget); +} + +bool QGLFormat::hasOpenGLOverlays() +{ + return false; +} + +QColor QGLContext::overlayTransparentColor() const +{ + return QColor(); // Invalid color +} + +uint QGLContext::colorIndex(const QColor&) const +{ + return 0; +} + +void QGLContext::generateFontDisplayLists(const QFont & fnt, int listBase) +{ + Q_UNUSED(fnt); + Q_UNUSED(listBase); +} + +/* + QGLTemporaryContext implementation +*/ +class QGLTemporaryContextPrivate +{ +public: + QWidget *widget; + QGLContext *context; +}; + +QGLTemporaryContext::QGLTemporaryContext(bool, QWidget *) + : d(new QGLTemporaryContextPrivate) +{ + d->context = const_cast<QGLContext *>(QGLContext::currentContext()); + if (d->context) + d->context->doneCurrent(); + d->widget = new QWidget; + d->widget->setGeometry(0,0,3,3); + QPlatformWindowFormat format = d->widget->platformWindowFormat(); + format.setWindowApi(QPlatformWindowFormat::OpenGL); + d->widget->winId(); + + + d->widget->platformWindow()->glContext()->makeCurrent(); +} + +QGLTemporaryContext::~QGLTemporaryContext() +{ + d->widget->platformWindow()->glContext()->doneCurrent(); + if (d->context) + d->context->makeCurrent(); + delete d->widget; +} + + +bool QGLWidgetPrivate::renderCxPm(QPixmap*) +{ + return false; +} + +/*! \internal + Free up any allocated colormaps. This fn is only called for + top-level widgets. +*/ +void QGLWidgetPrivate::cleanupColormaps() +{ +} + +void QGLWidget::setMouseTracking(bool enable) +{ + Q_UNUSED(enable); +} + +bool QGLWidget::event(QEvent *e) +{ + Q_D(QGLWidget); + if (e->type() == QEvent::WinIdChange) { + if (d->glcx->isValid()) { + if (QGLContext::currentContext() == d->glcx) + QGLContextPrivate::setCurrentContext(0); //Its not valid anymore + setContext(new QGLContext(d->glcx->requestedFormat(), this)); + + } + } + return QWidget::event(e); +} + +void QGLWidget::resizeEvent(QResizeEvent *e) +{ + Q_D(QGLWidget); + if (!isValid()) + return; + makeCurrent(); + if (!d->glcx->initialized()) + glInit(); + resizeGL(width(), height()); + return QWidget::resizeEvent(e); +} + + +const QGLContext* QGLWidget::overlayContext() const +{ + return 0; +} + +void QGLWidget::makeOverlayCurrent() +{ +} + + +void QGLWidget::updateOverlayGL() +{ +} + +const QGLColormap & QGLWidget::colormap() const +{ + Q_D(const QGLWidget); + return d->cmap; +} + +void QGLWidget::setColormap(const QGLColormap & c) +{ + Q_UNUSED(c); +} + +QT_END_NAMESPACE diff --git a/src/opengl/qglpixelbuffer_p.h b/src/opengl/qglpixelbuffer_p.h index 2a1f671..69678d0 100644 --- a/src/opengl/qglpixelbuffer_p.h +++ b/src/opengl/qglpixelbuffer_p.h @@ -197,6 +197,10 @@ public: EGLSurface pbuf; QEglContext *ctx; int textureFormat; +#elif defined(Q_WS_QPA) + //stubs + void *pbuf; + void *ctx; #endif }; diff --git a/src/opengl/qglpixelbuffer_stub.cpp b/src/opengl/qglpixelbuffer_stub.cpp new file mode 100644 index 0000000..2caef6b --- /dev/null +++ b/src/opengl/qglpixelbuffer_stub.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtOpenGL 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 <qdebug.h> +#include "qglpixelbuffer.h" +#include "qglpixelbuffer_p.h" + +#include <qimage.h> +#include <private/qgl_p.h> + +QT_BEGIN_NAMESPACE + +bool QGLPixelBufferPrivate::init(const QSize &size, const QGLFormat &f, QGLWidget *shareWidget) +{ + Q_UNUSED(size); + Q_UNUSED(f); + Q_UNUSED(shareWidget); + return false; +} + +bool QGLPixelBufferPrivate::cleanup() +{ + return false; +} + +bool QGLPixelBuffer::bindToDynamicTexture(GLuint texture_id) +{ + Q_UNUSED(texture_id); + return false; +} + +void QGLPixelBuffer::releaseFromDynamicTexture() +{ +} + +GLuint QGLPixelBuffer::generateDynamicTexture() const +{ + return 0; +} + +bool QGLPixelBuffer::hasOpenGLPbuffers() +{ + return false; +} + +QT_END_NAMESPACE diff --git a/src/opengl/qwindowsurface_gl.cpp b/src/opengl/qwindowsurface_gl.cpp index cdd234a..47f36dd 100644 --- a/src/opengl/qwindowsurface_gl.cpp +++ b/src/opengl/qwindowsurface_gl.cpp @@ -314,7 +314,7 @@ QPaintEngine *QGLWindowSurfaceGLPaintDevice::paintEngine() const QGLWindowSurface::QGLWindowSurface(QWidget *window) : QWindowSurface(window), d_ptr(new QGLWindowSurfacePrivate) { - Q_ASSERT(window->isTopLevel()); +// Q_ASSERT(window->isTopLevel()); d_ptr->pb = 0; d_ptr->fbo = 0; d_ptr->ctx = 0; @@ -397,6 +397,8 @@ void QGLWindowSurface::hijackWindow(QWidget *widget) setPartialUpdateSupport(false); // Force full-screen updates else setPartialUpdateSupport(true); +#else + setPartialUpdateSupport(false); #endif widgetPrivate->extraData()->glContext = ctx; @@ -505,8 +507,13 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint & QWidget *parent = widget->internalWinId() ? widget : widget->nativeParentWidget(); Q_ASSERT(parent); +#if !defined(Q_WS_QPA) if (!geometry().isValid()) return; +#else + if (!size().isValid()) + return; +#endif // Needed to support native child-widgets... hijackWindow(parent); @@ -728,19 +735,31 @@ void QGLWindowSurface::flush(QWidget *widget, const QRegion &rgn, const QPoint & } +#if !defined(Q_WS_QPA) void QGLWindowSurface::setGeometry(const QRect &rect) { QWindowSurface::setGeometry(rect); d_ptr->geometry_updated = true; } - +#else +void QGLWindowSurface::resize(const QSize &size) +{ + QWindowSurface::resize(size); + d_ptr->geometry_updated = true; +} +#endif void QGLWindowSurface::updateGeometry() { if (!d_ptr->geometry_updated) return; d_ptr->geometry_updated = false; - QRect rect = geometry(); +#ifdef Q_WS_QPA + QSize surfSize = size(); +#else + QSize surfSize = geometry().size(); +#endif + hijackWindow(window()); QGLContext *ctx = reinterpret_cast<QGLContext *>(window()->d_func()->extraData()->glContext); @@ -750,18 +769,18 @@ void QGLWindowSurface::updateGeometry() { const GLenum target = GL_TEXTURE_2D; - if (rect.width() <= 0 || rect.height() <= 0) + if (surfSize.width() <= 0 || surfSize.height() <= 0) return; - if (d_ptr->size == rect.size()) + if (d_ptr->size == surfSize) return; - d_ptr->size = rect.size(); + d_ptr->size = surfSize; if (d_ptr->ctx) { #ifndef QT_OPENGL_ES_2 if (d_ptr->destructive_swap_buffers) - initializeOffscreenTexture(rect.size()); + initializeOffscreenTexture(surfSize); #endif return; } @@ -784,10 +803,10 @@ void QGLWindowSurface::updateGeometry() { if (QGLExtensions::glExtensions() & QGLExtensions::FramebufferBlit) format.setSamples(8); - d_ptr->fbo = new QGLFramebufferObject(rect.size(), format); + d_ptr->fbo = new QGLFramebufferObject(surfSize, format); if (d_ptr->fbo->isValid()) { - qDebug() << "Created Window Surface FBO" << rect.size() + qDebug() << "Created Window Surface FBO" << surfSize << "with samples" << d_ptr->fbo->format().samples(); return; } else { @@ -808,7 +827,7 @@ void QGLWindowSurface::updateGeometry() { delete d_ptr->pb; - d_ptr->pb = new QGLPixelBuffer(rect.width(), rect.height(), + d_ptr->pb = new QGLPixelBuffer(surfSize.width(), surfSize.height(), QGLFormat(QGL::SampleBuffers | QGL::StencilBuffer | QGL::DepthBuffer), qt_gl_share_widget()); @@ -818,7 +837,7 @@ void QGLWindowSurface::updateGeometry() { glGenTextures(1, &d_ptr->pb_tex_id); glBindTexture(target, d_ptr->pb_tex_id); - glTexImage2D(target, 0, GL_RGBA, rect.width(), rect.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + glTexImage2D(target, 0, GL_RGBA, surfSize.width(), surfSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -842,7 +861,7 @@ void QGLWindowSurface::updateGeometry() { #ifndef QT_OPENGL_ES_2 if (d_ptr->destructive_swap_buffers) - initializeOffscreenTexture(rect.size()); + initializeOffscreenTexture(surfSize); #endif qDebug() << "QGLWindowSurface: Using plain widget as window surface" << this;; diff --git a/src/opengl/qwindowsurface_gl_p.h b/src/opengl/qwindowsurface_gl_p.h index 6906f35..4f4ec92 100644 --- a/src/opengl/qwindowsurface_gl_p.h +++ b/src/opengl/qwindowsurface_gl_p.h @@ -89,7 +89,13 @@ public: QPaintDevice *paintDevice(); void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + +#if !defined(Q_WS_QPA) void setGeometry(const QRect &rect); +#else + virtual void resize(const QSize &size); +#endif + void updateGeometry(); bool scroll(const QRegion &area, int dx, int dy); diff --git a/src/plugins/generic/linuxinput/linuxinput.pro b/src/plugins/generic/linuxinput/linuxinput.pro new file mode 100644 index 0000000..ad9f6a9 --- /dev/null +++ b/src/plugins/generic/linuxinput/linuxinput.pro @@ -0,0 +1,18 @@ +TARGET = qlinuxinputplugin +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/generic +target.path = $$[QT_INSTALL_PLUGINS]/generic +INSTALLS += target + +DEFINES += QT_QWS_KBD_LINUXINPUT + +HEADERS = qlinuxinput.h + +SOURCES = main.cpp \ + qlinuxinput.cpp + +HEADERS += $$QT_SOURCE_TREE/src/gui/embedded/qkbd_qws.h \ + $$QT_SOURCE_TREE/src/gui/embedded/qkbd_qws_p.h + +SOURCES += $$QT_SOURCE_TREE/src/gui/embedded/qkbd_qws.cpp diff --git a/src/plugins/generic/linuxinput/main.cpp b/src/plugins/generic/linuxinput/main.cpp new file mode 100644 index 0000000..dc05254 --- /dev/null +++ b/src/plugins/generic/linuxinput/main.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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 <qgenericplugin_qpa.h> +#include "qlinuxinput.h" + +QT_BEGIN_NAMESPACE + +class QLinuxInputPlugin : public QGenericPlugin +{ +public: + QLinuxInputPlugin(); + + QStringList keys() const; + QObject* create(const QString &key, const QString &specification); +}; + +QLinuxInputPlugin::QLinuxInputPlugin() + : QGenericPlugin() +{ +} + +QStringList QLinuxInputPlugin::keys() const +{ + return (QStringList() + << QLatin1String("LinuxInputMouse") + << QLatin1String("LinuxInputKeyboard")); +} + +QObject* QLinuxInputPlugin::create(const QString &key, + const QString &specification) +{ + if (!key.compare(QLatin1String("LinuxInputMouse"), Qt::CaseInsensitive)) + return new QLinuxInputMouseHandler(key, specification); + if (!key.compare(QLatin1String("LinuxInputKeyboard"), Qt::CaseInsensitive)) + return new QLinuxInputKeyboardHandler(key, specification); + return 0; + } + +Q_EXPORT_PLUGIN2(qlinuxinputplugin, QLinuxInputPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/generic/linuxinput/qlinuxinput.cpp b/src/plugins/generic/linuxinput/qlinuxinput.cpp new file mode 100644 index 0000000..c5bfd33 --- /dev/null +++ b/src/plugins/generic/linuxinput/qlinuxinput.cpp @@ -0,0 +1,557 @@ +/**************************************************************************** +** +** 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 QtGui 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 "qlinuxinput.h" + + +#include <QSocketNotifier> +#include <QStringList> +#include <QPoint> +#include <QWindowSystemInterface> + +#include <qkbd_qws.h> + + +#include <qplatformdefs.h> +#include <private/qcore_unix_p.h> // overrides QT_OPEN + +#include <errno.h> +#include <termios.h> + +#include <linux/kd.h> +#include <linux/input.h> + +#include <qdebug.h> + +QT_BEGIN_NAMESPACE + + +//#define QT_QPA_EXPERIMENTAL_TOUCHEVENT + +#ifdef QT_QPA_EXPERIMENTAL_TOUCHEVENT +class QLinuxInputMouseHandlerData +{ +public: + QLinuxInputMouseHandlerData() :seenMT(false), state(QEvent::TouchBegin), currentIdx(0) {} + + void ensureCurrentPoint() { + if (currentIdx >= touchPoints.size()) { + Q_ASSERT(currentIdx == touchPoints.size()); + QWindowSystemInterface::TouchPoint tp; + tp.id = currentIdx; + tp.isPrimary = (currentIdx == 0); + tp.pressure = 1; + tp.area = QRectF(0,0,1,1); + tp.state = Qt::TouchPointReleased; // init in neutral state + touchPoints.append(tp); + } + } + void setCurrentPoint(int i) { + currentIdx = i; + if (currentIdx < touchPoints.size()) { + currentX = int(touchPoints[currentIdx].area.left()); + currentY = int(touchPoints[currentIdx].area.top()); + } else { + currentY = currentX = -999; + } + } + void advanceCurrentPoint() { + setCurrentPoint(currentIdx + 1); + } + int currentPoint() { return currentIdx; } + void setCurrentX(int value) { + ensureCurrentPoint(); + touchPoints[currentIdx].area.moveLeft(value); + } + bool currentMoved() { + return currentX != touchPoints[currentIdx].area.left() || currentY != touchPoints[currentIdx].area.top(); + } + void updateCurrentPos() { + ensureCurrentPoint(); + touchPoints[currentIdx].area.moveTopLeft(QPointF(currentX, currentY)); + } + void setCurrentState(Qt::TouchPointState state) { + ensureCurrentPoint(); + touchPoints[currentIdx].state = state; + } + Qt::TouchPointState currentState() const { + if (currentIdx < touchPoints.size()) + return touchPoints[currentIdx].state; + return Qt::TouchPointReleased; + } + QList<QWindowSystemInterface::TouchPoint> touchPoints; + int currentX; + int currentY; + bool seenMT; + QEvent::Type state; +private: + int currentIdx; +}; +#endif + + +QLinuxInputMouseHandler::QLinuxInputMouseHandler(const QString &key, + const QString &specification) + : m_notify(0), m_x(0), m_y(0), m_prevx(0), m_prevy(0), m_xoffset(0), m_yoffset(0), m_buttons(0), d(0) +{ + qDebug() << "QLinuxInputMouseHandler" << key << specification; + + + setObjectName(QLatin1String("LinuxInputSubsystem Mouse Handler")); + + QString dev = QLatin1String("/dev/input/event0"); + m_compression = true; + m_smooth = false; + int jitterLimit = 0; + + QStringList args = specification.split(QLatin1Char(':')); + foreach (const QString &arg, args) { + if (arg == "nocompress") + m_compression = false; + else if (arg.startsWith("dejitter=")) + jitterLimit = arg.mid(9).toInt(); + else if (arg.startsWith("xoffset=")) + m_xoffset = arg.mid(8).toInt(); + else if (arg.startsWith("yoffset=")) + m_yoffset = arg.mid(8).toInt(); + else if (arg.startsWith(QLatin1String("/dev/"))) + dev = arg; + } + m_jitterLimitSquared = jitterLimit*jitterLimit; + + m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDONLY | O_NDELAY, 0); + if (m_fd >= 0) { + m_notify = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData())); + } else { + qWarning("Cannot open mouse input device '%s': %s", qPrintable(dev), strerror(errno)); + return; + } +#ifdef QT_QPA_EXPERIMENTAL_TOUCHEVENT + d = new QLinuxInputMouseHandlerData; +#endif +} + + +QLinuxInputMouseHandler::~QLinuxInputMouseHandler() +{ + if (m_fd >= 0) + QT_CLOSE(m_fd); +#ifdef QT_QPA_EXPERIMENTAL_TOUCHEVENT + delete d; +#endif +} + +void QLinuxInputMouseHandler::sendMouseEvent(int x, int y, Qt::MouseButtons buttons) +{ + QPoint pos(x+m_xoffset, y+m_yoffset); + QWindowSystemInterface::handleMouseEvent(0, pos, pos, m_buttons); + m_prevx = x; + m_prevy = y; +} + +void QLinuxInputMouseHandler::readMouseData() +{ + struct ::input_event buffer[32]; + int n = 0; + bool posChanged = false; + bool pendingMouseEvent = false; + int eventCompressCount = 0; + forever { + n = QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n); + + if (n == 0) { + qWarning("Got EOF from the input device."); + return; + } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) { + qWarning("Could not read from input device: %s", strerror(errno)); + return; + } else if (n % sizeof(buffer[0]) == 0) { + break; + } + } + + n /= sizeof(buffer[0]); + + for (int i = 0; i < n; ++i) { + struct ::input_event *data = &buffer[i]; + //qDebug() << ">>" << hex << data->type << data->code << dec << data->value; + bool unknown = false; + if (data->type == EV_ABS) { + if (data->code == ABS_X && m_x != data->value) { + m_x = data->value; + posChanged = true; + } else if (data->code == ABS_Y && m_y != data->value) { + m_y = data->value; + posChanged = true; + } else if (data->code == ABS_PRESSURE) { + //ignore for now... + } else if (data->code == ABS_TOOL_WIDTH) { + //ignore for now... + } else if (data->code == ABS_HAT0X) { + //ignore for now... + } else if (data->code == ABS_HAT0Y) { + //ignore for now... +#ifdef QT_QPA_EXPERIMENTAL_TOUCHEVENT + } else if (data->code == ABS_MT_POSITION_X) { + d->currentX = data->value; + d->seenMT = true; + } else if (data->code == ABS_MT_POSITION_Y) { + d->currentY = data->value; + d->seenMT = true; + } else if (data->code == ABS_MT_TOUCH_MAJOR) { + if (data->value == 0) + d->setCurrentState(Qt::TouchPointReleased); + //otherwise, ignore for now... + } else if (data->code == ABS_MT_TOUCH_MINOR) { + //ignore for now... +#endif + } else { + unknown = true; + } + } else if (data->type == EV_REL) { + if (data->code == REL_X) { + m_x += data->value; + posChanged = true; + } else if (data->code == REL_Y) { + m_y += data->value; + posChanged = true; + } else if (data->code == ABS_WHEEL) { // vertical scroll + // data->value: 1 == up, -1 == down + int delta = 120 * data->value; + QWindowSystemInterface::handleWheelEvent(0, QPoint(m_x, m_y), + QPoint(m_x, m_y), + delta, Qt::Vertical); + } else if (data->code == ABS_THROTTLE) { // horizontal scroll + // data->value: 1 == right, -1 == left + int delta = 120 * -data->value; + QWindowSystemInterface::handleWheelEvent(0, QPoint(m_x, m_y), + QPoint(m_x, m_y), + delta, Qt::Horizontal); + } else { + unknown = true; + } + } else if (data->type == EV_KEY && data->code == BTN_TOUCH) { + m_buttons = data->value ? Qt::LeftButton : Qt::NoButton; + + sendMouseEvent(m_x, m_y, m_buttons); + pendingMouseEvent = false; + } else if (data->type == EV_KEY && data->code >= BTN_LEFT && data->code <= BTN_MIDDLE) { + Qt::MouseButton button = Qt::NoButton; + switch (data->code) { + case BTN_LEFT: button = Qt::LeftButton; break; + case BTN_MIDDLE: button = Qt::MidButton; break; + case BTN_RIGHT: button = Qt::RightButton; break; + } + if (data->value) + m_buttons |= button; + else + m_buttons &= ~button; + sendMouseEvent(m_x, m_y, m_buttons); + pendingMouseEvent = false; + } else if (data->type == EV_SYN && data->code == SYN_REPORT) { + if (posChanged) { + posChanged = false; + if (m_compression) { + pendingMouseEvent = true; + eventCompressCount++; + } else { + sendMouseEvent(m_x, m_y, m_buttons); + } + } +#ifdef QT_QPA_EXPERIMENTAL_TOUCHEVENT + if (d->state == QEvent::TouchBegin && !d->seenMT) { + //no multipoint-touch events to send + } else { + if (!d->seenMT) + d->state = QEvent::TouchEnd; + + for (int i = d->currentPoint(); i < d->touchPoints.size(); ++i) { + d->touchPoints[i].pressure = 0; + d->touchPoints[i].state = Qt::TouchPointReleased; + } + //qDebug() << "handleTouchEvent" << d->state << d->touchPoints.size() << d->touchPoints[0].state; + QWindowSystemInterface::handleTouchEvent(0, d->state, QTouchEvent::TouchScreen, d->touchPoints); + if (d->seenMT) { + d->state = QEvent::TouchUpdate; + } else { + d->state = QEvent::TouchBegin; + d->touchPoints.clear(); + } + d->setCurrentPoint(0); + d->seenMT = false; + } + } else if (data->type == EV_SYN && data->code == SYN_MT_REPORT) { + //store data for this touch point + + if (!d->seenMT) { + d->setCurrentState(Qt::TouchPointReleased); + } else if (d->currentState() == Qt::TouchPointReleased) { + d->updateCurrentPos(); + d->setCurrentState(Qt::TouchPointPressed); + } else if (d->currentMoved()) { + d->updateCurrentPos(); + d->setCurrentState(Qt::TouchPointMoved); + } else { + d->setCurrentState(Qt::TouchPointStationary); + } + //qDebug() << "end of point" << d->currentPoint() << d->currentX << d->currentY << d->currentState(); + + //advance to next tp: + d->advanceCurrentPoint(); +#endif + } else if (data->type == EV_MSC && data->code == MSC_SCAN) { + // kernel encountered an unmapped key - just ignore it + continue; + } else { + unknown = true; + } +#ifdef QLINUXINPUT_EXTRA_DEBUG + if (unknown) { + qWarning("unknown mouse event type=%x, code=%x, value=%x", data->type, data->code, data->value); + } +#endif + } + if (m_compression && pendingMouseEvent) { + int distanceSquared = (m_x - m_prevx)*(m_x - m_prevx) + (m_y - m_prevy)*(m_y - m_prevy); + if (distanceSquared > m_jitterLimitSquared) + sendMouseEvent(m_x, m_y, m_buttons); + } +} + + + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//Keyboard handler + + + + +class QWSLinuxInputKeyboardHandler : public QWSKeyboardHandler +{ +public: + QWSLinuxInputKeyboardHandler(const QString&); + ~QWSLinuxInputKeyboardHandler(); + + virtual bool filterInputEvent(quint16 &input_code, qint32 &input_value); + +//private: +// QWSLinuxInputKbPrivate *d; +}; + + +QWSLinuxInputKeyboardHandler::QWSLinuxInputKeyboardHandler(const QString &device) + : QWSKeyboardHandler(device) +{ +} + +QWSLinuxInputKeyboardHandler::~QWSLinuxInputKeyboardHandler() +{ +} + +bool QWSLinuxInputKeyboardHandler::filterInputEvent(quint16 &, qint32 &) +{ + return false; +} + + +QLinuxInputKeyboardHandler::QLinuxInputKeyboardHandler(const QString &key, const QString &specification) + : m_handler(0), m_fd(-1), m_tty_fd(-1), m_orig_kbmode(K_XLATE) +{ + setObjectName(QLatin1String("LinuxInputSubsystem Keyboard Handler")); + + QString dev = QLatin1String("/dev/input/event1"); + int repeat_delay = -1; + int repeat_rate = -1; + + bool ttymode = false; + + QStringList args = specification.split(QLatin1Char(':')); + foreach (const QString &arg, args) { + if (arg.startsWith(QLatin1String("repeat-delay="))) + repeat_delay = arg.mid(13).toInt(); + else if (arg.startsWith(QLatin1String("repeat-rate="))) + repeat_rate = arg.mid(12).toInt(); + else if (arg.startsWith(QLatin1String("ttymode"))) + ttymode = true; + else if (arg.startsWith(QLatin1String("/dev/"))) + dev = arg; + } + + m_handler = new QWSLinuxInputKeyboardHandler(dev); //This is a hack to avoid copying all the QWS code + + m_fd = QT_OPEN(dev.toLocal8Bit().constData(), O_RDWR, 0); + if (m_fd >= 0) { + if (repeat_delay > 0 && repeat_rate > 0) { + int kbdrep[2] = { repeat_delay, repeat_rate }; + ::ioctl(m_fd, EVIOCSREP, kbdrep); + } + + QSocketNotifier *notifier; + notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); + connect(notifier, SIGNAL(activated(int)), this, SLOT(readKeycode())); + + if (ttymode) { + // play nice in case we are started from a shell (e.g. for debugging) + m_tty_fd = isatty(0) ? 0 : -1; + + if (m_tty_fd >= 0) { + // save tty config for restore. + tcgetattr(m_tty_fd, &m_tty_attr); + + struct ::termios termdata; + tcgetattr(m_tty_fd, &termdata); + + // record the original mode so we can restore it again in the destructor. + ::ioctl(m_tty_fd, KDGKBMODE, &m_orig_kbmode); + + // setting this translation mode is even needed in INPUT mode to prevent + // the shell from also interpreting codes, if the process has a tty + // attached: e.g. Ctrl+C wouldn't copy, but kill the application. + ::ioctl(m_tty_fd, KDSKBMODE, K_MEDIUMRAW); + + // set the tty layer to pass-through + termdata.c_iflag = (IGNPAR | IGNBRK) & (~PARMRK) & (~ISTRIP); + termdata.c_oflag = 0; + termdata.c_cflag = CREAD | CS8; + termdata.c_lflag = 0; + termdata.c_cc[VTIME]=0; + termdata.c_cc[VMIN]=1; + cfsetispeed(&termdata, 9600); + cfsetospeed(&termdata, 9600); + tcsetattr(m_tty_fd, TCSANOW, &termdata); + } + } + } else { + qWarning("Cannot open keyboard input device '%s': %s", qPrintable(dev), strerror(errno)); + return; + } +} + +QLinuxInputKeyboardHandler::~QLinuxInputKeyboardHandler() +{ + if (m_tty_fd >= 0) { + ::ioctl(m_tty_fd, KDSKBMODE, m_orig_kbmode); + tcsetattr(m_tty_fd, TCSANOW, &m_tty_attr); + } + if (m_fd >= 0) + QT_CLOSE(m_fd); + delete m_handler; +} + +void QLinuxInputKeyboardHandler::switchLed(int led, bool state) +{ + struct ::input_event led_ie; + ::gettimeofday(&led_ie.time, 0); + led_ie.type = EV_LED; + led_ie.code = led; + led_ie.value = state; + + QT_WRITE(m_fd, &led_ie, sizeof(led_ie)); +} + + + +void QLinuxInputKeyboardHandler::readKeycode() +{ + struct ::input_event buffer[32]; + int n = 0; + + forever { + n = QT_READ(m_fd, reinterpret_cast<char *>(buffer) + n, sizeof(buffer) - n); + + if (n == 0) { + qWarning("Got EOF from the input device."); + return; + } else if (n < 0 && (errno != EINTR && errno != EAGAIN)) { + qWarning("Could not read from input device: %s", strerror(errno)); + return; + } else if (n % sizeof(buffer[0]) == 0) { + break; + } + } + + n /= sizeof(buffer[0]); + + for (int i = 0; i < n; ++i) { + if (buffer[i].type != EV_KEY) + continue; + + quint16 code = buffer[i].code; + qint32 value = buffer[i].value; + + if (m_handler->filterInputEvent(code, value)) + continue; + + QWSKeyboardHandler::KeycodeAction ka; + ka = m_handler->processKeycode(code, value != 0, value == 2); + + switch (ka) { + case QWSKeyboardHandler::CapsLockOn: + case QWSKeyboardHandler::CapsLockOff: + switchLed(LED_CAPSL, ka == QWSKeyboardHandler::CapsLockOn); + break; + + case QWSKeyboardHandler::NumLockOn: + case QWSKeyboardHandler::NumLockOff: + switchLed(LED_NUML, ka == QWSKeyboardHandler::NumLockOn); + break; + + case QWSKeyboardHandler::ScrollLockOn: + case QWSKeyboardHandler::ScrollLockOff: + switchLed(LED_SCROLLL, ka == QWSKeyboardHandler::ScrollLockOn); + break; + + default: + // ignore console switching and reboot + break; + } + } +} + + + + + +QT_END_NAMESPACE + diff --git a/src/plugins/generic/linuxinput/qlinuxinput.h b/src/plugins/generic/linuxinput/qlinuxinput.h new file mode 100644 index 0000000..c94c0f4 --- /dev/null +++ b/src/plugins/generic/linuxinput/qlinuxinput.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** 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 QtGui 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$ +** +****************************************************************************/ + +#ifndef QLINUXINPUT_H +#define QLINUXINPUT_H + +#include <qobject.h> +#include <Qt> +#include <termios.h> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QSocketNotifier; + +class QLinuxInputMouseHandlerData; + +class QLinuxInputMouseHandler : public QObject +{ + Q_OBJECT +public: + QLinuxInputMouseHandler(const QString &key, const QString &specification); + ~QLinuxInputMouseHandler(); + +private slots: + void readMouseData(); + +private: + void sendMouseEvent(int x, int y, Qt::MouseButtons buttons); + QSocketNotifier * m_notify; + int m_fd; + int m_x, m_y; + int m_prevx, m_prevy; + int m_xoffset, m_yoffset; + int m_smoothx, m_smoothy; + Qt::MouseButtons m_buttons; + bool m_compression; + bool m_smooth; + int m_jitterLimitSquared; + QLinuxInputMouseHandlerData *d; +}; + + +class QWSLinuxInputKeyboardHandler; + +class QLinuxInputKeyboardHandler : public QObject +{ + Q_OBJECT +public: + QLinuxInputKeyboardHandler(const QString &key, const QString &specification); + ~QLinuxInputKeyboardHandler(); + + +private: + void switchLed(int, bool); + +private slots: + void readKeycode(); + +private: + QWSLinuxInputKeyboardHandler *m_handler; + int m_fd; + int m_tty_fd; + struct termios m_tty_attr; + int m_orig_kbmode; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QLINUXINPUT_H diff --git a/src/plugins/generic/tslib/main.cpp b/src/plugins/generic/tslib/main.cpp new file mode 100644 index 0000000..502c6a0 --- /dev/null +++ b/src/plugins/generic/tslib/main.cpp @@ -0,0 +1,78 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 <qgenericplugin_qpa.h> +#include "qtslib.h" + +QT_BEGIN_NAMESPACE + +class QTsLibPlugin : public QGenericPlugin +{ +public: + QTsLibPlugin(); + + QStringList keys() const; + QObject* create(const QString &key, const QString &specification); +}; + +QTsLibPlugin::QTsLibPlugin() + : QGenericPlugin() +{ +} + +QStringList QTsLibPlugin::keys() const +{ + return (QStringList() + << QLatin1String("Tslib") + << QLatin1String("TslibRaw")); +} + +QObject* QTsLibPlugin::create(const QString &key, + const QString &specification) +{ + if (!key.compare(QLatin1String("Tslib"), Qt::CaseInsensitive) || !key.compare(QLatin1String("TslibRaw"), Qt::CaseInsensitive)) + return new QTsLibMouseHandler(key, specification); + return 0; + } + +Q_EXPORT_PLUGIN2(qtslibplugin, QTsLibPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/generic/tslib/qtslib.cpp b/src/plugins/generic/tslib/qtslib.cpp new file mode 100644 index 0000000..12963a0 --- /dev/null +++ b/src/plugins/generic/tslib/qtslib.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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 "qtslib.h" + + +#include <QSocketNotifier> +#include <QStringList> +#include <QPoint> +#include <QWindowSystemInterface> + +#include <Qt> + +#include <errno.h> +#include <tslib.h> + +#include <qdebug.h> + +QT_BEGIN_NAMESPACE + +QTsLibMouseHandler::QTsLibMouseHandler(const QString &key, + const QString &specification) + : m_notify(0), m_x(0), m_y(0), m_pressed(0), m_rawMode(false) +{ + qDebug() << "QTsLibMouseHandler" << key << specification; + setObjectName(QLatin1String("TSLib Mouse Handler")); + + QByteArray device = "/dev/input/event1"; + if (specification.startsWith("/dev/")) + device = specification.toLocal8Bit(); + + m_dev = ts_open(device.constData(), 1); + + if (ts_config(m_dev)) { + perror("Error configuring\n"); + } + + + m_rawMode = !key.compare(QLatin1String("TslibRaw"), Qt::CaseInsensitive); + + int fd = ts_fd(m_dev); + if (fd >= 0) { + m_notify = new QSocketNotifier(fd, QSocketNotifier::Read, this); + connect(m_notify, SIGNAL(activated(int)), this, SLOT(readMouseData())); + } else { + qWarning("Cannot open mouse input device '%s': %s", device.constData(), strerror(errno)); + return; + } +} + + +QTsLibMouseHandler::~QTsLibMouseHandler() +{ + if (m_dev) + ts_close(m_dev); +} + + +static bool get_sample(struct tsdev *dev, struct ts_sample *sample, bool rawMode) +{ + if (rawMode) { + return (ts_read_raw(dev, sample, 1) == 1); + } else { + int ret = ts_read(dev, sample, 1); + return ( ret == 1); + } +} + + +void QTsLibMouseHandler::readMouseData() +{ + ts_sample sample; + while (get_sample(m_dev, &sample, m_rawMode)) { + + bool pressed = sample.pressure; + int x = sample.x; + int y = sample.y; + + + if (!m_rawMode) { + //filtering: ignore movements of 2 pixels or less + int dx = x - m_x; + int dy = y - m_y; + if (dx*dx <= 4 && dy*dy <= 4 && pressed == m_pressed) + continue; + } else { + // work around missing coordinates on mouse release in raw mode + if (sample.pressure == 0 && sample.x == 0 && sample.y == 0) { + x = m_x; + y = m_y; + } + } + QPoint pos(x, y); + + //printf("handleMouseEvent %d %d %d %ld\n", m_x, m_y, pressed, sample.tv.tv_usec); + + QWindowSystemInterface::handleMouseEvent(0, pos, pos, pressed ? Qt::LeftButton : Qt::NoButton); + + m_x = x; + m_y = y; + m_pressed = pressed; + } +} + +QT_END_NAMESPACE diff --git a/src/plugins/generic/tslib/qtslib.h b/src/plugins/generic/tslib/qtslib.h new file mode 100644 index 0000000..5eab8b9 --- /dev/null +++ b/src/plugins/generic/tslib/qtslib.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtGui 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$ +** +****************************************************************************/ + +#ifndef QTSLIB_H +#define QTSLIB_H + +#include <qobject.h> +//#include <Qt> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QSocketNotifier; +struct tsdev; + +class QTsLibMouseHandler : public QObject +{ + Q_OBJECT +public: + QTsLibMouseHandler(const QString &key, const QString &specification); + ~QTsLibMouseHandler(); + +private slots: + void readMouseData(); + +private: + QSocketNotifier * m_notify; + tsdev *m_dev; + int m_x, m_y; + bool m_pressed; + bool m_rawMode; +}; + +QT_END_NAMESPACE + +QT_END_HEADER + +#endif // QTSLIB_H diff --git a/src/plugins/generic/tslib/tslib.pro b/src/plugins/generic/tslib/tslib.pro new file mode 100644 index 0000000..74c7fd2 --- /dev/null +++ b/src/plugins/generic/tslib/tslib.pro @@ -0,0 +1,13 @@ +TARGET = qlinuxinputplugin +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/generic +target.path = $$[QT_INSTALL_PLUGINS]/generic +INSTALLS += target + +HEADERS = qtslib.h + +SOURCES = main.cpp \ + qtslib.cpp + +LIBS += -lts diff --git a/src/plugins/graphicssystems/graphicssystems.pro b/src/plugins/graphicssystems/graphicssystems.pro index 29a1f34..5c99291 100644 --- a/src/plugins/graphicssystems/graphicssystems.pro +++ b/src/plugins/graphicssystems/graphicssystems.pro @@ -1,7 +1,9 @@ TEMPLATE = subdirs SUBDIRS += trace !wince*:contains(QT_CONFIG, opengl):SUBDIRS += opengl -contains(QT_CONFIG, openvg):contains(QT_CONFIG, egl):SUBDIRS += openvg +contains(QT_CONFIG, openvg):contains(QT_CONFIG, egl) { + SUBDIRS += openvg +} contains(QT_CONFIG, shivavg) { # Only works under X11 at present diff --git a/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp b/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp index 6bf9d6b..e2b9f99 100644 --- a/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp +++ b/src/plugins/graphicssystems/trace/qgraphicssystem_trace.cpp @@ -98,7 +98,11 @@ QPaintDevice *QTraceWindowSurface::paintDevice() { if (!buffer) { buffer = new QPaintBuffer; +#ifdef Q_WS_QPA + buffer->setBoundingRect(QRect(QPoint(), size())); +#else buffer->setBoundingRect(geometry()); +#endif } return buffer; } diff --git a/src/plugins/phonon/gstreamer/gstreamer.pro b/src/plugins/phonon/gstreamer/gstreamer.pro index 1013205..02e0848 100644 --- a/src/plugins/phonon/gstreamer/gstreamer.pro +++ b/src/plugins/phonon/gstreamer/gstreamer.pro @@ -58,7 +58,7 @@ SOURCES += $$PHONON_GSTREAMER_DIR/abstractrenderer.cpp \ $$PHONON_GSTREAMER_DIR/volumefadereffect.cpp \ $$PHONON_GSTREAMER_DIR/widgetrenderer.cpp -!embedded { +x11 { HEADERS += $$PHONON_GSTREAMER_DIR/x11renderer.h SOURCES += $$PHONON_GSTREAMER_DIR/x11renderer.cpp } diff --git a/src/plugins/platforms/cocoa/cocoa.pro b/src/plugins/platforms/cocoa/cocoa.pro new file mode 100644 index 0000000..1633ee4 --- /dev/null +++ b/src/plugins/platforms/cocoa/cocoa.pro @@ -0,0 +1,29 @@ +TARGET = qcocoa +include(../../qpluginbase.pri) +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +OBJECTIVE_SOURCES = main.mm \ + qcocoaintegration.mm \ + qcocoawindowsurface.mm \ + qcocoawindow.mm \ + qnsview.mm \ + qcocoaeventloopintegration.mm \ + qcocoaautoreleasepool.mm \ + qnswindowdelegate.mm + +OBJECTIVE_HEADERS = qcocoaintegration.h \ + qcocoawindowsurface.h \ + qcocoawindow.h \ + qnsview.h \ + qcocoaeventloopintegration.h \ + qcocoaautoreleasepool.h \ + qnswindowdelegate.h + +#add libz for freetype. +LIBS += -lz +LIBS += -framework cocoa + +include(../fontdatabases/coretext/coretext.pri) +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target + diff --git a/src/plugins/platforms/cocoa/main.mm b/src/plugins/platforms/cocoa/main.mm new file mode 100644 index 0000000..8be8883 --- /dev/null +++ b/src/plugins/platforms/cocoa/main.mm @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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 <Cocoa/Cocoa.h> + +#include <QtGui/QPlatformIntegrationPlugin> +#include "qcocoaintegration.h" + +QT_BEGIN_NAMESPACE + +class QCocoaIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QCocoaIntegrationPlugin::keys() const +{ + QStringList list; + list << "Cocoa"; + return list; +} + +QPlatformIntegration * QCocoaIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "cocoa") + return new QCocoaIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(Cocoa, QCocoaIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h new file mode 100644 index 0000000..47b94d1 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.h @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QCOCOAAUTORELEASEPOOL_H +#define QCOCOAAUTORELEASEPOOL_H + +#include <Cocoa/Cocoa.h> + +class QCocoaAutoReleasePool +{ +public: + QCocoaAutoReleasePool(); + ~QCocoaAutoReleasePool(); + +private: + NSAutoreleasePool *pool; +}; + +#endif // QCOCOAAUTORELEASEPOOL_H diff --git a/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm new file mode 100644 index 0000000..9a18fe2 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaautoreleasepool.mm @@ -0,0 +1,52 @@ +/**************************************************************************** +** +** 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 "qcocoaautoreleasepool.h" + +QCocoaAutoReleasePool::QCocoaAutoReleasePool() +{ + pool = [[NSAutoreleasePool alloc] init]; +} + +QCocoaAutoReleasePool::~QCocoaAutoReleasePool() +{ + [pool release]; +} diff --git a/src/plugins/platforms/cocoa/qcocoaeventloopintegration.h b/src/plugins/platforms/cocoa/qcocoaeventloopintegration.h new file mode 100644 index 0000000..8c21944 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaeventloopintegration.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QCOCAEVENTLOOPINTEGRATION_H +#define QCOCAEVENTLOOPINTEGRATION_H + +#include <Cocoa/Cocoa.h> + +#include <QPlatformEventLoopIntegration> + +@interface OurApplication: NSApplication +{ + bool shouldKeepRunning; +} + +- (void) run; +- (void) processEvents: (int) msec; + +@end + +class QCocoaEventLoopIntegration : public QPlatformEventLoopIntegration +{ +public: + QCocoaEventLoopIntegration(); + void processEvents( qint64 msec ); + void wakeup(); + + static int wakeupEventId; +private: + OurApplication *app; +}; + + + +#endif // QCOCAEVENTLOOPINTEGRATION_H + diff --git a/src/plugins/platforms/cocoa/qcocoaeventloopintegration.mm b/src/plugins/platforms/cocoa/qcocoaeventloopintegration.mm new file mode 100644 index 0000000..b184f90 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaeventloopintegration.mm @@ -0,0 +1,128 @@ +/**************************************************************************** +** +** 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 "qcocoaeventloopintegration.h" + +#import <Cocoa/Cocoa.h> + +#include "qcocoaautoreleasepool.h" + +#include <QtCore/QElapsedTimer> + +#include <QDebug> + +@implementation OurApplication + +- (void) run +{ + QCocoaAutoReleasePool pool; + [self finishLaunching]; + + shouldKeepRunning = YES; +} + +- (void) processEvents : (int) msec +{ + QCocoaAutoReleasePool pool; + Q_UNUSED(pool); + + QElapsedTimer timer; + timer.start(); + + NSTimeInterval seconds = NSTimeInterval(msec)/1000; + id untilDate = [NSDate dateWithTimeIntervalSinceNow:seconds]; + bool continueLooping = true; + while ((timer.elapsed() < (msec-1)) && continueLooping) { + NSEvent *event = + [self nextEventMatchingMask:NSAnyEventMask + untilDate:untilDate + inMode:NSDefaultRunLoopMode + dequeue:YES]; + if ([event type] == NSApplicationDefined + && [event subtype] == QCocoaEventLoopIntegration::wakeupEventId) { + continueLooping = false; + } else { + [self sendEvent:event]; + } + + } + [self updateWindows]; +} + +@end + +int QCocoaEventLoopIntegration::wakeupEventId = SHRT_MAX; + +QCocoaEventLoopIntegration::QCocoaEventLoopIntegration() : + QPlatformEventLoopIntegration() +{ + app = (OurApplication *)[OurApplication sharedApplication]; + [app run]; +} + +void QCocoaEventLoopIntegration::processEvents(qint64 msec) +{ + [app processEvents:msec]; +} + +void QCocoaEventLoopIntegration::wakeup() +{ + QCocoaAutoReleasePool pool; + Q_UNUSED(pool); + + NSPoint p = NSMakePoint(0,0); + NSWindow *nswin = [app keyWindow]; + double timestamp = (double)(AbsoluteToDuration(UpTime())) / 1000.0; + NSEvent *event = [NSEvent + otherEventWithType:NSApplicationDefined + location:NSZeroPoint + modifierFlags:0 + timestamp: timestamp + windowNumber:[nswin windowNumber] + context:0 + subtype:QCocoaEventLoopIntegration::wakeupEventId + data1:0 + data2:0 + ]; + [app postEvent:event atStart:NO]; + +} + diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.h b/src/plugins/platforms/cocoa/qcocoaintegration.h new file mode 100644 index 0000000..e7ecf2a --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaintegration.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QPLATFORMINTEGRATION_COCOA_H +#define QPLATFORMINTEGRATION_COCOA_H + +#include <Cocoa/Cocoa.h> + +#include "qcocoaautoreleasepool.h" + +#include <QtGui/QPlatformIntegration> + +QT_BEGIN_NAMESPACE + +class QCocoaScreen : public QPlatformScreen +{ +public: + QCocoaScreen(int screenIndex); + ~QCocoaScreen(); + + 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; } + +public: + NSScreen *m_screen; + QRect m_geometry; + int m_depth; + QImage::Format m_format; + QSize m_physicalSize; +}; + +class QCocoaIntegration : public QPlatformIntegration +{ +public: + QCocoaIntegration(); + ~QCocoaIntegration(); + + 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 { return mScreens; } + + QPlatformFontDatabase *fontDatabase() const; + + QPlatformEventLoopIntegration *createEventLoopIntegration() const; + +private: + QList<QPlatformScreen *> mScreens; + QPlatformFontDatabase *mFontDb; + + QCocoaAutoReleasePool *mPool; +}; + +QT_END_NAMESPACE + +#endif + diff --git a/src/plugins/platforms/cocoa/qcocoaintegration.mm b/src/plugins/platforms/cocoa/qcocoaintegration.mm new file mode 100644 index 0000000..79d5f51 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoaintegration.mm @@ -0,0 +1,122 @@ +/**************************************************************************** +** +** 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 "qcocoaintegration.h" + +#include "qcocoawindow.h" +#include "qcocoawindowsurface.h" +#include "qcocoaeventloopintegration.h" + +#include "qcoretextfontdatabase.h" + +#include <QtGui/QApplication> + +#include <private/qpixmap_raster_p.h> + +QT_BEGIN_NAMESPACE + +QCocoaScreen::QCocoaScreen(int screenIndex) + :QPlatformScreen() +{ + m_screen = [[NSScreen screens] objectAtIndex:screenIndex]; + NSRect rect = [m_screen frame]; + m_geometry = QRect(rect.origin.x,rect.origin.y,rect.size.width,rect.size.height); + + m_format = QImage::Format_ARGB32; + + m_depth = NSBitsPerPixelFromDepth([m_screen depth]); + + const int dpi = 72; + const qreal inch = 25.4; + m_physicalSize = QSize(qRound(m_geometry.width() * inch / dpi), qRound(m_geometry.height() *inch / dpi)); +} + +QCocoaScreen::~QCocoaScreen() +{ +} + +QCocoaIntegration::QCocoaIntegration() + : mFontDb(new QCoreTextFontDatabase()) +{ + mPool = new QCocoaAutoReleasePool; + + //Make sure we have a nsapplication :) + [OurApplication sharedApplication]; +// [[OurApplication alloc] init]; + + NSArray *screens = [NSScreen screens]; + for (uint i = 0; i < [screens count]; i++) { + QCocoaScreen *screen = new QCocoaScreen(i); + mScreens.append(screen); + } +} + +QCocoaIntegration::~QCocoaIntegration() +{ + delete mPool; +} + +QPixmapData *QCocoaIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QPlatformWindow *QCocoaIntegration::createPlatformWindow(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + return new QCocoaWindow(widget); +} + +QWindowSurface *QCocoaIntegration::createWindowSurface(QWidget *widget, WId winId) const +{ + return new QCocoaWindowSurface(widget,winId); +} + +QPlatformFontDatabase *QCocoaIntegration::fontDatabase() const +{ + return mFontDb; +} + +QPlatformEventLoopIntegration *QCocoaIntegration::createEventLoopIntegration() const +{ + return new QCocoaEventLoopIntegration(); +} +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qcocoawindow.h b/src/plugins/platforms/cocoa/qcocoawindow.h new file mode 100644 index 0000000..660e9f8 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoawindow.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QCOCOAWINDOW_H +#define QCOCOAWINDOW_H + +#include <Cocoa/Cocoa.h> + +#include <QPlatformWindow> + +QT_BEGIN_NAMESPACE + +class QCocoaWindow : public QPlatformWindow +{ +public: + QCocoaWindow(QWidget *tlw); + ~QCocoaWindow(); + + void setGeometry(const QRect &rect); + + void setVisible(bool visible); + + WId winId() const; + + NSView *contentView() const; + void setContentView(NSView *contentView); + + void windowDidResize(); + +private: + NSWindow *m_nsWindow; +}; + +QT_END_NAMESPACE + +#endif // QCOCOAWINDOW_H + diff --git a/src/plugins/platforms/cocoa/qcocoawindow.mm b/src/plugins/platforms/cocoa/qcocoawindow.mm new file mode 100644 index 0000000..f004cb8 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoawindow.mm @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** 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 "qcocoawindow.h" +#include "qnswindowdelegate.h" +#include "qcocoaautoreleasepool.h" + +#include <QWidget> + +#include <QtGui/QApplication> + +#include <QWindowSystemInterface> + +#include <QDebug> + +QCocoaWindow::QCocoaWindow(QWidget *tlw) + : QPlatformWindow(tlw) +{ + QCocoaAutoReleasePool pool; + const QRect geo = tlw->geometry(); + NSRect frame = NSMakeRect(geo.x(), geo.y(), geo.width(), geo.height()); + + m_nsWindow = [[NSWindow alloc] initWithContentRect:frame + styleMask:NSTitledWindowMask|NSClosableWindowMask|NSMiniaturizableWindowMask|NSResizableWindowMask + backing:NSBackingStoreBuffered + defer:YES]; + + QNSWindowDelegate *delegate = [[QNSWindowDelegate alloc] initWithQCocoaWindow:this]; + [m_nsWindow setDelegate:delegate]; + + [m_nsWindow makeKeyAndOrderFront:nil]; + [m_nsWindow setAcceptsMouseMovedEvents:YES]; +} + +QCocoaWindow::~QCocoaWindow() +{ +} + +void QCocoaWindow::setGeometry(const QRect &rect) +{ + QPlatformWindow::setGeometry(rect); + + NSRect bounds = NSMakeRect(rect.x(), rect.y(), rect.width(), rect.height()); + [[m_nsWindow contentView]setFrameSize:bounds.size]; +} + +void QCocoaWindow::setVisible(bool visible) +{ + Q_UNUSED(visible); +} + +WId QCocoaWindow::winId() const +{ + return WId([m_nsWindow windowNumber]); +} + +NSView *QCocoaWindow::contentView() const +{ + return [m_nsWindow contentView]; +} + +void QCocoaWindow::setContentView(NSView *contentView) +{ + [m_nsWindow setContentView:contentView]; +} + +void QCocoaWindow::windowDidResize() +{ + //jlind: XXX This isn't ideal. Eventdispatcher does not run when resizing... + NSRect rect = [[m_nsWindow contentView]frame]; + QRect geo(rect.origin.x,rect.origin.y,rect.size.width,rect.size.height); + if (geometry() != geo) { + widget()->setGeometry(geo); + QResizeEvent e(geo.size(), geometry().size()); + setGeometry(geo); + QApplication::sendEvent(widget(), &e); + widget()->repaint(); + } +} diff --git a/src/plugins/platforms/cocoa/qcocoawindowsurface.h b/src/plugins/platforms/cocoa/qcocoawindowsurface.h new file mode 100644 index 0000000..35f4064 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoawindowsurface.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_COCOA_H +#define QWINDOWSURFACE_COCOA_H + +#include <Cocoa/Cocoa.h> + +#include "qcocoawindow.h" +#include "qnsview.h" + +#include <QtGui/private/qwindowsurface_p.h> + +QT_BEGIN_NAMESPACE + +class QCocoaWindowSurface : public QWindowSurface +{ +public: + QCocoaWindowSurface(QWidget *window, WId wid); + ~QCocoaWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize (const QSize &size); + +private: + + QCocoaWindow *m_cocoaWindow; + QImage *m_image; + QNSView *m_contentView; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/cocoa/qcocoawindowsurface.mm b/src/plugins/platforms/cocoa/qcocoawindowsurface.mm new file mode 100644 index 0000000..443a486 --- /dev/null +++ b/src/plugins/platforms/cocoa/qcocoawindowsurface.mm @@ -0,0 +1,103 @@ +/**************************************************************************** +** +** 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 "qcocoawindowsurface.h" + +#include <QtCore/qdebug.h> + +#include <QtGui/QPainter> + +QT_BEGIN_NAMESPACE + +QRect flipedRect(const QRect &sourceRect,int height) +{ + if (!sourceRect.isValid()) + return QRect(); + QRect flippedRect = sourceRect; + flippedRect.moveTop(height - sourceRect.y()); + return flippedRect; +} + +QCocoaWindowSurface::QCocoaWindowSurface(QWidget *window, WId wId) + : QWindowSurface(window) +{ + m_cocoaWindow = static_cast<QCocoaWindow *>(window->platformWindow()); + + const QRect geo = window->geometry(); + NSRect rect = NSMakeRect(geo.x(),geo.y(),geo.width(),geo.height()); + m_contentView = [[QNSView alloc] initWithWidget:window]; + m_cocoaWindow->setContentView(m_contentView); + + m_image = new QImage(window->size(),QImage::Format_ARGB32); +} + +QCocoaWindowSurface::~QCocoaWindowSurface() +{ + delete m_image; +} + +QPaintDevice *QCocoaWindowSurface::paintDevice() +{ + return m_image; +} + +void QCocoaWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(offset); + + QRect geo = region.boundingRect(); + + NSRect rect = NSMakeRect(geo.x(), geo.y(), geo.width(), geo.height()); + [m_contentView displayRect:rect]; +} + +void QCocoaWindowSurface::resize(const QSize &size) +{ + QWindowSurface::resize(size); + delete m_image; + m_image = new QImage(size,QImage::Format_ARGB32_Premultiplied); + NSSize newSize = NSMakeSize(size.width(),size.height()); + [m_contentView setImage:m_image]; + +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/cocoa/qnsview.h b/src/plugins/platforms/cocoa/qnsview.h new file mode 100644 index 0000000..0523725 --- /dev/null +++ b/src/plugins/platforms/cocoa/qnsview.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QNSVIEW_H +#define QNSVIEW_H + +#include <Cocoa/Cocoa.h> + +#include <QtGui/QImage> + +@interface QNSView : NSView { + CGImageRef m_cgImage; + QWidget *m_widget; + Qt::MouseButtons m_buttons; +} + +- (id)init; +- (id)initWithWidget:(QWidget *)widget; + +- (void)setImage:(QImage *)image; +- (void)drawRect:(NSRect)dirtyRect; + +- (BOOL)isFlipped; + +- (void)handleMouseEvent:(NSEvent *)theEvent; +- (void)mouseDown:(NSEvent *)theEvent; +- (void)mouseDragged:(NSEvent *)theEvent; +- (void)mouseUp:(NSEvent *)theEvent; +- (void)mouseMoved:(NSEvent *)theEvent; +- (void)mouseEntered:(NSEvent *)theEvent; +- (void)mouseExited:(NSEvent *)theEvent; +- (void)rightMouseDown:(NSEvent *)theEvent; +- (void)rightMouseDragged:(NSEvent *)theEvent; +- (void)rightMouseUp:(NSEvent *)theEvent; +- (void)otherMouseDown:(NSEvent *)theEvent; +- (void)otherMouseDragged:(NSEvent *)theEvent; +- (void)otherMouseUp:(NSEvent *)theEvent; + +@end + +#endif //QNSVIEW_H diff --git a/src/plugins/platforms/cocoa/qnsview.mm b/src/plugins/platforms/cocoa/qnsview.mm new file mode 100644 index 0000000..60de6ba --- /dev/null +++ b/src/plugins/platforms/cocoa/qnsview.mm @@ -0,0 +1,211 @@ +/**************************************************************************** +** +** 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 "qnsview.h" + +#include <QtGui/QWindowSystemInterface> + +#include <QtCore/QDebug> + +@implementation QNSView + +- (id) init +{ + self = [super init]; + if (self) { + m_cgImage = 0; + m_widget = 0; + m_buttons = Qt::NoButton; + } + return self; +} + +- (id)initWithWidget:(QWidget *)widget { + self = [self init]; + if (self) { + m_widget = widget; + } + return self; +} + +- (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, + kCGImageAlphaNone, + cgDataProviderRef, + NULL, + false, + kCGRenderingIntentDefault); + + CGColorSpaceRelease(cgColourSpaceRef); + +} + +- (void) drawRect:(NSRect)dirtyRect +{ + if (!m_cgImage) + return; + + CGRect dirtyCGRect = NSRectToCGRect(dirtyRect); + + NSGraphicsContext *nsGraphicsContext = [NSGraphicsContext currentContext]; + CGContextRef cgContext = (CGContextRef) [nsGraphicsContext graphicsPort]; + + CGContextSaveGState( cgContext ); + int dy = dirtyCGRect.origin.y + CGRectGetMaxY(dirtyCGRect); + CGContextTranslateCTM(cgContext, 0, dy); + CGContextScaleCTM(cgContext, 1, -1); + + CGImageRef subImage = CGImageCreateWithImageInRect(m_cgImage, dirtyCGRect); + CGContextDrawImage(cgContext,dirtyCGRect,subImage); + + CGContextRestoreGState(cgContext); + + CGImageRelease(subImage); + +} + +- (BOOL) isFlipped +{ + return YES; +} + +- (void)handleMouseEvent:(NSEvent *)theEvent; +{ + NSPoint point = [self convertPoint: [theEvent locationInWindow] fromView: nil]; + QPoint qt_localPoint(point.x,point.y); + + NSTimeInterval timestamp = [theEvent timestamp]; + ulong qt_timestamp = timestamp * 1000; + + QWindowSystemInterface::handleMouseEvent(m_widget,qt_timestamp,qt_localPoint,QPoint(),m_buttons); + +} + - (void)mouseDown:(NSEvent *)theEvent + { + m_buttons |= Qt::LeftButton; + [self handleMouseEvent:theEvent]; + } + - (void)mouseDragged:(NSEvent *)theEvent + { + if (!(m_buttons & Qt::LeftButton)) + qWarning("Internal Mousebutton tracking invalid(missing Qt::LeftButton"); + [self handleMouseEvent:theEvent]; + } + - (void)mouseUp:(NSEvent *)theEvent + { + m_buttons &= QFlag(~int(Qt::LeftButton)); + [self handleMouseEvent:theEvent]; + } + +- (void)mouseMoved:(NSEvent *)theEvent +{ + qDebug() << "mouseMove"; + [self handleMouseEvent:theEvent]; +} +- (void)mouseEntered:(NSEvent *)theEvent +{ + Q_UNUSED(theEvent); + QWindowSystemInterface::handleEnterEvent(m_widget); +} +- (void)mouseExited:(NSEvent *)theEvent +{ + Q_UNUSED(theEvent); + QWindowSystemInterface::handleLeaveEvent(m_widget); +} +- (void)rightMouseDown:(NSEvent *)theEvent +{ + m_buttons |= Qt::RightButton; + [self handleMouseEvent:theEvent]; +} +- (void)rightMouseDragged:(NSEvent *)theEvent +{ + if (!(m_buttons & Qt::LeftButton)) + qWarning("Internal Mousebutton tracking invalid(missing Qt::LeftButton"); + [self handleMouseEvent:theEvent]; +} +- (void)rightMouseUp:(NSEvent *)theEvent +{ + m_buttons &= QFlag(~int(Qt::RightButton)); + [self handleMouseEvent:theEvent]; +} +- (void)otherMouseDown:(NSEvent *)theEvent +{ + m_buttons |= Qt::RightButton; + [self handleMouseEvent:theEvent]; +} +- (void)otherMouseDragged:(NSEvent *)theEvent +{ + if (!(m_buttons & Qt::LeftButton)) + qWarning("Internal Mousebutton tracking invalid(missing Qt::LeftButton"); + [self handleMouseEvent:theEvent]; +} +- (void)otherMouseUp:(NSEvent *)theEvent +{ + m_buttons &= QFlag(~int(Qt::MiddleButton)); + [self handleMouseEvent:theEvent]; +} + + + +@end diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.h b/src/plugins/platforms/cocoa/qnswindowdelegate.h new file mode 100644 index 0000000..9fc1d63 --- /dev/null +++ b/src/plugins/platforms/cocoa/qnswindowdelegate.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QNSWINDOWDELEGATE_H +#define QNSWINDOWDELEGATE_H + +#include <Cocoa/Cocoa.h> + +#include "qcocoawindow.h" + +@interface QNSWindowDelegate : NSObject <NSWindowDelegate> +{ + QCocoaWindow *m_cocoaWindow; +} + +- (id)initWithQCocoaWindow: (QCocoaWindow *) cocoaWindow; + +- (void)windowDidResize:(NSNotification *)notification; +- (void)windowWillClose:(NSNotification *)notification; + +@end + +#endif // QNSWINDOWDELEGATE_H diff --git a/src/plugins/platforms/cocoa/qnswindowdelegate.mm b/src/plugins/platforms/cocoa/qnswindowdelegate.mm new file mode 100644 index 0000000..c04602b --- /dev/null +++ b/src/plugins/platforms/cocoa/qnswindowdelegate.mm @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 "qnswindowdelegate.h" + +#include <QDebug> +#include <QWindowSystemInterface> + +@implementation QNSWindowDelegate + +- (id) initWithQCocoaWindow: (QCocoaWindow *) cocoaWindow +{ + self = [super init]; + + if (self) { + m_cocoaWindow = cocoaWindow; + } + return self; +} + +- (void)windowDidResize:(NSNotification *)notification +{ + Q_UNUSED(notification); + if (m_cocoaWindow) { + m_cocoaWindow->windowDidResize(); + } +} + +- (void)windowWillClose:(NSNotification *)notification +{ + Q_UNUSED(notification); + QWindowSystemInterface::handleCloseEvent(m_cocoaWindow->widget()); +} + +@end diff --git a/src/plugins/platforms/directfb/directfb.pro b/src/plugins/platforms/directfb/directfb.pro new file mode 100644 index 0000000..65c49e3 --- /dev/null +++ b/src/plugins/platforms/directfb/directfb.pro @@ -0,0 +1,35 @@ +TARGET = qdirectfb +include(../../qpluginbase.pri) +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +isEmpty(DIRECTFB_LIBS) { + DIRECTFB_LIBS = -ldirectfb -lfusion -ldirect -lpthread +} +isEmpty(DIRECTFB_INCLUDEPATH) { + DIRECTFB_INCLUDEPATH = /usr/include/directfb +} + +INCLUDEPATH += $$DIRECTFB_INCLUDEPATH +LIBS += $$DIRECTFB_LIBS + +SOURCES = main.cpp \ + qdirectfbintegration.cpp \ + qdirectfbwindowsurface.cpp \ + qdirectfbblitter.cpp \ + qdirectfbconvenience.cpp \ + qdirectfbinput.cpp \ + qdirectfbcursor.cpp \ + qdirectfbwindow.cpp \ + qdirectfbglcontext.cpp +HEADERS = qdirectfbintegration.h \ + qdirectfbwindowsurface.h \ + qdirectfbblitter.h \ + qdirectfbconvenience.h \ + qdirectfbinput.h \ + qdirectfbcursor.h \ + qdirectfbwindow.h \ + qdirectfbglcontext.h + +include(../fontdatabases/genericunix/genericunix.pri) +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target diff --git a/src/plugins/platforms/directfb/main.cpp b/src/plugins/platforms/directfb/main.cpp new file mode 100644 index 0000000..f4ece32 --- /dev/null +++ b/src/plugins/platforms/directfb/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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 <QtGui/QPlatformIntegrationPlugin> +#include "qdirectfbintegration.h" + +QT_BEGIN_NAMESPACE + +class QDirectFbIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QDirectFbIntegrationPlugin::keys() const +{ + QStringList list; + list << "directfb"; + return list; +} + +QPlatformIntegration * QDirectFbIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "directfb") + return new QDirectFbIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(directfb, QDirectFbIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/directfb/qdirectfbblitter.cpp b/src/plugins/platforms/directfb/qdirectfbblitter.cpp new file mode 100644 index 0000000..d379b65 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbblitter.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qdirectfbblitter.h" +#include "qdirectfbconvenience.h" + +#include <QtGui/private/qpixmap_blitter_p.h> + +#include <QDebug> + +#include <directfb.h> + +QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, IDirectFBSurface *surface) + : QBlittable(rect, QBlittable::Capabilities(QBlittable::SolidRectCapability + |QBlittable::SourcePixmapCapability + |QBlittable::SourceOverPixmapCapability + |QBlittable::SourceOverScaledPixmapCapability)) +{ + if (surface) { + m_surface = surface; + } else { + DFBSurfaceDescription surfaceDesc; + memset(&surfaceDesc,0,sizeof(DFBSurfaceDescription)); + surfaceDesc.width = rect.width(); + surfaceDesc.height = rect.height(); + surfaceDesc.caps = DSCAPS_PREMULTIPLIED; + surfaceDesc.pixelformat = DSPF_ARGB; + surfaceDesc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_CAPS | DSDESC_PIXELFORMAT); + + IDirectFB *dfb = QDirectFbConvenience::dfbInterface(); + dfb->CreateSurface(dfb,&surfaceDesc, &m_surface); + m_surface->Clear(m_surface,0,0,0,0); + } + +} + +QDirectFbBlitter::~QDirectFbBlitter() +{ + unlock(); + m_surface->Release(m_surface); +} + +void QDirectFbBlitter::fillRect(const QRectF &rect, const QColor &color) +{ + m_surface->SetColor(m_surface, color.red(), color.green(), color.blue(), color.alpha()); +// When the blitter api supports non opaque blits, also remember to change +// qpixmap_blitter.cpp::fill +// DFBSurfaceDrawingFlags drawingFlags = color.alpha() ? DSDRAW_BLEND : DSDRAW_NOFX; +// m_surface->SetDrawingFlags(m_surface, drawingFlags); + m_surface->SetDrawingFlags(m_surface, DSDRAW_NOFX); + m_surface->FillRectangle(m_surface, rect.x(), rect.y(), + rect.width(), rect.height()); +} + +void QDirectFbBlitter::drawPixmap(const QRectF &rect, const QPixmap &pixmap, const QRectF &srcRect) +{ + QPixmapData *data = pixmap.pixmapData(); + Q_ASSERT(data->width() && data->height()); + Q_ASSERT(data->classId() == QPixmapData::BlitterClass); + QBlittablePixmapData *blitPm = static_cast<QBlittablePixmapData*>(data); + QDirectFbBlitter *dfbBlitter = static_cast<QDirectFbBlitter *>(blitPm->blittable()); + dfbBlitter->unlock(); + + IDirectFBSurface *s = dfbBlitter->m_surface; + + DFBSurfaceBlittingFlags blittingFlags = DSBLIT_NOFX; + DFBSurfacePorterDuffRule porterDuff = DSPD_SRC; + if (pixmap.hasAlpha()) { + blittingFlags = DSBLIT_BLEND_ALPHACHANNEL; + porterDuff = DSPD_SRC_OVER; + } + + m_surface->SetBlittingFlags(m_surface, DFBSurfaceBlittingFlags(blittingFlags)); + m_surface->SetPorterDuff(m_surface,porterDuff); + m_surface->SetDstBlendFunction(m_surface,DSBF_INVSRCALPHA); + + const DFBRectangle sRect = { srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height() }; + + DFBResult result; + if (rect.width() == srcRect.width() && rect.height() == srcRect.height()) + result = m_surface->Blit(m_surface, s, &sRect, rect.x(), rect.y()); + else { + const DFBRectangle dRect = { rect.x(), rect.y(), rect.width(), rect.height() }; + result = m_surface->StretchBlit(m_surface, s, &sRect, &dRect); + } + if (result != DFB_OK) + DirectFBError("QDirectFBBlitter::drawPixmap()", result); +} + +QImage *QDirectFbBlitter::doLock() +{ + Q_ASSERT(m_surface); + Q_ASSERT(size().isValid()); + + void *mem; + int bpl; + const DFBResult result = m_surface->Lock(m_surface, DFBSurfaceLockFlags(DSLF_WRITE|DSLF_READ), static_cast<void**>(&mem), &bpl); + if (result == DFB_OK) { + DFBSurfacePixelFormat dfbFormat; + DFBSurfaceCapabilities dfbCaps; + m_surface->GetPixelFormat(m_surface,&dfbFormat); + m_surface->GetCapabilities(m_surface,&dfbCaps); + QImage::Format format = QDirectFbConvenience::imageFormatFromSurfaceFormat(dfbFormat, dfbCaps); + int w, h; + m_surface->GetSize(m_surface,&w,&h); + m_image = QImage(static_cast<uchar *>(mem),w,h,bpl,format); + } else { + DirectFBError("Failed to lock image", result); + } + + return &m_image; +} + +void QDirectFbBlitter::doUnlock() +{ + m_surface->Unlock(m_surface); +} diff --git a/src/plugins/platforms/directfb/qdirectfbblitter.h b/src/plugins/platforms/directfb/qdirectfbblitter.h new file mode 100644 index 0000000..1e874ba --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbblitter.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QDIRECTFBBLITTER_H +#define QDIRECTFBBLITTER_H + +#include "qdirectfbconvenience.h" + +#include <private/qblittable_p.h> + +#include <directfb.h> + +class QDirectFbBlitter : public QBlittable +{ +public: + QDirectFbBlitter(const QSize &size, IDirectFBSurface *surface = 0); + virtual ~QDirectFbBlitter(); + + virtual void fillRect(const QRectF &rect, const QColor &color); + virtual void drawPixmap(const QRectF &rect, const QPixmap &pixmap, const QRectF &subrect); + +protected: + virtual QImage *doLock(); + virtual void doUnlock(); + + IDirectFBSurface *m_surface; + QImage m_image; + + friend class QDirectFbConvenience; +}; + +class QDirectFbBlitterPixmapData : public QBlittablePixmapData +{ +public: + QBlittable *createBlittable(const QSize &size) const { return new QDirectFbBlitter(size); } +}; + +#endif // QDIRECTFBBLITTER_H diff --git a/src/plugins/platforms/directfb/qdirectfbconvenience.cpp b/src/plugins/platforms/directfb/qdirectfbconvenience.cpp new file mode 100644 index 0000000..91a1b3a --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbconvenience.cpp @@ -0,0 +1,376 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qdirectfbconvenience.h" +#include "qdirectfbblitter.h" + +#include <private/qpixmap_blitter_p.h> + +IDirectFB *QDirectFbConvenience::dfbInterface() +{ + static IDirectFB *dfb = 0; + if (!dfb) { + DFBResult result = DirectFBCreate(&dfb); + if (result != DFB_OK) { + DirectFBError("QDirectFBConvenience: error creating DirectFB interface",result); + return 0; + } + } + return dfb; +} + +IDirectFBDisplayLayer *QDirectFbConvenience::dfbDisplayLayer(int display) +{ + IDirectFBDisplayLayer *layer; + DFBResult result = QDirectFbConvenience::dfbInterface()->GetDisplayLayer(QDirectFbConvenience::dfbInterface(),display,&layer); + if (result != DFB_OK) { + DirectFBError("QDirectFbConvenience: " + "Unable to get primary display layer!", result); + } + return layer; +} + +QImage::Format QDirectFbConvenience::imageFormatFromSurfaceFormat(const DFBSurfacePixelFormat format, const DFBSurfaceCapabilities caps) +{ + switch (format) { + case DSPF_LUT8: + return QImage::Format_Indexed8; + case DSPF_RGB24: + return QImage::Format_RGB888; + case DSPF_ARGB4444: + return QImage::Format_ARGB4444_Premultiplied; + case DSPF_RGB444: + return QImage::Format_RGB444; + case DSPF_RGB555: + case DSPF_ARGB1555: + return QImage::Format_RGB555; + case DSPF_RGB16: + return QImage::Format_RGB16; + case DSPF_ARGB6666: + return QImage::Format_ARGB6666_Premultiplied; + case DSPF_RGB18: + return QImage::Format_RGB666; + case DSPF_RGB32: + return QImage::Format_RGB32; + case DSPF_ARGB: { + if (caps & DSCAPS_PREMULTIPLIED) + return QImage::Format_ARGB32_Premultiplied; + else return QImage::Format_ARGB32; } + default: + break; + } + return QImage::Format_Invalid; + +} + +int QDirectFbConvenience::colorDepthForSurface(const DFBSurfacePixelFormat format) +{ + return ((0x1f << 7) & format) >> 7; +} + +IDirectFBSurface *QDirectFbConvenience::dfbSurfaceForPixmapData(QPixmapData *pixmapData) +{ + QBlittablePixmapData *blittablePmData = static_cast<QBlittablePixmapData *>(pixmapData); + if (blittablePmData) { + QBlittable *blittable = blittablePmData->blittable(); + QDirectFbBlitter *dfbBlitter = static_cast<QDirectFbBlitter *>(blittable); + return dfbBlitter->m_surface; + } + return 0; +} + +Qt::MouseButton QDirectFbConvenience::mouseButton(DFBInputDeviceButtonIdentifier identifier) +{ + switch (identifier){ + case DIBI_LEFT: + return Qt::LeftButton; + case DIBI_MIDDLE: + return Qt::MidButton; + case DIBI_RIGHT: + return Qt::RightButton; + default: + return Qt::NoButton; + } +} + +Qt::MouseButtons QDirectFbConvenience::mouseButtons(DFBInputDeviceButtonMask mask) +{ + Qt::MouseButtons buttons = Qt::NoButton; + + if (mask & DIBM_LEFT) { + buttons |= Qt::LeftButton; + } + if (mask & DIBM_MIDDLE) { + buttons |= Qt::MidButton; + } + if (mask & DIBM_RIGHT) { + buttons |= Qt::RightButton; + } + return buttons; +} + +Qt::KeyboardModifiers QDirectFbConvenience::keyboardModifiers(DFBInputDeviceModifierMask mask) +{ + Qt::KeyboardModifiers modifiers = Qt::NoModifier; + + if (mask & DIMM_SHIFT) { + modifiers |= Qt::ShiftModifier; + } + if (mask & DIMM_ALT) { + modifiers |= Qt::AltModifier; + } + if (mask & DIMM_ALTGR) { + modifiers |= Qt::MetaModifier; + } + if (mask & DIMM_CONTROL) { + modifiers |= Qt::ControlModifier; + } + if (mask & DIMM_META) { + modifiers | Qt::MetaModifier; + } + return modifiers; +} + +QEvent::Type QDirectFbConvenience::eventType(DFBWindowEventType type) +{ + switch(type) { + case DWET_BUTTONDOWN: + return QEvent::MouseButtonPress; + case DWET_BUTTONUP: + return QEvent::MouseButtonRelease; + case DWET_MOTION: + return QEvent::MouseMove; + case DWET_WHEEL: + return QEvent::Wheel; + case DWET_KEYDOWN: + return QEvent::KeyPress; + case DWET_KEYUP: + return QEvent::KeyRelease; + default: + return QEvent::None; + } +} +QDirectFbKeyMap *QDirectFbConvenience::dfbKeymap = 0; +QDirectFbKeyMap *QDirectFbConvenience::keyMap() +{ + if (!dfbKeymap) + dfbKeymap = new QDirectFbKeyMap(); + return dfbKeymap; +} + +QDirectFbKeyMap::QDirectFbKeyMap() +{ + insert(DIKS_BACKSPACE , Qt::Key_Backspace); + insert(DIKS_TAB , Qt::Key_Tab); + insert(DIKS_RETURN , Qt::Key_Return); + insert(DIKS_ESCAPE , Qt::Key_Escape); + insert(DIKS_DELETE , Qt::Key_Delete); + + insert(DIKS_CURSOR_LEFT , Qt::Key_Left); + insert(DIKS_CURSOR_RIGHT , Qt::Key_Right); + insert(DIKS_CURSOR_UP , Qt::Key_Up); + insert(DIKS_CURSOR_DOWN , Qt::Key_Down); + insert(DIKS_INSERT , Qt::Key_Insert); + insert(DIKS_HOME , Qt::Key_Home); + insert(DIKS_END , Qt::Key_End); + insert(DIKS_PAGE_UP , Qt::Key_PageUp); + insert(DIKS_PAGE_DOWN , Qt::Key_PageDown); + insert(DIKS_PRINT , Qt::Key_Print); + insert(DIKS_PAUSE , Qt::Key_Pause); + insert(DIKS_SELECT , Qt::Key_Select); + insert(DIKS_GOTO , Qt::Key_OpenUrl); + insert(DIKS_CLEAR , Qt::Key_Clear); + insert(DIKS_MENU , Qt::Key_Menu); + insert(DIKS_HELP , Qt::Key_Help); + + insert(DIKS_INTERNET , Qt::Key_HomePage); + insert(DIKS_MAIL , Qt::Key_LaunchMail); + insert(DIKS_FAVORITES , Qt::Key_Favorites); + + insert(DIKS_BACK , Qt::Key_Back); + insert(DIKS_FORWARD , Qt::Key_Forward); + insert(DIKS_VOLUME_UP , Qt::Key_VolumeUp); + insert(DIKS_VOLUME_DOWN , Qt::Key_VolumeDown); + insert(DIKS_MUTE , Qt::Key_VolumeMute); + insert(DIKS_PLAYPAUSE , Qt::Key_Pause); + insert(DIKS_PLAY , Qt::Key_MediaPlay); + insert(DIKS_STOP , Qt::Key_MediaStop); + insert(DIKS_RECORD , Qt::Key_MediaRecord); + insert(DIKS_PREVIOUS , Qt::Key_MediaPrevious); + insert(DIKS_NEXT , Qt::Key_MediaNext); + + insert(DIKS_F1 , Qt::Key_F1); + insert(DIKS_F2 , Qt::Key_F2); + insert(DIKS_F3 , Qt::Key_F3); + insert(DIKS_F4 , Qt::Key_F4); + insert(DIKS_F5 , Qt::Key_F5); + insert(DIKS_F6 , Qt::Key_F6); + insert(DIKS_F7 , Qt::Key_F7); + insert(DIKS_F8 , Qt::Key_F8); + insert(DIKS_F9 , Qt::Key_F9); + insert(DIKS_F10 , Qt::Key_F10); + insert(DIKS_F11 , Qt::Key_F11); + insert(DIKS_F12 , Qt::Key_F12); + + insert(DIKS_SHIFT , Qt::Key_Shift); + insert(DIKS_CONTROL , Qt::Key_Control); + insert(DIKS_ALT , Qt::Key_Alt); + insert(DIKS_ALTGR , Qt::Key_AltGr); + + insert(DIKS_META , Qt::Key_Meta); + insert(DIKS_SUPER , Qt::Key_Super_L); // ??? + insert(DIKS_HYPER , Qt::Key_Hyper_L); // ??? + + insert(DIKS_CAPS_LOCK , Qt::Key_CapsLock); + insert(DIKS_NUM_LOCK , Qt::Key_NumLock); + insert(DIKS_SCROLL_LOCK , Qt::Key_ScrollLock); + + insert(DIKS_DEAD_ABOVEDOT , Qt::Key_Dead_Abovedot); + insert(DIKS_DEAD_ABOVERING , Qt::Key_Dead_Abovering); + insert(DIKS_DEAD_ACUTE , Qt::Key_Dead_Acute); + insert(DIKS_DEAD_BREVE , Qt::Key_Dead_Breve); + insert(DIKS_DEAD_CARON , Qt::Key_Dead_Caron); + insert(DIKS_DEAD_CEDILLA , Qt::Key_Dead_Cedilla); + insert(DIKS_DEAD_CIRCUMFLEX , Qt::Key_Dead_Circumflex); + insert(DIKS_DEAD_DIAERESIS , Qt::Key_Dead_Diaeresis); + insert(DIKS_DEAD_DOUBLEACUTE , Qt::Key_Dead_Doubleacute); + insert(DIKS_DEAD_GRAVE , Qt::Key_Dead_Grave); + insert(DIKS_DEAD_IOTA , Qt::Key_Dead_Iota); + insert(DIKS_DEAD_MACRON , Qt::Key_Dead_Macron); + insert(DIKS_DEAD_OGONEK , Qt::Key_Dead_Ogonek); + insert(DIKS_DEAD_SEMIVOICED_SOUND , Qt::Key_Dead_Semivoiced_Sound); + insert(DIKS_DEAD_TILDE , Qt::Key_Dead_Tilde); + insert(DIKS_DEAD_VOICED_SOUND , Qt::Key_Dead_Voiced_Sound); + insert(DIKS_SPACE , Qt::Key_Space); + insert(DIKS_EXCLAMATION_MARK , Qt::Key_Exclam); + insert(DIKS_QUOTATION , Qt::Key_QuoteDbl); + insert(DIKS_NUMBER_SIGN , Qt::Key_NumberSign); + insert(DIKS_DOLLAR_SIGN , Qt::Key_Dollar); + insert(DIKS_PERCENT_SIGN , Qt::Key_Percent); + insert(DIKS_AMPERSAND , Qt::Key_Ampersand); + insert(DIKS_APOSTROPHE , Qt::Key_Apostrophe); + insert(DIKS_PARENTHESIS_LEFT , Qt::Key_ParenLeft); + insert(DIKS_PARENTHESIS_RIGHT , Qt::Key_ParenRight); + insert(DIKS_ASTERISK , Qt::Key_Asterisk); + insert(DIKS_PLUS_SIGN , Qt::Key_Plus); + insert(DIKS_COMMA , Qt::Key_Comma); + insert(DIKS_MINUS_SIGN , Qt::Key_Minus); + insert(DIKS_PERIOD , Qt::Key_Period); + insert(DIKS_SLASH , Qt::Key_Slash); + insert(DIKS_0 , Qt::Key_0); + insert(DIKS_1 , Qt::Key_1); + insert(DIKS_2 , Qt::Key_2); + insert(DIKS_3 , Qt::Key_3); + insert(DIKS_4 , Qt::Key_4); + insert(DIKS_5 , Qt::Key_5); + insert(DIKS_6 , Qt::Key_6); + insert(DIKS_7 , Qt::Key_7); + insert(DIKS_8 , Qt::Key_8); + insert(DIKS_9 , Qt::Key_9); + insert(DIKS_COLON , Qt::Key_Colon); + insert(DIKS_SEMICOLON , Qt::Key_Semicolon); + insert(DIKS_LESS_THAN_SIGN , Qt::Key_Less); + insert(DIKS_EQUALS_SIGN , Qt::Key_Equal); + insert(DIKS_GREATER_THAN_SIGN , Qt::Key_Greater); + insert(DIKS_QUESTION_MARK , Qt::Key_Question); + insert(DIKS_AT , Qt::Key_At); + insert(DIKS_CAPITAL_A , Qt::Key_A); + insert(DIKS_CAPITAL_B , Qt::Key_B); + insert(DIKS_CAPITAL_C , Qt::Key_C); + insert(DIKS_CAPITAL_D , Qt::Key_D); + insert(DIKS_CAPITAL_E , Qt::Key_E); + insert(DIKS_CAPITAL_F , Qt::Key_F); + insert(DIKS_CAPITAL_G , Qt::Key_G); + insert(DIKS_CAPITAL_H , Qt::Key_H); + insert(DIKS_CAPITAL_I , Qt::Key_I); + insert(DIKS_CAPITAL_J , Qt::Key_J); + insert(DIKS_CAPITAL_K , Qt::Key_K); + insert(DIKS_CAPITAL_L , Qt::Key_L); + insert(DIKS_CAPITAL_M , Qt::Key_M); + insert(DIKS_CAPITAL_N , Qt::Key_N); + insert(DIKS_CAPITAL_O , Qt::Key_O); + insert(DIKS_CAPITAL_P , Qt::Key_P); + insert(DIKS_CAPITAL_Q , Qt::Key_Q); + insert(DIKS_CAPITAL_R , Qt::Key_R); + insert(DIKS_CAPITAL_S , Qt::Key_S); + insert(DIKS_CAPITAL_T , Qt::Key_T); + insert(DIKS_CAPITAL_U , Qt::Key_U); + insert(DIKS_CAPITAL_V , Qt::Key_V); + insert(DIKS_CAPITAL_W , Qt::Key_W); + insert(DIKS_CAPITAL_X , Qt::Key_X); + insert(DIKS_CAPITAL_Y , Qt::Key_Y); + insert(DIKS_CAPITAL_Z , Qt::Key_Z); + insert(DIKS_SQUARE_BRACKET_LEFT , Qt::Key_BracketLeft); + insert(DIKS_BACKSLASH , Qt::Key_Backslash); + insert(DIKS_SQUARE_BRACKET_RIGHT , Qt::Key_BracketRight); + insert(DIKS_CIRCUMFLEX_ACCENT , Qt::Key_AsciiCircum); + insert(DIKS_UNDERSCORE , Qt::Key_Underscore); + insert(DIKS_SMALL_A , Qt::Key_A); + insert(DIKS_SMALL_B , Qt::Key_B); + insert(DIKS_SMALL_C , Qt::Key_C); + insert(DIKS_SMALL_D , Qt::Key_D); + insert(DIKS_SMALL_E , Qt::Key_E); + insert(DIKS_SMALL_F , Qt::Key_F); + insert(DIKS_SMALL_G , Qt::Key_G); + insert(DIKS_SMALL_H , Qt::Key_H); + insert(DIKS_SMALL_I , Qt::Key_I); + insert(DIKS_SMALL_J , Qt::Key_J); + insert(DIKS_SMALL_K , Qt::Key_K); + insert(DIKS_SMALL_L , Qt::Key_L); + insert(DIKS_SMALL_M , Qt::Key_M); + insert(DIKS_SMALL_N , Qt::Key_N); + insert(DIKS_SMALL_O , Qt::Key_O); + insert(DIKS_SMALL_P , Qt::Key_P); + insert(DIKS_SMALL_Q , Qt::Key_Q); + insert(DIKS_SMALL_R , Qt::Key_R); + insert(DIKS_SMALL_S , Qt::Key_S); + insert(DIKS_SMALL_T , Qt::Key_T); + insert(DIKS_SMALL_U , Qt::Key_U); + insert(DIKS_SMALL_V , Qt::Key_V); + insert(DIKS_SMALL_W , Qt::Key_W); + insert(DIKS_SMALL_X , Qt::Key_X); + insert(DIKS_SMALL_Y , Qt::Key_Y); + insert(DIKS_SMALL_Z , Qt::Key_Z); + insert(DIKS_CURLY_BRACKET_LEFT , Qt::Key_BraceLeft); + insert(DIKS_VERTICAL_BAR , Qt::Key_Bar); + insert(DIKS_CURLY_BRACKET_RIGHT , Qt::Key_BraceRight); + insert(DIKS_TILDE , Qt::Key_AsciiTilde); +} diff --git a/src/plugins/platforms/directfb/qdirectfbconvenience.h b/src/plugins/platforms/directfb/qdirectfbconvenience.h new file mode 100644 index 0000000..3669159 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbconvenience.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QDIRECTFBCONVENIENCE_H +#define QDIRECTFBCONVENIENCE_H + +#include <QtGui/qimage.h> +#include <QtCore/QHash> +#include <QtCore/QEvent> +#include <QtGui/QPixmap> + +#include <directfb.h> + +class QDirectFbKeyMap: public QHash<DFBInputDeviceKeySymbol, Qt::Key> +{ +public: + QDirectFbKeyMap(); +}; + + +class QDirectFbConvenience +{ +public: + static QImage::Format imageFormatFromSurfaceFormat(const DFBSurfacePixelFormat format, const DFBSurfaceCapabilities caps); + static bool pixelFomatHasAlpha(const DFBSurfacePixelFormat format) { return (1 << 16) & format; } + static int colorDepthForSurface(const DFBSurfacePixelFormat format); + + //This is set by the graphicssystem constructor + static IDirectFB *dfbInterface(); + static IDirectFBDisplayLayer *dfbDisplayLayer(int display = DLID_PRIMARY); + + static IDirectFBSurface *dfbSurfaceForPixmapData(QPixmapData *); + + static Qt::MouseButton mouseButton(DFBInputDeviceButtonIdentifier identifier); + static Qt::MouseButtons mouseButtons(DFBInputDeviceButtonMask mask); + static Qt::KeyboardModifiers keyboardModifiers(DFBInputDeviceModifierMask mask); + static QEvent::Type eventType(DFBWindowEventType type); + + static QDirectFbKeyMap *keyMap(); + +private: + static QDirectFbKeyMap *dfbKeymap; + friend class QDirectFbIntegration; +}; + +#endif // QDIRECTFBCONVENIENCE_H diff --git a/src/plugins/platforms/directfb/qdirectfbcursor.cpp b/src/plugins/platforms/directfb/qdirectfbcursor.cpp new file mode 100644 index 0000000..51502f8 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbcursor.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qdirectfbcursor.h" +#include "qdirectfbconvenience.h" + + +QDirectFBCursor::QDirectFBCursor(QPlatformScreen* screen) : + QPlatformCursor(screen), surface(0) +{ + QDirectFbConvenience::dfbInterface()->GetDisplayLayer(QDirectFbConvenience::dfbInterface(),DLID_PRIMARY, &m_layer); + image = new QPlatformCursorImage(0, 0, 0, 0, 0, 0); +} + +void QDirectFBCursor::changeCursor(QCursor * cursor, QWidget * widget) +{ + Q_UNUSED(widget); + int xSpot; + int ySpot; + QPixmap map; + + if (cursor->shape() != Qt::BitmapCursor) { + image->set(cursor->shape()); + xSpot = image->hotspot().x(); + ySpot = image->hotspot().y(); + QImage *i = image->image(); + map = QPixmap::fromImage(*i); + } else { + QPoint point = cursor->hotSpot(); + xSpot = point.x(); + ySpot = point.y(); + map = cursor->pixmap(); + } + + IDirectFBSurface *surface = QDirectFbConvenience::dfbSurfaceForPixmapData(map.pixmapData()); + + if (m_layer->SetCooperativeLevel(m_layer, DLSCL_ADMINISTRATIVE) != DFB_OK) { + return; + } + m_layer->SetCursorShape( m_layer, surface, xSpot, ySpot); + m_layer->SetCooperativeLevel(m_layer, DLSCL_SHARED); +} diff --git a/src/plugins/platforms/directfb/qdirectfbcursor.h b/src/plugins/platforms/directfb/qdirectfbcursor.h new file mode 100644 index 0000000..ea8b7b0 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbcursor.h @@ -0,0 +1,63 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QDIRECTFBCURSOR_H +#define QDIRECTFBCURSOR_H + +#include <QPlatformCursor> +#include <directfb.h> +class QDirectFbScreen; +class QDirectFbBlitter; + +class QDirectFBCursor : public QPlatformCursor +{ +public: + QDirectFBCursor(QPlatformScreen *screem); + void changeCursor(QCursor * cursor, QWidget * widget); + +private: + IDirectFBDisplayLayer * m_layer; + IDirectFBSurface * surface; + QPlatformCursorImage * image; + QDirectFbBlitter *blitter; +}; + +#endif // QDIRECTFBCURSOR_H diff --git a/src/plugins/platforms/directfb/qdirectfbglcontext.cpp b/src/plugins/platforms/directfb/qdirectfbglcontext.cpp new file mode 100644 index 0000000..033ff1e --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbglcontext.cpp @@ -0,0 +1,99 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qdirectfbglcontext.h" + +#include <directfb/directfbgl.h> + +#include <QDebug> + +QDirectFbGLContext::QDirectFbGLContext(IDirectFBGL *glContext) + : m_dfbGlContext(glContext) +{ + DFBResult result; + DFBGLAttributes glAttribs; + result = m_dfbGlContext->GetAttributes(glContext, &glAttribs); + if (result == DFB_OK) { + m_windowFormat.setDepthBufferSize(glAttribs.depth_size); + m_windowFormat.setStencilBufferSize(glAttribs.stencil_size); + + m_windowFormat.setRedBufferSize(glAttribs.red_size); + m_windowFormat.setGreenBufferSize(glAttribs.green_size); + m_windowFormat.setBlueBufferSize(glAttribs.blue_size); + m_windowFormat.setAlphaBufferSize(glAttribs.alpha_size); + + m_windowFormat.setAccumBufferSize(glAttribs.accum_red_size); + m_windowFormat.setAlpha(glAttribs.accum_alpha_size); + + m_windowFormat.setDoubleBuffer(glAttribs.double_buffer); + m_windowFormat.setStereo(glAttribs.stereo); + } +} + +void QDirectFbGLContext::makeCurrent() +{ + m_dfbGlContext->Lock(m_dfbGlContext); +} + +void QDirectFbGLContext::doneCurrent() +{ + m_dfbGlContext->Unlock(m_dfbGlContext); +} + +void *QDirectFbGLContext::getProcAddress(const QString &procName) +{ + void *proc; + DFBResult result = m_dfbGlContext->GetProcAddress(m_dfbGlContext,qPrintable(procName),&proc); + if (result == DFB_OK) + return proc; + return 0; +} + +void QDirectFbGLContext::swapBuffers() +{ +// m_dfbGlContext->Unlock(m_dfbGlContext); //maybe not in doneCurrent() + qDebug() << "Swap buffers"; +} + +QPlatformWindowFormat QDirectFbGLContext::platformWindowFormat() const +{ + return m_windowFormat; +} diff --git a/src/plugins/platforms/directfb/qdirectfbglcontext.h b/src/plugins/platforms/directfb/qdirectfbglcontext.h new file mode 100644 index 0000000..1785666 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbglcontext.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QDIRECTFBGLCONTEXT_H +#define QDIRECTFBGLCONTEXT_H + +#include <QPlatformGLContext> + +#include "qdirectfbconvenience.h" + +class QDirectFbGLContext : public QPlatformGLContext +{ +public: + explicit QDirectFbGLContext(IDirectFBGL *glContext); + + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void *getProcAddress(const QString &procName); + + QPlatformWindowFormat platformWindowFormat() const; + + +private: + IDirectFBGL *m_dfbGlContext; + + QPlatformWindowFormat m_windowFormat; + +}; + +#endif // QDIRECTFBGLCONTEXT_H diff --git a/src/plugins/platforms/directfb/qdirectfbinput.cpp b/src/plugins/platforms/directfb/qdirectfbinput.cpp new file mode 100644 index 0000000..9d2a8a8 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbinput.cpp @@ -0,0 +1,208 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qdirectfbinput.h" +#include "qdirectfbconvenience.h" + +#include <QThread> +#include <QDebug> +#include <QWindowSystemInterface> +#include <QMouseEvent> +#include <QEvent> +#include <QApplication> + +#include <directfb.h> + +QDirectFbInput::QDirectFbInput(QObject *parent) + : QObject(parent), m_shouldStop(false) +{ + m_dfbInterface = QDirectFbConvenience::dfbInterface(); + + DFBResult ok = m_dfbInterface->CreateEventBuffer(m_dfbInterface,&m_eventBuffer); + if (ok != DFB_OK) + DirectFBError("Failed to initialise eventbuffer", ok); + + m_dfbInterface->GetDisplayLayer(m_dfbInterface,DLID_PRIMARY, &m_dfbDisplayLayer); + +} + +void QDirectFbInput::runInputEventLoop() +{ + while (true) { + m_eventBuffer->WaitForEvent(m_eventBuffer); + if (m_shouldStop) { + m_waitStop.release(); + break; + } + handleEvents(); + } +} + +void QDirectFbInput::stopInputEventLoop() +{ + m_shouldStop = true; + m_waitStop.acquire(); +} + +void QDirectFbInput::addWindow(DFBWindowID id, QWidget *tlw) +{ + m_tlwMap.insert(id,tlw); + IDirectFBWindow *window; + m_dfbDisplayLayer->GetWindow(m_dfbDisplayLayer,id,&window); + + window->AttachEventBuffer(window,m_eventBuffer); +} + +void QDirectFbInput::removeWindow(WId wId) +{ + IDirectFBWindow *window; + m_dfbDisplayLayer->GetWindow(m_dfbDisplayLayer,wId, &window); + + window->DetachEventBuffer(window,m_eventBuffer); + m_tlwMap.remove(wId); +} + +void QDirectFbInput::handleEvents() +{ + DFBResult hasEvent = m_eventBuffer->HasEvent(m_eventBuffer); + while(hasEvent == DFB_OK){ + DFBEvent event; + DFBResult ok = m_eventBuffer->GetEvent(m_eventBuffer,&event); + if (ok != DFB_OK) + DirectFBError("Failed to get event",ok); + if (event.clazz == DFEC_WINDOW) { + switch (event.window.type) { + case DWET_BUTTONDOWN: + case DWET_BUTTONUP: + case DWET_MOTION: + handleMouseEvents(event); + break; + case DWET_WHEEL: + handleWheelEvent(event); + break; + case DWET_KEYDOWN: + case DWET_KEYUP: + handleKeyEvents(event); + break; + case DWET_ENTER: + case DWET_LEAVE: + handleEnterLeaveEvents(event); + default: + break; + } + + } + + hasEvent = m_eventBuffer->HasEvent(m_eventBuffer); + } +} + +void QDirectFbInput::handleMouseEvents(const DFBEvent &event) +{ + QPoint p(event.window.x, event.window.y); + QPoint globalPos = globalPoint(event); + Qt::MouseButtons buttons = QDirectFbConvenience::mouseButtons(event.window.buttons); + + IDirectFBDisplayLayer *layer = QDirectFbConvenience::dfbDisplayLayer(); + IDirectFBWindow *window; + layer->GetWindow(layer,event.window.window_id,&window); + + long timestamp = (event.window.timestamp.tv_sec*1000) + (event.window.timestamp.tv_usec/1000); + + if (event.window.type == DWET_BUTTONDOWN) { + window->GrabPointer(window); + } else if (event.window.type == DWET_BUTTONUP) { + window->UngrabPointer(window); + } + QWidget *tlw = m_tlwMap.value(event.window.window_id); + QWindowSystemInterface::handleMouseEvent(tlw, timestamp, p, globalPos, buttons); +} + +void QDirectFbInput::handleWheelEvent(const DFBEvent &event) +{ + QPoint p(event.window.cx, event.window.cy); + QPoint globalPos = globalPoint(event); + long timestamp = (event.window.timestamp.tv_sec*1000) + (event.window.timestamp.tv_usec/1000); + QWidget *tlw = m_tlwMap.value(event.window.window_id); + QWindowSystemInterface::handleWheelEvent(tlw, timestamp, p, globalPos, + event.window.step*120, + Qt::Vertical); +} + +void QDirectFbInput::handleKeyEvents(const DFBEvent &event) +{ + QEvent::Type type = QDirectFbConvenience::eventType(event.window.type); + Qt::Key key = QDirectFbConvenience::keyMap()->value(event.window.key_symbol); + Qt::KeyboardModifiers modifiers = QDirectFbConvenience::keyboardModifiers(event.window.modifiers); + + long timestamp = (event.window.timestamp.tv_sec*1000) + (event.window.timestamp.tv_usec/1000); + + QChar character; + if (DFB_KEY_TYPE(event.window.key_symbol) == DIKT_UNICODE) + character = QChar(event.window.key_symbol); + QWidget *tlw = m_tlwMap.value(event.window.window_id); + QWindowSystemInterface::handleKeyEvent(tlw, timestamp, type, key, modifiers, character); +} + +void QDirectFbInput::handleEnterLeaveEvents(const DFBEvent &event) +{ + QWidget *tlw = m_tlwMap.value(event.window.window_id); + switch (event.window.type) { + case DWET_ENTER: + QWindowSystemInterface::handleEnterEvent(tlw); + break; + case DWET_LEAVE: + QWindowSystemInterface::handleLeaveEvent(tlw); + break; + default: + break; + } +} + +inline QPoint QDirectFbInput::globalPoint(const DFBEvent &event) const +{ + IDirectFBWindow *window; + m_dfbDisplayLayer->GetWindow(m_dfbDisplayLayer,event.window.window_id,&window); + int x,y; + window->GetPosition(window,&x,&y); + return QPoint(event.window.cx +x, event.window.cy + y); +} + diff --git a/src/plugins/platforms/directfb/qdirectfbinput.h b/src/plugins/platforms/directfb/qdirectfbinput.h new file mode 100644 index 0000000..bca155f --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbinput.h @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QDIRECTFBINPUT_H +#define QDIRECTFBINPUT_H + +#include <QSemaphore> +#include <QObject> +#include <QHash> +#include <QPoint> +#include <QEvent> + +#include <QtGui/qwindowdefs.h> + +#include <directfb.h> + +class QDirectFbInput : public QObject +{ + Q_OBJECT +public: + QDirectFbInput(QObject *parent); + void addWindow(DFBWindowID id, QWidget *tlw); + void removeWindow(WId wId); + +public slots: + void runInputEventLoop(); + void stopInputEventLoop(); + void handleEvents(); + +private: + void handleMouseEvents(const DFBEvent &event); + void handleWheelEvent(const DFBEvent &event); + void handleKeyEvents(const DFBEvent &event); + void handleEnterLeaveEvents(const DFBEvent &event); + inline QPoint globalPoint(const DFBEvent &event) const; + + + IDirectFB *m_dfbInterface; + IDirectFBDisplayLayer *m_dfbDisplayLayer; + IDirectFBEventBuffer *m_eventBuffer; + + bool m_shouldStop; + QSemaphore m_waitStop; + + QHash<DFBWindowID,QWidget *>m_tlwMap; +}; + +#endif // QDIRECTFBINPUT_H diff --git a/src/plugins/platforms/directfb/qdirectfbintegration.cpp b/src/plugins/platforms/directfb/qdirectfbintegration.cpp new file mode 100644 index 0000000..8639bdb --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbintegration.cpp @@ -0,0 +1,144 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qdirectfbintegration.h" +#include "qdirectfbwindowsurface.h" +#include "qdirectfbblitter.h" +#include "qdirectfbconvenience.h" +#include "qdirectfbcursor.h" +#include "qdirectfbwindow.h" + +#include "qgenericunixfontdatabase.h" + +#include <private/qwindowsurface_raster_p.h> +#include <private/qpixmap_raster_p.h> + +#include <QtGui/private/qpixmap_blitter_p.h> +#include <QtGui/private/qpixmapdata_p.h> +#include <QtCore/QCoreApplication> +#include <QtCore/QThread> + +QT_BEGIN_NAMESPACE + +QDirectFbScreen::QDirectFbScreen(int display) + :QPlatformScreen() +{ + m_layer = QDirectFbConvenience::dfbDisplayLayer(display); + m_layer->SetCooperativeLevel(m_layer,DLSCL_SHARED); + + DFBDisplayLayerConfig config; + m_layer->GetConfiguration(m_layer, &config); + + m_format = QDirectFbConvenience::imageFormatFromSurfaceFormat(config.pixelformat, config.surface_caps); + m_geometry = QRect(0,0,config.width,config.height); + const int dpi = 72; + const qreal inch = 25.4; + m_depth = QDirectFbConvenience::colorDepthForSurface(config.pixelformat); + m_physicalSize = QSize(qRound(config.width * inch / dpi), qRound(config.height *inch / dpi)); + + cursor = new QDirectFBCursor(this); +} + +QDirectFbScreen::~QDirectFbScreen() +{ +} + +QDirectFbIntegration::QDirectFbIntegration() + : mFontDb(new QGenericUnixFontDatabase()) +{ + const QStringList args = QCoreApplication::arguments(); + int argc = args.size(); + char **argv = new char*[argc]; + + for (int i = 0; i < argc; ++i) + argv[i] = qstrdup(args.at(i).toLocal8Bit().constData()); + + DFBResult result = DirectFBInit(&argc, &argv); + if (result != DFB_OK) { + DirectFBError("QDirectFBScreen: error initializing DirectFB", + result); + } + delete[] argv; + + + QDirectFbScreen *primaryScreen = new QDirectFbScreen(0); + mScreens.append(primaryScreen); + + mInputRunner = new QThread; + mInput = new QDirectFbInput(0); + mInput->moveToThread(mInputRunner); + QObject::connect(mInputRunner,SIGNAL(started()),mInput,SLOT(runInputEventLoop())); + mInputRunner->start(); +} + +QDirectFbIntegration::~QDirectFbIntegration() +{ + mInput->stopInputEventLoop(); + delete mInputRunner; + delete mInput; +} + +QPixmapData *QDirectFbIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + if (type == QPixmapData::BitmapType) + return new QRasterPixmapData(type); + else + return new QDirectFbBlitterPixmapData; +} + +QPlatformWindow *QDirectFbIntegration::createPlatformWindow(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + QDirectFbInput *input = const_cast<QDirectFbInput *>(mInput);//gah + return new QDirectFbWindow(widget,input); +} + +QWindowSurface *QDirectFbIntegration::createWindowSurface(QWidget *widget, WId winId) const +{ + return new QDirectFbWindowSurface(widget,winId); +} + +QPlatformFontDatabase *QDirectFbIntegration::fontDatabase() const +{ + return mFontDb; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/directfb/qdirectfbintegration.h b/src/plugins/platforms/directfb/qdirectfbintegration.h new file mode 100644 index 0000000..965bdd2 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbintegration.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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_DIRECTFB_H +#define QPLATFORMINTEGRATION_DIRECTFB_H + +#include "qdirectfbinput.h" + +#include <QtGui/QPlatformIntegration> +#include <directfb.h> +#include <directfb_version.h> + +QT_BEGIN_NAMESPACE + +class QThread; +class QDirectFBCursor; + +class QDirectFbScreen : public QPlatformScreen +{ +Q_OBJECT +public: + QDirectFbScreen(int display); + ~QDirectFbScreen(); + + 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; } + +public: + QRect m_geometry; + int m_depth; + QImage::Format m_format; + QSize m_physicalSize; + + IDirectFBDisplayLayer *m_layer; + +private: + QDirectFBCursor * cursor; + +}; + +class QDirectFbIntegration : public QPlatformIntegration +{ +public: + QDirectFbIntegration(); + ~QDirectFbIntegration(); + + 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 { return mScreens; } + + QPlatformFontDatabase *fontDatabase() const; + +private: + QList<QPlatformScreen *> mScreens; + QDirectFbInput *mInput; + QThread *mInputRunner; + QPlatformFontDatabase *mFontDb; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/directfb/qdirectfbwindow.cpp b/src/plugins/platforms/directfb/qdirectfbwindow.cpp new file mode 100644 index 0000000..1cd23ad --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbwindow.cpp @@ -0,0 +1,191 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qdirectfbwindow.h" +#include "qdirectfbinput.h" +#include "qdirectfbglcontext.h" + +#include <QWidget> + +#include "qdirectfbwindowsurface.h" + +#include <directfb.h> + +QDirectFbWindow::QDirectFbWindow(QWidget *tlw, QDirectFbInput *inputhandler) + : QPlatformWindow(tlw), m_inputHandler(inputhandler), m_context(0) +{ + IDirectFBDisplayLayer *layer = QDirectFbConvenience::dfbDisplayLayer(); + DFBDisplayLayerConfig layerConfig; + layer->GetConfiguration(layer,&layerConfig); + + DFBWindowDescription description; + memset(&description,0,sizeof(DFBWindowDescription)); + description.flags = DFBWindowDescriptionFlags(DWDESC_WIDTH|DWDESC_HEIGHT|DWDESC_POSX|DWDESC_POSY|DWDESC_SURFACE_CAPS +#if DIRECTFB_MINOR_VERSION >= 1 + |DWDESC_OPTIONS +#endif + |DWDESC_CAPS); + description.width = tlw->rect().width(); + description.height = tlw->rect().height(); + description.posx = tlw->rect().x(); + description.posy = tlw->rect().y(); + + if (layerConfig.surface_caps & DSCAPS_PREMULTIPLIED) + description.surface_caps = DSCAPS_PREMULTIPLIED; + description.pixelformat = layerConfig.pixelformat; + +#if DIRECTFB_MINOR_VERSION >= 1 + description.options = DFBWindowOptions(DWOP_ALPHACHANNEL); +#endif + description.caps = DFBWindowCapabilities(DWCAPS_DOUBLEBUFFER|DWCAPS_ALPHACHANNEL); + description.surface_caps = DSCAPS_PREMULTIPLIED; + + DFBResult result = layer->CreateWindow(layer,&description,&m_dfbWindow); + if (result != DFB_OK) { + DirectFBError("QDirectFbGraphicsSystemScreen: failed to create window",result); + } + + m_dfbWindow->SetOpacity(m_dfbWindow,0xff); + + setVisible(widget()->isVisible()); + + DFBWindowID id; + m_dfbWindow->GetID(m_dfbWindow, &id); + m_inputHandler->addWindow(id,tlw); +} + +QDirectFbWindow::~QDirectFbWindow() +{ + m_inputHandler->removeWindow(winId()); + m_dfbWindow->Destroy(m_dfbWindow); +} + +void QDirectFbWindow::setGeometry(const QRect &rect) +{ + bool isMoveOnly = (rect.topLeft() != geometry().topLeft()) && (rect.size() == geometry().size()); + QPlatformWindow::setGeometry(rect); + if (widget()->isVisible() && !(widget()->testAttribute(Qt::WA_DontShowOnScreen))) { + m_dfbWindow->SetBounds(m_dfbWindow, rect.x(),rect.y(), + rect.width(), rect.height()); + + //Hack. When moving since the WindowSurface of a window becomes invalid when moved + if (isMoveOnly) { //if resize then windowsurface is updated. + widget()->windowSurface()->resize(rect.size()); + widget()->update(); + } + } +} + +void QDirectFbWindow::setOpacity(qreal level) +{ + const quint8 windowOpacity = quint8(level * 0xff); + m_dfbWindow->SetOpacity(m_dfbWindow,windowOpacity); +} + +void QDirectFbWindow::setVisible(bool visible) +{ + if (visible) { + int x = geometry().x(); + int y = geometry().y(); + m_dfbWindow->MoveTo(m_dfbWindow,x,y); + } else { + IDirectFBDisplayLayer *displayLayer; + QDirectFbConvenience::dfbInterface()->GetDisplayLayer(QDirectFbConvenience::dfbInterface(),DLID_PRIMARY,&displayLayer); + + DFBDisplayLayerConfig config; + displayLayer->GetConfiguration(displayLayer,&config); + m_dfbWindow->MoveTo(m_dfbWindow,config.width+1,config.height + 1); + } +} + +Qt::WindowFlags QDirectFbWindow::setWindowFlags(Qt::WindowFlags flags) +{ + switch (flags & Qt::WindowType_Mask) { + case Qt::ToolTip: { + DFBWindowOptions options; + m_dfbWindow->GetOptions(m_dfbWindow,&options); + options = DFBWindowOptions(options | DWOP_GHOST); + m_dfbWindow->SetOptions(m_dfbWindow,options); + break; } + default: + break; + } + + m_dfbWindow->SetStackingClass(m_dfbWindow, flags & Qt::WindowStaysOnTopHint ? DWSC_UPPER : DWSC_MIDDLE); + return flags; +} + +void QDirectFbWindow::raise() +{ + m_dfbWindow->RaiseToTop(m_dfbWindow); +} + +void QDirectFbWindow::lower() +{ + m_dfbWindow->LowerToBottom(m_dfbWindow); +} + +WId QDirectFbWindow::winId() const +{ + DFBWindowID id; + m_dfbWindow->GetID(m_dfbWindow, &id); + return WId(id); +} + +QPlatformGLContext *QDirectFbWindow::glContext() const +{ + if (!m_context) { + IDirectFBSurface *surface; + DFBResult result = m_dfbWindow->GetSurface(m_dfbWindow,&surface); + if (result != DFB_OK) { + qWarning("could not retrieve surface in QDirectFbWindow::glContext()"); + return 0; + } + IDirectFBGL *gl; + result = surface->GetGL(surface,&gl); + if (result != DFB_OK) { + qWarning("could not retrieve IDirectFBGL in QDirectFbWindow::glContext()"); + return 0; + } + const_cast<QDirectFbWindow *>(this)->m_context = new QDirectFbGLContext(gl); + } + return m_context; +} diff --git a/src/plugins/platforms/directfb/qdirectfbwindow.h b/src/plugins/platforms/directfb/qdirectfbwindow.h new file mode 100644 index 0000000..19491c5 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbwindow.h @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QDIRECTFBWINDOW_H +#define QDIRECTFBWINDOW_H + +#include <QPlatformWindow> + +#include "qdirectfbconvenience.h" +#include "qdirectfbinput.h" + +QT_BEGIN_NAMESPACE + +class QDirectFbWindow : public QPlatformWindow +{ +public: + QDirectFbWindow(QWidget *tlw, QDirectFbInput *inputhandler); + ~QDirectFbWindow(); + + void setGeometry(const QRect &rect); + void setOpacity(qreal level); + + void setVisible(bool visible); + + Qt::WindowFlags setWindowFlags(Qt::WindowFlags flags); + void raise(); + void lower(); + WId winId() const; + + QPlatformGLContext *glContext() const; + +private: + IDirectFBWindow *m_dfbWindow; + QDirectFbInput *m_inputHandler; + + QPlatformGLContext *m_context; +}; + +QT_END_NAMESPACE + +#endif // QDIRECTFBWINDOW_H diff --git a/src/plugins/platforms/directfb/qdirectfbwindowsurface.cpp b/src/plugins/platforms/directfb/qdirectfbwindowsurface.cpp new file mode 100644 index 0000000..b1a8899 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbwindowsurface.cpp @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qdirectfbwindowsurface.h" +#include "qdirectfbintegration.h" +#include "qdirectfbblitter.h" +#include "qdirectfbconvenience.h" +#include <private/qpixmap_blitter_p.h> + +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +QDirectFbWindowSurface::QDirectFbWindowSurface(QWidget *window, WId wId) + : QWindowSurface(window), m_pixmap(0), m_pmdata(0), m_dfbSurface(0) +{ + + IDirectFBDisplayLayer *layer = QDirectFbConvenience::dfbDisplayLayer(); + + DFBWindowID id(wId); + IDirectFBWindow *dfbWindow; + + layer->GetWindow(layer,id,&dfbWindow); + + dfbWindow->GetSurface(dfbWindow,&m_dfbSurface); +//WRONGSIZE + QDirectFbBlitter *blitter = new QDirectFbBlitter(window->rect().size(), m_dfbSurface); + m_pmdata = new QDirectFbBlitterPixmapData; + m_pmdata->setBlittable(blitter); + m_pixmap = new QPixmap(m_pmdata); +} + +QDirectFbWindowSurface::~QDirectFbWindowSurface() +{ + delete m_pixmap; +} + +QPaintDevice *QDirectFbWindowSurface::paintDevice() +{ + return m_pixmap; +} + +void QDirectFbWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + m_pmdata->blittable()->unlock(); + + QVector<QRect> rects = region.rects(); + for (int i = 0 ; i < rects.size(); i++) { + const QRect rect = rects.at(i); + DFBRegion dfbReg = { rect.x() + offset.x(),rect.y() + offset.y(),rect.right() + offset.x(),rect.bottom() + offset.y()}; + m_dfbSurface->Flip(m_dfbSurface, &dfbReg, DFBSurfaceFlipFlags(DSFLIP_BLIT|DSFLIP_ONSYNC)); + } +} + +void QDirectFbWindowSurface::resize(const QSize &size) +{ + QWindowSurface::resize(size); + + //Have to add 1 ref ass it will be removed by deleting the old blitter in setBlittable + m_dfbSurface->AddRef(m_dfbSurface); + QDirectFbBlitter *blitter = new QDirectFbBlitter(size,m_dfbSurface); + m_pmdata->setBlittable(blitter); +} + +static inline void scrollSurface(IDirectFBSurface *surface, const QRect &r, int dx, int dy) +{ + const DFBRectangle rect = { r.x(), r.y(), r.width(), r.height() }; + surface->Blit(surface, surface, &rect, r.x() + dx, r.y() + dy); + const DFBRegion region = { rect.x + dx, rect.y + dy, r.right() + dx, r.bottom() + dy }; + surface->Flip(surface, ®ion, DFBSurfaceFlipFlags(DSFLIP_BLIT)); +} + +bool QDirectFbWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + m_pmdata->blittable()->unlock(); + + if (!m_dfbSurface || area.isEmpty()) + return false; + m_dfbSurface->SetBlittingFlags(m_dfbSurface, DSBLIT_NOFX); + if (area.rectCount() == 1) { + scrollSurface(m_dfbSurface, area.boundingRect(), dx, dy); + } else { + const QVector<QRect> rects = area.rects(); + const int n = rects.size(); + for (int i=0; i<n; ++i) { + scrollSurface(m_dfbSurface, rects.at(i), dx, dy); + } + } + return true; +} + +void QDirectFbWindowSurface::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +void QDirectFbWindowSurface::endPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/directfb/qdirectfbwindowsurface.h b/src/plugins/platforms/directfb/qdirectfbwindowsurface.h new file mode 100644 index 0000000..aaa74d4 --- /dev/null +++ b/src/plugins/platforms/directfb/qdirectfbwindowsurface.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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_DIRECTFB_H +#define QWINDOWSURFACE_DIRECTFB_H + +#include <QtGui/private/qwindowsurface_p.h> +#include <private/qpixmap_blitter_p.h> + +#include <directfb.h> + +QT_BEGIN_NAMESPACE + +class QDirectFbWindowSurface : public QWindowSurface +{ +public: + QDirectFbWindowSurface(QWidget *window, WId wid); + ~QDirectFbWindowSurface(); + + 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 ®ion); + void endPaint(const QRegion ®ion); + +private: + void lockSurfaceToImage(); + + QPixmap *m_pixmap; + QBlittablePixmapData *m_pmdata; + + IDirectFBSurface *m_dfbSurface; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/eglconvenience/qeglconvenience.cpp b/src/plugins/platforms/eglconvenience/qeglconvenience.cpp new file mode 100644 index 0000000..b203fe8 --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qeglconvenience.cpp @@ -0,0 +1,316 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qeglconvenience.h" + +QT_BEGIN_NAMESPACE + +QVector<EGLint> q_createConfigAttributesFromFormat(const QPlatformWindowFormat &format) +{ + int redSize = format.redBufferSize(); + int greenSize = format.greenBufferSize(); + int blueSize = format.blueBufferSize(); + int alphaSize = format.alphaBufferSize(); + int depthSize = format.depthBufferSize(); + int stencilSize = format.stencilBufferSize(); + int sampleCount = format.samples(); + + // QPlatformWindowFormat uses a magic value of -1 to indicate "don't care", even when a buffer of that + // type has been requested. So we must check QPlatformWindowFormat's booleans too if size is -1: + if (format.alpha() && alphaSize <= 0) + alphaSize = 1; + if (format.depth() && depthSize <= 0) + depthSize = 1; + if (format.stencil() && stencilSize <= 0) + stencilSize = 1; + if (format.sampleBuffers() && sampleCount <= 0) + sampleCount = 1; + + // We want to make sure 16-bit configs are chosen over 32-bit configs as they will provide + // the best performance. The EGL config selection algorithm is a bit stange in this regard: + // The selection criteria for EGL_BUFFER_SIZE is "AtLeast", so we can't use it to discard + // 32-bit configs completely from the selection. So it then comes to the sorting algorithm. + // The red/green/blue sizes have a sort priority of 3, so they are sorted by first. The sort + // order is special and described as "by larger _total_ number of color bits.". So EGL will + // put 32-bit configs in the list before the 16-bit configs. However, the spec also goes on + // to say "If the requested number of bits in attrib_list for a particular component is 0, + // then the number of bits for that component is not considered". This part of the spec also + // seems to imply that setting the red/green/blue bits to zero means none of the components + // are considered and EGL disregards the entire sorting rule. It then looks to the next + // highest priority rule, which is EGL_BUFFER_SIZE. Despite the selection criteria being + // "AtLeast" for EGL_BUFFER_SIZE, it's sort order is "smaller" meaning 16-bit configs are + // put in the list before 32-bit configs. So, to make sure 16-bit is preffered over 32-bit, + // we must set the red/green/blue sizes to zero. This has an unfortunate consequence that + // if the application sets the red/green/blue size to 5/6/5 on the QPlatformWindowFormat, + // they will probably get a 32-bit config, even when there's an RGB565 config available. + + // Now normalize the values so -1 becomes 0 + redSize = redSize > 0 ? redSize : 0; + greenSize = greenSize > 0 ? greenSize : 0; + blueSize = blueSize > 0 ? blueSize : 0; + alphaSize = alphaSize > 0 ? alphaSize : 0; + depthSize = depthSize > 0 ? depthSize : 0; + stencilSize = stencilSize > 0 ? stencilSize : 0; + sampleCount = sampleCount > 0 ? sampleCount : 0; + + QVector<EGLint> configAttributes; + + configAttributes.append(EGL_RED_SIZE); + configAttributes.append(redSize); + + configAttributes.append(EGL_GREEN_SIZE); + configAttributes.append(greenSize); + + configAttributes.append(EGL_BLUE_SIZE); + configAttributes.append(blueSize); + + configAttributes.append(EGL_ALPHA_SIZE); + configAttributes.append(alphaSize); + + configAttributes.append(EGL_DEPTH_SIZE); + configAttributes.append(depthSize); + + configAttributes.append(EGL_STENCIL_SIZE); + configAttributes.append(stencilSize); + + configAttributes.append(EGL_SAMPLES); + configAttributes.append(sampleCount); + + configAttributes.append(EGL_SAMPLE_BUFFERS); + configAttributes.append(sampleCount? 1:0); + + return configAttributes; +} + +bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes) +{ + int i = -1; + // Reduce the complexity of a configuration request to ask for less + // because the previous request did not result in success. Returns + // true if the complexity was reduced, or false if no further + // reductions in complexity are possible. + + i = configAttributes->indexOf(EGL_SWAP_BEHAVIOR); + if (i >= 0) { + configAttributes->remove(i,2); + } + +#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT + // For OpenVG, we sometimes try to create a surface using a pre-multiplied format. If we can't + // find a config which supports pre-multiplied formats, remove the flag on the surface type: + + i = configAttributes->indexOf(EGL_SURFACE_TYPE); + if (i >= 0) { + EGLint surfaceType = configAttributes->at(i +1); + if (surfaceType & EGL_VG_ALPHA_FORMAT_PRE_BIT) { + surfaceType ^= EGL_VG_ALPHA_FORMAT_PRE_BIT; + configAttributes->replace(i+1,surfaceType); + return true; + } + } +#endif + + // EGL chooses configs with the highest color depth over + // those with smaller (but faster) lower color depths. One + // way around this is to set EGL_BUFFER_SIZE to 16, which + // trumps the others. Of course, there may not be a 16-bit + // config available, so it's the first restraint we remove. + i = configAttributes->indexOf(EGL_BUFFER_SIZE); + if (i >= 0) { + if (configAttributes->at(i+1) == 16) { + configAttributes->remove(i,2); + return true; + } + } + + i = configAttributes->indexOf(EGL_SAMPLE_BUFFERS); + if (i >= 0) { + configAttributes->remove(i,2); + i = configAttributes->indexOf(EGL_SAMPLES); + if (i >= 0) { + configAttributes->remove(i,2); + } + return true; + } + + i = configAttributes->indexOf(EGL_ALPHA_SIZE); + if (i >= 0) { + configAttributes->remove(i,2); +#if defined(EGL_BIND_TO_TEXTURE_RGBA) && defined(EGL_BIND_TO_TEXTURE_RGB) + i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGBA); + if (i >= 0) { + configAttributes->replace(i,EGL_BIND_TO_TEXTURE_RGB); + configAttributes->replace(i+1,TRUE); + + } +#endif + return true; + } + + i = configAttributes->indexOf(EGL_STENCIL_SIZE); + if (i >= 0) { + configAttributes->remove(i,2); + return true; + } + i = configAttributes->indexOf(EGL_DEPTH_SIZE); + if (i >= 0) { + configAttributes->remove(i,2); + return true; + } +#ifdef EGL_BIND_TO_TEXTURE_RGB + i = configAttributes->indexOf(EGL_BIND_TO_TEXTURE_RGB); + if (i >= 0) { + configAttributes->remove(i,2); + return true; + } +#endif + + return false; +} + +EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format) +{ + EGLConfig cfg = 0; + QVector<EGLint> configureAttributes = q_createConfigAttributesFromFormat(format); + configureAttributes.append(EGL_SURFACE_TYPE); //we only support eglconfigs for windows for now + configureAttributes.append(EGL_WINDOW_BIT); + + configureAttributes.append(EGL_RENDERABLE_TYPE); + if (format.windowApi() == QPlatformWindowFormat::OpenVG) { + configureAttributes.append(EGL_OPENVG_BIT); + } else { + configureAttributes.append(EGL_OPENGL_ES2_BIT); + } + configureAttributes.append(EGL_NONE); + + do { + // Get the number of matching configurations for this set of properties. + EGLint matching = 0; + 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; +// } + + // Fetch all of the matching configurations and find the + // first that matches the pixel format we wanted. + int i = configureAttributes.indexOf(EGL_RED_SIZE); + int confAttrRed = configureAttributes.at(i+1); + i = configureAttributes.indexOf(EGL_GREEN_SIZE); + int confAttrGreen = configureAttributes.at(i+1); + i = configureAttributes.indexOf(EGL_BLUE_SIZE); + int confAttrBlue = configureAttributes.at(i+1); + i = configureAttributes.indexOf(EGL_ALPHA_SIZE); + int confAttrAlpha = configureAttributes.at(i+1); + + EGLint size = matching; + EGLConfig *configs = new EGLConfig [size]; + eglChooseConfig(display, configureAttributes.constData(), configs, size, &matching); + for (EGLint index = 0; index < size; ++index) { + EGLint red, green, blue, alpha; + eglGetConfigAttrib(display, configs[index], EGL_RED_SIZE, &red); + eglGetConfigAttrib(display, configs[index], EGL_GREEN_SIZE, &green); + eglGetConfigAttrib(display, configs[index], EGL_BLUE_SIZE, &blue); + eglGetConfigAttrib(display, configs[index], EGL_ALPHA_SIZE, &alpha); + if (red == confAttrRed && + green == confAttrGreen && + blue == confAttrBlue && + (confAttrAlpha == 0 || + alpha == confAttrAlpha)) { + cfg = configs[index]; + delete [] configs; + return cfg; + } + } + delete [] configs; + } while (q_reduceConfigAttributes(&configureAttributes)); + qWarning("Cant find EGLConfig, returning null config"); + return 0; +} + +QPlatformWindowFormat qt_qPlatformWindowFormatFromConfig(EGLDisplay display, const EGLConfig config) +{ + QPlatformWindowFormat format; + EGLint redSize = 0; + EGLint greenSize = 0; + EGLint blueSize = 0; + EGLint alphaSize = 0; + EGLint depthSize = 0; + EGLint stencilSize = 0; + EGLint sampleCount = 0; + EGLint level = 0; + + eglGetConfigAttrib(display, config, EGL_RED_SIZE, &redSize); + eglGetConfigAttrib(display, config, EGL_GREEN_SIZE, &greenSize); + eglGetConfigAttrib(display, config, EGL_BLUE_SIZE, &blueSize); + eglGetConfigAttrib(display, config, EGL_ALPHA_SIZE, &alphaSize); + eglGetConfigAttrib(display, config, EGL_DEPTH_SIZE, &depthSize); + eglGetConfigAttrib(display, config, EGL_STENCIL_SIZE, &stencilSize); + eglGetConfigAttrib(display, config, EGL_SAMPLES, &sampleCount); + eglGetConfigAttrib(display, config, EGL_LEVEL, &level); + + format.setRedBufferSize(redSize); + format.setGreenBufferSize(greenSize); + format.setBlueBufferSize(blueSize); + format.setAlphaBufferSize(alphaSize); + format.setDepthBufferSize(depthSize); + format.setStencilBufferSize(stencilSize); + format.setSamples(sampleCount); + format.setDirectRendering(true); // All EGL contexts are direct-rendered + format.setRgba(true); // EGL doesn't support colour index rendering + format.setStereo(false); // EGL doesn't support stereo buffers + format.setAccumBufferSize(0); // EGL doesn't support accululation buffers + + // Clear the EGL error state because some of the above may + // have errored out because the attribute is not applicable + // to the surface type. Such errors don't matter. + eglGetError(); + + return format; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglconvenience/qeglconvenience.h b/src/plugins/platforms/eglconvenience/qeglconvenience.h new file mode 100644 index 0000000..604262b --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qeglconvenience.h @@ -0,0 +1,59 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QEGLCONVENIENCE_H +#define QEGLCONVENIENCE_H + + +#include <QtGui/QPlatformWindowFormat> +#include <QtCore/QVector> + +#include <EGL/egl.h> +QT_BEGIN_NAMESPACE + +QVector<EGLint> q_createConfigAttributesFromFormat(const QPlatformWindowFormat &format); +bool q_reduceConfigAttributes(QVector<EGLint> *configAttributes); +EGLConfig q_configFromQPlatformWindowFormat(EGLDisplay display, const QPlatformWindowFormat &format); +QPlatformWindowFormat qt_qPlatformWindowFormatFromConfig(EGLDisplay display, const EGLConfig config); + +QT_END_NAMESPACE + +#endif //QEGLCONVENIENCE_H diff --git a/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp b/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp new file mode 100644 index 0000000..ae3b539 --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qeglplatformcontext.cpp @@ -0,0 +1,155 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qeglplatformcontext.h" + + +#include <QtGui/QPlatformWindow> + +#include "qeglconvenience.h" + +#include <EGL/egl.h> + +QEGLPlatformContext::QEGLPlatformContext(EGLDisplay display, EGLConfig config, EGLint contextAttrs[], EGLSurface surface, EGLenum eglApi) + : QPlatformGLContext() + , m_eglDisplay(display) + , m_eglSurface(surface) + , m_eglApi(eglApi) +{ + if (m_eglSurface == EGL_NO_SURFACE) { + qWarning("Createing QEGLPlatformContext with no surface"); + } + + eglBindAPI(m_eglApi); + m_eglContext = eglCreateContext(m_eglDisplay,config, 0,contextAttrs); + if (m_eglContext == EGL_NO_CONTEXT) { + qWarning("Could not create the egl context\n"); + eglTerminate(m_eglDisplay); + qFatal("EGL error"); + } + + m_windowFormat = qt_qPlatformWindowFormatFromConfig(display,config); +} + +QEGLPlatformContext::~QEGLPlatformContext() +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::~QEglContext(): %p\n",this); +#endif + if (m_eglSurface != EGL_NO_SURFACE) { + doneCurrent(); + eglDestroySurface(m_eglDisplay, m_eglSurface); + m_eglSurface = EGL_NO_SURFACE; + } + + if (m_eglContext != EGL_NO_CONTEXT) { + eglDestroyContext(m_eglDisplay, m_eglContext); + m_eglContext = EGL_NO_CONTEXT; + } +} + +void QEGLPlatformContext::makeCurrent() +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::makeCurrent: %p\n",this); +#endif + eglBindAPI(m_eglApi); + bool ok = eglMakeCurrent(m_eglDisplay, m_eglSurface, m_eglSurface, m_eglContext); + if (!ok) + qWarning("QEGLPlatformContext::makeCurrent: eglError: %d, this: %p \n", eglGetError(), this); +#ifdef QEGL_EXTRA_DEBUG + static bool showDebug = true; + if (showDebug) { + showDebug = false; + const char *str = (const char*)glGetString(GL_VENDOR); + qWarning("Vendor %s\n", str); + str = (const char*)glGetString(GL_RENDERER); + qWarning("Renderer %s\n", str); + str = (const char*)glGetString(GL_VERSION); + qWarning("Version %s\n", str); + + str = (const char*)glGetString(GL_SHADING_LANGUAGE_VERSION); + qWarning("Extensions %s\n",str); + + str = (const char*)glGetString(GL_EXTENSIONS); + qWarning("Extensions %s\n", str); + + } +#endif +} +void QEGLPlatformContext::doneCurrent() +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::doneCurrent:%p\n",this); +#endif + eglBindAPI(m_eglApi); + bool ok = eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (!ok) + qWarning("QEGLPlatformContext::doneCurrent(): eglError: %d, this: %p \n", eglGetError(), this); +} +void QEGLPlatformContext::swapBuffers() +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::swapBuffers:%p\n",this); +#endif + eglBindAPI(m_eglApi); + bool ok = eglSwapBuffers(m_eglDisplay, m_eglSurface); + if (!ok) + qWarning("QEGLPlatformContext::swapBuffers(): eglError: %d, this: %p \n", eglGetError(), this); +} +void* QEGLPlatformContext::getProcAddress(const QString& procName) +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglContext::getProcAddress%p\n",this); +#endif + eglBindAPI(m_eglApi); + return (void *)eglGetProcAddress(qPrintable(procName)); +} + +void QEGLPlatformContext::makeDefaultSaredContext() +{ + setDefaultSharedContext(this); +} + +QPlatformWindowFormat QEGLPlatformContext::platformWindowFormat() const +{ + return m_windowFormat; +} diff --git a/src/plugins/platforms/eglconvenience/qeglplatformcontext.h b/src/plugins/platforms/eglconvenience/qeglplatformcontext.h new file mode 100644 index 0000000..ae1a891 --- /dev/null +++ b/src/plugins/platforms/eglconvenience/qeglplatformcontext.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QOPENKODEGLINTEGRATION_H +#define QOPENKODEGLINTEGRATION_H + +#include <QtGui/QPlatformGLContext> +#include <EGL/egl.h> + +class QEGLPlatformContext : public QPlatformGLContext +{ +public: + QEGLPlatformContext(EGLDisplay display, EGLConfig config, EGLint contextAttrs[], EGLSurface surface, EGLenum eglApi); + ~QEGLPlatformContext(); + + void makeCurrent(); + void doneCurrent(); + void swapBuffers(); + void* getProcAddress(const QString& procName); + + void makeDefaultSaredContext(); + + QPlatformWindowFormat platformWindowFormat() const; +private: + EGLContext m_eglContext; + EGLDisplay m_eglDisplay; + EGLSurface m_eglSurface; + EGLenum m_eglApi; + + QPlatformWindowFormat m_windowFormat; +}; + +#endif //QOPENKODEGLINTEGRATION_H diff --git a/src/plugins/platforms/eglfs/eglfs.pro b/src/plugins/platforms/eglfs/eglfs.pro new file mode 100644 index 0000000..7ad8fd9 --- /dev/null +++ b/src/plugins/platforms/eglfs/eglfs.pro @@ -0,0 +1,31 @@ +TARGET = qeglfs +TEMPLATE = lib +CONFIG += plugin + +QT += opengl + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +#DEFINES += QEGL_EXTRA_DEBUG + +#DEFINES += Q_OPENKODE + +SOURCES = main.cpp \ + qeglfsintegration.cpp \ + ../eglconvenience/qeglconvenience.cpp \ + ../eglconvenience/qeglplatformcontext.cpp \ + qeglfswindow.cpp \ + qeglfswindowsurface.cpp \ + qeglfsscreen.cpp + +HEADERS = qeglfsintegration.h \ + ../eglconvenience/qeglconvenience.h \ + ../eglconvenience/qeglplatformcontext.h \ + qeglfswindow.h \ + qeglfswindowsurface.h \ + qeglfsscreen.h + +include(../fontdatabases/genericunix/genericunix.pri) + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target diff --git a/src/plugins/platforms/eglfs/main.cpp b/src/plugins/platforms/eglfs/main.cpp new file mode 100644 index 0000000..d0a82b7 --- /dev/null +++ b/src/plugins/platforms/eglfs/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qeglfsintegration.h" + +QT_BEGIN_NAMESPACE + +class QEglIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QEglIntegrationPlugin::keys() const +{ + QStringList list; + list << "EglFS"; + return list; +} + +QPlatformIntegration* QEglIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "eglfs") + return new QEglFSIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(eglintegration, QEglIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.cpp b/src/plugins/platforms/eglfs/qeglfsintegration.cpp new file mode 100644 index 0000000..a48fde8 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsintegration.cpp @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qeglfsintegration.h" + +#include "qeglfswindow.h" +#include "qeglfswindowsurface.h" + +#include <QtGui/QPlatformWindow> +#include <QtGui/QPlatformWindowFormat> +#include <QtOpenGL/private/qpixmapdata_gl_p.h> + +#include "qgenericunixfontdatabase.h" + +#include <EGL/egl.h> + +QT_BEGIN_NAMESPACE + +QEglFSIntegration::QEglFSIntegration() + : mFontDb(new QGenericUnixFontDatabase()) +{ + m_primaryScreen = new QEglFSScreen(EGL_DEFAULT_DISPLAY); + + mScreens.append(m_primaryScreen); +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglIntegration\n"); +#endif +} + +QPixmapData *QEglFSIntegration::createPixmapData(QPixmapData::PixelType type) const +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglIntegration::createPixmapData %d\n", type); +#endif + return new QGLPixmapData(type); +} + +QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglIntegration::createPlatformWindow %p\n",widget); +#endif + return new QEglFSWindow(widget, m_primaryScreen); +} + + +QWindowSurface *QEglFSIntegration::createWindowSurface(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglIntegration::createWindowSurface %p\n",widget); +#endif + return new QEglFSWindowSurface(m_primaryScreen,widget); +} + +QPlatformFontDatabase *QEglFSIntegration::fontDatabase() const +{ + return mFontDb; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsintegration.h b/src/plugins/platforms/eglfs/qeglfsintegration.h new file mode 100644 index 0000000..0342539 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsintegration.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 EGLINTEGRATION_H +#define EGLINTEGRATION_H + +#include "qeglfsscreen.h" + +#include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformScreen> + +QT_BEGIN_HEADER + +QT_BEGIN_NAMESPACE + +class QEglFSIntegration : public QPlatformIntegration +{ +public: + QEglFSIntegration(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QList<QPlatformScreen *> screens() const { return mScreens; } + + QPlatformFontDatabase *fontDatabase() const; + +private: + QPlatformFontDatabase *mFontDb; + QList<QPlatformScreen *> mScreens; + QEglFSScreen *m_primaryScreen; +}; + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.cpp b/src/plugins/platforms/eglfs/qeglfsscreen.cpp new file mode 100644 index 0000000..9a40b86 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsscreen.cpp @@ -0,0 +1,203 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qeglfsscreen.h" + +#include "../eglconvenience/qeglconvenience.h" +#include "../eglconvenience/qeglplatformcontext.h" + +#ifdef Q_OPENKODE +#include <KD/kd.h> +#include <KD/NV_initialize.h> +#endif //Q_OPENKODE + +QT_BEGIN_NAMESPACE + +// #define QEGL_EXTRA_DEBUG + +#ifdef QEGL_EXTRA_DEBUG +struct AttrInfo { EGLint attr; const char *name; }; +static struct AttrInfo attrs[] = { + {EGL_BUFFER_SIZE, "EGL_BUFFER_SIZE"}, + {EGL_ALPHA_SIZE, "EGL_ALPHA_SIZE"}, + {EGL_BLUE_SIZE, "EGL_BLUE_SIZE"}, + {EGL_GREEN_SIZE, "EGL_GREEN_SIZE"}, + {EGL_RED_SIZE, "EGL_RED_SIZE"}, + {EGL_DEPTH_SIZE, "EGL_DEPTH_SIZE"}, + {EGL_STENCIL_SIZE, "EGL_STENCIL_SIZE"}, + {EGL_CONFIG_CAVEAT, "EGL_CONFIG_CAVEAT"}, + {EGL_CONFIG_ID, "EGL_CONFIG_ID"}, + {EGL_LEVEL, "EGL_LEVEL"}, + {EGL_MAX_PBUFFER_HEIGHT, "EGL_MAX_PBUFFER_HEIGHT"}, + {EGL_MAX_PBUFFER_PIXELS, "EGL_MAX_PBUFFER_PIXELS"}, + {EGL_MAX_PBUFFER_WIDTH, "EGL_MAX_PBUFFER_WIDTH"}, + {EGL_NATIVE_RENDERABLE, "EGL_NATIVE_RENDERABLE"}, + {EGL_NATIVE_VISUAL_ID, "EGL_NATIVE_VISUAL_ID"}, + {EGL_NATIVE_VISUAL_TYPE, "EGL_NATIVE_VISUAL_TYPE"}, + {EGL_SAMPLES, "EGL_SAMPLES"}, + {EGL_SAMPLE_BUFFERS, "EGL_SAMPLE_BUFFERS"}, + {EGL_SURFACE_TYPE, "EGL_SURFACE_TYPE"}, + {EGL_TRANSPARENT_TYPE, "EGL_TRANSPARENT_TYPE"}, + {EGL_TRANSPARENT_BLUE_VALUE, "EGL_TRANSPARENT_BLUE_VALUE"}, + {EGL_TRANSPARENT_GREEN_VALUE, "EGL_TRANSPARENT_GREEN_VALUE"}, + {EGL_TRANSPARENT_RED_VALUE, "EGL_TRANSPARENT_RED_VALUE"}, + {EGL_BIND_TO_TEXTURE_RGB, "EGL_BIND_TO_TEXTURE_RGB"}, + {EGL_BIND_TO_TEXTURE_RGBA, "EGL_BIND_TO_TEXTURE_RGBA"}, + {EGL_MIN_SWAP_INTERVAL, "EGL_MIN_SWAP_INTERVAL"}, + {EGL_MAX_SWAP_INTERVAL, "EGL_MAX_SWAP_INTERVAL"}, + {-1, 0}}; +#endif //QEGL_EXTRA_DEBUG + +QEglFSScreen::QEglFSScreen(EGLNativeDisplayType display) + : m_depth(32), m_format(QImage::Format_ARGB32_Premultiplied), m_platformContext(0) +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglScreen %p\n", this); +#endif + + EGLint major, minor; +#ifdef QEGL_EXTRA_DEBUG + EGLint index; +#endif + if (!eglBindAPI(EGL_OPENGL_ES_API)) { + qWarning("Could not bind GL_ES API\n"); + qFatal("EGL error"); + } + + m_dpy = eglGetDisplay(display); + if (m_dpy == EGL_NO_DISPLAY) { + qWarning("Could not open egl display\n"); + qFatal("EGL error"); + } + qWarning("Opened display %p\n", m_dpy); + + if (!eglInitialize(m_dpy, &major, &minor)) { + qWarning("Could not initialize egl display\n"); + qFatal("EGL error"); + } + + qWarning("Initialized display %d %d\n", major, minor); + + QPlatformWindowFormat platformFormat; + platformFormat.setWindowApi(QPlatformWindowFormat::OpenGL); + + QByteArray depthString = qgetenv("QT_QPA_EGLFS_DEPTH"); + if (depthString.toInt() == 16) { + platformFormat.setDepth(16); + platformFormat.setRedBufferSize(5); + platformFormat.setGreenBufferSize(6); + platformFormat.setBlueBufferSize(5); + m_depth = 16; + m_format = QImage::Format_RGB16; + } else { + platformFormat.setDepth(32); + platformFormat.setRedBufferSize(8); + platformFormat.setGreenBufferSize(8); + platformFormat.setBlueBufferSize(8); + } + + if (!qgetenv("QT_QPA_EGLFS_MULTISAMPLE").isEmpty()) { + platformFormat.setSampleBuffers(true); + } + + int swapInterval = 1; + QByteArray swapIntervalString = qgetenv("QT_QPA_EGLFS_SWAPINTERVAL"); + if (!swapIntervalString.isEmpty()) { + bool ok; + swapInterval = swapIntervalString.toInt(&ok); + if (!ok) + swapInterval = 1; + } + + EGLConfig config = q_configFromQPlatformWindowFormat(m_dpy, platformFormat); + eglSwapInterval(display, swapInterval); + + EGLNativeWindowType eglWindow = 0; +#ifdef Q_OPENKODE + if (kdInitializeNV() == KD_ENOTINITIALIZED) { + qFatal("Did not manage to initialize openkode"); + } + KDWindow *window = kdCreateWindow(m_dpy,config,0); + + kdRealizeWindow(window,&eglWindow); +#endif + + m_surface = eglCreateWindowSurface(m_dpy, config, eglWindow, NULL); + if (m_surface == EGL_NO_SURFACE) { + qWarning("Could not create the egl surface: error = 0x%x\n", eglGetError()); + eglTerminate(m_dpy); + qFatal("EGL error"); + } + // qWarning("Created surface %dx%d\n", w, h); + +#ifdef QEGL_EXTRA_DEBUG + qWarning("Configuration %d matches requirements\n", (int)config); + + for (index = 0; attrs[index].attr != -1; ++index) { + EGLint value; + if (eglGetConfigAttrib(m_dpy, config, attrs[index].attr, &value)) { + qWarning("\t%s: %d\n", attrs[index].name, (int)value); + } + } + qWarning("\n"); +#endif + + EGLint temp; + EGLint attribList[32]; + + temp = 0; + + attribList[temp++] = EGL_CONTEXT_CLIENT_VERSION; + attribList[temp++] = 2; // GLES version 2 + attribList[temp++] = EGL_NONE; + + m_platformContext = new QEGLPlatformContext(m_dpy,config,attribList,m_surface,EGL_OPENGL_ES_API); + +// qWarning("Created platformcontext"); + EGLint w,h; + + eglQuerySurface(m_dpy, m_surface, EGL_WIDTH, &w); + eglQuerySurface(m_dpy, m_surface, EGL_HEIGHT, &h); + + m_geometry = QRect(0,0,w,h); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsscreen.h b/src/plugins/platforms/eglfs/qeglfsscreen.h new file mode 100644 index 0000000..9ed1b04 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfsscreen.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QEGLSCREEN_H +#define QEGLSCREEN_H + +#include <QPlatformScreen> + + +#include <EGL/egl.h> + +QT_BEGIN_NAMESPACE + +class QPlatformGLContext; + +class QEglFSScreen : public QPlatformScreen //huh: FullScreenScreen ;) just to follow namespace +{ +public: + QEglFSScreen(EGLNativeDisplayType display); + ~QEglFSScreen() {} + + QRect geometry() const { return m_geometry; } + int depth() const { return m_depth; } + QImage::Format format() const { return m_format; } + + QPlatformGLContext *platformContext() const { return m_platformContext; } + +private: + QRect m_geometry; + int m_depth; + QImage::Format m_format; + QPlatformGLContext *m_platformContext; + EGLDisplay m_dpy; + EGLSurface m_surface; +}; + +QT_END_NAMESPACE +#endif // QEGLSCREEN_H diff --git a/src/plugins/platforms/eglfs/qeglfswindow.cpp b/src/plugins/platforms/eglfs/qeglfswindow.cpp new file mode 100644 index 0000000..d0e15d3 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfswindow.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qeglfswindow.h" + +#include <QtGui/QWindowSystemInterface> + +QT_BEGIN_NAMESPACE + +QEglFSWindow::QEglFSWindow(QWidget *w, QEglFSScreen *screen) + : QPlatformWindow(w), m_screen(screen) +{ + static int serialNo = 0; + m_winid = ++serialNo; +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglWindow %p: %p %p 0x%x\n", this, w, screen, uint(m_winid)); +#endif +} + + +void QEglFSWindow::setGeometry(const QRect &) +{ + // We only support full-screen windows + QRect rect(m_screen->availableGeometry()); + QWindowSystemInterface::handleGeometryChange(this->widget(), rect); + + QPlatformWindow::setGeometry(rect); +} + +WId QEglFSWindow::winId() const +{ + return m_winid; +} + + + +QPlatformGLContext *QEglFSWindow::glContext() const +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglWindow::glContext %p\n", m_screen->platformContext()); +#endif + Q_ASSERT(m_screen); + return m_screen->platformContext(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfswindow.h b/src/plugins/platforms/eglfs/qeglfswindow.h new file mode 100644 index 0000000..43f185b --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfswindow.h @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QEGLWINDOW_H +#define QEGLWINDOW_H + +#include "qeglfsintegration.h" +#include "qeglfsscreen.h" + + +#include <QPlatformWindow> +#include <QtGui/QWidget> + +#include <EGL/egl.h> + +QT_BEGIN_NAMESPACE + +class QEglFSWindow : public QPlatformWindow +{ +public: + QEglFSWindow(QWidget *w, QEglFSScreen *screen); + + void setGeometry(const QRect &); + WId winId() const; + + QPlatformGLContext *glContext() const; + +private: + QEglFSScreen *m_screen; + WId m_winid; +}; +QT_END_NAMESPACE +#endif // QEGLWINDOW_H diff --git a/src/plugins/platforms/eglfs/qeglfswindowsurface.cpp b/src/plugins/platforms/eglfs/qeglfswindowsurface.cpp new file mode 100644 index 0000000..fcea4d3 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfswindowsurface.cpp @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qeglfswindowsurface.h" + +#include <QtGui/QPlatformGLContext> + +#include <QtOpenGL/private/qgl_p.h> +#include <QtOpenGL/private/qglpaintdevice_p.h> + +QT_BEGIN_NAMESPACE + +class QEglFSPaintDevice : public QGLPaintDevice +{ +public: + QEglFSPaintDevice(QEglFSScreen *screen, QWidget *widget) + :QGLPaintDevice(), m_screen(screen) + { + #ifdef QEGL_EXTRA_DEBUG + qWarning("QEglPaintDevice %p, %p, %p",this, screen, widget); + #endif + QGLFormat format; + m_context = new QGLContext(format, widget); + m_context->create(); + } + + QSize size() const { return m_screen->geometry().size(); } + QGLContext* context() const { return m_context;} + + QPaintEngine *paintEngine() const { return qt_qgl_paint_engine(); } + + void beginPaint(){ + QGLPaintDevice::beginPaint(); + } +private: + QEglFSScreen *m_screen; + QGLContext *m_context; +}; + + +QEglFSWindowSurface::QEglFSWindowSurface( QEglFSScreen *screen, QWidget *window ) + :QWindowSurface(window) +{ +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglWindowSurface %p, %p", window, screen); +#endif + m_paintDevice = new QEglFSPaintDevice(screen,window); +} + +void QEglFSWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(region); + Q_UNUSED(offset); +#ifdef QEGL_EXTRA_DEBUG + qWarning("QEglWindowSurface::flush %p",widget); +#endif + widget->platformWindow()->glContext()->swapBuffers(); +} + +void QEglFSWindowSurface::resize(const QSize &size) +{ + Q_UNUSED(size); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfswindowsurface.h b/src/plugins/platforms/eglfs/qeglfswindowsurface.h new file mode 100644 index 0000000..f8aca40 --- /dev/null +++ b/src/plugins/platforms/eglfs/qeglfswindowsurface.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QEGLWINDOWSURFACE_H +#define QEGLWINDOWSURFACE_H + +#include "qeglfsintegration.h" +#include "qeglfswindow.h" + +#include <QtGui/private/qwindowsurface_p.h> + +QT_BEGIN_NAMESPACE + +class QEglFSWindowSurface : public QWindowSurface +{ +public: + QEglFSWindowSurface(QEglFSScreen *screen, QWidget *window); + ~QEglFSWindowSurface() {} + + QPaintDevice *paintDevice() { return m_paintDevice; } + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); +private: + QPaintDevice *m_paintDevice; +}; + +QT_END_NAMESPACE + +#endif // QEGLWINDOWSURFACE_H diff --git a/src/plugins/platforms/fb_base/fb_base.cpp b/src/plugins/platforms/fb_base/fb_base.cpp new file mode 100644 index 0000000..b000a18 --- /dev/null +++ b/src/plugins/platforms/fb_base/fb_base.cpp @@ -0,0 +1,507 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "fb_base.h" +#include <qpainter.h> +#include <qdebug.h> +#include <qbitmap.h> +#include <QPlatformCursor> +#include <QWindowSystemInterface> + +QPlatformSoftwareCursor::QPlatformSoftwareCursor(QPlatformScreen *scr) + : QPlatformCursor(scr), currentRect(QRect()), prevRect(QRect()) +{ + graphic = new QPlatformCursorImage(0, 0, 0, 0, 0, 0); + setCursor(Qt::ArrowCursor); +} + +QRect QPlatformSoftwareCursor::getCurrentRect() +{ + QRect rect = graphic->image()->rect().translated(-graphic->hotspot().x(), + -graphic->hotspot().y()); + rect.translate(QCursor::pos()); + QPoint screenOffset = screen->geometry().topLeft(); + rect.translate(-screenOffset); // global to local translation + return rect; +} + + +void QPlatformSoftwareCursor::pointerEvent(const QMouseEvent & e) +{ + Q_UNUSED(e); + QPoint screenOffset = screen->geometry().topLeft(); + currentRect = getCurrentRect(); + // global to local translation + if (onScreen || screen->geometry().intersects(currentRect.translated(screenOffset))) { + setDirty(); + } +} + +QRect QPlatformSoftwareCursor::drawCursor(QPainter & painter) +{ + dirty = false; + if (currentRect.isNull()) + return QRect(); + + // We need this because the cursor might be dirty due to moving off screen + QPoint screenOffset = screen->geometry().topLeft(); + // global to local translation + if (!currentRect.translated(screenOffset).intersects(screen->geometry())) + return QRect(); + + prevRect = currentRect; + painter.drawImage(prevRect, *graphic->image()); + onScreen = true; + return prevRect; +} + +QRect QPlatformSoftwareCursor::dirtyRect() +{ + if (onScreen) { + onScreen = false; + return prevRect; + } + return QRect(); +} + +void QPlatformSoftwareCursor::setCursor(Qt::CursorShape shape) +{ + graphic->set(shape); +} + +void QPlatformSoftwareCursor::setCursor(const QImage &image, int hotx, int hoty) +{ + graphic->set(image, hotx, hoty); +} + +void QPlatformSoftwareCursor::setCursor(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY) +{ + graphic->set(data, mask, width, height, hotX, hotY); +} + +void QPlatformSoftwareCursor::changeCursor(QCursor * widgetCursor, QWidget * widget) +{ + Q_UNUSED(widget); + Qt::CursorShape shape = widgetCursor->shape(); + + if (shape == Qt::BitmapCursor) { + // application supplied cursor + QPoint spot = widgetCursor->hotSpot(); + setCursor(widgetCursor->pixmap().toImage(), spot.x(), spot.y()); + } else { + // system cursor + setCursor(shape); + } + currentRect = getCurrentRect(); + QPoint screenOffset = screen->geometry().topLeft(); // global to local translation + if (onScreen || screen->geometry().intersects(currentRect.translated(screenOffset))) + setDirty(); +} + +QFbScreen::QFbScreen() : cursor(0), mGeometry(), mDepth(16), mFormat(QImage::Format_RGB16), mScreenImage(0), compositePainter(0), isUpToDate(false) +{ + mScreenImage = new QImage(mGeometry.size(), mFormat); + redrawTimer.setSingleShot(true); + redrawTimer.setInterval(0); + QObject::connect(&redrawTimer, SIGNAL(timeout()), this, SLOT(doRedraw())); +} + +void QFbScreen::setGeometry(QRect rect) +{ + delete mScreenImage; + mGeometry = rect; + mScreenImage = new QImage(mGeometry.size(), mFormat); + delete compositePainter; + compositePainter = 0; + invalidateRectCache(); +} + +void QFbScreen::setDepth(int depth) +{ + mDepth = depth; +} + +void QFbScreen::setPhysicalSize(QSize size) +{ + mPhysicalSize = size; +} + +void QFbScreen::setFormat(QImage::Format format) +{ + mFormat = format; + delete mScreenImage; + mScreenImage = new QImage(mGeometry.size(), mFormat); + delete compositePainter; + compositePainter = 0; +} + +QFbScreen::~QFbScreen() +{ + delete compositePainter; + delete mScreenImage; +} + +void QFbScreen::setDirty(const QRect &rect) +{ + QRect intersection = rect.intersected(mGeometry); + QPoint screenOffset = mGeometry.topLeft(); + repaintRegion += intersection.translated(-screenOffset); // global to local translation + if (!redrawTimer.isActive()) { + redrawTimer.start(); + } +} + +void QFbScreen::generateRects() +{ + cachedRects.clear(); + QPoint screenOffset = mGeometry.topLeft(); + QRegion remainingScreen(mGeometry.translated(-screenOffset)); // global to local translation + + for (int i = 0; i < windowStack.length(); i++) { + if (remainingScreen.isEmpty()) + break; + if (!windowStack[i]->visible()) + continue; + if (windowStack[i]->widget()->isMinimized()) + continue; + + if (!windowStack[i]->widget()->testAttribute(Qt::WA_TranslucentBackground)) { + QRect localGeometry = windowStack.at(i)->geometry().translated(-screenOffset); // global to local translation + remainingScreen -= localGeometry; + QRegion windowRegion(localGeometry); + windowRegion -= remainingScreen; + foreach(QRect rect, windowRegion.rects()) { + cachedRects += QPair<QRect, int>(rect, i); + } + } + } + foreach (QRect rect, remainingScreen.rects()) + cachedRects += QPair<QRect, int>(rect, -1); + isUpToDate = true; + return; +} + + + +QRegion QFbScreen::doRedraw() +{ + QPoint screenOffset = mGeometry.topLeft(); + + QRegion touchedRegion; + if (cursor && cursor->isDirty() && cursor->isOnScreen()) { + QRect lastCursor = cursor->dirtyRect(); + repaintRegion += lastCursor; + } + if (repaintRegion.isEmpty() && (!cursor || !cursor->isDirty())) { + return touchedRegion; + } + + QVector<QRect> rects = repaintRegion.rects(); + + if (!isUpToDate) + generateRects(); + + if (!compositePainter) + compositePainter = new QPainter(mScreenImage); + for (int rectIndex = 0; rectIndex < repaintRegion.numRects(); rectIndex++) { + QRegion rectRegion = rects[rectIndex]; + + for(int i = 0; i < cachedRects.length(); i++) { + QRect screenSubRect = cachedRects[i].first; + int layer = cachedRects[i].second; + QRegion intersect = rectRegion.intersected(screenSubRect); + + if (intersect.isEmpty()) + continue; + + rectRegion -= intersect; + + // we only expect one rectangle, but defensive coding... + foreach (QRect rect, intersect.rects()) { + bool firstLayer = true; + if (layer == -1) { + compositePainter->fillRect(rect, Qt::black); + firstLayer = false; + layer = windowStack.size() - 1; + } + + for (int layerIndex = layer; layerIndex != -1; layerIndex--) { + if (!windowStack[layerIndex]->visible()) + continue; + if (windowStack[layerIndex]->widget()->isMinimized()) + continue; + QRect windowRect = windowStack[layerIndex]->geometry().translated(-screenOffset); + QRect windowIntersect = rect.translated(-windowRect.left(), + -windowRect.top()); + compositePainter->drawImage(rect, windowStack[layerIndex]->surface->image(), + windowIntersect); + if (firstLayer) { + firstLayer = false; + } + } + } + } + } + + QRect cursorRect; + if (cursor && (cursor->isDirty() || repaintRegion.intersects(cursor->lastPainted()))) { + cursorRect = cursor->drawCursor(*compositePainter); + touchedRegion += cursorRect; + } + touchedRegion += repaintRegion; + repaintRegion = QRegion(); + + + +// qDebug() << "QFbScreen::doRedraw" << windowStack.size() << mScreenImage->size() << touchedRegion; + + + return touchedRegion; +} + +void QFbScreen::addWindow(QFbWindow *surface) +{ + windowStack.prepend(surface); + surface->mScreens.append(this); + invalidateRectCache(); + setDirty(surface->geometry()); +} + +void QFbScreen::removeWindow(QFbWindow * surface) +{ + windowStack.removeOne(surface); + surface->mScreens.removeOne(this); + invalidateRectCache(); + setDirty(surface->geometry()); +} + +void QFbWindow::raise() +{ + QList<QFbScreen *>::const_iterator i = mScreens.constBegin(); + QList<QFbScreen *>::const_iterator end = mScreens.constEnd(); + while (i != end) { + (*i)->raise(this); + ++i; + } +} + +void QFbScreen::raise(QPlatformWindow * surface) +{ + QFbWindow *s = static_cast<QFbWindow *>(surface); + int index = windowStack.indexOf(s); + if (index <= 0) + return; + windowStack.move(index, 0); + invalidateRectCache(); + setDirty(s->geometry()); +} + +void QFbWindow::lower() +{ + QList<QFbScreen *>::const_iterator i = mScreens.constBegin(); + QList<QFbScreen *>::const_iterator end = mScreens.constEnd(); + while (i != end) { + (*i)->lower(this); + ++i; + } +} + +void QFbScreen::lower(QPlatformWindow * surface) +{ + QFbWindow *s = static_cast<QFbWindow *>(surface); + int index = windowStack.indexOf(s); + if (index == -1 || index == (windowStack.size() - 1)) + return; + windowStack.move(index, windowStack.size() - 1); + invalidateRectCache(); + setDirty(s->geometry()); +} + +QWidget * QFbScreen::topLevelAt(const QPoint & p) const +{ + for(int i = 0; i < windowStack.size(); i++) { + if (windowStack[i]->geometry().contains(p, false) && + windowStack[i]->visible() && + !windowStack[i]->widget()->isMinimized()) { + return windowStack[i]->widget(); + } + } + return 0; +} + +QFbWindow::QFbWindow(QWidget *window) + :QPlatformWindow(window), + visibleFlag(false) +{ + static QAtomicInt winIdGenerator(1); + windowId = winIdGenerator.fetchAndAddRelaxed(1); +} + + +QFbWindow::~QFbWindow() +{ + QList<QFbScreen *>::const_iterator i = mScreens.constBegin(); + QList<QFbScreen *>::const_iterator end = mScreens.constEnd(); + while (i != end) { + (*i)->removeWindow(this); + ++i; + } +} + + +QFbWindowSurface::QFbWindowSurface(QFbScreen *screen, QWidget *window) + : QWindowSurface(window), + mScreen(screen) +{ + mImage = QImage(window->size(), mScreen->format()); + + platformWindow = static_cast<QFbWindow*>(window->platformWindow()); + platformWindow->surface = this; +} + +QFbWindowSurface::~QFbWindowSurface() +{ +} + +void QFbWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(offset); + + +// qDebug() << "QFbWindowSurface::flush" << region; + + + platformWindow->repaint(region); +} + + +void QFbWindow::repaint(const QRegion ®ion) +{ + QRect currentGeometry = geometry(); + + QRect dirtyClient = region.boundingRect(); + QRect dirtyRegion(currentGeometry.left() + dirtyClient.left(), + currentGeometry.top() + dirtyClient.top(), + dirtyClient.width(), + dirtyClient.height()); + QList<QFbScreen *>::const_iterator i = mScreens.constBegin(); + QList<QFbScreen *>::const_iterator end = mScreens.constEnd(); + QRect oldGeometryLocal = oldGeometry; + oldGeometry = currentGeometry; + while (i != end) { + // If this is a move, redraw the previous location + if (oldGeometryLocal != currentGeometry) { + (*i)->setDirty(oldGeometryLocal); + } + (*i)->setDirty(dirtyRegion); + ++i; + } +} + +void QFbWindowSurface::resize(const QSize &size) +{ + // change the widget's QImage if this is a resize + if (mImage.size() != size) + mImage = QImage(size, mScreen->format()); + QWindowSurface::resize(size); +} + +void QFbWindow::setGeometry(const QRect &rect) +{ +// store previous geometry for screen update + oldGeometry = geometry(); + + + QList<QFbScreen *>::const_iterator i = mScreens.constBegin(); + QList<QFbScreen *>::const_iterator end = mScreens.constEnd(); + while (i != end) { + (*i)->invalidateRectCache(); + ++i; + } +//### QWindowSystemInterface::handleGeometryChange(window(), rect); + + QPlatformWindow::setGeometry(rect); +} + +bool QFbWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + return QWindowSurface::scroll(area, dx, dy); +} + +void QFbWindowSurface::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +void QFbWindowSurface::endPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +void QFbWindow::setVisible(bool visible) +{ + visibleFlag = visible; + QList<QFbScreen *>::const_iterator i = mScreens.constBegin(); + QList<QFbScreen *>::const_iterator end = mScreens.constEnd(); + while (i != end) { + (*i)->invalidateRectCache(); + (*i)->setDirty(geometry()); + ++i; + } +} + +Qt::WindowFlags QFbWindow::setWindowFlags(Qt::WindowFlags type) +{ + flags = type; + QList<QFbScreen *>::const_iterator i = mScreens.constBegin(); + QList<QFbScreen *>::const_iterator end = mScreens.constEnd(); + while (i != end) { + (*i)->invalidateRectCache(); + ++i; + } + return flags; +} + +Qt::WindowFlags QFbWindow::windowFlags() const +{ + return flags; +} diff --git a/src/plugins/platforms/fb_base/fb_base.h b/src/plugins/platforms/fb_base/fb_base.h new file mode 100644 index 0000000..45a5663 --- /dev/null +++ b/src/plugins/platforms/fb_base/fb_base.h @@ -0,0 +1,210 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QLIGHTHOUSEGRAPHICSSCREEN_H +#define QLIGHTHOUSEGRAPHICSSCREEN_H + +#include <qrect.h> +#include <qimage.h> +#include <qtimer.h> +#include <qpainter.h> +#include <QPlatformCursor> +#include <QPlatformScreen> +#include <QPlatformWindow> +#include <QtGui/private/qwindowsurface_p.h> + +class QMouseEvent; +class QSize; +class QPainter; + +class QFbScreen; + +class QPlatformSoftwareCursor : public QPlatformCursor +{ +public: + QPlatformSoftwareCursor(QPlatformScreen * scr); + + // output methods + QRect dirtyRect(); + virtual QRect drawCursor(QPainter & painter); + + // input methods + virtual void pointerEvent(const QMouseEvent & event); + virtual void changeCursor(QCursor * widgetCursor, QWidget * widget); + + virtual void setDirty() { dirty = true; screen->setDirty(QRect()); } + virtual bool isDirty() { return dirty; } + virtual bool isOnScreen() { return onScreen; } + virtual QRect lastPainted() { return prevRect; } + +protected: + QPlatformCursorImage * graphic; + +private: + void setCursor(const uchar *data, const uchar *mask, int width, int height, int hotX, int hotY); + void setCursor(Qt::CursorShape shape); + void setCursor(const QImage &image, int hotx, int hoty); + QRect currentRect; // next place to draw the cursor + QRect prevRect; // last place the cursor was drawn + QRect getCurrentRect(); + bool dirty; + bool onScreen; +}; + +class QFbWindow; + +class QFbWindowSurface : public QWindowSurface +{ +public: + QFbWindowSurface(QFbScreen *screen, QWidget *window); + ~QFbWindowSurface(); + + virtual QPaintDevice *paintDevice() { return &mImage; } + virtual void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + virtual bool scroll(const QRegion &area, int dx, int dy); + + virtual void beginPaint(const QRegion ®ion); + virtual void endPaint(const QRegion ®ion); + + + const QImage image() { return mImage; } + void resize(const QSize &size); + +protected: + friend class QFbWindow; + QFbWindow *platformWindow; + + QFbScreen *mScreen; + QImage mImage; +}; + + +class QFbWindow : public QPlatformWindow +{ +public: + + QFbWindow(QWidget *window); + ~QFbWindow(); + + + virtual void setVisible(bool visible); + virtual bool visible() { return visibleFlag; } + + virtual void raise(); + virtual void lower(); + + void setGeometry(const QRect &rect); + + virtual Qt::WindowFlags setWindowFlags(Qt::WindowFlags type); + virtual Qt::WindowFlags windowFlags() const; + + WId winId() const { return windowId; } + + virtual void repaint(const QRegion&); + +protected: + friend class QFbWindowSurface; + friend class QFbScreen; + QFbWindowSurface *surface; + QList<QFbScreen *> mScreens; + QRect oldGeometry; + bool visibleFlag; + Qt::WindowFlags flags; + + WId windowId; +}; + +class QFbScreen : public QPlatformScreen +{ + Q_OBJECT +public: + QFbScreen(); + ~QFbScreen(); + + virtual QRect geometry() const { return mGeometry; } + virtual int depth() const { return mDepth; } + virtual QImage::Format format() const { return mFormat; } + virtual QSize physicalSize() const { return mPhysicalSize; } + + virtual void setGeometry(QRect rect); + virtual void setDepth(int depth); + virtual void setFormat(QImage::Format format); + virtual void setPhysicalSize(QSize size); + + virtual void setDirty(const QRect &rect); + + virtual void removeWindow(QFbWindow * surface); + virtual void addWindow(QFbWindow * surface); + virtual void raise(QPlatformWindow * surface); + virtual void lower(QPlatformWindow * surface); + virtual QWidget * topLevelAt(const QPoint & p) const; + + QImage * image() const { return mScreenImage; } + QPaintDevice * paintDevice() const { return mScreenImage; } + +protected: + QList<QFbWindow *> windowStack; + QRegion repaintRegion; + QPlatformSoftwareCursor * cursor; + QTimer redrawTimer; + +protected slots: + virtual QRegion doRedraw(); + +protected: + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + QSize mPhysicalSize; + QImage *mScreenImage; + +private: + QPainter * compositePainter; + void generateRects(); + QList<QPair<QRect, int> > cachedRects; + + void invalidateRectCache() { isUpToDate = false; } + friend class QFbWindowSurface; + friend class QFbWindow; + bool isUpToDate; +}; + +#endif // QLIGHTHOUSEGRAPHICSSCREEN_H diff --git a/src/plugins/platforms/fb_base/fb_base.pri b/src/plugins/platforms/fb_base/fb_base.pri new file mode 100644 index 0000000..41bd87f --- /dev/null +++ b/src/plugins/platforms/fb_base/fb_base.pri @@ -0,0 +1,2 @@ +SOURCES += ../fb_base/fb_base.cpp +HEADERS += ../fb_base/fb_base.h diff --git a/src/plugins/platforms/fb_base/fb_base.pro b/src/plugins/platforms/fb_base/fb_base.pro new file mode 100644 index 0000000..e08c0c5 --- /dev/null +++ b/src/plugins/platforms/fb_base/fb_base.pro @@ -0,0 +1,23 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2009-11-05T13:22:31 +# +#------------------------------------------------- + +#QT -= core gui +TARGET = fb_base +#include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems + +TEMPLATE = lib + +#DEFINES += STATIC_LIBRARY +CONFIG += staticlib + +SOURCES += fb_base.cpp + +HEADERS += fb_base.h + +target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems +INSTALLS += target diff --git a/src/plugins/platforms/fontdatabases/basicunix/basicunix.pri b/src/plugins/platforms/fontdatabases/basicunix/basicunix.pri new file mode 100644 index 0000000..21aedba --- /dev/null +++ b/src/plugins/platforms/fontdatabases/basicunix/basicunix.pri @@ -0,0 +1,82 @@ +DEFINES += QT_NO_FONTCONFIG +HEADERS += \ + $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.h \ + $$QT_SOURCE_TREE/src/gui/text/qfontengine_ft_p.h + +SOURCES += \ + $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.cpp \ + $$QT_SOURCE_TREE/src/gui/text/qfontengine_ft.cpp + +INCLUDEPATH += $$QT_SOURCE_TREE/src/3rdparty/harfbuzz/src + +INCLUDEPATH += $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/basicunix + +CONFIG += opentype + +contains(QT_CONFIG, freetype) { + SOURCES += \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftbase.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftbbox.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftdebug.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftglyph.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftinit.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftmm.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/fttype1.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftsynth.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftbitmap.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/bdf/bdf.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/cache/ftcache.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/cff/cff.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/cid/type1cid.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/gzip/ftgzip.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/pcf/pcf.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/pfr/pfr.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/psaux/psaux.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/pshinter/pshinter.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/psnames/psmodule.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/raster/raster.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/sfnt/sfnt.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/smooth/smooth.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/truetype/truetype.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/type1/type1.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/type42/type42.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/winfonts/winfnt.c \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/lzw/ftlzw.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvalid.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvbase.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvgdef.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvjstf.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvcommn.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvgpos.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvgsub.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/otvalid/otvmod.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afangles.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afglobal.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/aflatin.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afmodule.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afdummy.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afhints.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/afloader.c\ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/autofit/autofit.c + + symbian { + SOURCES += \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src/base/ftsystem.c + } else { + SOURCES += \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/builds/unix/ftsystem.c + INCLUDEPATH += \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/builds/unix + } + + INCLUDEPATH += \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/src \ + $$QT_SOURCE_TREE/src/3rdparty/freetype/include + + DEFINES += FT2_BUILD_LIBRARY 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) + LIBS_PRIVATE += -lfreetype + } + diff --git a/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.cpp b/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.cpp new file mode 100644 index 0000000..4634477 --- /dev/null +++ b/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.cpp @@ -0,0 +1,326 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qbasicunixfontdatabase.h" + +#include <QtGui/private/qapplication_p.h> +#include <QtGui/QPlatformScreen> + +#include <QtCore/QFile> +#include <QtCore/QLibraryInfo> +#include <QtCore/QDir> + +#undef QT_NO_FREETYPE +#include <QtGui/private/qfontengine_ft_p.h> +#include <QtGui/private/qfontengine_p.h> + +#include <ft2build.h> +#include FT_TRUETYPE_TABLES_H + +#define SimplifiedChineseCsbBit 18 +#define TraditionalChineseCsbBit 20 +#define JapaneseCsbBit 17 +#define KoreanCsbBit 21 + +static int requiredUnicodeBits[QFontDatabase::WritingSystemsCount][2] = { + // Any, + { 127, 127 }, + // Latin, + { 0, 127 }, + // Greek, + { 7, 127 }, + // Cyrillic, + { 9, 127 }, + // Armenian, + { 10, 127 }, + // Hebrew, + { 11, 127 }, + // Arabic, + { 13, 127 }, + // Syriac, + { 71, 127 }, + //Thaana, + { 72, 127 }, + //Devanagari, + { 15, 127 }, + //Bengali, + { 16, 127 }, + //Gurmukhi, + { 17, 127 }, + //Gujarati, + { 18, 127 }, + //Oriya, + { 19, 127 }, + //Tamil, + { 20, 127 }, + //Telugu, + { 21, 127 }, + //Kannada, + { 22, 127 }, + //Malayalam, + { 23, 127 }, + //Sinhala, + { 73, 127 }, + //Thai, + { 24, 127 }, + //Lao, + { 25, 127 }, + //Tibetan, + { 70, 127 }, + //Myanmar, + { 74, 127 }, + // Georgian, + { 26, 127 }, + // Khmer, + { 80, 127 }, + // SimplifiedChinese, + { 126, 127 }, + // TraditionalChinese, + { 126, 127 }, + // Japanese, + { 126, 127 }, + // Korean, + { 56, 127 }, + // Vietnamese, + { 0, 127 }, // same as latin1 + // Other, + { 126, 127 }, + // Ogham, + { 78, 127 }, + // Runic, + { 79, 127 }, + // Nko, + { 14, 127 }, +}; + +static QSupportedWritingSystems determineWritingSystemsFromTrueTypeBits(quint32 unicodeRange[4], quint32 codePageRange[2]) +{ + QSupportedWritingSystems writingSystems; + bool hasScript = false; + + int i; + for(i = 0; i < QFontDatabase::WritingSystemsCount; i++) { + int bit = requiredUnicodeBits[i][0]; + int index = bit/32; + int flag = 1 << (bit&31); + if (bit != 126 && unicodeRange[index] & flag) { + bit = requiredUnicodeBits[i][1]; + index = bit/32; + + flag = 1 << (bit&31); + if (bit == 127 || unicodeRange[index] & flag) { + writingSystems.setSupported(QFontDatabase::WritingSystem(i)); + hasScript = true; + // qDebug("font %s: index=%d, flag=%8x supports script %d", familyName.latin1(), index, flag, i); + } + } + } + if(codePageRange[0] & (1 << SimplifiedChineseCsbBit)) { + writingSystems.setSupported(QFontDatabase::SimplifiedChinese); + hasScript = true; + //qDebug("font %s supports Simplified Chinese", familyName.latin1()); + } + if(codePageRange[0] & (1 << TraditionalChineseCsbBit)) { + writingSystems.setSupported(QFontDatabase::TraditionalChinese); + hasScript = true; + //qDebug("font %s supports Traditional Chinese", familyName.latin1()); + } + if(codePageRange[0] & (1 << JapaneseCsbBit)) { + writingSystems.setSupported(QFontDatabase::Japanese); + hasScript = true; + //qDebug("font %s supports Japanese", familyName.latin1()); + } + if(codePageRange[0] & (1 << KoreanCsbBit)) { + writingSystems.setSupported(QFontDatabase::Korean); + hasScript = true; + //qDebug("font %s supports Korean", familyName.latin1()); + } + if (!hasScript) + writingSystems.setSupported(QFontDatabase::Symbol); + + return writingSystems; +} + +static inline bool scriptRequiresOpenType(int script) +{ + return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala) + || script == QUnicodeTables::Khmer || script == QUnicodeTables::Nko); +} + +void QBasicUnixFontDatabase::populateFontDatabase() +{ + QPlatformFontDatabase::populateFontDatabase(); + QString fontpath = fontDir(); + + if(!QFile::exists(fontpath)) { + qFatal("QFontDatabase: Cannot find font directory %s - is Qt installed correctly?", + qPrintable(fontpath)); + } + + QDir dir(fontpath); + dir.setNameFilters(QStringList() << QLatin1String("*.ttf") + << QLatin1String("*.ttc") << QLatin1String("*.pfa") + << QLatin1String("*.pfb")); + dir.refresh(); + for (int i = 0; i < int(dir.count()); ++i) { + const QByteArray file = QFile::encodeName(dir.absoluteFilePath(dir[i])); +// qDebug() << "looking at" << file; + addTTFile(QByteArray(), file); + } +} + +QFontEngine *QBasicUnixFontDatabase::fontEngine(const QFontDef &fontDef, QUnicodeTables::Script script, void *usrPtr) +{ + QFontEngineFT *engine; + FontFile *fontfile = static_cast<FontFile *> (usrPtr); + QFontEngine::FaceId fid; + fid.filename = fontfile->fileName.toLocal8Bit(); + fid.index = fontfile->indexValue; + engine = new QFontEngineFT(fontDef); + + bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); + QFontEngineFT::GlyphFormat format = antialias? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; + if (!engine->init(fid,antialias,format)) { + delete engine; + engine = 0; + return engine; + } + if (engine->invalid()) { + delete engine; + engine = 0; + } else if (scriptRequiresOpenType(script)) { + HB_Face hbFace = engine->harfbuzzFace(); + if (!hbFace || !hbFace->supported_scripts[script]) { + delete engine; + engine = 0; + } + } + + return engine; +} + +QStringList QBasicUnixFontDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const +{ + Q_UNUSED(family); + Q_UNUSED(style); + Q_UNUSED(script); + return QStringList(); +} + +QStringList QBasicUnixFontDatabase::addApplicationFont(const QByteArray &fontData, const QString &fileName) +{ + return addTTFile(fontData,fileName.toLocal8Bit()); +} + +void QBasicUnixFontDatabase::releaseHandle(void *handle) +{ + FontFile *file = static_cast<FontFile *>(handle); + delete file; +} + +QStringList QBasicUnixFontDatabase::addTTFile(const QByteArray &fontData, const QByteArray &file) +{ + extern FT_Library qt_getFreetype(); + FT_Library library = qt_getFreetype(); + + int index = 0; + int numFaces = 0; + QStringList families; + do { + FT_Face face; + FT_Error error; + if (!fontData.isEmpty()) { + error = FT_New_Memory_Face(library, (const FT_Byte *)fontData.constData(), fontData.size(), index, &face); + } else { + error = FT_New_Face(library, file.constData(), index, &face); + } + if (error != FT_Err_Ok) { + qDebug() << "FT_New_Face failed with index" << index << ":" << hex << error; + break; + } + numFaces = face->num_faces; + + int weight = QFont::Normal; + + QFont::Style style = QFont::StyleNormal; + if (face->style_flags & FT_STYLE_FLAG_ITALIC) + style = QFont::StyleItalic; + + if (face->style_flags & FT_STYLE_FLAG_BOLD) + weight = QFont::Bold; + + QSupportedWritingSystems writingSystems; + // detect symbol fonts + for (int i = 0; i < face->num_charmaps; ++i) { + FT_CharMap cm = face->charmaps[i]; + if (cm->encoding == ft_encoding_adobe_custom + || cm->encoding == ft_encoding_symbol) { + writingSystems.setSupported(QFontDatabase::Symbol); + break; + } + } + + TT_OS2 *os2 = (TT_OS2 *)FT_Get_Sfnt_Table(face, ft_sfnt_os2); + if (os2) { + quint32 unicodeRange[4] = { + os2->ulUnicodeRange1, os2->ulUnicodeRange2, os2->ulUnicodeRange3, os2->ulUnicodeRange4 + }; + quint32 codePageRange[2] = { + os2->ulCodePageRange1, os2->ulCodePageRange2 + }; + + writingSystems = determineWritingSystemsFromTrueTypeBits(unicodeRange, codePageRange); + } + + QString family = QString::fromAscii(face->family_name); + FontFile *fontFile = new FontFile; + fontFile->fileName = file; + fontFile->indexValue = index; + + registerFont(family,"",weight,style,100,true,true,0,writingSystems,fontFile); + + families.append(family); + + FT_Done_Face(face); + ++index; + } while (index < numFaces); + return families; +} diff --git a/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.h b/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.h new file mode 100644 index 0000000..0af118d --- /dev/null +++ b/src/plugins/platforms/fontdatabases/basicunix/qbasicunixfontdatabase.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QBASICUNIXFONTDATABASE_H +#define QBASICUNIXFONTDATABASE_H + +#include <QPlatformFontDatabase> +#include <QtCore/QByteArray> +#include <QtCore/QString> + +struct FontFile +{ + QString fileName; + int indexValue; +}; + +class QBasicUnixFontDatabase : public QPlatformFontDatabase +{ +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 addApplicationFont(const QByteArray &fontData, const QString &fileName); + void releaseHandle(void *handle); + + static QStringList addTTFile(const QByteArray &fontData, const QByteArray &file); +}; + +#endif // QBASICUNIXFONTDATABASE_H diff --git a/src/plugins/platforms/fontdatabases/fontconfig/fontconfig.pri b/src/plugins/platforms/fontdatabases/fontconfig/fontconfig.pri new file mode 100644 index 0000000..19c74ed --- /dev/null +++ b/src/plugins/platforms/fontdatabases/fontconfig/fontconfig.pri @@ -0,0 +1,12 @@ +include(../basicunix/basicunix.pri) + +HEADERS += \ + $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h + +SOURCES += \ + $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp + +INCLUDEPATH += $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/fontconfig +LIBS_PRIVATE += -lfontconfig + + diff --git a/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp new file mode 100644 index 0000000..c9d1b74 --- /dev/null +++ b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.cpp @@ -0,0 +1,572 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qfontconfigdatabase.h" + +#include <QtCore/QList> +#include <QtGui/private/qfont_p.h> + +#include <QtCore/QElapsedTimer> + +#include <QtGui/private/qapplication_p.h> +#include <QtGui/QPlatformScreen> + +#include <QtGui/private/qfontengine_ft_p.h> +#include <QtGui/private/qfontengine_p.h> + + + +#include <ft2build.h> +#include FT_TRUETYPE_TABLES_H + +#include <fontconfig/fontconfig.h> + +#define SimplifiedChineseCsbBit 18 +#define TraditionalChineseCsbBit 20 +#define JapaneseCsbBit 17 +#define KoreanCsbBit 21 + +static inline bool requiresOpenType(int writingSystem) +{ + return ((writingSystem >= QFontDatabase::Syriac && writingSystem <= QFontDatabase::Sinhala) + || writingSystem == QFontDatabase::Khmer || writingSystem == QFontDatabase::Nko); +} +static inline bool scriptRequiresOpenType(int script) +{ + return ((script >= QUnicodeTables::Syriac && script <= QUnicodeTables::Sinhala) + || script == QUnicodeTables::Khmer || script == QUnicodeTables::Nko); +} + +static int getFCWeight(int fc_weight) +{ + int qtweight = QFont::Black; + if (fc_weight <= (FC_WEIGHT_LIGHT + FC_WEIGHT_MEDIUM) / 2) + qtweight = QFont::Light; + else if (fc_weight <= (FC_WEIGHT_MEDIUM + FC_WEIGHT_DEMIBOLD) / 2) + qtweight = QFont::Normal; + else if (fc_weight <= (FC_WEIGHT_DEMIBOLD + FC_WEIGHT_BOLD) / 2) + qtweight = QFont::DemiBold; + else if (fc_weight <= (FC_WEIGHT_BOLD + FC_WEIGHT_BLACK) / 2) + qtweight = QFont::Bold; + + return qtweight; +} + +static const char *specialLanguages[] = { + "en", // Common + "el", // Greek + "ru", // Cyrillic + "hy", // Armenian + "he", // Hebrew + "ar", // Arabic + "syr", // Syriac + "div", // Thaana + "hi", // Devanagari + "bn", // Bengali + "pa", // Gurmukhi + "gu", // Gujarati + "or", // Oriya + "ta", // Tamil + "te", // Telugu + "kn", // Kannada + "ml", // Malayalam + "si", // Sinhala + "th", // Thai + "lo", // Lao + "bo", // Tibetan + "my", // Myanmar + "ka", // Georgian + "ko", // Hangul + "", // Ogham + "", // Runic + "km", // Khmer + "" // N'Ko +}; +enum { SpecialLanguageCount = sizeof(specialLanguages) / sizeof(const char *) }; + +static const ushort specialChars[] = { + 0, // English + 0, // Greek + 0, // Cyrillic + 0, // Armenian + 0, // Hebrew + 0, // Arabic + 0, // Syriac + 0, // Thaana + 0, // Devanagari + 0, // Bengali + 0, // Gurmukhi + 0, // Gujarati + 0, // Oriya + 0, // Tamil + 0xc15, // Telugu + 0xc95, // Kannada + 0xd15, // Malayalam + 0xd9a, // Sinhala + 0, // Thai + 0, // Lao + 0, // Tibetan + 0x1000, // Myanmar + 0, // Georgian + 0, // Hangul + 0x1681, // Ogham + 0x16a0, // Runic + 0, // Khmer + 0x7ca // N'Ko +}; +enum { SpecialCharCount = sizeof(specialChars) / sizeof(ushort) }; + +// this could become a list of all languages used for each writing +// system, instead of using the single most common language. +static const char *languageForWritingSystem[] = { + 0, // Any + "en", // Latin + "el", // Greek + "ru", // Cyrillic + "hy", // Armenian + "he", // Hebrew + "ar", // Arabic + "syr", // Syriac + "div", // Thaana + "hi", // Devanagari + "bn", // Bengali + "pa", // Gurmukhi + "gu", // Gujarati + "or", // Oriya + "ta", // Tamil + "te", // Telugu + "kn", // Kannada + "ml", // Malayalam + "si", // Sinhala + "th", // Thai + "lo", // Lao + "bo", // Tibetan + "my", // Myanmar + "ka", // Georgian + "km", // Khmer + "zh-cn", // SimplifiedChinese + "zh-tw", // TraditionalChinese + "ja", // Japanese + "ko", // Korean + "vi", // Vietnamese + 0, // Symbol + 0, // Ogham + 0, // Runic + 0 // N'Ko +}; +enum { LanguageCount = sizeof(languageForWritingSystem) / sizeof(const char *) }; + +// Unfortunately FontConfig doesn't know about some languages. We have to test these through the +// charset. The lists below contain the systems where we need to do this. +static const ushort sampleCharForWritingSystem[] = { + 0, // Any + 0, // Latin + 0, // Greek + 0, // Cyrillic + 0, // Armenian + 0, // Hebrew + 0, // Arabic + 0, // Syriac + 0, // Thaana + 0, // Devanagari + 0, // Bengali + 0, // Gurmukhi + 0, // Gujarati + 0, // Oriya + 0, // Tamil + 0xc15, // Telugu + 0xc95, // Kannada + 0xd15, // Malayalam + 0xd9a, // Sinhala + 0, // Thai + 0, // Lao + 0, // Tibetan + 0x1000, // Myanmar + 0, // Georgian + 0, // Khmer + 0, // SimplifiedChinese + 0, // TraditionalChinese + 0, // Japanese + 0, // Korean + 0, // Vietnamese + 0, // Symbol + 0x1681, // Ogham + 0x16a0, // Runic + 0x7ca // N'Ko +}; +enum { SampleCharCount = sizeof(sampleCharForWritingSystem) / sizeof(ushort) }; + +// Newer FontConfig let's us sort out fonts that contain certain glyphs, but no +// open type tables for is directly. Do this so we don't pick some strange +// pseudo unicode font +static const char *openType[] = { + 0, // Any + 0, // Latin + 0, // Greek + 0, // Cyrillic + 0, // Armenian + 0, // Hebrew + 0, // Arabic + "syrc", // Syriac + "thaa", // Thaana + "deva", // Devanagari + "beng", // Bengali + "guru", // Gurmukhi + "gurj", // Gujarati + "orya", // Oriya + "taml", // Tamil + "telu", // Telugu + "knda", // Kannada + "mlym", // Malayalam + "sinh", // Sinhala + 0, // Thai + 0, // Lao + "tibt", // Tibetan + "mymr", // Myanmar + 0, // Georgian + "khmr", // Khmer + 0, // SimplifiedChinese + 0, // TraditionalChinese + 0, // Japanese + 0, // Korean + 0, // Vietnamese + 0, // Symbol + 0, // Ogham + 0, // Runic + "nko " // N'Ko +}; + +void QFontconfigDatabase::populateFontDatabase() +{ + FcFontSet *fonts; + + QString familyName; + FcChar8 *value = 0; + int weight_value; + int slant_value; + int spacing_value; + FcChar8 *file_value; + int indexValue; + FcChar8 *foundry_value; + FcBool scalable; + FcBool antialias; + + { + FcObjectSet *os = FcObjectSetCreate(); + FcPattern *pattern = FcPatternCreate(); + const char *properties [] = { + FC_FAMILY, FC_WEIGHT, FC_SLANT, + FC_SPACING, FC_FILE, FC_INDEX, + FC_LANG, FC_CHARSET, FC_FOUNDRY, FC_SCALABLE, FC_PIXEL_SIZE, FC_WEIGHT, + FC_WIDTH, +#if FC_VERSION >= 20297 + FC_CAPABILITY, +#endif + (const char *)0 + }; + const char **p = properties; + while (*p) { + FcObjectSetAdd(os, *p); + ++p; + } + fonts = FcFontList(0, pattern, os); + FcObjectSetDestroy(os); + FcPatternDestroy(pattern); + } + + for (int i = 0; i < fonts->nfont; i++) { + if (FcPatternGetString(fonts->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) + continue; + // capitalize(value); + familyName = QString::fromUtf8((const char *)value); + slant_value = FC_SLANT_ROMAN; + weight_value = FC_WEIGHT_MEDIUM; + spacing_value = FC_PROPORTIONAL; + file_value = 0; + indexValue = 0; + scalable = FcTrue; + + + if (FcPatternGetInteger (fonts->fonts[i], FC_SLANT, 0, &slant_value) != FcResultMatch) + slant_value = FC_SLANT_ROMAN; + if (FcPatternGetInteger (fonts->fonts[i], FC_WEIGHT, 0, &weight_value) != FcResultMatch) + weight_value = FC_WEIGHT_MEDIUM; + if (FcPatternGetInteger (fonts->fonts[i], FC_SPACING, 0, &spacing_value) != FcResultMatch) + spacing_value = FC_PROPORTIONAL; + if (FcPatternGetString (fonts->fonts[i], FC_FILE, 0, &file_value) != FcResultMatch) + file_value = 0; + if (FcPatternGetInteger (fonts->fonts[i], FC_INDEX, 0, &indexValue) != FcResultMatch) + indexValue = 0; + if (FcPatternGetBool(fonts->fonts[i], FC_SCALABLE, 0, &scalable) != FcResultMatch) + scalable = FcTrue; + if (FcPatternGetString(fonts->fonts[i], FC_FOUNDRY, 0, &foundry_value) != FcResultMatch) + foundry_value = 0; + if(FcPatternGetBool(fonts->fonts[i],FC_ANTIALIAS,0,&antialias) != FcResultMatch) + antialias = true; + + QSupportedWritingSystems writingSystems; + FcLangSet *langset = 0; + FcResult res = FcPatternGetLangSet(fonts->fonts[i], FC_LANG, 0, &langset); + if (res == FcResultMatch) { + for (int i = 1; i < LanguageCount; ++i) { + const FcChar8 *lang = (const FcChar8*) languageForWritingSystem[i]; + if (lang) { + FcLangResult langRes = FcLangSetHasLang(langset, lang); + if (langRes != FcLangDifferentLang) + writingSystems.setSupported(QFontDatabase::WritingSystem(i)); + } + } + } else { + // we set Other to supported for symbol fonts. It makes no + // sense to merge these with other ones, as they are + // special in a way. + writingSystems.setSupported(QFontDatabase::Other); + } + + FcCharSet *cs = 0; + res = FcPatternGetCharSet(fonts->fonts[i], FC_CHARSET, 0, &cs); + if (res == FcResultMatch) { + // some languages are not supported by FontConfig, we rather check the + // charset to detect these + for (int i = 1; i < SampleCharCount; ++i) { + if (!sampleCharForWritingSystem[i]) + continue; + if (FcCharSetHasChar(cs, sampleCharForWritingSystem[i])) + writingSystems.setSupported(QFontDatabase::WritingSystem(i)); + } + } + +#if FC_VERSION >= 20297 + for (int j = 1; j < LanguageCount; ++j) { + if (writingSystems.supported(QFontDatabase::WritingSystem(j)) + && requiresOpenType(j) && openType[j]) { + FcChar8 *cap; + res = FcPatternGetString (fonts->fonts[i], FC_CAPABILITY, 0, &cap); + if (res != FcResultMatch || !strstr((const char *)cap, openType[j])) + writingSystems.setSupported(QFontDatabase::WritingSystem(j),false); + } + } +#endif + + FontFile *fontFile = new FontFile; + fontFile->fileName = QLatin1String((const char *)file_value); + fontFile->indexValue = indexValue; + + QFont::Style style = (slant_value == FC_SLANT_ITALIC) + ? QFont::StyleItalic + : ((slant_value == FC_SLANT_OBLIQUE) + ? QFont::StyleOblique + : QFont::StyleNormal); + int weight = getFCWeight(weight_value); + + double pixel_size = 0; + if (!scalable) { + int width = 100; + FcPatternGetInteger (fonts->fonts[i], FC_WIDTH, 0, &width); + FcPatternGetDouble (fonts->fonts[i], FC_PIXEL_SIZE, 0, &pixel_size); + } + + QPlatformFontDatabase::registerFont(familyName,QLatin1String((const char *)foundry_value),weight,style,100,antialias,scalable,pixel_size,writingSystems,fontFile); +// qDebug() << familyName << (const char *)foundry_value << weight << style << &writingSystems << scalable << true << pixel_size; + } + + FcFontSetDestroy (fonts); + + struct FcDefaultFont { + const char *qtname; + const char *rawname; + bool fixed; + }; + const FcDefaultFont defaults[] = { + { "Serif", "serif", false }, + { "Sans Serif", "sans-serif", false }, + { "Monospace", "monospace", true }, + { 0, 0, false } + }; + const FcDefaultFont *f = defaults; + // aliases only make sense for 'common', not for any of the specials + QSupportedWritingSystems ws; + ws.setSupported(QFontDatabase::Latin); + + while (f->qtname) { + registerFont(f->qtname,"",50,QFont::StyleNormal,100,true,true,0,ws,0); + registerFont(f->qtname,"",50,QFont::StyleItalic,100,true,true,0,ws,0); + registerFont(f->qtname,"",50,QFont::StyleOblique,100,true,true,0,ws,0); + ++f; + } + + //Lighthouse has very lazy population of the font db. We want it to be initialized when + //QApplication is constructed, so that the population procedure can do something like this to + //set the default font +// const FcDefaultFont *s = defaults; +// QFont font("Sans Serif"); +// font.setPointSize(9); +// QApplication::setFont(font); +} + +QFontEngine *QFontconfigDatabase::fontEngine(const QFontDef &f, QUnicodeTables::Script script, void *usrPtr) +{ + QFontDef fontDef = f; + + QFontEngineFT *engine; + FontFile *fontfile = static_cast<FontFile *> (usrPtr); + QFontEngine::FaceId fid; + fid.filename = fontfile->fileName.toLocal8Bit(); + fid.index = fontfile->indexValue; + + //try and get the pattern + FcPattern *pattern = FcPatternCreate(); + + bool antialias = !(fontDef.styleStrategy & QFont::NoAntialias); + QFontEngineFT::GlyphFormat format = antialias? QFontEngineFT::Format_A8 : QFontEngineFT::Format_Mono; + + engine = new QFontEngineFT(fontDef); + + FcValue value; + value.type = FcTypeString; + QByteArray cs = fontDef.family.toUtf8(); + value.u.s = (const FcChar8 *)cs.data(); + FcPatternAdd(pattern,FC_FAMILY,value,true); + + + value.u.s = (const FcChar8 *)fid.filename.data(); + FcPatternAdd(pattern,FC_FILE,value,true); + + value.type = FcTypeInteger; + value.u.i = fid.index; + FcPatternAdd(pattern,FC_INDEX,value,true); + + QFontEngineFT::HintStyle default_hint_style; + + if (FcConfigSubstitute(0,pattern,FcMatchPattern)) { + + //hinting + int hint_style = 0; + if (FcPatternGetInteger (pattern, FC_HINT_STYLE, 0, &hint_style) == FcResultNoMatch) + hint_style = QFontEngineFT::HintFull; + switch (hint_style) { + case FC_HINT_NONE: + default_hint_style = QFontEngineFT::HintNone; + break; + case FC_HINT_SLIGHT: + default_hint_style = QFontEngineFT::HintLight; + break; + case FC_HINT_MEDIUM: + default_hint_style = QFontEngineFT::HintMedium; + break; + default: + default_hint_style = QFontEngineFT::HintFull; + break; + } + } + + engine->setDefaultHintStyle(default_hint_style); + if (!engine->init(fid,antialias,format)) { + delete engine; + engine = 0; + return engine; + } + if (engine->invalid()) { + delete engine; + engine = 0; + } else if (scriptRequiresOpenType(script)) { + HB_Face hbFace = engine->harfbuzzFace(); + if (!hbFace || !hbFace->supported_scripts[script]) { + delete engine; + engine = 0; + } + } + + return engine; +} + +QStringList QFontconfigDatabase::fallbacksForFamily(const QString family, const QFont::Style &style, const QUnicodeTables::Script &script) const +{ + QStringList fallbackFamilies; + FcPattern *pattern = FcPatternCreate(); + if (!pattern) + return fallbackFamilies; + + FcValue value; + value.type = FcTypeString; + QByteArray cs = family.toUtf8(); + value.u.s = (const FcChar8 *)cs.data(); + FcPatternAdd(pattern,FC_FAMILY,value,true); + + int slant_value = FC_SLANT_ROMAN; + if (style == QFont::StyleItalic) + slant_value = FC_SLANT_ITALIC; + else if (style == QFont::StyleOblique) + slant_value = FC_SLANT_OBLIQUE; + FcPatternAddInteger(pattern, FC_SLANT, slant_value); + + if (script != QUnicodeTables::Common && *specialLanguages[script] != '\0') { + Q_ASSERT(script < QUnicodeTables::ScriptCount); + FcLangSet *ls = FcLangSetCreate(); + FcLangSetAdd(ls, (const FcChar8*)specialLanguages[script]); + FcPatternAddLangSet(pattern, FC_LANG, ls); + FcLangSetDestroy(ls); + } + + FcConfigSubstitute(0, pattern, FcMatchPattern); + FcConfigSubstitute(0, pattern, FcMatchFont); + + FcResult result = FcResultMatch; + FcFontSet *fontSet = FcFontSort(0,pattern,FcFalse,0,&result); + + if (fontSet && result == FcResultMatch) + { + for (int i = 0; i < fontSet->nfont; i++) { + FcChar8 *value = 0; + if (FcPatternGetString(fontSet->fonts[i], FC_FAMILY, 0, &value) != FcResultMatch) + continue; + // capitalize(value); + QString familyName = QString::fromUtf8((const char *)value); + if (!fallbackFamilies.contains(familyName,Qt::CaseInsensitive)) { + fallbackFamilies << familyName; + } + + } + } +// qDebug() << "fallbackFamilies for:" << family << fallbackFamilies; + + return fallbackFamilies; +} diff --git a/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h new file mode 100644 index 0000000..33382dc --- /dev/null +++ b/src/plugins/platforms/fontdatabases/fontconfig/qfontconfigdatabase.h @@ -0,0 +1,56 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QFONTCONFIGDATABASE_H +#define QFONTCONFIGDATABASE_H + +#include <QPlatformFontDatabase> +#include "qbasicunixfontdatabase.h" + +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; +}; + +#endif // QFONTCONFIGDATABASE_H diff --git a/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri b/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri new file mode 100644 index 0000000..dbcfbce --- /dev/null +++ b/src/plugins/platforms/fontdatabases/genericunix/genericunix.pri @@ -0,0 +1,10 @@ +contains(QT_CONFIG, fontconfig) { + include(../fontconfig/fontconfig.pri) + DEFINES += Q_FONTCONFIGDATABASE +} else { + include(../basicunix/basicunix.pri) +} + +INCLUDEPATH += $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/genericunix +HEADERS += \ + $$QT_SOURCE_TREE/src/plugins/platforms/fontdatabases/genericunix/qgenericunixfontdatabase.h diff --git a/src/plugins/platforms/fontdatabases/genericunix/qgenericunixfontdatabase.h b/src/plugins/platforms/fontdatabases/genericunix/qgenericunixfontdatabase.h new file mode 100644 index 0000000..327c8f5 --- /dev/null +++ b/src/plugins/platforms/fontdatabases/genericunix/qgenericunixfontdatabase.h @@ -0,0 +1,53 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QGENERICUNIXFONTDATABASE_H +#define QGENERICUNIXFONTDATABASE_H + +#ifdef Q_FONTCONFIGDATABASE +#include "qfontconfigdatabase.h" +typedef QFontconfigDatabase QGenericUnixFontDatabase; +#else +#include "qbasicunixfontdatabase.h" +typedef QBasicUnixFontDatabase QGenericUnixFontDatabase; +#endif //Q_FONTCONFIGDATABASE + +#endif // QGENERICUNIXFONTDATABASE_H diff --git a/src/plugins/platforms/linuxfb/linuxfb.pro b/src/plugins/platforms/linuxfb/linuxfb.pro new file mode 100644 index 0000000..216b899 --- /dev/null +++ b/src/plugins/platforms/linuxfb/linuxfb.pro @@ -0,0 +1,13 @@ +TARGET = qlinuxfbgraphicssystem +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +SOURCES = main.cpp qlinuxfbintegration.cpp +HEADERS = qlinuxfbintegration.h + +include(../fb_base/fb_base.pri) +include(../fontdatabases/genericunix/genericunix.pri) + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target diff --git a/src/plugins/platforms/linuxfb/main.cpp b/src/plugins/platforms/linuxfb/main.cpp new file mode 100644 index 0000000..c5f7fe0 --- /dev/null +++ b/src/plugins/platforms/linuxfb/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** 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 <QPlatformIntegrationPlugin> +#include "qlinuxfbintegration.h" + +QT_BEGIN_NAMESPACE + +class QLinuxFbIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QLinuxFbIntegrationPlugin::keys() const +{ + QStringList list; + list << "LinuxFb"; + return list; +} + +QPlatformIntegration* QLinuxFbIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "linuxfb") + return new QLinuxFbIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(linuxfb, QLinuxFbIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp new file mode 100644 index 0000000..aa1d401 --- /dev/null +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.cpp @@ -0,0 +1,866 @@ +/**************************************************************************** +** +** 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 "qlinuxfbintegration.h" +#include "../fb_base/fb_base.h" +#include "qgenericunixfontdatabase.h" +#include <QtGui/private/qpixmap_raster_p.h> +#include <private/qcore_unix_p.h> // overrides QT_OPEN +#include <qimage.h> +#include <qdebug.h> + +#include <unistd.h> +#include <stdlib.h> +#include <sys/ioctl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/mman.h> +#include <sys/kd.h> +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <limits.h> +#include <signal.h> + +#if !defined(Q_OS_DARWIN) && !defined(Q_OS_FREEBSD) +#include <linux/fb.h> + +#ifdef __i386__ +#include <asm/mtrr.h> +#endif +#endif + +QT_BEGIN_NAMESPACE + +class QLinuxFbIntegrationPrivate +{ +public: + QLinuxFbIntegrationPrivate(); + ~QLinuxFbIntegrationPrivate(); + + void openTty(); + void closeTty(); + + int fd; + int startupw; + int startuph; + int startupd; + bool blank; + + bool doGraphicsMode; +#ifdef QT_QWS_DEPTH_GENERIC + bool doGenericColors; +#endif + int ttyfd; + long oldKdMode; + QString ttyDevice; + QString displaySpec; +}; + +QLinuxFbIntegrationPrivate::QLinuxFbIntegrationPrivate() + : fd(-1), blank(true), doGraphicsMode(true), +#ifdef QT_QWS_DEPTH_GENERIC + doGenericColors(false), +#endif + ttyfd(-1), oldKdMode(KD_TEXT) +{ +} + +QLinuxFbIntegrationPrivate::~QLinuxFbIntegrationPrivate() +{ + closeTty(); +} + +void QLinuxFbIntegrationPrivate::openTty() +{ + const char *const devs[] = {"/dev/tty0", "/dev/tty", "/dev/console", 0}; + + if (ttyDevice.isEmpty()) { + for (const char * const *dev = devs; *dev; ++dev) { + ttyfd = QT_OPEN(*dev, O_RDWR); + if (ttyfd != -1) + break; + } + } else { + ttyfd = QT_OPEN(ttyDevice.toAscii().constData(), O_RDWR); + } + + if (ttyfd == -1) + return; + + if (doGraphicsMode) { + ioctl(ttyfd, KDGETMODE, &oldKdMode); + if (oldKdMode != KD_GRAPHICS) { + int ret = ioctl(ttyfd, KDSETMODE, KD_GRAPHICS); + if (ret == -1) + doGraphicsMode = false; + } + } + + // No blankin' screen, no blinkin' cursor!, no cursor! + const char termctl[] = "\033[9;0]\033[?33l\033[?25l\033[?1c"; + QT_WRITE(ttyfd, termctl, sizeof(termctl)); +} + +void QLinuxFbIntegrationPrivate::closeTty() +{ + if (ttyfd == -1) + return; + + if (doGraphicsMode) + ioctl(ttyfd, KDSETMODE, oldKdMode); + + // Blankin' screen, blinkin' cursor! + const char termctl[] = "\033[9;15]\033[?33h\033[?25h\033[?0c"; + QT_WRITE(ttyfd, termctl, sizeof(termctl)); + + QT_CLOSE(ttyfd); + ttyfd = -1; +} + +QLinuxFbIntegration::QLinuxFbIntegration() + :fontDb(new QGenericUnixFontDatabase()) +{ + d_ptr = new QLinuxFbIntegrationPrivate(); + + // XXX + QString displaySpec = QString::fromLatin1(qgetenv("QWS_DISPLAY")); + + if (!connect(displaySpec)) + qFatal("QLinuxFbIntegration: could not initialize screen"); + initDevice(); + + // Create a QImage directly on the screen's framebuffer. + // This is the blit target for copying windows to the screen. + mPrimaryScreen = new QLinuxFbScreen(data, w, h, lstep, + screenFormat); + mPrimaryScreen->setPhysicalSize(QSize(physWidth, physHeight)); + mScreens.append(mPrimaryScreen); +} + +QLinuxFbIntegration::~QLinuxFbIntegration() +{ + delete mPrimaryScreen; + delete d_ptr; +} + +bool QLinuxFbIntegration::connect(const QString &displaySpec) +{ + const QStringList args = displaySpec.split(QLatin1Char(':')); + + if (args.contains(QLatin1String("nographicsmodeswitch"))) + d_ptr->doGraphicsMode = false; + +#ifdef QT_QWS_DEPTH_GENERIC + if (args.contains(QLatin1String("genericcolors"))) + d_ptr->doGenericColors = true; +#endif + + QRegExp ttyRegExp(QLatin1String("tty=(.*)")); + if (args.indexOf(ttyRegExp) != -1) + d_ptr->ttyDevice = ttyRegExp.cap(1); + +#if 0 +#if Q_BYTE_ORDER == Q_BIG_ENDIAN +#ifndef QT_QWS_FRAMEBUFFER_LITTLE_ENDIAN + if (args.contains(QLatin1String("littleendian"))) +#endif + QScreen::setFrameBufferLittleEndian(true); +#endif +#endif + + // Check for explicitly specified device + const int len = 8; // "/dev/fbx" + int m = displaySpec.indexOf(QLatin1String("/dev/fb")); + + QString dev; + if (m > 0) + dev = displaySpec.mid(m, len); + else + dev = QLatin1String("/dev/fb0"); + + if (access(dev.toLatin1().constData(), R_OK|W_OK) == 0) + d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDWR); + if (d_ptr->fd == -1) { + if (access(dev.toLatin1().constData(), R_OK) == 0) + d_ptr->fd = QT_OPEN(dev.toLatin1().constData(), O_RDONLY); + if (d_ptr->fd == 1) { + qWarning("Error opening framebuffer device %s", qPrintable(dev)); + return false; + } + } + + fb_fix_screeninfo finfo; + fb_var_screeninfo vinfo; + //####################### + // Shut up Valgrind + memset(&vinfo, 0, sizeof(vinfo)); + memset(&finfo, 0, sizeof(finfo)); + //####################### + + /* Get fixed screen information */ + if (d_ptr->fd != -1 && ioctl(d_ptr->fd, FBIOGET_FSCREENINFO, &finfo)) { + perror("QLinuxFbIntegration::connect"); + qWarning("Error reading fixed information"); + return false; + } + + if (finfo.type == FB_TYPE_VGA_PLANES) { + qWarning("VGA16 video mode not supported"); + return false; + } + + /* Get variable screen information */ + if (d_ptr->fd != -1 && ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) { + perror("QLinuxFbIntegration::connect"); + qWarning("Error reading variable information"); + return false; + } + + grayscale = vinfo.grayscale; + d = vinfo.bits_per_pixel; + if (d == 24) { + d = vinfo.red.length + vinfo.green.length + vinfo.blue.length; + if (d <= 0) + d = 24; // reset if color component lengths are not reported + } else if (d == 16) { + d = vinfo.red.length + vinfo.green.length + vinfo.blue.length; + if (d <= 0) + d = 16; + } + lstep = finfo.line_length; + + int xoff = vinfo.xoffset; + int yoff = vinfo.yoffset; + const char* qwssize; + if((qwssize=::getenv("QWS_SIZE")) && sscanf(qwssize,"%dx%d",&w,&h)==2) { + if (d_ptr->fd != -1) { + if ((uint)w > vinfo.xres) w = vinfo.xres; + if ((uint)h > vinfo.yres) h = vinfo.yres; + } + dw=w; + dh=h; + int xxoff, yyoff; + if (sscanf(qwssize, "%*dx%*d+%d+%d", &xxoff, &yyoff) == 2) { + if (xxoff < 0 || xxoff + w > (int)(vinfo.xres)) + xxoff = vinfo.xres - w; + if (yyoff < 0 || yyoff + h > (int)(vinfo.yres)) + yyoff = vinfo.yres - h; + xoff += xxoff; + yoff += yyoff; + } else { + xoff += (vinfo.xres - w)/2; + yoff += (vinfo.yres - h)/2; + } + } else { + dw=w=vinfo.xres; + dh=h=vinfo.yres; + } + + if (w == 0 || h == 0) { + qWarning("QLinuxFbIntegration::connect(): Unable to find screen geometry, " + "will use 320x240."); + dw = w = 320; + dh = h = 240; + } + + setPixelFormat(vinfo); + + // Handle display physical size spec. + QStringList displayArgs = displaySpec.split(QLatin1Char(':')); + QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)")); + int dimIdxW = displayArgs.indexOf(mmWidthRx); + QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)")); + int dimIdxH = displayArgs.indexOf(mmHeightRx); + if (dimIdxW >= 0) { + mmWidthRx.exactMatch(displayArgs.at(dimIdxW)); + physWidth = mmWidthRx.cap(1).toInt(); + if (dimIdxH < 0) + physHeight = dh*physWidth/dw; + } + if (dimIdxH >= 0) { + mmHeightRx.exactMatch(displayArgs.at(dimIdxH)); + physHeight = mmHeightRx.cap(1).toInt(); + if (dimIdxW < 0) + physWidth = dw*physHeight/dh; + } + if (dimIdxW < 0 && dimIdxH < 0) { + if (vinfo.width != 0 && vinfo.height != 0 + && vinfo.width != UINT_MAX && vinfo.height != UINT_MAX) { + physWidth = vinfo.width; + physHeight = vinfo.height; + } else { + const int dpi = 72; + physWidth = qRound(dw * 25.4 / dpi); + physHeight = qRound(dh * 25.4 / dpi); + } + } + + dataoffset = yoff * lstep + xoff * d / 8; + //qDebug("Using %dx%dx%d screen",w,h,d); + + /* Figure out the size of the screen in bytes */ + size = h * lstep; + + mapsize = finfo.smem_len; + + data = (unsigned char *)-1; + if (d_ptr->fd != -1) + data = (unsigned char *)mmap(0, mapsize, PROT_READ | PROT_WRITE, + MAP_SHARED, d_ptr->fd, 0); + + if ((long)data == -1) { + perror("QLinuxFbIntegration::connect"); + qWarning("Error: failed to map framebuffer device to memory."); + return false; + } else { + data += dataoffset; + } + +#if 0 + canaccel = useOffscreen(); + if(canaccel) + setupOffScreen(); +#endif + canaccel = false; + + // Now read in palette + if((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4)) { + screencols= (vinfo.bits_per_pixel==8) ? 256 : 16; + int loopc; + fb_cmap startcmap; + startcmap.start=0; + startcmap.len=screencols; + startcmap.red=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + startcmap.green=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + startcmap.blue=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + startcmap.transp=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + if (d_ptr->fd == -1 || ioctl(d_ptr->fd, FBIOGETCMAP, &startcmap)) { + perror("QLinuxFbIntegration::connect"); + qWarning("Error reading palette from framebuffer, using default palette"); + createPalette(startcmap, vinfo, finfo); + } + int bits_used = 0; + for(loopc=0;loopc<screencols;loopc++) { + screenclut[loopc]=qRgb(startcmap.red[loopc] >> 8, + startcmap.green[loopc] >> 8, + startcmap.blue[loopc] >> 8); + bits_used |= startcmap.red[loopc] + | startcmap.green[loopc] + | startcmap.blue[loopc]; + } + // WORKAROUND: Some framebuffer drivers only return 8 bit + // color values, so we need to not bit shift them.. + if ((bits_used & 0x00ff) && !(bits_used & 0xff00)) { + for(loopc=0;loopc<screencols;loopc++) { + screenclut[loopc] = qRgb(startcmap.red[loopc], + startcmap.green[loopc], + startcmap.blue[loopc]); + } + qWarning("8 bits cmap returned due to faulty FB driver, colors corrected"); + } + free(startcmap.red); + free(startcmap.green); + free(startcmap.blue); + free(startcmap.transp); + } else { + screencols=0; + } + + return true; +} + +bool QLinuxFbIntegration::initDevice() +{ + d_ptr->openTty(); + + // Grab current mode so we can reset it + fb_var_screeninfo vinfo; + fb_fix_screeninfo finfo; + //####################### + // Shut up Valgrind + memset(&vinfo, 0, sizeof(vinfo)); + memset(&finfo, 0, sizeof(finfo)); + //####################### + + if (ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) { + perror("QLinuxFbScreen::initDevice"); + qFatal("Error reading variable information in card init"); + return false; + } + +#ifdef DEBUG_VINFO + qDebug("Greyscale %d",vinfo.grayscale); + qDebug("Nonstd %d",vinfo.nonstd); + qDebug("Red %d %d %d",vinfo.red.offset,vinfo.red.length, + vinfo.red.msb_right); + qDebug("Green %d %d %d",vinfo.green.offset,vinfo.green.length, + vinfo.green.msb_right); + qDebug("Blue %d %d %d",vinfo.blue.offset,vinfo.blue.length, + vinfo.blue.msb_right); + qDebug("Transparent %d %d %d",vinfo.transp.offset,vinfo.transp.length, + vinfo.transp.msb_right); +#endif + + d_ptr->startupw=vinfo.xres; + d_ptr->startuph=vinfo.yres; + d_ptr->startupd=vinfo.bits_per_pixel; + grayscale = vinfo.grayscale; + + if (ioctl(d_ptr->fd, FBIOGET_FSCREENINFO, &finfo)) { + perror("QLinuxFbScreen::initDevice"); + qCritical("Error reading fixed information in card init"); + // It's not an /error/ as such, though definitely a bad sign + // so we return true + return true; + } + +#ifdef __i386__ + // Now init mtrr + if(!::getenv("QWS_NOMTRR")) { + int mfd=QT_OPEN("/proc/mtrr",O_WRONLY,0); + // MTRR entry goes away when file is closed - i.e. + // hopefully when QWS is killed + if(mfd != -1) { + mtrr_sentry sentry; + sentry.base=(unsigned long int)finfo.smem_start; + //qDebug("Physical framebuffer address %p",(void*)finfo.smem_start); + // Size needs to be in 4k chunks, but that's not always + // what we get thanks to graphics card registers. Write combining + // these is Not Good, so we write combine what we can + // (which is not much - 4 megs on an 8 meg card, it seems) + unsigned int size=finfo.smem_len; + size=size >> 22; + size=size << 22; + sentry.size=size; + sentry.type=MTRR_TYPE_WRCOMB; + if(ioctl(mfd,MTRRIOC_ADD_ENTRY,&sentry)==-1) { + //printf("Couldn't add mtrr entry for %lx %lx, %s\n", + //sentry.base,sentry.size,strerror(errno)); + } + } + + // Should we close mfd here? + //QT_CLOSE(mfd); + } +#endif + if ((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4) || (finfo.visual==FB_VISUAL_DIRECTCOLOR)) + { + fb_cmap cmap; + createPalette(cmap, vinfo, finfo); + if (ioctl(d_ptr->fd, FBIOPUTCMAP, &cmap)) { + perror("QLinuxFbScreen::initDevice"); + qWarning("Error writing palette to framebuffer"); + } + free(cmap.red); + free(cmap.green); + free(cmap.blue); + free(cmap.transp); + } + +#if 0 + if (canaccel) { + *entryp=0; + *lowest = mapsize; + insert_entry(*entryp, *lowest, *lowest); // dummy entry to mark start + } + + shared->fifocount = 0; + shared->buffer_offset = 0xffffffff; // 0 would be a sensible offset (screen) + shared->linestep = 0; + shared->cliptop = 0xffffffff; + shared->clipleft = 0xffffffff; + shared->clipright = 0xffffffff; + shared->clipbottom = 0xffffffff; + shared->rop = 0xffffffff; +#endif + +#ifdef QT_QWS_DEPTH_GENERIC + if (pixelFormat() == QImage::Format_Invalid && screencols == 0 + && d_ptr->doGenericColors) + { + qt_set_generic_blit(this, vinfo.bits_per_pixel, + vinfo.red.length, vinfo.green.length, + vinfo.blue.length, vinfo.transp.length, + vinfo.red.offset, vinfo.green.offset, + vinfo.blue.offset, vinfo.transp.offset); + } +#endif + +#if 0 +#ifndef QT_NO_QWS_CURSOR + QScreenCursor::initSoftwareCursor(); +#endif +#endif + blank(false); + + return true; +} + +void QLinuxFbIntegration::setPixelFormat(struct fb_var_screeninfo info) +{ + const fb_bitfield rgba[4] = { info.red, info.green, + info.blue, info.transp }; + + QImage::Format format = QImage::Format_Invalid; + + switch (d) { + case 32: { + const fb_bitfield argb8888[4] = {{16, 8, 0}, {8, 8, 0}, + {0, 8, 0}, {24, 8, 0}}; + const fb_bitfield abgr8888[4] = {{0, 8, 0}, {8, 8, 0}, + {16, 8, 0}, {24, 8, 0}}; + if (memcmp(rgba, argb8888, 4 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_ARGB32; + } else if (memcmp(rgba, argb8888, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB32; + } else if (memcmp(rgba, abgr8888, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB32; + pixeltype = BGRPixel; + } + break; + } + case 24: { + const fb_bitfield rgb888[4] = {{16, 8, 0}, {8, 8, 0}, + {0, 8, 0}, {0, 0, 0}}; + const fb_bitfield bgr888[4] = {{0, 8, 0}, {8, 8, 0}, + {16, 8, 0}, {0, 0, 0}}; + if (memcmp(rgba, rgb888, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB888; + } else if (memcmp(rgba, bgr888, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB888; + pixeltype = BGRPixel; + } + break; + } + case 18: { + const fb_bitfield rgb666[4] = {{12, 6, 0}, {6, 6, 0}, + {0, 6, 0}, {0, 0, 0}}; + if (memcmp(rgba, rgb666, 3 * sizeof(fb_bitfield)) == 0) + format = QImage::Format_RGB666; + break; + } + case 16: { + const fb_bitfield rgb565[4] = {{11, 5, 0}, {5, 6, 0}, + {0, 5, 0}, {0, 0, 0}}; + const fb_bitfield bgr565[4] = {{0, 5, 0}, {5, 6, 0}, + {11, 5, 0}, {0, 0, 0}}; + if (memcmp(rgba, rgb565, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB16; + } else if (memcmp(rgba, bgr565, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB16; + pixeltype = BGRPixel; + } + break; + } + case 15: { + const fb_bitfield rgb1555[4] = {{10, 5, 0}, {5, 5, 0}, + {0, 5, 0}, {15, 1, 0}}; + const fb_bitfield bgr1555[4] = {{0, 5, 0}, {5, 5, 0}, + {10, 5, 0}, {15, 1, 0}}; + if (memcmp(rgba, rgb1555, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB555; + } else if (memcmp(rgba, bgr1555, 3 * sizeof(fb_bitfield)) == 0) { + format = QImage::Format_RGB555; + pixeltype = BGRPixel; + } + break; + } + case 12: { + const fb_bitfield rgb444[4] = {{8, 4, 0}, {4, 4, 0}, + {0, 4, 0}, {0, 0, 0}}; + if (memcmp(rgba, rgb444, 3 * sizeof(fb_bitfield)) == 0) + format = QImage::Format_RGB444; + break; + } + case 8: + break; + case 1: + format = QImage::Format_Mono; //###: LSB??? + break; + default: + break; + } + + screenFormat = format; +} + +void QLinuxFbIntegration::createPalette(fb_cmap &cmap, fb_var_screeninfo &vinfo, fb_fix_screeninfo &finfo) +{ + if((vinfo.bits_per_pixel==8) || (vinfo.bits_per_pixel==4)) { + screencols= (vinfo.bits_per_pixel==8) ? 256 : 16; + cmap.start=0; + cmap.len=screencols; + cmap.red=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + cmap.green=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + cmap.blue=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + cmap.transp=(unsigned short int *) + malloc(sizeof(unsigned short int)*screencols); + + if (screencols==16) { + if (finfo.type == FB_TYPE_PACKED_PIXELS) { + // We'll setup a grayscale cmap for 4bpp linear + int val = 0; + for (int idx = 0; idx < 16; ++idx, val += 17) { + cmap.red[idx] = (val<<8)|val; + cmap.green[idx] = (val<<8)|val; + cmap.blue[idx] = (val<<8)|val; + screenclut[idx]=qRgb(val, val, val); + } + } else { + // Default 16 colour palette + // Green is now trolltech green so certain images look nicer + // black d_gray l_gray white red green blue cyan magenta yellow + unsigned char reds[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0xFF, 0xA2, 0x00, 0xFF, 0xFF, 0x00, 0x7F, 0x7F, 0x00, 0x00, 0x00, 0x82 }; + unsigned char greens[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0x00, 0xC5, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x7F, 0x7F, 0x7F }; + unsigned char blues[16] = { 0x00, 0x7F, 0xBF, 0xFF, 0x00, 0x11, 0xFF, 0x00, 0xFF, 0xFF, 0x00, 0x7F, 0x7F, 0x7F, 0x00, 0x00 }; + + for (int idx = 0; idx < 16; ++idx) { + cmap.red[idx] = ((reds[idx]) << 8)|reds[idx]; + cmap.green[idx] = ((greens[idx]) << 8)|greens[idx]; + cmap.blue[idx] = ((blues[idx]) << 8)|blues[idx]; + cmap.transp[idx] = 0; + screenclut[idx]=qRgb(reds[idx], greens[idx], blues[idx]); + } + } + } else { + if (grayscale) { + // Build grayscale palette + int i; + for(i=0;i<screencols;++i) { + int bval = screencols == 256 ? i : (i << 4); + ushort val = (bval << 8) | bval; + cmap.red[i] = val; + cmap.green[i] = val; + cmap.blue[i] = val; + cmap.transp[i] = 0; + screenclut[i] = qRgb(bval,bval,bval); + } + } else { + // 6x6x6 216 color cube + int idx = 0; + for(int ir = 0x0; ir <= 0xff; ir+=0x33) { + for(int ig = 0x0; ig <= 0xff; ig+=0x33) { + for(int ib = 0x0; ib <= 0xff; ib+=0x33) { + cmap.red[idx] = (ir << 8)|ir; + cmap.green[idx] = (ig << 8)|ig; + cmap.blue[idx] = (ib << 8)|ib; + cmap.transp[idx] = 0; + screenclut[idx]=qRgb(ir, ig, ib); + ++idx; + } + } + } + // Fill in rest with 0 + for (int loopc=0; loopc<40; ++loopc) { + screenclut[idx]=0; + ++idx; + } + screencols=idx; + } + } + } else if(finfo.visual==FB_VISUAL_DIRECTCOLOR) { + cmap.start=0; + int rbits=0,gbits=0,bbits=0; + switch (vinfo.bits_per_pixel) { + case 8: + rbits=vinfo.red.length; + gbits=vinfo.green.length; + bbits=vinfo.blue.length; + if(rbits==0 && gbits==0 && bbits==0) { + // cyber2000 driver bug hack + rbits=3; + gbits=3; + bbits=2; + } + break; + case 15: + rbits=5; + gbits=5; + bbits=5; + break; + case 16: + rbits=5; + gbits=6; + bbits=5; + break; + case 18: + case 19: + rbits=6; + gbits=6; + bbits=6; + break; + case 24: case 32: + rbits=gbits=bbits=8; + break; + } + screencols=cmap.len=1<<qMax(rbits,qMax(gbits,bbits)); + cmap.red=(unsigned short int *) + malloc(sizeof(unsigned short int)*256); + cmap.green=(unsigned short int *) + malloc(sizeof(unsigned short int)*256); + cmap.blue=(unsigned short int *) + malloc(sizeof(unsigned short int)*256); + cmap.transp=(unsigned short int *) + malloc(sizeof(unsigned short int)*256); + for(unsigned int i = 0x0; i < cmap.len; i++) { + cmap.red[i] = i*65535/((1<<rbits)-1); + cmap.green[i] = i*65535/((1<<gbits)-1); + cmap.blue[i] = i*65535/((1<<bbits)-1); + cmap.transp[i] = 0; + } + } +} + +void QLinuxFbIntegration::blank(bool on) +{ + if (d_ptr->blank == on) + return; + +#if defined(QT_QWS_IPAQ) + if (on) + system("apm -suspend"); +#else + if (d_ptr->fd == -1) + return; +// Some old kernel versions don't have this. These defines should go +// away eventually +#if defined(FBIOBLANK) +#if defined(VESA_POWERDOWN) && defined(VESA_NO_BLANKING) + ioctl(d_ptr->fd, FBIOBLANK, on ? VESA_POWERDOWN : VESA_NO_BLANKING); +#else + ioctl(d_ptr->fd, FBIOBLANK, on ? 1 : 0); +#endif +#endif +#endif + + d_ptr->blank = on; +} + +QPixmapData *QLinuxFbIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QWindowSurface *QLinuxFbIntegration::createWindowSurface(QWidget *widget, WId) const +{ + QFbWindowSurface * surface = + new QFbWindowSurface(mPrimaryScreen, widget); + return surface; +} + +QPlatformWindow *QLinuxFbIntegration::createPlatformWindow(QWidget *widget, WId /*winId*/) const +{ + QFbWindow *w = new QFbWindow(widget); + mPrimaryScreen->addWindow(w); + return w; +} + +QPlatformFontDatabase *QLinuxFbIntegration::fontDatabase() const +{ + return fontDb; +} + +QLinuxFbScreen::QLinuxFbScreen(uchar * d, int w, + int h, int lstep, QImage::Format screenFormat) : compositePainter(0) +{ + data = d; + mGeometry = QRect(0,0,w,h); + bytesPerLine = lstep; + mFormat = screenFormat; + mDepth = 16; + mScreenImage = new QImage(mGeometry.width(), mGeometry.height(), + mFormat); + mFbScreenImage = new QImage(data, mGeometry.width(), mGeometry.height(), + bytesPerLine, mFormat); + cursor = new QPlatformSoftwareCursor(this); +} + +void QLinuxFbScreen::setGeometry(QRect rect) +{ + mGeometry = rect; + delete mFbScreenImage; + mFbScreenImage = new QImage(data, mGeometry.width(), mGeometry.height(), + bytesPerLine, mFormat); + delete compositePainter; + compositePainter = 0; + + delete mScreenImage; + mScreenImage = new QImage(mGeometry.width(), mGeometry.height(), + mFormat); +} + +void QLinuxFbScreen::setFormat(QImage::Format format) +{ + mFormat = format; + delete mFbScreenImage; + mFbScreenImage = new QImage(data, mGeometry.width(), mGeometry.height(), + bytesPerLine, mFormat); + delete compositePainter; + compositePainter = 0; + + delete mScreenImage; + mScreenImage = new QImage(mGeometry.width(), mGeometry.height(), + mFormat); +} + +QRegion QLinuxFbScreen::doRedraw() +{ + QRegion touched; + touched = QFbScreen::doRedraw(); + + if (!compositePainter) { + compositePainter = new QPainter(mFbScreenImage); + } + + QVector<QRect> rects = touched.rects(); + for (int i = 0; i < rects.size(); i++) + compositePainter->drawImage(rects[i], *mScreenImage, rects[i]); + return touched; +} +QT_END_NAMESPACE diff --git a/src/plugins/platforms/linuxfb/qlinuxfbintegration.h b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h new file mode 100644 index 0000000..e93495c --- /dev/null +++ b/src/plugins/platforms/linuxfb/qlinuxfbintegration.h @@ -0,0 +1,133 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSYSTEM_LINUXFB_H +#define QGRAPHICSSYSTEM_LINUXFB_H + +#include <QPlatformIntegration> +#include "../fb_base/fb_base.h" + +QT_BEGIN_NAMESPACE + +class QLinuxFbScreen : public QFbScreen +{ + Q_OBJECT +public: + QLinuxFbScreen(uchar * d, int w, int h, int lstep, QImage::Format screenFormat); + void setGeometry(QRect rect); + void setFormat(QImage::Format format); + +public slots: + QRegion doRedraw(); + +private: + QImage * mFbScreenImage; + uchar * data; + int bytesPerLine; + + QPainter *compositePainter; +}; + +class QLinuxFbIntegrationPrivate; +struct fb_cmap; +struct fb_var_screeninfo; +struct fb_fix_screeninfo; + +class QLinuxFbIntegration : public QPlatformIntegration +{ +public: + QLinuxFbIntegration(); + ~QLinuxFbIntegration(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId WinId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId WinId) const; + + QList<QPlatformScreen *> screens() const { return mScreens; } + + QPlatformFontDatabase *fontDatabase() const; + +private: + QLinuxFbScreen *mPrimaryScreen; + QList<QPlatformScreen *> mScreens; + QLinuxFbIntegrationPrivate *d_ptr; + + enum PixelType { NormalPixel, BGRPixel }; + + QRgb screenclut[256]; + int screencols; + + uchar * data; + + QImage::Format screenFormat; + int w; + int lstep; + int h; + int d; + PixelType pixeltype; + bool grayscale; + + int dw; + int dh; + + int size; // Screen size + int mapsize; // Total mapped memory + + int displayId; + + int physWidth; + int physHeight; + + bool canaccel; + int dataoffset; + int cacheStart; + + bool connect(const QString &displaySpec); + bool initDevice(); + void setPixelFormat(struct fb_var_screeninfo); + void createPalette(fb_cmap &cmap, fb_var_screeninfo &vinfo, fb_fix_screeninfo &finfo); + void blank(bool on); + QPlatformFontDatabase *fontDb; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/minimal/main.cpp b/src/plugins/platforms/minimal/main.cpp new file mode 100644 index 0000000..82c15c2 --- /dev/null +++ b/src/plugins/platforms/minimal/main.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qminimalintegration.h" + +QT_BEGIN_NAMESPACE + +class QMinimalIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QMinimalIntegrationPlugin::keys() const +{ + QStringList list; + list << "Minimal"; + return list; +} + +QPlatformIntegration *QMinimalIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "minimal") + return new QMinimalIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(minimal, QMinimalIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/minimal/minimal.pro b/src/plugins/platforms/minimal/minimal.pro new file mode 100644 index 0000000..438a88e --- /dev/null +++ b/src/plugins/platforms/minimal/minimal.pro @@ -0,0 +1,13 @@ +TARGET = qminimal +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +SOURCES = main.cpp \ + qminimalintegration.cpp \ + qminimalwindowsurface.cpp +HEADERS = qminimalintegration.h \ + qminimalwindowsurface.h + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target diff --git a/src/plugins/platforms/minimal/qminimalintegration.cpp b/src/plugins/platforms/minimal/qminimalintegration.cpp new file mode 100644 index 0000000..c90e92e --- /dev/null +++ b/src/plugins/platforms/minimal/qminimalintegration.cpp @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qminimalintegration.h" +#include "qminimalwindowsurface.h" + +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtGui/QPlatformWindow> + +QMinimalIntegration::QMinimalIntegration() +{ + QMinimalScreen *mPrimaryScreen = new QMinimalScreen(); + + mPrimaryScreen->mGeometry = QRect(0, 0, 240, 320); + mPrimaryScreen->mDepth = 16; + mPrimaryScreen->mFormat = QImage::Format_RGB16; + + mScreens.append(mPrimaryScreen); +} + +QPixmapData *QMinimalIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QPlatformWindow *QMinimalIntegration::createPlatformWindow(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + return new QPlatformWindow(widget); +} + +QWindowSurface *QMinimalIntegration::createWindowSurface(QWidget *widget, WId winId) const +{ + Q_UNUSED(winId); + return new QMinimalWindowSurface(widget); +} diff --git a/src/plugins/platforms/minimal/qminimalintegration.h b/src/plugins/platforms/minimal/qminimalintegration.h new file mode 100644 index 0000000..95b952e --- /dev/null +++ b/src/plugins/platforms/minimal/qminimalintegration.h @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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_MINIMAL_H +#define QPLATFORMINTEGRATION_MINIMAL_H + +#include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformScreen> + +QT_BEGIN_NAMESPACE + +class QMinimalScreen : public QPlatformScreen +{ +public: + QMinimalScreen() + : mDepth(16), mFormat(QImage::Format_RGB16) {} + + QRect geometry() const { return mGeometry; } + int depth() const { return mDepth; } + QImage::Format format() const { return mFormat; } + +public: + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + QSize mPhysicalSize; +}; + +class QMinimalIntegration : public QPlatformIntegration +{ +public: + QMinimalIntegration(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QList<QPlatformScreen *> screens() const { return mScreens; } + +private: + QList<QPlatformScreen *> mScreens; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/minimal/qminimalwindowsurface.cpp b/src/plugins/platforms/minimal/qminimalwindowsurface.cpp new file mode 100644 index 0000000..acf0e6e --- /dev/null +++ b/src/plugins/platforms/minimal/qminimalwindowsurface.cpp @@ -0,0 +1,86 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qminimalwindowsurface.h" +#include <QtCore/qdebug.h> +#include <QtGui/private/qapplication_p.h> + +QT_BEGIN_NAMESPACE + +QMinimalWindowSurface::QMinimalWindowSurface(QWidget *window) + : QWindowSurface(window) +{ + //qDebug() << "QMinimalWindowSurface::QMinimalWindowSurface:" << (long)this; +} + +QMinimalWindowSurface::~QMinimalWindowSurface() +{ +} + +QPaintDevice *QMinimalWindowSurface::paintDevice() +{ + //qDebug() << "QMinimalWindowSurface::paintDevice"; + return &mImage; +} + +void QMinimalWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(region); + Q_UNUSED(offset); + + static int c = 0; + QString filename = QString("output%1.png").arg(c++, 4, 10, QLatin1Char('0')); + qDebug() << "QMinimalWindowSurface::flush() saving contents to" << filename.toLocal8Bit().constData(); + mImage.save(filename); +} + +void QMinimalWindowSurface::resize(const QSize &size) +{ + //qDebug() << "QMinimalWindowSurface::setGeometry:" << (long)this << rect; + QWindowSurface::resize(size); + QImage::Format format = QApplicationPrivate::platformIntegration()->screens().first()->format(); + if (mImage.size() != size) + mImage = QImage(size, format); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/minimal/qminimalwindowsurface.h b/src/plugins/platforms/minimal/qminimalwindowsurface.h new file mode 100644 index 0000000..98b26f6 --- /dev/null +++ b/src/plugins/platforms/minimal/qminimalwindowsurface.h @@ -0,0 +1,67 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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_MINIMAL_H +#define QWINDOWSURFACE_MINIMAL_H + +#include <QtGui/private/qwindowsurface_p.h> + +#include <QtGui/QPlatformWindow> + +QT_BEGIN_NAMESPACE + +class QMinimalWindowSurface : public QWindowSurface +{ +public: + QMinimalWindowSurface(QWidget *window); + ~QMinimalWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + +private: + QImage mImage; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/openkode/main.cpp b/src/plugins/platforms/openkode/main.cpp new file mode 100644 index 0000000..527747e --- /dev/null +++ b/src/plugins/platforms/openkode/main.cpp @@ -0,0 +1,72 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qopenkodeintegration.h" + +QT_BEGIN_NAMESPACE + +class QOpenKODEPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QOpenKODEPlugin::keys() const +{ + QStringList list; + list << "OpenKODE"; + return list; +} + +QPlatformIntegration * QOpenKODEPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "openkode") + return new QOpenKODEIntegration; + + return 0; +} + +Q_EXPORT_PLUGIN2(openkode, QOpenKODEPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/openkode/openkode.pro b/src/plugins/platforms/openkode/openkode.pro new file mode 100644 index 0000000..c8ae415 --- /dev/null +++ b/src/plugins/platforms/openkode/openkode.pro @@ -0,0 +1,42 @@ +TARGET = qopenkodeintegration +include(../../qpluginbase.pri) + +QT += opengl + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +SOURCES = main.cpp \ + qopenkodeintegration.cpp \ + qopenkodewindow.cpp \ + ../eglconvenience/qeglplatformcontext.cpp \ + ../eglconvenience/qeglconvenience.cpp \ + qopenkodeeventloopintegration.cpp + +HEADERS = qopenkodeintegration.h \ + qopenkodewindow.h \ + ../eglconvenience/qeglplatformcontext.h \ + ../eglconvenience/qeglconvenience.h \ + qopenkodeeventloopintegration.h \ + openkodekeytranslator.h + +include (../fontdatabases/genericunix/genericunix.pri) + +RESOURCES = resources.qrc + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target + +LIBS += -lKD -lEGL +!isEmpty(QMAKE_INCDIR_OPENGL_ES2){ + INCLUDEPATH += $$QMAKE_INCDIR_OPENGL_ES2 +} +!isEmpty(QMAKE_LIBDIR_OPENGL_ES2){ + for(p, QMAKE_LIBDIR_OPENGL_ES2) { + exists($$p):LIBS += -L$$p + } +} +!isEmpty(QMAKE_LIBS_OPENGL_ES2){ + LIBS += $$QMAKE_LIBS_OPENGL_ES2 +} else { + LIBS += -lGLESv2 +} diff --git a/src/plugins/platforms/openkode/openkodekeytranslator.h b/src/plugins/platforms/openkode/openkodekeytranslator.h new file mode 100644 index 0000000..0070edc --- /dev/null +++ b/src/plugins/platforms/openkode/openkodekeytranslator.h @@ -0,0 +1,244 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 OPENKODEKEYTRANSLATOR_H +#define OPENKODEKEYTRANSLATOR_H + +#ifdef KD_ATX_keyboard + +#include <KD/ATX_keyboard.h> + +QT_BEGIN_NAMESPACE + +Qt::Key keyTranslator( int key ) +{ + switch (key) { +// KD_KEY_ACCEPT_ATX: +// KD_KEY_AGAIN_ATX: +// KD_KEY_ALLCANDIDATES_ATX +// KD_KEY_ALPHANUMERIC_ATX + case KD_KEY_ALT_ATX: + return Qt::Key_Alt; + case KD_KEY_ALTGRAPH_ATX: + return Qt::Key_AltGr; +// KD_KEY_APPS_ATX +// KD_KEY_ATTN_ATX +// KD_KEY_BROWSERBACK_ATX +// KD_KEY_BROWSERFAVORITES_ATX +// KD_KEY_BROWSERFORWARD_ATX +// KD_KEY_BROWSERHOME_ATX +// KD_KEY_BROWSERREFRESH_ATX +// KD_KEY_BROWSERSEARCH_ATX +// KD_KEY_BROWSERSTOP_ATX + case KD_KEY_CAPSLOCK_ATX: + return Qt::Key_CapsLock; + case KD_KEY_CLEAR_ATX: + return Qt::Key_Clear; + case KD_KEY_CODEINPUT_ATX: + return Qt::Key_Codeinput; +// KD_KEY_COMPOSE_ATX + case KD_KEY_CONTROL_ATX: + return Qt::Key_Control; +// KD_KEY_CRSEL_ATX +// KD_KEY_CONVERT_ATX + case KD_KEY_COPY_ATX: + return Qt::Key_Copy; + case KD_KEY_CUT_ATX: + return Qt::Key_Cut; + case KD_KEY_DOWN_ATX: + return Qt::Key_Down; + case KD_KEY_END_ATX: + return Qt::Key_End; + case KD_KEY_ENTER_ATX: + return Qt::Key_Enter; +// KD_KEY_ERASEEOF_ATX +// KD_KEY_EXECUTE_ATX +// KD_KEY_EXSEL_ATX + case KD_KEY_F1_ATX: + return Qt::Key_F1; + case KD_KEY_F2_ATX: + return Qt::Key_F2; + case KD_KEY_F3_ATX: + return Qt::Key_F3; + case KD_KEY_F4_ATX: + return Qt::Key_F4; + case KD_KEY_F5_ATX: + return Qt::Key_F5; + case KD_KEY_F6_ATX: + return Qt::Key_F6; + case KD_KEY_F7_ATX: + return Qt::Key_F7; + case KD_KEY_F8_ATX: + return Qt::Key_F8; + case KD_KEY_F9_ATX: + return Qt::Key_F9; + case KD_KEY_F10_ATX: + return Qt::Key_F10; + case KD_KEY_F11_ATX: + return Qt::Key_F11; + case KD_KEY_F12_ATX: + return Qt::Key_F12; + case KD_KEY_F13_ATX: + return Qt::Key_F13; + case KD_KEY_F14_ATX: + return Qt::Key_F14; + case KD_KEY_F15_ATX: + return Qt::Key_F15; + case KD_KEY_F16_ATX: + return Qt::Key_F16; + case KD_KEY_F17_ATX: + return Qt::Key_F17; + case KD_KEY_F18_ATX: + return Qt::Key_F18; + case KD_KEY_F19_ATX: + return Qt::Key_F19; + case KD_KEY_F20_ATX: + return Qt::Key_F20; + case KD_KEY_F21_ATX: + return Qt::Key_F21; + case KD_KEY_F22_ATX: + return Qt::Key_F22; + case KD_KEY_F23_ATX: + return Qt::Key_F23; + case KD_KEY_F24_ATX: + return Qt::Key_F24; +// KD_KEY_FINALMODE_ATX +// KD_KEY_FIND_ATX +// KD_KEY_FULLWIDTH_ATX +// KD_KEY_HALFWIDTH_ATX + case KD_KEY_HANGULMODE_ATX: + return Qt::Key_Hangul; +// KD_KEY_HANJAMODE_ATX + case KD_KEY_HELP_ATX: + return Qt::Key_Help; + case KD_KEY_HIRAGANA_ATX: + return Qt::Key_Hiragana; + case KD_KEY_HOME_ATX: + return Qt::Key_Home; + case KD_KEY_INSERT_ATX: + return Qt::Key_Insert; +// KD_KEY_JAPANESEHIRAGANA_ATX: +// KD_KEY_JAPANESEKATAKANA_ATX +// KD_KEY_JAPANESEROMAJI_ATX +// KD_KEY_JUNJAMODE_ATX + case KD_KEY_KANAMODE_ATX: + return Qt::Key_Kana_Lock; //? + case KD_KEY_KANJIMODE_ATX: + return Qt::Key_Kanji; +// KD_KEY_KATAKANA_ATX +// KD_KEY_LAUNCHAPPLICATION1_ATX +// KD_KEY_LAUNCHAPPLICATION2_ATX + case KD_KEY_LAUNCHMAIL_ATX: + return Qt::Key_MailForward; + case KD_KEY_LEFT_ATX: + return Qt::Key_Left; + case KD_KEY_META_ATX: + return Qt::Key_Meta; + case KD_KEY_MEDIANEXTTRACK_ATX: + return Qt::Key_MediaNext; + case KD_KEY_MEDIAPLAYPAUSE_ATX: + return Qt::Key_MediaPause; + case KD_KEY_MEDIAPREVIOUSTRACK_ATX: + return Qt::Key_MediaPrevious; + case KD_KEY_MEDIASTOP_ATX: + return Qt::Key_MediaStop; + case KD_KEY_MODECHANGE_ATX: + return Qt::Key_Mode_switch; +// KD_KEY_NONCONVERT_ATX + case KD_KEY_NUMLOCK_ATX: + return Qt::Key_NumLock; + case KD_KEY_PAGEDOWN_ATX: + return Qt::Key_PageDown; + case KD_KEY_PAGEUP_ATX: + return Qt::Key_PageUp; + case KD_KEY_PASTE_ATX: + return Qt::Key_Paste; + case KD_KEY_PAUSE_ATX: + return Qt::Key_Pause; + case KD_KEY_PLAY_ATX: + return Qt::Key_Play; +// KD_KEY_PREVIOUSCANDIDATE_ATX + case KD_KEY_PRINTSCREEN_ATX: + return Qt::Key_Print; +// case KD_KEY_PROCESS_ATX +// case KD_KEY_PROPS_ATX + case KD_KEY_RIGHT_ATX: + return Qt::Key_Right; +// KD_KEY_ROMANCHARACTERS_ATX + case KD_KEY_SCROLL_ATX: + return Qt::Key_ScrollLock; + case KD_KEY_SELECT_ATX: + return Qt::Key_Select; +// KD_KEY_SELECTMEDIA_ATX + case KD_KEY_SHIFT_ATX: + return Qt::Key_Shift; + case KD_KEY_STOP_ATX: + return Qt::Key_Stop; + case KD_KEY_UP_ATX: + return Qt::Key_Up; +// KD_KEY_UNDO_ATX + case KD_KEY_VOLUMEDOWN_ATX: + return Qt::Key_VolumeDown; + case KD_KEY_VOLUMEMUTE_ATX: + return Qt::Key_VolumeMute; + case KD_KEY_VOLUMEUP_ATX: + return Qt::Key_VolumeUp; + case KD_KEY_WIN_ATX: + return Qt::Key_Meta; + case KD_KEY_ZOOM_ATX: + return Qt::Key_Zoom; + case 0x8: + return Qt::Key_Backspace; + case 0x1b: + return Qt::Key_Escape; + case 0x9: + return Qt::Key_Tab; + + default: + break; + } + + return Qt::Key_Escape; +} + +QT_END_NAMESPACE +#endif //KD_ATX_keyboard +#endif // OPENKODEKEYTRANSLATOR_H diff --git a/src/plugins/platforms/openkode/qopenkodeeventloopintegration.cpp b/src/plugins/platforms/openkode/qopenkodeeventloopintegration.cpp new file mode 100644 index 0000000..73d874c --- /dev/null +++ b/src/plugins/platforms/openkode/qopenkodeeventloopintegration.cpp @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qopenkodeeventloopintegration.h" + +#include <QDebug> + +#include <KD/kd.h> +#include <KD/ATX_keyboard.h> + +QT_BEGIN_NAMESPACE + +static const int QT_EVENT_WAKEUP_EVENTLOOP = KD_EVENT_USER + 1; + +void kdprocessevent( const KDEvent *event) +{ + switch (event->type) { + case KD_EVENT_INPUT: + qDebug() << "KD_EVENT_INPUT"; + break; + case KD_EVENT_INPUT_POINTER: + qDebug() << "KD_EVENT_INPUT_POINTER"; + break; + case KD_EVENT_WINDOW_CLOSE: + qDebug() << "KD_EVENT_WINDOW_CLOSE"; + break; + case KD_EVENT_WINDOWPROPERTY_CHANGE: + qDebug() << "KD_EVENT_WINDOWPROPERTY_CHANGE"; + qDebug() << event->data.windowproperty.pname; + break; + case KD_EVENT_WINDOW_FOCUS: + qDebug() << "KD_EVENT_WINDOW_FOCUS"; + break; + case KD_EVENT_WINDOW_REDRAW: + qDebug() << "KD_EVENT_WINDOW_REDRAW"; + break; + case KD_EVENT_USER: + qDebug() << "KD_EVENT_USER"; + break; + case KD_EVENT_INPUT_KEY_ATX: + qDebug() << "KD_EVENT_INPUT_KEY_ATX"; + break; + case QT_EVENT_WAKEUP_EVENTLOOP: +// qDebug() << "QT_EVENT_WAKEUP_EVENTLOOP"; + break; + default: + break; + } + + kdDefaultEvent(event); + +} + +QOpenKODEEventLoopIntegration::QOpenKODEEventLoopIntegration() +{ + m_kdThread = kdThreadSelf(); + kdInstallCallback(&kdprocessevent,QT_EVENT_WAKEUP_EVENTLOOP,this); +} + +void QOpenKODEEventLoopIntegration::processEvents(qint64 msec) +{ + if (msec == 0) + msec = -1; + const KDEvent *event = kdWaitEvent(msec*1000); + if (event) { + kdDefaultEvent(event); + while ((event = kdWaitEvent(0)) != 0) { + kdDefaultEvent(event); + } + } +} + +void QOpenKODEEventLoopIntegration::wakeup() +{ + KDEvent *event = kdCreateEvent(); + event->type = QT_EVENT_WAKEUP_EVENTLOOP; + event->userptr = this; + kdPostThreadEvent(event,m_kdThread); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/openkode/qopenkodeeventloopintegration.h b/src/plugins/platforms/openkode/qopenkodeeventloopintegration.h new file mode 100644 index 0000000..61bd444 --- /dev/null +++ b/src/plugins/platforms/openkode/qopenkodeeventloopintegration.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QOPENKODEEVENTLOOPINTEGRATION_H +#define QOPENKODEEVENTLOOPINTEGRATION_H + +#include <QtGui/QPlatformEventLoopIntegration> + +class KDThread; +class KDEvent; + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QOpenKODEEventLoopIntegration : public QPlatformEventLoopIntegration +{ +public: + QOpenKODEEventLoopIntegration(); + void processEvents(qint64 msec); + void wakeup(); + + void processInputEvent(const KDEvent *event); +private: + + KDThread *m_kdThread; +}; + +QT_END_NAMESPACE +QT_END_HEADER + +#endif // QOPENKODEEVENTLOOPINTEGRATION_H diff --git a/src/plugins/platforms/openkode/qopenkodeintegration.cpp b/src/plugins/platforms/openkode/qopenkodeintegration.cpp new file mode 100644 index 0000000..60be897 --- /dev/null +++ b/src/plugins/platforms/openkode/qopenkodeintegration.cpp @@ -0,0 +1,240 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qopenkodeintegration.h" +#include "qopenkodewindow.h" +#include "qopenkodeeventloopintegration.h" + +#include <QtOpenGL/private/qpixmapdata_gl_p.h> +#include <QtOpenGL/private/qwindowsurface_gl_p.h> + +#include <QtGui/private/qpixmap_raster_p.h> + +#include <QtCore/qdebug.h> +#include <QtCore/qthread.h> +#include <QtCore/qfile.h> + +#include "qgenericunixfontdatabase.h" + +#include <KD/kd.h> +#include <KD/NV_display.h> +#include <KD/NV_initialize.h> + +#include <EGL/egl.h> + +#include "GLES2/gl2ext.h" + +QT_BEGIN_NAMESPACE + +QOpenKODEScreen::QOpenKODEScreen(KDDisplayNV *kdDisplay, KDDesktopNV *kdDesktop) + : mIsFullScreen(false) +{ + qDebug() << "QOpenKODEScreen::QOpenKODEIntegrationScreen()"; + + KDboolean enabled = KD_TRUE; + kdSetDisplayPropertybvNV(kdDisplay, + KD_DISPLAYPROPERTY_ENABLED_NV, + &enabled); + KDboolean power = KD_DISPLAY_POWER_ON; + kdSetDisplayPropertyivNV(kdDisplay, + KD_DISPLAYPROPERTY_POWER_NV, + &power); + + kdSetDisplayPropertycvNV(kdDisplay, + KD_DISPLAYPROPERTY_DESKTOP_NAME_NV, + KD_DEFAULT_DESKTOP_NV); + + KDDisplayModeNV mode; + if (kdGetDisplayModeNV(kdDisplay, &mode)) { + qErrnoWarning(kdGetError(), "Could not get display mode"); + return; + } + + qDebug() << " - display mode " << mode.width << "x" << mode.height << " refresh " << mode.refresh; + + KDint desktopSize[] = { mode.width, mode.height }; + + if (kdSetDesktopPropertyivNV(kdDesktop, KD_DESKTOPPROPERTY_SIZE_NV, desktopSize)) { + qErrnoWarning(kdGetError(), "Could not set desktop size"); + return; + } + + // Once we've set up the desktop and display we don't need them anymore + kdReleaseDisplayNV(kdDisplay); + kdReleaseDesktopNV(kdDesktop); + + mEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (mEglDisplay == EGL_NO_DISPLAY) { + qErrnoWarning("EGL failed to obtain display"); + } + + /* Initialize EGL display */ + EGLBoolean rvbool = eglInitialize(mEglDisplay, 0, 0); + if (!rvbool) { + qErrnoWarning("EGL failed to initialize display"); + } + +// cursor = new QOpenKODECursor(this); + + mGeometry = QRect(0, 0, mode.width, mode.height); + mDepth = 24; + mFormat = QImage::Format_RGB32; + + +} + +QOpenKODEIntegration::QOpenKODEIntegration() + : mEventLoopIntegration(0), mFontDb(new QGenericUnixFontDatabase()) +{ + if (kdInitializeNV() == KD_ENOTINITIALIZED) { + qFatal("Did not manage to initialize openkode"); + } + + KDDisplaySystemNV *kdDisplaySystem = kdCreateDisplaySystemSnapshotNV(this); + KDint32 displayCount = 0; + kdGetDisplaySystemPropertyivNV(kdDisplaySystem, KD_DISPLAYPROPERTY_COUNT_NV, 0, &displayCount); + + for (int i = 0; i < displayCount; i++) { + KDchar *displayName = 0; + KDsize displayNameLength = 0; + kdGetDisplaySystemPropertycvNV(kdDisplaySystem,KD_DISPLAYPROPERTY_NAME_NV,i,0,&displayNameLength); + if (!displayNameLength) + continue; + displayName = new KDchar[displayNameLength]; + kdGetDisplaySystemPropertycvNV(kdDisplaySystem,KD_DISPLAYPROPERTY_NAME_NV,i,displayName,&displayNameLength); + + KDDisplayNV *display = kdGetDisplayNV(displayName,this); + if (!display || display == (void*)-1) { + qErrnoWarning(kdGetError(), "Could not obtain KDDisplayNV pointer"); + return; + } + if (displayNameLength) + delete displayName; + + KDchar *desktopName = 0; + KDsize desktopNameLength = 0; + bool openkodeImpDoesNotFail = false; + if (openkodeImpDoesNotFail) { + qDebug() << "printing desktopname"; + kdGetDisplayPropertycvNV(display,KD_DISPLAYPROPERTY_DESKTOP_NAME_NV,desktopName,&desktopNameLength); + if (desktopNameLength) { + desktopName = new KDchar[desktopNameLength]; + kdGetDisplayPropertycvNV(display,KD_DISPLAYPROPERTY_DESKTOP_NAME_NV,desktopName,&desktopNameLength); + } else { + desktopName = KD_DEFAULT_DESKTOP_NV; + } + } else { + desktopName = KD_DEFAULT_DESKTOP_NV; + } + + KDDesktopNV *desktop = kdGetDesktopNV(desktopName,this); + if (!desktop || desktop == (void*)-1) { + qErrnoWarning(kdGetError(), "Could not obtain KDDesktopNV pointer"); + kdReleaseDisplayNV(display); + return; + } + if (desktopNameLength) + delete desktopName; + + QOpenKODEScreen *screen = new QOpenKODEScreen(display,desktop); + mScreens.append(screen); + } +} + +QOpenKODEIntegration::~QOpenKODEIntegration() +{ + delete mEventLoopIntegration; + delete mFontDb; +} + +QPixmapData *QOpenKODEIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QGLPixmapData(type); +} + +QPlatformWindow *QOpenKODEIntegration::createPlatformWindow(QWidget *tlw, WId ) const +{ + return new QOpenKODEWindow(tlw); +} + +QWindowSurface *QOpenKODEIntegration::createWindowSurface(QWidget *widget, WId) const +{ + QWindowSurface *returnSurface = 0; + switch (widget->platformWindowFormat().windowApi()) { + + case QPlatformWindowFormat::Raster: + case QPlatformWindowFormat::OpenGL: + returnSurface = new QGLWindowSurface(widget); + break; + + case QPlatformWindowFormat::OpenVG: +// returnSurface = new QVGWindowSurface(widget); + break; + + default: + returnSurface = new QGLWindowSurface(widget); + break; + } + + return returnSurface; +} + +bool QOpenKODEIntegration::hasOpenGL() const +{ + return true; +} + +QPlatformEventLoopIntegration *QOpenKODEIntegration::createEventLoopIntegration() const +{ + if (!mEventLoopIntegration) { + QOpenKODEIntegration *that = const_cast<QOpenKODEIntegration *>(this); + that->mEventLoopIntegration = new QOpenKODEEventLoopIntegration; + } + return mEventLoopIntegration; +} + +QPlatformFontDatabase *QOpenKODEIntegration::fontDatabase() const +{ + return mFontDb; +} + + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/openkode/qopenkodeintegration.h b/src/plugins/platforms/openkode/qopenkodeintegration.h new file mode 100644 index 0000000..a067491 --- /dev/null +++ b/src/plugins/platforms/openkode/qopenkodeintegration.h @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QGRAPHICSSYSTEM_OPENKODE_H +#define QGRAPHICSSYSTEM_OPENKODE_H + +#include "qopenkodeeventloopintegration.h" + +#include <QtCore/qsemaphore.h> + +#include <QtGui/QPlatformIntegration> +#include <QtGui/QPlatformScreen> +#include <QtGui/QPlatformGLContext> +#include <QtGui/QPlatformFontDatabase> + +#include <GLES2/gl2.h> +#include <EGL/egl.h> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +struct KDDesktopNV; +struct KDDisplayNV; +class QOpenKODECursor; + +class QOpenKODEScreen : public QPlatformScreen +{ + Q_OBJECT +public: + QOpenKODEScreen(KDDisplayNV *kdDisplay, KDDesktopNV *kdDesktop); + ~QOpenKODEScreen() {} + + QRect geometry() const { return mGeometry; } + int depth() const { return mDepth; } + QImage::Format format() const { return mFormat; } + + EGLDisplay eglDisplay() { return mEglDisplay; } + + bool isFullScreen() const {return mIsFullScreen;} + void setFullScreen(bool fullscreen) { mIsFullScreen = fullscreen; } +private: + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + EGLDisplay mEglDisplay; + bool mIsFullScreen; +}; + +class QOpenKODEIntegration : public QPlatformIntegration +{ +public: + QOpenKODEIntegration(); + ~QOpenKODEIntegration(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId = 0) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + bool hasOpenGL() const; + + QPlatformEventLoopIntegration *createEventLoopIntegration() const; + + QPlatformFontDatabase *fontDatabase() const; + + virtual QList<QPlatformScreen *> screens() const { return mScreens; } + + static GLuint blitterProgram(); + +private: + QList<QPlatformScreen *> mScreens; + QOpenKODEEventLoopIntegration *mEventLoopIntegration; + QPlatformFontDatabase *mFontDb; +}; + +QT_END_NAMESPACE +QT_END_HEADER + +#endif diff --git a/src/plugins/platforms/openkode/qopenkodewindow.cpp b/src/plugins/platforms/openkode/qopenkodewindow.cpp new file mode 100644 index 0000000..32517c6 --- /dev/null +++ b/src/plugins/platforms/openkode/qopenkodewindow.cpp @@ -0,0 +1,316 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 "qopenkodewindow.h" +#include "qopenkodeintegration.h" +#include "../eglconvenience/qeglplatformcontext.h" +#include "../eglconvenience/qeglconvenience.h" + +#include <KD/kd.h> +#include <KD/NV_display.h> +#include <KD/kdplatform.h> +#ifdef KD_ATX_keyboard +#include "openkodekeytranslator.h" +#endif + +#include <EGL/egl.h> + +#include <QtGui/qwidget.h> +#include <QtGui/private/qwidget_p.h> +#include <QtGui/private/qapplication_p.h> + +#include <QtCore/qvector.h> +#include <QtCore/QDebug> + +QT_BEGIN_NAMESPACE + +void kdProcessMouseEvents( const KDEvent *event ) +{ + QOpenKODEWindow *window = static_cast<QOpenKODEWindow *>(event->userptr); + window->processMouseEvents(event); +} + +#ifdef KD_ATX_keyboard +void kdProcessKeyEvents( const KDEvent *event ) +{ + QOpenKODEWindow *window = static_cast<QOpenKODEWindow *>(event->userptr); + window->processKeyEvents(event); +} +#endif //KD_ATX_keyboard + +QOpenKODEWindow::QOpenKODEWindow(QWidget *tlw) + : QPlatformWindow(tlw), isFullScreen(false) +{ + if (tlw->platformWindowFormat().windowApi() == QPlatformWindowFormat::OpenVG) { + m_eglApi = EGL_OPENVG_API; + } else { + m_eglContextAttrs.append(EGL_CONTEXT_CLIENT_VERSION); + m_eglContextAttrs.append(2); + + m_eglApi = EGL_OPENGL_ES_API; + } + eglBindAPI(m_eglApi); + + m_eglContextAttrs.append(EGL_NONE); + m_eglWindowAttrs.append(EGL_NONE); + + QList<QPlatformScreen *> screens = QApplicationPrivate::platformIntegration()->screens(); + //XXXX: jl figure out how to pick the correct screen. +// Q_ASSERT(screens.size() > tlw->d_func()->screenNumber); +// QOpenKODEScreen *screen = qobject_cast<QOpenKODEScreen *>(screens.at(tlw->d_func()->screenNumber)); + QOpenKODEScreen *screen = qobject_cast<QOpenKODEScreen *>(screens.at(0)); + if (!screen) { + qErrnoWarning("Could not make QOpenKODEWindow without a screen"); + } + + QPlatformWindowFormat format = tlw->platformWindowFormat(); + format.setRedBufferSize(5); + format.setGreenBufferSize(6); + format.setBlueBufferSize(5); + + m_eglConfig = q_configFromQPlatformWindowFormat(screen->eglDisplay(),format); + + m_kdWindow = kdCreateWindow(screen->eglDisplay(), + m_eglConfig, + this); + kdInstallCallback(kdProcessMouseEvents,KD_EVENT_INPUT_POINTER,this); +#ifdef KD_ATX_keyboard + kdInstallCallback(kdProcessKeyEvents, KD_EVENT_INPUT_KEY_ATX,this); +#endif //KD_ATX_keyboard + + if (!m_kdWindow) { + qErrnoWarning(kdGetError(), "Error creating native window"); + return; + } + + KDboolean exclusive(false); + if (kdSetWindowPropertybv(m_kdWindow,KD_WINDOWPROPERTY_DESKTOP_EXCLUSIVE_NV, &exclusive)) { + isFullScreen = true; + } + + if (isFullScreen) { + tlw->setGeometry(screen->geometry()); + screen->setFullScreen(isFullScreen); + }else { + const KDint windowSize[2] = { tlw->width(), tlw->height() }; + if (kdSetWindowPropertyiv(m_kdWindow, KD_WINDOWPROPERTY_SIZE, windowSize)) { + qErrnoWarning(kdGetError(), "Could not set native window size"); + } + KDboolean visibillity(false); + if (kdSetWindowPropertybv(m_kdWindow, KD_WINDOWPROPERTY_VISIBILITY, &visibillity)) { + qErrnoWarning(kdGetError(), "Could not set visibillity to false"); + } + + const KDint windowPos[2] = { tlw->x(), tlw->y() }; + if (kdSetWindowPropertyiv(m_kdWindow, KD_WINDOWPROPERTY_DESKTOP_OFFSET_NV, windowPos)) { + qErrnoWarning(kdGetError(), "Could not set native window position"); + return; + } + } + + + + + if (!isFullScreen || (isFullScreen && !QPlatformGLContext::defaultSharedContext())) { + if (kdRealizeWindow(m_kdWindow, &m_eglWindow)) { + qErrnoWarning(kdGetError(), "Could not realize native window"); + return; + } + + EGLSurface surface = eglCreateWindowSurface(screen->eglDisplay(),m_eglConfig,m_eglWindow,m_eglWindowAttrs.constData()); + m_platformGlContext = new QEGLPlatformContext(screen->eglDisplay(), m_eglConfig, + m_eglContextAttrs.data(), surface, m_eglApi); + m_platformGlContext->makeDefaultSaredContext(); + } else { + m_platformGlContext = static_cast<QEGLPlatformContext *>(QPlatformGLContext::defaultSharedContext()); + kdDestroyWindow(m_kdWindow); + m_kdWindow = 0; + } +} + + +QOpenKODEWindow::~QOpenKODEWindow() +{ + if (m_platformGlContext != QPlatformGLContext::defaultSharedContext()) { + delete m_platformGlContext; + } + if (m_kdWindow) + kdDestroyWindow(m_kdWindow); +} +void QOpenKODEWindow::setGeometry(const QRect &rect) +{ + if (isFullScreen) { + QList<QPlatformScreen *> screens = QApplicationPrivate::platformIntegration()->screens(); + QOpenKODEScreen *screen = qobject_cast<QOpenKODEScreen *>(screens.at(0)); + widget()->setGeometry(screen->geometry()); + return; + } + bool needToDeleteContext = false; + if (!isFullScreen) { + const QRect geo = geometry(); + if (geo.size() != rect.size()) { + const KDint windowSize[2] = { rect.width(), rect.height() }; + if (kdSetWindowPropertyiv(m_kdWindow, KD_WINDOWPROPERTY_SIZE, windowSize)) { + qErrnoWarning(kdGetError(), "Could not set native window size"); + //return; + } else { + needToDeleteContext = true; + } + } + + if (geo.topLeft() != rect.topLeft()) { + const KDint windowPos[2] = { rect.x(), rect.y() }; + if (kdSetWindowPropertyiv(m_kdWindow, KD_WINDOWPROPERTY_DESKTOP_OFFSET_NV, windowPos)) { + qErrnoWarning(kdGetError(), "Could not set native window position"); + //return; + } else { + needToDeleteContext = true; + } + } + } + + //need to recreate context + if (needToDeleteContext) { + qDebug() << "deleting context"; + delete m_platformGlContext; + + QList<QPlatformScreen *> screens = QApplicationPrivate::platformIntegration()->screens(); + QOpenKODEScreen *screen = qobject_cast<QOpenKODEScreen *>(screens.at(0)); + EGLSurface surface = eglCreateWindowSurface(screen->eglDisplay(),m_eglConfig,m_eglWindow,m_eglWindowAttrs.constData()); + m_platformGlContext = new QEGLPlatformContext(screen->eglDisplay(),m_eglConfig, + m_eglContextAttrs.data(),surface,m_eglApi); + } +} + +void QOpenKODEWindow::setVisible(bool visible) +{ + if (!m_kdWindow) + return; + KDboolean visibillity(visible); + if (kdSetWindowPropertybv(m_kdWindow, KD_WINDOWPROPERTY_VISIBILITY, &visibillity)) { + qErrnoWarning(kdGetError(), "Could not set visibillity property"); + } +} + +WId QOpenKODEWindow::winId() const +{ + static int i = 0; + return i++; +} + +QPlatformGLContext *QOpenKODEWindow::glContext() const +{ + return m_platformGlContext; +} + +void QOpenKODEWindow::raise() +{ + if (!m_kdWindow) + return; + KDboolean focus(true); + if (kdSetWindowPropertybv(m_kdWindow, KD_WINDOWPROPERTY_FOCUS, &focus)) { + qErrnoWarning(kdGetError(), "Could not set focus"); + } +} + +void QOpenKODEWindow::lower() +{ + if (!m_kdWindow) + return; + KDboolean focus(false); + if (kdSetWindowPropertybv(m_kdWindow, KD_WINDOWPROPERTY_FOCUS, &focus)) { + qErrnoWarning(kdGetError(), "Could not set focus"); + } +} + +void QOpenKODEWindow::processMouseEvents(const KDEvent *event) +{ + int x = event->data.inputpointer.x; + int y = event->data.inputpointer.y; + Qt::MouseButtons buttons; + switch(event->data.inputpointer.select) { + case 1: + buttons = Qt::LeftButton; + break; + default: + buttons = Qt::NoButton; + } + QPoint pos(x,y); + QWindowSystemInterface::handleMouseEvent(0,event->timestamp,pos,pos,buttons); +} + +void QOpenKODEWindow::processKeyEvents(const KDEvent *event) +{ +#ifdef KD_ATX_keyboard + //KD_KEY_PRESS_ATX 1 + QEvent::Type keyPressed = QEvent::KeyRelease; + if (event->data.keyboardInputKey.flags) + keyPressed = QEvent::KeyPress; +//KD_KEY_LOCATION_LEFT_ATX // dont care for now +//KD_KEY_LOCATION_RIGHT_ATX +//KD_KEY_LOCATION_NUMPAD_ATX + Qt::KeyboardModifiers mod = Qt::NoModifier; + int openkodeMods = event->data.keyboardInputKey.flags; + if (openkodeMods & KD_KEY_MODIFIER_SHIFT_ATX) + mod |= Qt::ShiftModifier; + if (openkodeMods & KD_KEY_MODIFIER_CTRL_ATX) + mod |= Qt::ControlModifier; + if (openkodeMods & KD_KEY_MODIFIER_ALT_ATX) + mod |= Qt::AltModifier; + if (openkodeMods & KD_KEY_MODIFIER_META_ATX) + mod |= Qt::MetaModifier; + + Qt::Key qtKey; + QChar keyText; + int key = event->data.keyboardInputKey.keycode; + if (key >= 0x20 && key <= 0x0ff){ // 8 bit printable Latin1 + qtKey = Qt::Key(key); + keyText = QChar(event->data.keyboardInputKeyChar.character); + if (!(mod & Qt::ShiftModifier)) + keyText = keyText.toLower(); + } else { + qtKey = keyTranslator(key); + } + QWindowSystemInterface::handleKeyEvent(0,event->timestamp,keyPressed,qtKey,mod,keyText); +#endif +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/openkode/qopenkodewindow.h b/src/plugins/platforms/openkode/qopenkodewindow.h new file mode 100644 index 0000000..4992807 --- /dev/null +++ b/src/plugins/platforms/openkode/qopenkodewindow.h @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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 QOPENKODEWINDOW_H +#define QOPENKODEWINDOW_H + +#include <QtGui/QPlatformWindow> +#include <QtCore/QVector> + +#include <KD/kd.h> + +QT_BEGIN_HEADER +QT_BEGIN_NAMESPACE + +class QEGLPlatformContext; +class QPlatformEventLoopIntegration; + +class QOpenKODEWindow : public QPlatformWindow +{ +public: + QOpenKODEWindow(QWidget *tlw); + ~QOpenKODEWindow(); + + void setGeometry(const QRect &rect); + void setVisible(bool visible); + WId winId() const; + + QPlatformGLContext *glContext() const; + + void raise(); + void lower(); + + void processKeyEvents( const KDEvent *event ); + void processMouseEvents( const KDEvent *event ); + +private: + struct KDWindow *m_kdWindow; + EGLNativeWindowType m_eglWindow; + EGLConfig m_eglConfig; + QVector<EGLint> m_eglWindowAttrs; + QVector<EGLint> m_eglContextAttrs; + EGLenum m_eglApi; + QEGLPlatformContext *m_platformGlContext; + + bool isFullScreen; +}; + +QT_END_NAMESPACE +QT_END_HEADER + +#endif //QOPENKODEWINDOW_H diff --git a/src/plugins/platforms/openkode/resources.qrc b/src/plugins/platforms/openkode/resources.qrc new file mode 100644 index 0000000..dbb3419 --- /dev/null +++ b/src/plugins/platforms/openkode/resources.qrc @@ -0,0 +1,6 @@ +<!DOCTYPE RCC><RCC version="1.0"> +<qresource> + <file>shaders/vert.glslv</file> + <file>shaders/frag.glslf</file> +</qresource> +</RCC> diff --git a/src/plugins/platforms/openkode/shaders/frag.glslf b/src/plugins/platforms/openkode/shaders/frag.glslf new file mode 100644 index 0000000..c768437 --- /dev/null +++ b/src/plugins/platforms/openkode/shaders/frag.glslf @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** +****************************************************************************/ + +uniform sampler2D tex_samp; + +varying vec2 texcoord_var; + +void main(void) +{ + gl_FragColor = texture2D(tex_samp, texcoord_var); +} diff --git a/src/plugins/platforms/openkode/shaders/vert.glslv b/src/plugins/platforms/openkode/shaders/vert.glslv new file mode 100644 index 0000000..8a64f4d --- /dev/null +++ b/src/plugins/platforms/openkode/shaders/vert.glslv @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2010 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$ +** +****************************************************************************/ + +uniform vec2 window; // window size + +// Per-vertex attributes] +attribute vec2 pos_attr; +attribute vec2 texcoord_attr; + +// Output vertex color +varying vec2 texcoord_var; + +void main() +{ + gl_Position = vec4( (2.0 * pos_attr / window -1.0) * vec2(1.0, -1.0), 0.0, 1.0); + texcoord_var = texcoord_attr; +} diff --git a/src/plugins/platforms/openvglite/main.cpp b/src/plugins/platforms/openvglite/main.cpp new file mode 100644 index 0000000..dc0b4a8 --- /dev/null +++ b/src/plugins/platforms/openvglite/main.cpp @@ -0,0 +1,71 @@ +/**************************************************************************** +** +** 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 <private/qgraphicssystemplugin_p.h> +#include "qgraphicssystem_vglite.h" + +QT_BEGIN_NAMESPACE + +class QVGGraphicsSystemPlugin : public QGraphicsSystemPlugin +{ +public: + QStringList keys() const; + QGraphicsSystem *create(const QString&); +}; + +QStringList QVGGraphicsSystemPlugin::keys() const +{ + QStringList list; + list << "OpenVG"; + return list; +} + +QGraphicsSystem* QVGGraphicsSystemPlugin::create(const QString& system) +{ + if (system.toLower() == "openvg") + return new QVGLiteGraphicsSystem; + + return 0; +} + +Q_EXPORT_PLUGIN2(openvg, QVGGraphicsSystemPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/openvglite/openvglite.pro b/src/plugins/platforms/openvglite/openvglite.pro new file mode 100644 index 0000000..9d7860a --- /dev/null +++ b/src/plugins/platforms/openvglite/openvglite.pro @@ -0,0 +1,12 @@ +TARGET = qvglitegraphicssystem +include(../../qpluginbase.pri) + +QT += openvg + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/graphicssystems + +SOURCES = main.cpp qgraphicssystem_vglite.cpp qwindowsurface_vglite.cpp +HEADERS = qgraphicssystem_vglite.h qwindowsurface_vglite.h + +target.path += $$[QT_INSTALL_PLUGINS]/graphicssystems +INSTALLS += target diff --git a/src/plugins/platforms/openvglite/qgraphicssystem_vglite.cpp b/src/plugins/platforms/openvglite/qgraphicssystem_vglite.cpp new file mode 100644 index 0000000..41b2303 --- /dev/null +++ b/src/plugins/platforms/openvglite/qgraphicssystem_vglite.cpp @@ -0,0 +1,193 @@ +/**************************************************************************** +** +** 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 "qgraphicssystem_vglite.h" +#include "qwindowsurface_vglite.h" +#include <QtOpenVG/private/qpixmapdata_vg_p.h> +#include <QtGui/private/qegl_p.h> +#include <QtCore/qdebug.h> +#ifdef OPENVG_USBHP_INIT +extern "C" { +#include <linuxusbhp.h> +}; +#endif + +QT_BEGIN_NAMESPACE + +QVGLiteGraphicsSystem::QVGLiteGraphicsSystem() + : w(0), h(0), d(0), dw(0), dh(0), physWidth(0), physHeight(0), + surface(0), context(0), rootWindow(0), + screenFormat(QImage::Format_RGB16), preservedSwap(false) +{ +#ifdef OPENVG_USBHP_INIT + initLibrary(); +#endif + + // The graphics system is also the screen definition. + mScreens.append(this); + + QString displaySpec = QString::fromLatin1(qgetenv("QWS_DISPLAY")); + QStringList displayArgs = displaySpec.split(QLatin1Char(':')); + + // Initialize EGL and create the global EGL context. + context = qt_vg_create_context(0); + if (!context) { + qFatal("QVGLiteGraphicsSystem: could not initialize EGL"); + return; + } + + // Get the root window handle to use. Default to zero. + QRegExp winidRx(QLatin1String("winid=?(\\d+)")); + int winidIdx = displayArgs.indexOf(winidRx); + int handle = 0; + if (winidIdx >= 0) { + winidRx.exactMatch(displayArgs.at(winidIdx)); + handle = winidRx.cap(1).toInt(); + } + + // Create a full-screen window based on the native handle. + // If the context is premultiplied, the window should be too. + QEglProperties props; +#ifdef EGL_VG_ALPHA_FORMAT_PRE_BIT + EGLint surfaceType = 0; + if (context->configAttrib(EGL_SURFACE_TYPE, &surfaceType) && + (surfaceType & EGL_VG_ALPHA_FORMAT_PRE_BIT) != 0) + props.setValue(EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE); +#endif + rootWindow = eglCreateWindowSurface + (context->display(), context->config(), + (EGLNativeWindowType)handle, props.properties()); + if (rootWindow == EGL_NO_SURFACE) { + delete context; + context = 0; + qFatal("QVGLiteGraphicsSystem: could not create full-screen window"); + return; + } + + // Try to turn on preserved swap behaviour on the root window. + // This will allow us to optimize compositing to focus on just + // the screen region that has changed. Otherwise we must + // re-composite the entire screen every frame. +#if !defined(QVG_NO_PRESERVED_SWAP) + eglGetError(); // Clear error state first. + eglSurfaceAttrib(context->display(), rootWindow, + EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED); + preservedSwap = (eglGetError() == EGL_SUCCESS); +#else + preservedSwap = false; +#endif + + // Fetch the root window properties. + eglQuerySurface(context->display(), rootWindow, EGL_WIDTH, &w); + eglQuerySurface(context->display(), rootWindow, EGL_HEIGHT, &h); + screenFormat = qt_vg_config_to_image_format(context); + switch (screenFormat) { + case QImage::Format_ARGB32_Premultiplied: + case QImage::Format_ARGB32: + case QImage::Format_RGB32: + default: + d = 32; + break; + case QImage::Format_RGB16: + case QImage::Format_ARGB4444_Premultiplied: + d = 16; + break; + } + dw = w; + dh = h; + qDebug("screen size: %dx%dx%d", w, h, d); + + // Handle display physical size spec. From qscreenlinuxfb_qws.cpp. + QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)")); + int dimIdxW = displayArgs.indexOf(mmWidthRx); + QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)")); + int dimIdxH = displayArgs.indexOf(mmHeightRx); + if (dimIdxW >= 0) { + mmWidthRx.exactMatch(displayArgs.at(dimIdxW)); + physWidth = mmWidthRx.cap(1).toInt(); + if (dimIdxH < 0) + physHeight = dh*physWidth/dw; + } + if (dimIdxH >= 0) { + mmHeightRx.exactMatch(displayArgs.at(dimIdxH)); + physHeight = mmHeightRx.cap(1).toInt(); + if (dimIdxW < 0) + physWidth = dw*physHeight/dh; + } + if (dimIdxW < 0 && dimIdxH < 0) { + const int dpi = 72; + physWidth = qRound(dw * 25.4 / dpi); + physHeight = qRound(dh * 25.4 / dpi); + } +} + +QVGLiteGraphicsSystem::~QVGLiteGraphicsSystem() +{ +} + +QPixmapData *QVGLiteGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const +{ +#if !defined(QVGLite_NO_SINGLE_CONTEXT) && !defined(QVGLite_NO_PIXMAP_DATA) + // Pixmaps can use QVGLitePixmapData; bitmaps must use raster. + if (type == QPixmapData::PixmapType) + return new QVGPixmapData(type); + else + return new QRasterPixmapData(type); +#else + return new QRasterPixmapData(type); +#endif +} + +QWindowSurface *QVGLiteGraphicsSystem::createWindowSurface(QWidget *widget) const +{ + if (widget->windowType() == Qt::Desktop) + return 0; // Don't create an explicit window surface for the destkop. + if (surface) { + qWarning() << "QVGLiteGraphicsSystem: only one window surface " + "is supported at a time"; + return 0; + } + surface = new QVGLiteWindowSurface + (const_cast<QVGLiteGraphicsSystem *>(this), widget); + return surface; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/openvglite/qgraphicssystem_vglite.h b/src/plugins/platforms/openvglite/qgraphicssystem_vglite.h new file mode 100644 index 0000000..512793d --- /dev/null +++ b/src/plugins/platforms/openvglite/qgraphicssystem_vglite.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSYSTEM_VGLITE_H +#define QGRAPHICSSYSTEM_VGLITE_H + +#include <QtGui/private/qgraphicssystem_p.h> +#include <QtGui/private/qegl_p.h> +#include <QtGui/qimage.h> + +QT_BEGIN_NAMESPACE + +class QVGLiteWindowSurface; + +class QVGLiteGraphicsSystem : public QGraphicsSystem, + public QGraphicsSystemScreen +{ +public: + QVGLiteGraphicsSystem(); + ~QVGLiteGraphicsSystem(); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QWindowSurface *createWindowSurface(QWidget *widget) const; + QList<QGraphicsSystemScreen *> screens() const { return mScreens; } + + QRect geometry() const { return QRect(0, 0, w, h); } + int depth() const { return d; } + QImage::Format format() const { return screenFormat; } + QSize physicalSize() const { return QSize(physWidth, physHeight); } + +private: + friend class QVGLiteWindowSurface; + + int w; + int h; + int d; + + int dw; + int dh; + + int physWidth; + int physHeight; + + mutable QVGLiteWindowSurface *surface; + QEglContext *context; + EGLSurface rootWindow; + QImage::Format screenFormat; + bool preservedSwap; + + QList<QGraphicsSystemScreen *> mScreens; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/openvglite/qwindowsurface_vglite.cpp b/src/plugins/platforms/openvglite/qwindowsurface_vglite.cpp new file mode 100644 index 0000000..c73e35a --- /dev/null +++ b/src/plugins/platforms/openvglite/qwindowsurface_vglite.cpp @@ -0,0 +1,131 @@ +/**************************************************************************** +** +** 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 "qwindowsurface_vglite.h" +#include "qgraphicssystem_vglite.h" +#include <QtOpenVG/qvg.h> +#include <QtOpenVG/private/qvg_p.h> +#include <QtOpenVG/private/qpaintengine_vg_p.h> + +QT_BEGIN_NAMESPACE + +QVGLiteWindowSurface::QVGLiteWindowSurface + (QVGLiteGraphicsSystem *gs, QWidget *window) + : QWindowSurface(window), graphicsSystem(gs), + isPaintingActive(false), engine(0) +{ +} + +QVGLiteWindowSurface::~QVGLiteWindowSurface() +{ + graphicsSystem->surface = 0; + if (engine) + qt_vg_destroy_paint_engine(engine); +} + +QPaintDevice *QVGLiteWindowSurface::paintDevice() +{ + qt_vg_make_current(graphicsSystem->context, graphicsSystem->rootWindow); + isPaintingActive = true; + // TODO: clear the parts of the back buffer that are not + // covered by the window surface to black. + return this; +} + +void QVGLiteWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(region); + Q_UNUSED(offset); + QEglContext *context = graphicsSystem->context; + if (context) { + if (!isPaintingActive) + qt_vg_make_current(context, graphicsSystem->rootWindow); + context->swapBuffers(); + qt_vg_done_current(context); + context->setSurface(EGL_NO_SURFACE); + isPaintingActive = false; + } +} + +void QVGLiteWindowSurface::setGeometry(const QRect &rect) +{ + QWindowSurface::setGeometry(rect); +} + +bool QVGLiteWindowSurface::scroll(const QRegion &area, int dx, int dy) +{ + return QWindowSurface::scroll(area, dx, dy); +} + +void QVGLiteWindowSurface::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +void QVGLiteWindowSurface::endPaint(const QRegion ®ion) +{ + Q_UNUSED(region); +} + +QPaintEngine *QVGLiteWindowSurface::paintEngine() const +{ + if (!engine) + engine = qt_vg_create_paint_engine(); + return engine; +} + +// We need to get access to QWidget::metric() from QVGLiteWindowSurface::metric, +// but it is not a friend of QWidget. To get around this, we create a +// fake QX11PaintEngine class, which is a friend. +class QX11PaintEngine +{ +public: + static int metric(const QWidget *widget, QPaintDevice::PaintDeviceMetric met) + { + return widget->metric(met); + } +}; + +int QVGLiteWindowSurface::metric(PaintDeviceMetric met) const +{ + return QX11PaintEngine::metric(window(), met); +} diff --git a/src/plugins/platforms/openvglite/qwindowsurface_vglite.h b/src/plugins/platforms/openvglite/qwindowsurface_vglite.h new file mode 100644 index 0000000..59faba8 --- /dev/null +++ b/src/plugins/platforms/openvglite/qwindowsurface_vglite.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_VGLITE_H +#define QWINDOWSURFACE_VGLITE_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtGui/private/qwindowsurface_p.h> +#include <QtGui/private/qegl_p.h> + +QT_BEGIN_NAMESPACE + +class QVGLiteGraphicsSystem; +class QVGPaintEngine; + +class Q_OPENVG_EXPORT QVGLiteWindowSurface : public QWindowSurface, public QPaintDevice +{ +public: + QVGLiteWindowSurface(QVGLiteGraphicsSystem *gs, QWidget *window); + ~QVGLiteWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void setGeometry(const QRect &rect); + bool scroll(const QRegion &area, int dx, int dy); + + void beginPaint(const QRegion ®ion); + void endPaint(const QRegion ®ion); + + QPaintEngine *paintEngine() const; + +protected: + int metric(PaintDeviceMetric metric) const; + +private: + QVGLiteGraphicsSystem *graphicsSystem; + bool isPaintingActive; + mutable QVGPaintEngine *engine; +}; + +QT_END_NAMESPACE + +#endif // QWINDOWSURFACE_VGLITE_H diff --git a/src/plugins/platforms/platforms.pro b/src/plugins/platforms/platforms.pro new file mode 100644 index 0000000..26ccd44 --- /dev/null +++ b/src/plugins/platforms/platforms.pro @@ -0,0 +1,4 @@ +TEMPLATE = subdirs + +SUBDIRS += minimal + diff --git a/src/plugins/platforms/qvfb/main.cpp b/src/plugins/platforms/qvfb/main.cpp new file mode 100644 index 0000000..997e544 --- /dev/null +++ b/src/plugins/platforms/qvfb/main.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 <QPlatformIntegrationPlugin> +#include "qvfbintegration.h" +#include <qstringlist.h> + +QT_BEGIN_NAMESPACE + +class QVFbIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QVFbIntegrationPlugin::keys() const +{ + QStringList list; + list << "QVFb"; + return list; +} + +QPlatformIntegration* QVFbIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "qvfb") + return new QVFbIntegration(paramList); + + return 0; +} + +Q_EXPORT_PLUGIN2(qvfb, QVFbIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/qvfb/qvfb.pro b/src/plugins/platforms/qvfb/qvfb.pro new file mode 100644 index 0000000..d2b332a --- /dev/null +++ b/src/plugins/platforms/qvfb/qvfb.pro @@ -0,0 +1,13 @@ +TARGET = qvfbintegration +include(../../qpluginbase.pri) + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + + +SOURCES = main.cpp qvfbintegration.cpp qvfbwindowsurface.cpp +HEADERS = qvfbintegration.h qvfbwindowsurface.h + +include(../fontdatabases/genericunix/genericunix.pri) + +target.path += $$[QT_INSTALL_PLUGINS]/platforms +INSTALLS += target diff --git a/src/plugins/platforms/qvfb/qvfbintegration.cpp b/src/plugins/platforms/qvfb/qvfbintegration.cpp new file mode 100644 index 0000000..0cc3938 --- /dev/null +++ b/src/plugins/platforms/qvfb/qvfbintegration.cpp @@ -0,0 +1,448 @@ +/**************************************************************************** +** +** 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 <stdlib.h> +#include <sys/types.h> +#include <sys/ipc.h> +#include <sys/shm.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <private/qcore_unix_p.h> // overrides QT_OPEN + +#include <qvfbhdr.h> +#include <qsocketnotifier.h> + +#include "qvfbintegration.h" +#include "qvfbwindowsurface.h" +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtCore/qdebug.h> +#include <QMouseEvent> + +#include <qsocketnotifier.h> +#include <QApplication> +#include <QWindowSystemInterface> + +#include "qgenericunixfontdatabase.h" + +QT_BEGIN_NAMESPACE + + +class QVFbScreenKeyboardHandler : public QObject +{ + Q_OBJECT +public: + QVFbScreenKeyboardHandler(int displayId); + ~QVFbScreenKeyboardHandler(); + +private slots: + void readKeyboardData(); + +private: + int kbdFD; + int kbdIdx; + int kbdBufferLen; + unsigned char *kbdBuffer; + QSocketNotifier *keyNotifier; +}; + +QVFbScreenKeyboardHandler::QVFbScreenKeyboardHandler(int displayId) +{ + const QString keyboardDev = QT_VFB_KEYBOARD_PIPE(displayId); + + + kbdFD = -1; + kbdIdx = 0; + kbdBufferLen = sizeof(QVFbKeyData) * 5; + kbdBuffer = new unsigned char [kbdBufferLen]; + + kbdFD = QT_OPEN(keyboardDev.toLatin1().constData(), O_RDWR | O_NDELAY); + + if (kbdFD == -1) { + perror("QVFbScreenKeyboardHandler"); + qWarning("QVFbScreenKeyboardHandler: Unable to open device %s", + qPrintable(keyboardDev)); + return; + } + + // Clear pending input + char buf[2]; + while (QT_READ(kbdFD, buf, 1) > 0) { } + + keyNotifier = new QSocketNotifier(kbdFD, QSocketNotifier::Read, this); + connect(keyNotifier, SIGNAL(activated(int)),this, SLOT(readKeyboardData())); + +} + +QVFbScreenKeyboardHandler::~QVFbScreenKeyboardHandler() +{ + if (kbdFD >= 0) + QT_CLOSE(kbdFD); + delete [] kbdBuffer; +} + + +void QVFbScreenKeyboardHandler::readKeyboardData() +{ + int n; + do { + n = QT_READ(kbdFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx); + if (n > 0) + kbdIdx += n; + } while (n > 0); + + int idx = 0; + while (kbdIdx - idx >= (int)sizeof(QVFbKeyData)) { + QVFbKeyData *kd = (QVFbKeyData *)(kbdBuffer + idx); + if (kd->unicode == 0 && kd->keycode == 0 && kd->modifiers == 0 && kd->press) { + // magic exit key + qWarning("Instructed to quit by Virtual Keyboard"); + qApp->quit(); + } + + //QWSServer::processKeyEvent(kd->unicode ? kd->unicode : 0xffff, kd->keycode, kd->modifiers, kd->press, kd->repeat); + + QEvent::Type type = kd->press ? QEvent::KeyPress : QEvent::KeyRelease; + + QString text; + if (kd->unicode && kd->unicode != 0xffff) + text += QChar(kd->unicode); + +// qDebug() << "readKeyboardData" << type << hex << kd->keycode << kd->modifiers << text; + + QWindowSystemInterface::handleKeyEvent(0, type, kd->keycode, kd->modifiers, text, kd->repeat, int(text.length())); + idx += sizeof(QVFbKeyData); + } + + int surplus = kbdIdx - idx; + for (int i = 0; i < surplus; i++) + kbdBuffer[i] = kbdBuffer[idx+i]; + kbdIdx = surplus; +} + + + + +class QVFbScreenMouseHandler : public QObject +{ + Q_OBJECT +public: + QVFbScreenMouseHandler(int displayId); + ~QVFbScreenMouseHandler(); + +private slots: + void readMouseData(); + +private: + int mouseFD; + int mouseIdx; + enum {mouseBufSize = 128}; + uchar mouseBuf[mouseBufSize]; + QSocketNotifier *mouseNotifier; + + int oldButtonState; +}; + +QVFbScreenMouseHandler::QVFbScreenMouseHandler(int displayId) +{ + QString mouseDev = QT_VFB_MOUSE_PIPE(displayId); + + mouseFD = QT_OPEN(mouseDev.toLatin1().constData(), O_RDWR | O_NDELAY); + + if (mouseFD == -1) { + perror("QVFbMouseHandler::QVFbMouseHandler"); + qWarning("QVFbMouseHander: Unable to open device %s", + qPrintable(mouseDev)); + return; + } + + // Clear pending input + char buf[2]; + while (QT_READ(mouseFD, buf, 1) > 0) { } + + mouseIdx = 0; + oldButtonState = 0; + mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read, this); + connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData())); +} + + +QVFbScreenMouseHandler::~QVFbScreenMouseHandler() +{ + if (mouseFD >= 0) + QT_CLOSE(mouseFD); +} + +void QVFbScreenMouseHandler::readMouseData() +{ + int n; + do { + n = QT_READ(mouseFD, mouseBuf+mouseIdx, mouseBufSize-mouseIdx); + if (n > 0) + mouseIdx += n; + } while (n > 0); + + int idx = 0; + static const int packetsize = sizeof(QPoint) + 2*sizeof(int); + while (mouseIdx-idx >= packetsize) { + uchar *mb = mouseBuf+idx; + QPoint mousePos = *reinterpret_cast<QPoint *>(mb); + mb += sizeof(QPoint); + int bstate = *reinterpret_cast<int *>(mb); + mb += sizeof(int); + //int wheel = *reinterpret_cast<int *>(mb); + + int button = bstate ^ oldButtonState; + QEvent::Type type = QEvent::MouseMove; + + if (button) { + type = (button & bstate) ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease; + } + QWindowSystemInterface::handleMouseEvent(0, mousePos, mousePos, Qt::MouseButtons(bstate)); + +// qDebug() << "readMouseData" << mousePos << button << bstate << oldButtonState << type; + + oldButtonState = bstate; + + idx += packetsize; + } + + int surplus = mouseIdx - idx; + for (int i = 0; i < surplus; i++) + mouseBuf[i] = mouseBuf[idx+i]; + mouseIdx = surplus; + +} + + +class QVFbScreenPrivate +{ +public: + QVFbScreenPrivate(int id) + : shmrgn(0), hdr(0), data(0), mouseHandler(0), keyboardHandler(0) + { + displayId = id; + connect(displayId); + } + + ~QVFbScreenPrivate() { disconnect(); } + void setDirty(const QRect &r); + + bool connect(int displayId); + void disconnect(); + + QImage *screenImage() { return &img; } + QSize screenSize() { return img.size(); } + + int depth() const { return img.depth(); } + QImage::Format format() const { return img.format(); } + +private: + unsigned char *shmrgn; + QVFbHeader *hdr; + uchar *data; + QVFbScreenMouseHandler *mouseHandler; + QVFbScreenKeyboardHandler *keyboardHandler; + int displayId; + + QImage img; +}; + + +void QVFbScreenPrivate::setDirty(const QRect &r) +{ + hdr->dirty = true; + hdr->update = hdr->update.united(r); +} + + +bool QVFbScreenPrivate::connect(int displayId) +{ + qDebug() << "QVFbScreenPrivate::connect" << displayId; + key_t key = ftok(QT_VFB_MOUSE_PIPE(displayId).toLatin1(), 'b'); + + if (key == -1) + return false; + + + int shmId = shmget(key, 0, 0); + if (shmId != -1) + shmrgn = (unsigned char *)shmat(shmId, 0, 0); + else + return false; + + if ((long)shmrgn == -1 || shmrgn == 0) { + qDebug("No shmrgn %ld", (long)shmrgn); + return false; + } + + hdr = (QVFbHeader *)shmrgn; + data = shmrgn + hdr->dataoffset; + + int w = hdr->width; + int h = hdr->height; + int d = hdr->depth; + int lstep = hdr->linestep; + + QImage::Format format = QImage::Format_Invalid; + if (d == 32) + format = QImage::Format_ARGB32_Premultiplied; + else if (d == 16) + format = QImage::Format_RGB16; + + + if (format == QImage::Format_Invalid) { + img = QImage(); + return false; + } + + img = QImage(data, w, h, lstep, format); + + qDebug("connected %dx%d %d bpp", w, h, d); + + + mouseHandler = new QVFbScreenMouseHandler(displayId); + keyboardHandler = new QVFbScreenKeyboardHandler(displayId); + return true; +} + +void QVFbScreenPrivate::disconnect() +{ + if ((long)shmrgn != -1 && shmrgn) { + shmdt((char*)shmrgn); + shmrgn = 0; + } + delete mouseHandler; + mouseHandler = 0; + delete keyboardHandler; + keyboardHandler = 0; +} + + +QVFbScreen::QVFbScreen(int id) +{ + d_ptr = new QVFbScreenPrivate(id); +} + + +QVFbScreen::~QVFbScreen() +{ + delete d_ptr; +} + +void QVFbScreen::setDirty(const QRect &rect) +{ + d_ptr->setDirty(rect); +} + + + +QRect QVFbScreen::geometry() const { + return QRect(QPoint(), d_ptr->screenSize()); +} + + +int QVFbScreen::depth() const +{ + return d_ptr->depth(); +} + +QImage::Format QVFbScreen::format() const +{ + return d_ptr->format(); +} + +QSize QVFbScreen::physicalSize() const { + return (d_ptr->screenSize()*254)/720; +} + +#if 0 +int QVFbScreen::linestep() const { + return d_ptr->screenImage() ? d_ptr->screenImage()->bytesPerLine() : 0; +} + +uchar *QVFbScreen::base() const { + return d_ptr->screenImage() ? d_ptr->screenImage()->bits() : 0; +} +#endif + +QImage *QVFbScreen::screenImage() +{ + return d_ptr->screenImage(); +} + +QVFbIntegration::QVFbIntegration(const QStringList ¶mList) + : mFontDb(new QGenericUnixFontDatabase()) +{ + int displayId = 0; + if (paramList.length() > 0) + displayId = paramList.at(0).toInt(); + + mPrimaryScreen = new QVFbScreen(displayId); + + mScreens.append(mPrimaryScreen); +} + +QPixmapData *QVFbIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QWindowSurface *QVFbIntegration::createWindowSurface(QWidget *widget, WId) const +{ + return new QVFbWindowSurface(mPrimaryScreen, widget); +} + + +QPlatformWindow *QVFbIntegration::createPlatformWindow(QWidget *widget, WId) const +{ + return new QVFbWindow(mPrimaryScreen, widget); +} + +QPlatformFontDatabase *QVFbIntegration::fontDatabase() const +{ + return mFontDb; +} + +QT_END_NAMESPACE + +#include "qvfbintegration.moc" diff --git a/src/plugins/platforms/qvfb/qvfbintegration.h b/src/plugins/platforms/qvfb/qvfbintegration.h new file mode 100644 index 0000000..198a45c --- /dev/null +++ b/src/plugins/platforms/qvfb/qvfbintegration.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSYSTEM_QVFB_H +#define QGRAPHICSSYSTEM_QVFB_H + +#include <QPlatformScreen> +#include <QPlatformIntegration> + +QT_BEGIN_NAMESPACE + + +class QVFbScreenPrivate; + +class QVFbScreen : public QPlatformScreen +{ +public: + QVFbScreen(int id); + ~QVFbScreen(); + + QRect geometry() const; + int depth() const; + QImage::Format format() const; + QSize physicalSize() const; + + QImage *screenImage(); + + void setDirty(const QRect &rect); + +public: + + QVFbScreenPrivate *d_ptr; +}; + +class QVFbIntegrationPrivate; + + +class QVFbIntegration : public QPlatformIntegration +{ +public: + QVFbIntegration(const QStringList ¶mList); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QList<QPlatformScreen *> screens() const { return mScreens; } + + QPlatformFontDatabase *fontDatabase() const; + +private: + QVFbScreen *mPrimaryScreen; + QList<QPlatformScreen *> mScreens; + QPlatformFontDatabase *mFontDb; +}; + + + +QT_END_NAMESPACE + + +#endif diff --git a/src/plugins/platforms/qvfb/qvfbwindowsurface.cpp b/src/plugins/platforms/qvfb/qvfbwindowsurface.cpp new file mode 100644 index 0000000..6699072 --- /dev/null +++ b/src/plugins/platforms/qvfb/qvfbwindowsurface.cpp @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** 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 "qvfbwindowsurface.h" +#include "qvfbintegration.h" +#include <QtCore/qdebug.h> +#include <QtGui/qpainter.h> +#include <private/qapplication_p.h> + +QT_BEGIN_NAMESPACE + +QVFbWindowSurface::QVFbWindowSurface(//QVFbIntegration *graphicsSystem, + QVFbScreen *screen, QWidget *window) + : QWindowSurface(window), + mScreen(screen) +{ +} + +QVFbWindowSurface::~QVFbWindowSurface() +{ +} + +QPaintDevice *QVFbWindowSurface::paintDevice() +{ + return mScreen->screenImage(); +} + +void QVFbWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) +{ + Q_UNUSED(widget); + Q_UNUSED(offset); + +// QRect rect = geometry(); +// QPoint topLeft = rect.topLeft(); + + mScreen->setDirty(region.boundingRect()); +} + +void QVFbWindowSurface::resize(const QSize&) +{ + +// any size you like as long as it's full-screen... + + QRect rect(mScreen->availableGeometry()); + QWindowSurface::resize(rect.size()); +} + + +QVFbWindow::QVFbWindow(QVFbScreen *screen, QWidget *window) + : QPlatformWindow(window), + mScreen(screen) +{ +} + + +void QVFbWindow::setGeometry(const QRect &) +{ + +// any size you like as long as it's full-screen... + + QRect rect(mScreen->availableGeometry()); + QWindowSystemInterface::handleGeometryChange(this->widget(), rect); + + QPlatformWindow::setGeometry(rect); +} + + + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/qvfb/qvfbwindowsurface.h b/src/plugins/platforms/qvfb/qvfbwindowsurface.h new file mode 100644 index 0000000..9228189 --- /dev/null +++ b/src/plugins/platforms/qvfb/qvfbwindowsurface.h @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_QVFB_H +#define QWINDOWSURFACE_QVFB_H + +#include <QtGui/private/qwindowsurface_p.h> +#include <QPlatformWindow> + +QT_BEGIN_NAMESPACE + +class QVFbIntegration; +class QVFbScreen; + +class QVFbWindowSurface : public QWindowSurface +{ +public: + QVFbWindowSurface(QVFbScreen *screen, QWidget *window); + ~QVFbWindowSurface(); + + QPaintDevice *paintDevice(); + void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); + void resize(const QSize &size); + +private: + QVFbScreen *mScreen; +}; + +class QVFbWindow : public QPlatformWindow +{ +public: + QVFbWindow(QVFbScreen *screen, QWidget *window); + void setGeometry(const QRect &rect); + +private: + QVFbScreen *mScreen; +}; + + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/testlite/main.cpp b/src/plugins/platforms/testlite/main.cpp new file mode 100644 index 0000000..2f6aa8b --- /dev/null +++ b/src/plugins/platforms/testlite/main.cpp @@ -0,0 +1,79 @@ +/**************************************************************************** +** +** 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 <QtGui/QPlatformIntegrationPlugin> +#include "qtestliteintegration.h" + +QT_BEGIN_NAMESPACE + +class QTestLiteIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList&); +}; + +QStringList QTestLiteIntegrationPlugin::keys() const +{ + QStringList list; + list << "TestLite"; +#ifndef QT_NO_OPENGL + list << "TestLiteGL"; +#endif + return list; +} + +QPlatformIntegration* QTestLiteIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "testlite") + return new QTestLiteIntegration; +#ifndef QT_NO_OPENGL + if (system.toLower() == "testlitegl") + return new QTestLiteIntegration(true); +#endif + + return 0; +} + +Q_EXPORT_PLUGIN2(testlite, QTestLiteIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qglxintegration.cpp b/src/plugins/platforms/testlite/qglxintegration.cpp new file mode 100644 index 0000000..e262d5b --- /dev/null +++ b/src/plugins/platforms/testlite/qglxintegration.cpp @@ -0,0 +1,370 @@ +/**************************************************************************** +** +** 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 <QDebug> +#include <QLibrary> +#include <QGLFormat> + +#include "qtestlitewindow.h" + +#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 QGLXGLContext::m_defaultSharedContextMutex(QMutex::Recursive); + +QVector<int> QGLXGLContext::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 QGLXGLContext::findConfig(const MyDisplay *xd, 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(xd->display,xd->screen,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(xd->display,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 *QGLXGLContext::findVisualInfo(const MyDisplay *xd, const QPlatformWindowFormat &format) +{ + GLXFBConfig config = QGLXGLContext::findConfig(xd,format); + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(xd->display,config); + return visualInfo; +} + +QPlatformWindowFormat QGLXGLContext::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 QGLXGLContext::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; +} + +QGLXGLContext::QGLXGLContext(Window window, MyDisplay *xd, const QPlatformWindowFormat &format) + : QPlatformGLContext() + , m_xd(xd) + , m_drawable((Drawable)window) + , m_context(0) +{ + + QPlatformGLContext *sharePlatformContext; + if (format.useDefaultSharedContext()) { + if (!QPlatformGLContext::defaultSharedContext()) { + if (m_defaultSharedContextMutex.tryLock()){ + createDefaultSharedContex(xd); + 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<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); + +#ifdef MYX11_DEBUG + qDebug() << "QGLXGLContext::create context" << m_context; +#endif +} + +QGLXGLContext::QGLXGLContext(MyDisplay *display, Drawable drawable, GLXContext context) + : QPlatformGLContext(), m_xd(display), m_drawable(drawable), m_context(context) +{ + +} + +QGLXGLContext::~QGLXGLContext() +{ + if (m_context) { + qDebug("Destroying GLX context 0x%p", m_context); + glXDestroyContext(m_xd->display, m_context); + } +} + +void QGLXGLContext::createDefaultSharedContex(MyDisplay *xd) +{ + int x = 0; + int y = 0; + int w = 3; + int h = 3; + + QPlatformWindowFormat format = QPlatformWindowFormat::defaultFormat(); + GLXContext context; + GLXFBConfig config = findConfig(xd,format); + if (config) { + XVisualInfo *visualInfo = glXGetVisualFromFBConfig(xd->display,config); + Colormap cmap = XCreateColormap(xd->display,xd->rootWindow(),visualInfo->visual,AllocNone); + XSetWindowAttributes a; + a.colormap = cmap; + Window sharedWindow = XCreateWindow(xd->display, xd->rootWindow(),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); + QPlatformGLContext::setDefaultSharedContext(sharedContext); + } else { + qWarning("Warning no shared context created"); + } +} + +void QGLXGLContext::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); +} + +void QGLXGLContext::doneCurrent() +{ + glXMakeCurrent(m_xd->display, 0, 0); +} + +void QGLXGLContext::swapBuffers() +{ + glXSwapBuffers(m_xd->display, m_drawable); +} + +void* QGLXGLContext::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_xd->display, 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 QGLXGLContext::platformWindowFormat() const +{ + return m_windowFormat; +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qglxintegration.h b/src/plugins/platforms/testlite/qglxintegration.h new file mode 100644 index 0000000..479be4b --- /dev/null +++ b/src/plugins/platforms/testlite/qglxintegration.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef Q_GLX_CONTEXT_H +#define Q_GLX_CONTEXT_H + +#include "qtestlitewindow.h" + +#include <QtGui/QPlatformGLContext> +#include <QtGui/QPlatformWindowFormat> + +#include <QtCore/QMutex> + +#include <GL/glx.h> + +QT_BEGIN_NAMESPACE + +class MyDisplay; + +class QGLXGLContext : public QPlatformGLContext +{ +public: + QGLXGLContext(Window window, MyDisplay *xd, const QPlatformWindowFormat &format); + ~QGLXGLContext(); + + virtual void makeCurrent(); + virtual void doneCurrent(); + virtual void swapBuffers(); + virtual void* getProcAddress(const QString& procName); + + GLXContext glxContext() {return m_context;} + + QPlatformWindowFormat platformWindowFormat() const; + + static XVisualInfo *findVisualInfo(const MyDisplay *xd, const QPlatformWindowFormat &format); +private: + static GLXFBConfig findConfig(const MyDisplay *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; + Drawable m_drawable; + GLXContext m_context; + QPlatformWindowFormat m_windowFormat; + + QGLXGLContext (MyDisplay *display, Drawable drawable, GLXContext context); + static QMutex m_defaultSharedContextMutex; + static void createDefaultSharedContex(MyDisplay *xd); +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/testlite/qtestliteintegration.cpp b/src/plugins/platforms/testlite/qtestliteintegration.cpp new file mode 100644 index 0000000..68e9051 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestliteintegration.cpp @@ -0,0 +1,153 @@ +/**************************************************************************** +** +** 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/qtestliteintegration.h b/src/plugins/platforms/testlite/qtestliteintegration.h new file mode 100644 index 0000000..8286ef0 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestliteintegration.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#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 + +class MyDisplay; + +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; } + +public: + QRect mGeometry; + int mDepth; + QImage::Format mFormat; + QSize mPhysicalSize; +}; + +class QTestLiteIntegration : public QPlatformIntegration +{ +public: + QTestLiteIntegration(bool useOpenGL = false); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QPixmap grabWindow(WId window, int x, int y, int width, int height) const; + + QList<QPlatformScreen *> screens() const { return mScreens; } + + QPlatformFontDatabase *fontDatabase() const; + + bool hasOpenGL() const; + + MyDisplay *xd; + +private: + bool mUseOpenGL; + QTestLiteScreen *mPrimaryScreen; + QList<QPlatformScreen *> mScreens; + QPlatformFontDatabase *mFontDb; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/testlite/qtestlitewindow.cpp b/src/plugins/platforms/testlite/qtestlitewindow.cpp new file mode 100644 index 0000000..1de4b9d --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitewindow.cpp @@ -0,0 +1,1587 @@ +/**************************************************************************** +** +** 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()); + XMapWindow(xd->display, x_window); +} + +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/qtestlitewindow.h b/src/plugins/platforms/testlite/qtestlitewindow.h new file mode 100644 index 0000000..dc628f1 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitewindow.h @@ -0,0 +1,157 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QTESTLITEWINDOW_H +#define QTESTLITEWINDOW_H + +#include <QPlatformWindow> +#include <qevent.h> + +#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(); + + Window rootWindow() { return RootWindow(display, screen); } + unsigned long blackPixel() { return BlackPixel(display, screen); } + unsigned long whitePixel() { return WhitePixel(display, screen); } + + bool handleEvent(XEvent *xe); + QImage grabWindow(Window window, int x, int y, int w, int h); + +public slots: + void eventDispatcher(); + +public: //### + Display * display; + int screen; + int width, height; + int physicalWidth; + int physicalHeight; + + QList<QTestLiteWindow*> windowList; + + MyX11Cursors * cursors; +}; + +struct MyShmImageInfo; + +class QTestLiteWindow : public QPlatformWindow +{ +public: + QTestLiteWindow(const QTestLiteIntegration *platformIntegration, + QTestLiteScreen *screen, QWidget *window); + ~QTestLiteWindow(); + + + void mousePressEvent(XButtonEvent*); + void handleMouseEvent(QEvent::Type, XButtonEvent *ev); + + void handleKeyEvent(QEvent::Type, void *); + void handleCloseEvent(); + void handleEnterEvent(); + void handleLeaveEvent(); + + void resizeEvent(XConfigureEvent *configure_event); + void paintEvent(); + + + void setGeometry(const QRect &rect); + + Qt::WindowFlags setWindowFlags(Qt::WindowFlags type); + Qt::WindowFlags windowFlags() const; + void setVisible(bool visible); + WId winId() const; + void setParent(const QPlatformWindow *window); + void raise(); + void lower(); + void setWindowTitle(const QString &title); + + void setCursor(QCursor * cursor); + + QPlatformGLContext *glContext() const; + +private: + int xpos, ypos; + int width, height; + 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 +}; + + + + + +#endif diff --git a/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp b/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp new file mode 100644 index 0000000..b3232c8 --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitewindowsurface.cpp @@ -0,0 +1,226 @@ +/**************************************************************************** +** +** 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 "qtestlitewindowsurface.h" +#include "qtestliteintegration.h" + +#include <QtCore/qdebug.h> +#include <QWindowSystemInterface> + +#include "qtestlitewindow.h" + +# include <sys/ipc.h> +# include <sys/shm.h> +# include <X11/extensions/XShm.h> + +QT_BEGIN_NAMESPACE + + +struct MyShmImageInfo { + MyShmImageInfo(Display *xdisplay) : image(0), display(xdisplay) {} + ~MyShmImageInfo() { destroy(); } + + void destroy(); + + XShmSegmentInfo shminfo; + XImage *image; + Display *display; +}; + +//void QTestLiteWindowSurface::flush() + + +#ifndef DONT_USE_MIT_SHM +void MyShmImageInfo::destroy() +{ + XShmDetach (display, &shminfo); + XDestroyImage (image); + shmdt (shminfo.shmaddr); + shmctl (shminfo.shmid, IPC_RMID, 0); +} +#endif + +void QTestLiteWindowSurface::resizeShmImage(int width, int height) +{ + MyDisplay *xd = xw->xd; + +#ifdef DONT_USE_MIT_SHM + shm_img = QImage(width, height, QImage::Format_RGB32); +#else + if (image_info) + image_info->destroy(); + else + image_info = new MyShmImageInfo(xd->display); + + Visual *visual = DefaultVisual(xd->display, xd->screen); + + + XImage *image = XShmCreateImage (xd->display, visual, 24, ZPixmap, 0, + &image_info->shminfo, width, height); + + + image_info->shminfo.shmid = shmget (IPC_PRIVATE, + image->bytes_per_line * image->height, IPC_CREAT|0777); + + image_info->shminfo.shmaddr = image->data = (char*)shmat (image_info->shminfo.shmid, 0, 0); + image_info->shminfo.readOnly = False; + + image_info->image = image; + + Status shm_attach_status = XShmAttach(xd->display, &image_info->shminfo); + + Q_ASSERT(shm_attach_status == True); + + shm_img = QImage( (uchar*) image->data, image->width, image->height, image->bytes_per_line, QImage::Format_RGB32 ); +#endif + painted = false; +} + + +void QTestLiteWindowSurface::resizeBuffer(QSize s) +{ + if (shm_img.size() != s) + resizeShmImage(s.width(), s.height()); +} + +QSize QTestLiteWindowSurface::bufferSize() const +{ + return shm_img.size(); +} + +QTestLiteWindowSurface::QTestLiteWindowSurface (QTestLiteScreen */*screen*/, QWidget *window) + : QWindowSurface(window), + painted(false), image_info(0) +{ + xw = static_cast<QTestLiteWindow*>(window->platformWindow()); +// qDebug() << "QTestLiteWindowSurface::QTestLiteWindowSurface:" << xw->window; +} + +QTestLiteWindowSurface::~QTestLiteWindowSurface() +{ + delete image_info; +} + +QPaintDevice *QTestLiteWindowSurface::paintDevice() +{ + return &shm_img; +} + + +void QTestLiteWindowSurface::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; +#ifdef DONT_USE_MIT_SHM + // just convert the image every time... + if (!shm_img.isNull()) { + Visual *visual = DefaultVisual(xd->display, xd->screen); + + QImage image = shm_img; + //img.convertToFormat( + XImage *xi = XCreateImage(xd->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()); + + xi->data = 0; // QImage owns these bits + XDestroyImage(xi); + } +#else + // Use MIT_SHM + if (image_info && image_info->image) { + //qDebug() << "Here we go" << image_info->image->width << image_info->image->height; + int x = 0; + int y = 0; + + // 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, + x, y, image_info->image->width, image_info->image->height, + /*send_event*/ False); + + XSync(xd->display, False); + } +#endif +} + +// 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) +{ + if (shm_img.isNull()) + return false; + + const QVector<QRect> rects = area.rects(); + for (int i = 0; i < rects.size(); ++i) + qt_scrollRectInImage(shm_img, rects.at(i), QPoint(dx, dy)); + + return true; +} + + +void QTestLiteWindowSurface::beginPaint(const QRegion ®ion) +{ + Q_UNUSED(region); + resizeBuffer(size()); +} + +void QTestLiteWindowSurface::endPaint(const QRegion ®ion) +{ + Q_UNUSED(region); + painted = true; //there is content in the buffer +} +QT_END_NAMESPACE diff --git a/src/plugins/platforms/testlite/qtestlitewindowsurface.h b/src/plugins/platforms/testlite/qtestlitewindowsurface.h new file mode 100644 index 0000000..915e7fe --- /dev/null +++ b/src/plugins/platforms/testlite/qtestlitewindowsurface.h @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QWINDOWSURFACE_TESTLITE_H +#define QWINDOWSURFACE_TESTLITE_H + +#include <QtGui/private/qwindowsurface_p.h> + + +QT_BEGIN_NAMESPACE + +class QTestLiteWindow; +class QTestLiteIntegration; +class QTestLiteScreen; +class MyShmImageInfo; + +class QTestLiteWindowSurface : public QWindowSurface +{ +public: + QTestLiteWindowSurface (QTestLiteScreen *screen, QWidget *window); + ~QTestLiteWindowSurface(); + + 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); + void endPaint(const QRegion ®ion); + +private: + bool painted; + void resizeBuffer(QSize); + QSize bufferSize() const; + + + void resizeShmImage(int width, int height); + + QImage shm_img; + MyShmImageInfo *image_info; + + QTestLiteWindow *xw; + +}; + + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/platforms/testlite/testlite.pro b/src/plugins/platforms/testlite/testlite.pro new file mode 100644 index 0000000..05bd384 --- /dev/null +++ b/src/plugins/platforms/testlite/testlite.pro @@ -0,0 +1,29 @@ +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/vnc/main.cpp b/src/plugins/platforms/vnc/main.cpp new file mode 100644 index 0000000..e051e2d --- /dev/null +++ b/src/plugins/platforms/vnc/main.cpp @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 "qvncintegration.h" +#include <qstringlist.h> +#include <QtGui/QPlatformIntegrationPlugin> + +QT_BEGIN_NAMESPACE + +class QVNCIntegrationPlugin : public QPlatformIntegrationPlugin +{ +public: + QStringList keys() const; + QPlatformIntegration *create(const QString&, const QStringList &); +}; + +QStringList QVNCIntegrationPlugin::keys() const +{ + QStringList list; + list << "VNC"; + return list; +} + +QPlatformIntegration* QVNCIntegrationPlugin::create(const QString& system, const QStringList& paramList) +{ + Q_UNUSED(paramList); + if (system.toLower() == "vnc") + return new QVNCIntegration(paramList); + + return 0; +} + +Q_EXPORT_PLUGIN2(vnc, QVNCIntegrationPlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/vnc/qvnccursor.cpp b/src/plugins/platforms/vnc/qvnccursor.cpp new file mode 100644 index 0000000..e83696d --- /dev/null +++ b/src/plugins/platforms/vnc/qvnccursor.cpp @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** 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 <QPainter> +#include <QTcpSocket> +#include <arpa/inet.h> +#include <QBitmap> +#include <QApplication> + +#include <QDebug> + +#include "qvnccursor.h" +#include "qvncserver.h" +#include "qvncintegration.h" + +QT_BEGIN_NAMESPACE + +QVNCCursor::QVNCCursor(QVNCServer * srvr, QVNCScreen *scr ) + :QPlatformSoftwareCursor(scr), useVncCursor(false), server(srvr) +{ +} + +void QVNCCursor::changeCursor(QCursor * widgetCursor, QWidget * widget) +{ + QPlatformSoftwareCursor::changeCursor(widgetCursor, widget); + if (useVncCursor) { + server->setDirtyCursor(); + } else { + setDirty(); + } +} + +void QVNCCursor::setCursorMode(bool vnc) +{ + if (vnc) { + setDirty(); + server->setDirtyCursor(); + } else { + server->setDirtyCursor(); + } + useVncCursor = vnc; +} + +QRect QVNCCursor::drawCursor(QPainter & painter) +{ + if (useVncCursor) + return QRect(); + + return QPlatformSoftwareCursor::drawCursor(painter); +} + +void QVNCCursor::clearClientCursor() +{ + QTcpSocket *socket = server->clientSocket(); + if (!socket) { + return; + } + // FramebufferUpdate header + { + const quint16 tmp[6] = { htons(0), + htons(1), + htons(0), htons(0), + htons(0), + htons(0) }; + socket->write((char*)tmp, sizeof(tmp)); + + const quint32 encoding = htonl(-239); + socket->write((char*)(&encoding), sizeof(encoding)); + } +} + +void QVNCCursor::sendClientCursor() +{ + if (useVncCursor == false) { + clearClientCursor(); + return; + } + QImage *image = graphic->image(); + if (image->isNull()) + return; + QTcpSocket *socket = server->clientSocket(); + if (!socket) { + return; + } + // FramebufferUpdate header + { + const quint16 tmp[6] = { htons(0), + htons(1), + htons(graphic->hotspot().x()), htons(graphic->hotspot().y()), + htons(image->width()), + htons(image->height()) }; + socket->write((char*)tmp, sizeof(tmp)); + + const quint32 encoding = htonl(-239); + socket->write((char*)(&encoding), sizeof(encoding)); + } + + // write pixels + //Q_ASSERT(cursor->hasAlphaChannel()); + const QImage img = image->convertToFormat(QImage::Format_RGB32); + const int n = server->clientBytesPerPixel() * img.width(); + char *buffer = new char[n]; + for (int i = 0; i < img.height(); ++i) { + server->convertPixels(buffer, (const char*)img.scanLine(i), img.width()); + socket->write(buffer, n); + } + delete[] buffer; + + // write mask + const QImage bitmap = image->createAlphaMask().convertToFormat(QImage::Format_Mono); + Q_ASSERT(bitmap.depth() == 1); + Q_ASSERT(bitmap.size() == img.size()); + const int width = (bitmap.width() + 7) / 8; + for (int i = 0; i < bitmap.height(); ++i) + socket->write((const char*)bitmap.scanLine(i), width); +} + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/vnc/qvnccursor.h b/src/plugins/platforms/vnc/qvnccursor.h new file mode 100644 index 0000000..eeb3686 --- /dev/null +++ b/src/plugins/platforms/vnc/qvnccursor.h @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ +#ifndef QVNCCURSOR_H +#define QVNCCURSOR_H + +#include "../fb_base/fb_base.h" +#include <QList> +#include <QImage> +#include <QMouseEvent> + +QT_BEGIN_NAMESPACE + +class QVNCScreen; +class QVNCServer; + +class QVNCCursor : public QPlatformSoftwareCursor { +public: + QVNCCursor(QVNCServer *, QVNCScreen *); + + // input methods + void setCursorMode(bool vnc); + void changeCursor(QCursor * widgetCursor, QWidget * widget); + + // output methods + QRect drawCursor(QPainter &); + + // VNC client communication + void sendClientCursor(); + void clearClientCursor(); +private: + bool useVncCursor; // VNC or local + + QVNCServer * server; // VNC server to get events from +}; + +QT_END_NAMESPACE + +#endif // QVNCCURSOR_H diff --git a/src/plugins/platforms/vnc/qvncintegration.cpp b/src/plugins/platforms/vnc/qvncintegration.cpp new file mode 100644 index 0000000..b36ff33 --- /dev/null +++ b/src/plugins/platforms/vnc/qvncintegration.cpp @@ -0,0 +1,242 @@ +/**************************************************************************** +** +** 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 "qvncintegration.h" +#include "../fb_base/fb_base.h" +#include <private/qapplication_p.h> +#include <QtGui/private/qpixmap_raster_p.h> +#include <QtCore/qdebug.h> + +#include <qvncserver.h> +#include <QtGui/QPainter> + +#include <QtCore/QTimer> +#include "qgenericunixfontdatabase.h" + +QVNCScreen::QVNCScreen(QRect screenSize, int screenId) + : QFbScreen::QFbScreen() +{ + setGeometry(screenSize); + setDepth(32); + setFormat(QImage::Format_RGB32); + setPhysicalSize((geometry().size()*254)/720); + + + d_ptr = new QVNCScreenPrivate(this, screenId); + + cursor = new QVNCCursor(d_ptr->vncServer, this); + d_ptr->vncServer->setCursor(static_cast<QVNCCursor *>(cursor)); +} + +QVNCDirtyMap *QVNCScreen::dirtyMap() +{ + return d_ptr->dirty; +} + +QRegion QVNCScreen::doRedraw() +{ + QRegion touched; + touched = QFbScreen::doRedraw(); + + QVector<QRect> rects = touched.rects(); + for (int i = 0; i < rects.size(); i++) + d_ptr->setDirty(rects[i]); + return touched; +} + +static inline int defaultWidth() { return 800; } +static inline int defaultHeight() { return 600; } +static inline int defaultDisplay() { return 0; } + +static void usage() +{ + qWarning() << "VNC Platform Integration options:"; + qWarning() << " size=<Width>x<Height> - set the display width and height"; + qWarning() << " defaults to" << defaultWidth() << "x" << defaultHeight(); + qWarning() << " display=<ID> - set the VNC display port to ID + 5900"; + qWarning() << " defaults to" << defaultDisplay(); + qWarning() << " offset=<X>x<Y> - set the current screens offset"; + qWarning() << " vnc - start configuration of a new screen"; + qWarning() << " size and offset are inherited from the previous screen if not set"; + qWarning() << " display id is incremented from the previous screen if not set"; + qWarning() << " virtual - manage the set of screens as a virtual desktop"; +} + +QVNCIntegration::QVNCIntegration(const QStringList& paramList) + : virtualDesktop(false), fontDb(new QGenericUnixFontDatabase()) +{ + int sizeX = defaultWidth(); + int sizeY = defaultHeight(); + int offsetX = 0; + int offsetY = 0; + int display = defaultDisplay(); + bool showUsage = false; + + foreach(QString confString, paramList) { + if (confString.startsWith(QLatin1String("size="))) { + QString val = confString.section(QLatin1Char('='), 1, 1); + sizeX = val.section(QLatin1Char('x'), 0, 0).toInt(); + sizeY = val.section(QLatin1Char('x'), 1, 1).toInt(); + } + else if (confString.startsWith(QLatin1String("display="))) { + display = confString.section(QLatin1Char('='), 1, 1).toInt(); + } + else if (confString.startsWith(QLatin1String("offset="))) { + QString val = confString.section(QLatin1Char('='), 1, 1); + offsetX = val.section(QLatin1Char('x'), 0, 0).toInt(); + offsetY = val.section(QLatin1Char('x'), 1, 1).toInt(); + } + else if (confString == QLatin1String("vnc")) { + QRect screenRect(offsetX, offsetY, sizeX, sizeY); + QVNCScreen *screen = new QVNCScreen(screenRect, display); + mScreens.append(screen); + screen->setObjectName(QString("screen %1").arg(display)); + screen->setDirty(screenRect); + ++display; + } + else if (confString == QLatin1String("virtual")) { + virtualDesktop = true; + } + else { + qWarning() << "Unknown VNC option:" << confString; + showUsage = true; + } + } + + if (showUsage) + usage(); + + QRect screenRect(offsetX, offsetY, sizeX, sizeY); + QVNCScreen *screen = new QVNCScreen(screenRect, display); + mScreens.append(screen); + mPrimaryScreen = qobject_cast<QVNCScreen *>(mScreens.first()); + screen->setObjectName(QString("screen %1").arg(display)); + screen->setDirty(screenRect); +} + +QPixmapData *QVNCIntegration::createPixmapData(QPixmapData::PixelType type) const +{ + return new QRasterPixmapData(type); +} + +QWindowSurface *QVNCIntegration::createWindowSurface(QWidget *widget, WId) const +{ + QFbWindowSurface * surface; + surface = new QFbWindowSurface(mPrimaryScreen, widget); + return surface; +} + + +QPlatformWindow *QVNCIntegration::createPlatformWindow(QWidget *widget, WId /*winId*/) const +{ + QFbWindow *w = new QFbWindow(widget); + if (virtualDesktop) { + QList<QPlatformScreen *>::const_iterator i = mScreens.constBegin(); + QList<QPlatformScreen *>::const_iterator end = mScreens.constEnd(); + QFbScreen *screen; + while (i != end) { + screen = static_cast<QFbScreen *>(*i); + screen->addWindow(w); + ++i; + } + } + else + mPrimaryScreen->addWindow(w); + return w; +} + +QPixmap QVNCIntegration::grabWindow(WId window, int x, int y, int width, int height) const +{ +// qDebug() << "QVNCIntegration::grabWindow" << window << x << y << width << height; + + if (window == 0) { //desktop + QImage *desktopImage = mPrimaryScreen->image(); + if (x==0 && y == 0 && width < 0 && height < 0) { + return QPixmap::fromImage(*desktopImage); + } + if (width < 0) + width = desktopImage->width() - x; + if (height < 0) + height = desktopImage->height() - y; + int bytesPerPixel = desktopImage->depth()/8; //We don't support 1, 2, or 4 bpp + QImage img(desktopImage->scanLine(y) + bytesPerPixel*x, width, height, desktopImage->bytesPerLine(), desktopImage->format()); + return QPixmap::fromImage(img); + } + QWidget *win = QWidget::find(window); + if (win) { + QRect r = win->geometry(); + if (width < 0) + width = r.width() - x; + if (height < 0) + height = r.height() - y; + QImage *desktopImage = mPrimaryScreen->image(); + int bytesPerPixel = desktopImage->depth()/8; //We don't support 1, 2, or 4 bpp + + QImage img(desktopImage->scanLine(r.top() + y) + bytesPerPixel*(r.left()+x), width, height, desktopImage->bytesPerLine(), desktopImage->format()); + return QPixmap::fromImage(img); + } + return QPixmap(); +} + + +void QVNCIntegration::moveToScreen(QWidget *window, int screen) +{ + if (virtualDesktop) { // all windows exist on all screens in virtual desktop mode + return; + } + if (screen < 0 || screen > mScreens.size()) + return; + QVNCScreen * newScreen = qobject_cast<QVNCScreen *>(mScreens.at(screen)); + for(int i = 0; i < mScreens.size(); i++) { + QVNCScreen *oldScreen = qobject_cast<QVNCScreen *>(mScreens.at(i)); + if (oldScreen->windowStack.contains(static_cast<QFbWindow *>(window->platformWindow()))) { + oldScreen->removeWindow(static_cast<QFbWindow *>(window->platformWindow())); + break; + } + } + window->platformWindow()->setGeometry(window->geometry()); // this should be unified elsewhere + newScreen->addWindow(static_cast<QFbWindow *>(window->platformWindow())); +} + +QPlatformFontDatabase *QVNCIntegration::fontDatabase() const +{ + return fontDb; +} diff --git a/src/plugins/platforms/vnc/qvncintegration.h b/src/plugins/platforms/vnc/qvncintegration.h new file mode 100644 index 0000000..dfc0e6b --- /dev/null +++ b/src/plugins/platforms/vnc/qvncintegration.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QGRAPHICSSYSTEM_VNC_H +#define QGRAPHICSSYSTEM_VNC_H + +#include "qvnccursor.h" +#include "../fb_base/fb_base.h" +#include <QPlatformIntegration> +#include "qgenericunixfontdatabase.h" + +QT_BEGIN_NAMESPACE + +class QVNCServer; +class QVNCDirtyMap; + +class QVNCScreenPrivate; + +class QVNCScreen : public QFbScreen +{ + Q_OBJECT +public: + QVNCScreen(QRect screenSize, int screenId); + + int linestep() const { return image() ? image()->bytesPerLine() : 0; } + uchar *base() const { return image() ? image()->bits() : 0; } + QVNCDirtyMap *dirtyMap(); + +public: + QVNCScreenPrivate *d_ptr; + +private: + QVNCServer *server; + QRegion doRedraw(); + friend class QVNCIntegration; +}; + +class QVNCIntegrationPrivate; + + +class QVNCIntegration : public QPlatformIntegration +{ +public: + QVNCIntegration(const QStringList& paramList); + + QPixmapData *createPixmapData(QPixmapData::PixelType type) const; + QPlatformWindow *createPlatformWindow(QWidget *widget, WId winId) const; + QWindowSurface *createWindowSurface(QWidget *widget, WId winId) const; + + QPixmap grabWindow(WId window, int x, int y, int width, int height) const; + + QList<QPlatformScreen *> screens() const { return mScreens; } + + bool isVirtualDesktop() { return virtualDesktop; } + void moveToScreen(QWidget *window, int screen); + + QPlatformFontDatabase *fontDatabase() const; + +private: + QVNCScreen *mPrimaryScreen; + QList<QPlatformScreen *> mScreens; + bool virtualDesktop; + QPlatformFontDatabase *fontDb; +}; + + + +QT_END_NAMESPACE + +#endif //QGRAPHICSSYSTEM_VNC_H + diff --git a/src/plugins/platforms/vnc/qvncserver.cpp b/src/plugins/platforms/vnc/qvncserver.cpp new file mode 100644 index 0000000..288d1bc --- /dev/null +++ b/src/plugins/platforms/vnc/qvncserver.cpp @@ -0,0 +1,1935 @@ +/**************************************************************************** +** +** 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 "qvncserver.h" + +#include <QtCore/qtimer.h> +#include <QtCore/qregexp.h> +#include <QtGui/qwidget.h> +#include <QtGui/qpolygon.h> +#include <QtGui/qpainter.h> + +#include <QtGui/qevent.h> +#include <QWindowSystemInterface> + +#include <qplatformdefs.h> + +#include <qdebug.h> + +#include <stdlib.h> + + +#define QT_QWS_VNC_DEBUG +#define QT_NO_QWS_CURSOR //### + + +QT_BEGIN_NAMESPACE + + + +//copied from qscreen_qws.h +#ifndef QT_QWS_DEPTH16_RGB +#define QT_QWS_DEPTH16_RGB 565 +#endif +static const int qt_rbits = (QT_QWS_DEPTH16_RGB/100); +static const int qt_gbits = (QT_QWS_DEPTH16_RGB/10%10); +static const int qt_bbits = (QT_QWS_DEPTH16_RGB%10); +static const int qt_red_shift = qt_bbits+qt_gbits-(8-qt_rbits); +static const int qt_green_shift = qt_bbits-(8-qt_gbits); +static const int qt_neg_blue_shift = 8-qt_bbits; +static const int qt_blue_mask = (1<<qt_bbits)-1; +static const int qt_green_mask = (1<<(qt_gbits+qt_bbits))-(1<<qt_bbits); +static const int qt_red_mask = (1<<(qt_rbits+qt_gbits+qt_bbits))-(1<<(qt_gbits+qt_bbits)); + +static const int qt_red_rounding_shift = qt_red_shift + qt_rbits; +static const int qt_green_rounding_shift = qt_green_shift + qt_gbits; +static const int qt_blue_rounding_shift = qt_bbits - qt_neg_blue_shift; + + +inline QRgb qt_conv16ToRgb(ushort c) +{ + const int r=(c & qt_red_mask); + const int g=(c & qt_green_mask); + const int b=(c & qt_blue_mask); + const int tr = r >> qt_red_shift | r >> qt_red_rounding_shift; + const int tg = g >> qt_green_shift | g >> qt_green_rounding_shift; + const int tb = b << qt_neg_blue_shift | b >> qt_blue_rounding_shift; + + return qRgb(tr,tg,tb); +} + + + +//=========================================================================== + +static const struct { + int keysym; + int keycode; +} keyMap[] = { + { 0xff08, Qt::Key_Backspace }, + { 0xff09, Qt::Key_Tab }, + { 0xff0d, Qt::Key_Return }, + { 0xff1b, Qt::Key_Escape }, + { 0xff63, Qt::Key_Insert }, + { 0xffff, Qt::Key_Delete }, + { 0xff50, Qt::Key_Home }, + { 0xff57, Qt::Key_End }, + { 0xff55, Qt::Key_PageUp }, + { 0xff56, Qt::Key_PageDown }, + { 0xff51, Qt::Key_Left }, + { 0xff52, Qt::Key_Up }, + { 0xff53, Qt::Key_Right }, + { 0xff54, Qt::Key_Down }, + { 0xffbe, Qt::Key_F1 }, + { 0xffbf, Qt::Key_F2 }, + { 0xffc0, Qt::Key_F3 }, + { 0xffc1, Qt::Key_F4 }, + { 0xffc2, Qt::Key_F5 }, + { 0xffc3, Qt::Key_F6 }, + { 0xffc4, Qt::Key_F7 }, + { 0xffc5, Qt::Key_F8 }, + { 0xffc6, Qt::Key_F9 }, + { 0xffc7, Qt::Key_F10 }, + { 0xffc8, Qt::Key_F11 }, + { 0xffc9, Qt::Key_F12 }, + { 0xffe1, Qt::Key_Shift }, + { 0xffe2, Qt::Key_Shift }, + { 0xffe3, Qt::Key_Control }, + { 0xffe4, Qt::Key_Control }, + { 0xffe7, Qt::Key_Meta }, + { 0xffe8, Qt::Key_Meta }, + { 0xffe9, Qt::Key_Alt }, + { 0xffea, Qt::Key_Alt }, + { 0, 0 } +}; + +void QRfbRect::read(QTcpSocket *s) +{ + quint16 buf[4]; + s->read((char*)buf, 8); + x = ntohs(buf[0]); + y = ntohs(buf[1]); + w = ntohs(buf[2]); + h = ntohs(buf[3]); +} + +void QRfbRect::write(QTcpSocket *s) const +{ + quint16 buf[4]; + buf[0] = htons(x); + buf[1] = htons(y); + buf[2] = htons(w); + buf[3] = htons(h); + s->write((char*)buf, 8); +} + +void QRfbPixelFormat::read(QTcpSocket *s) +{ + char buf[16]; + s->read(buf, 16); + bitsPerPixel = buf[0]; + depth = buf[1]; + bigEndian = buf[2]; + trueColor = buf[3]; + + quint16 a = ntohs(*(quint16 *)(buf + 4)); + redBits = 0; + while (a) { a >>= 1; redBits++; } + + a = ntohs(*(quint16 *)(buf + 6)); + greenBits = 0; + while (a) { a >>= 1; greenBits++; } + + a = ntohs(*(quint16 *)(buf + 8)); + blueBits = 0; + while (a) { a >>= 1; blueBits++; } + + redShift = buf[10]; + greenShift = buf[11]; + blueShift = buf[12]; +} + +void QRfbPixelFormat::write(QTcpSocket *s) +{ + char buf[16]; + buf[0] = bitsPerPixel; + buf[1] = depth; + buf[2] = bigEndian; + buf[3] = trueColor; + + quint16 a = 0; + for (int i = 0; i < redBits; i++) a = (a << 1) | 1; + *(quint16 *)(buf + 4) = htons(a); + + a = 0; + for (int i = 0; i < greenBits; i++) a = (a << 1) | 1; + *(quint16 *)(buf + 6) = htons(a); + + a = 0; + for (int i = 0; i < blueBits; i++) a = (a << 1) | 1; + *(quint16 *)(buf + 8) = htons(a); + + buf[10] = redShift; + buf[11] = greenShift; + buf[12] = blueShift; + s->write(buf, 16); +} + + +void QRfbServerInit::setName(const char *n) +{ + delete[] name; + name = new char [strlen(n) + 1]; + strcpy(name, n); +} + +void QRfbServerInit::read(QTcpSocket *s) +{ + s->read((char *)&width, 2); + width = ntohs(width); + s->read((char *)&height, 2); + height = ntohs(height); + format.read(s); + + quint32 len; + s->read((char *)&len, 4); + len = ntohl(len); + + name = new char [len + 1]; + s->read(name, len); + name[len] = '\0'; +} + +void QRfbServerInit::write(QTcpSocket *s) +{ + quint16 t = htons(width); + s->write((char *)&t, 2); + t = htons(height); + s->write((char *)&t, 2); + format.write(s); + quint32 len = strlen(name); + len = htonl(len); + s->write((char *)&len, 4); + s->write(name, strlen(name)); +} + +bool QRfbSetEncodings::read(QTcpSocket *s) +{ + if (s->bytesAvailable() < 3) + return false; + + char tmp; + s->read(&tmp, 1); // padding + s->read((char *)&count, 2); + count = ntohs(count); + + return true; +} + +bool QRfbFrameBufferUpdateRequest::read(QTcpSocket *s) +{ + if (s->bytesAvailable() < 9) + return false; + + s->read(&incremental, 1); + rect.read(s); + + return true; +} + +bool QRfbKeyEvent::read(QTcpSocket *s) +{ + if (s->bytesAvailable() < 7) + return false; + + s->read(&down, 1); + quint16 tmp; + s->read((char *)&tmp, 2); // padding + + quint32 key; + s->read((char *)&key, 4); + key = ntohl(key); + + unicode = 0; + keycode = 0; + int i = 0; + while (keyMap[i].keysym && !keycode) { + if (keyMap[i].keysym == (int)key) + keycode = keyMap[i].keycode; + i++; + } + if (!keycode) { + if (key <= 0xff) { + unicode = key; + if (key >= 'a' && key <= 'z') + keycode = Qt::Key_A + key - 'a'; + else if (key >= ' ' && key <= '~') + keycode = Qt::Key_Space + key - ' '; + } + } + + return true; +} + +bool QRfbPointerEvent::read(QTcpSocket *s) +{ + if (s->bytesAvailable() < 5) + return false; + + char buttonMask; + s->read(&buttonMask, 1); + + buttons = Qt::NoButton; + wheelDirection = WheelNone; + if (buttonMask & 1) + buttons |= Qt::LeftButton; + if (buttonMask & 2) + buttons |= Qt::MidButton; + if (buttonMask & 4) + buttons |= Qt::RightButton; + if (buttonMask & 8) + wheelDirection = WheelUp; + if (buttonMask & 16) + wheelDirection = WheelDown; + if (buttonMask & 32) + wheelDirection = WheelLeft; + if (buttonMask & 64) + wheelDirection = WheelRight; + + quint16 tmp; + s->read((char *)&tmp, 2); + x = ntohs(tmp); + s->read((char *)&tmp, 2); + y = ntohs(tmp); + + return true; +} + +bool QRfbClientCutText::read(QTcpSocket *s) +{ + if (s->bytesAvailable() < 7) + return false; + + char tmp[3]; + s->read(tmp, 3); // padding + s->read((char *)&length, 4); + length = ntohl(length); + + return true; +} + +//=========================================================================== + +QVNCServer::QVNCServer(QVNCScreen *screen) + : qvnc_screen(screen), cursor(0) +{ + init(5900); +} + +QVNCServer::QVNCServer(QVNCScreen *screen, int id) + : qvnc_screen(screen), cursor(0) +{ + init(5900 + id); +} + +void QVNCServer::init(uint port) +{ + qDebug() << "QVNCServer::init" << port; + + handleMsg = false; + client = 0; + encodingsPending = 0; + cutTextPending = 0; + keymod = 0; + state = Unconnected; + dirtyCursor = false; + + refreshRate = 25; + timer = new QTimer(this); + timer->setSingleShot(true); + connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate())); + + serverSocket = new QTcpServer(this); + if (!serverSocket->listen(QHostAddress::Any, port)) + qDebug() << "QVNCServer could not connect:" << serverSocket->errorString(); + else + qDebug("QVNCServer created on port %d", port); + + connect(serverSocket, SIGNAL(newConnection()), this, SLOT(newConnection())); + +#ifndef QT_NO_QWS_CURSOR + qvnc_cursor = 0; +#endif + encoder = 0; +} + +QVNCServer::~QVNCServer() +{ + delete encoder; + encoder = 0; + delete client; + client = 0; +#ifndef QT_NO_QWS_CURSOR + delete qvnc_cursor; + qvnc_cursor = 0; +#endif +} + +void QVNCServer::setDirty() +{ + if (state == Connected && !timer->isActive() && + ((dirtyMap()->numDirty > 0) || dirtyCursor)) { + timer->start(); + } +} + +void QVNCServer::newConnection() +{ + if (client) + delete client; + + client = serverSocket->nextPendingConnection(); + connect(client,SIGNAL(readyRead()),this,SLOT(readClient())); + connect(client,SIGNAL(disconnected()),this,SLOT(discardClient())); + handleMsg = false; + encodingsPending = 0; + cutTextPending = 0; + supportHextile = false; + wantUpdate = false; + + timer->start(1000 / refreshRate); + dirtyMap()->reset(); + + // send protocol version + const char *proto = "RFB 003.003\n"; + client->write(proto, 12); + state = Protocol; + +// if (!qvnc_screen->screen()) +// QWSServer::instance()->enablePainting(true); +} + +void QVNCServer::readClient() +{ + switch (state) { + case Protocol: + if (client->bytesAvailable() >= 12) { + char proto[13]; + client->read(proto, 12); + proto[12] = '\0'; + qDebug("Client protocol version %s", proto); + // No authentication + quint32 auth = htonl(1); + client->write((char *) &auth, sizeof(auth)); + state = Init; + } + break; + + case Init: + if (client->bytesAvailable() >= 1) { + quint8 shared; + client->read((char *) &shared, 1); + + // Server Init msg + QRfbServerInit sim; + QRfbPixelFormat &format = sim.format; + switch (qvnc_screen->depth()) { + case 32: + format.bitsPerPixel = 32; + format.depth = 32; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 8; + format.greenBits = 8; + format.blueBits = 8; + format.redShift = 16; + format.greenShift = 8; + format.blueShift = 0; + break; + + case 24: + format.bitsPerPixel = 24; + format.depth = 24; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 8; + format.greenBits = 8; + format.blueBits = 8; + format.redShift = 16; + format.greenShift = 8; + format.blueShift = 0; + break; + + case 18: + format.bitsPerPixel = 24; + format.depth = 18; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 6; + format.greenBits = 6; + format.blueBits = 6; + format.redShift = 12; + format.greenShift = 6; + format.blueShift = 0; + break; + + case 16: + format.bitsPerPixel = 16; + format.depth = 16; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 5; + format.greenBits = 6; + format.blueBits = 5; + format.redShift = 11; + format.greenShift = 5; + format.blueShift = 0; + break; + + case 15: + format.bitsPerPixel = 16; + format.depth = 15; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 5; + format.greenBits = 5; + format.blueBits = 5; + format.redShift = 10; + format.greenShift = 5; + format.blueShift = 0; + break; + + case 12: + format.bitsPerPixel = 16; + format.depth = 12; + format.bigEndian = 0; + format.trueColor = true; + format.redBits = 4; + format.greenBits = 4; + format.blueBits = 4; + format.redShift = 8; + format.greenShift = 4; + format.blueShift = 0; + break; + + case 8: + case 4: + format.bitsPerPixel = 8; + format.depth = 8; + format.bigEndian = 0; + format.trueColor = false; + format.redBits = 0; + format.greenBits = 0; + format.blueBits = 0; + format.redShift = 0; + format.greenShift = 0; + format.blueShift = 0; + break; + + default: + qDebug("QVNC cannot drive depth %d", qvnc_screen->depth()); + discardClient(); + return; + } + sim.width = qvnc_screen->geometry().width(); + sim.height = qvnc_screen->geometry().height(); + sim.setName("Qt for Embedded Linux VNC Server"); + sim.write(client); + state = Connected; + } + break; + + case Connected: + do { + if (!handleMsg) { + client->read((char *)&msgType, 1); + handleMsg = true; + } + if (handleMsg) { + switch (msgType ) { + case SetPixelFormat: + setPixelFormat(); + break; + case FixColourMapEntries: + qDebug("Not supported: FixColourMapEntries"); + handleMsg = false; + break; + case SetEncodings: + setEncodings(); + break; + case FramebufferUpdateRequest: + frameBufferUpdateRequest(); + break; + case KeyEvent: + keyEvent(); + break; + case PointerEvent: + pointerEvent(); + break; + case ClientCutText: + clientCutText(); + break; + default: + qDebug("Unknown message type: %d", (int)msgType); + handleMsg = false; + } + } + } while (!handleMsg && client->bytesAvailable()); + break; + default: + break; + } +} + +#if 0//Q_BYTE_ORDER == Q_BIG_ENDIAN +bool QVNCScreen::swapBytes() const +{ + if (depth() != 16) + return false; + + if (screen()) + return screen()->frameBufferLittleEndian(); + return frameBufferLittleEndian(); +} +#endif + +void QVNCServer::setPixelFormat() +{ + if (client->bytesAvailable() >= 19) { + char buf[3]; + client->read(buf, 3); // just padding + pixelFormat.read(client); +#ifdef QT_QWS_VNC_DEBUG + qDebug("Want format: %d %d %d %d %d %d %d %d %d %d", + int(pixelFormat.bitsPerPixel), + int(pixelFormat.depth), + int(pixelFormat.bigEndian), + int(pixelFormat.trueColor), + int(pixelFormat.redBits), + int(pixelFormat.greenBits), + int(pixelFormat.blueBits), + int(pixelFormat.redShift), + int(pixelFormat.greenShift), + int(pixelFormat.blueShift)); +#endif + if (!pixelFormat.trueColor) { + qDebug("Can only handle true color clients"); + discardClient(); + } + handleMsg = false; + sameEndian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) == !!pixelFormat.bigEndian; + needConversion = pixelConversionNeeded(); +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + swapBytes = qvnc_screen->swapBytes(); +#endif + } +} + +void QVNCServer::setEncodings() +{ + QRfbSetEncodings enc; + + if (!encodingsPending && enc.read(client)) { + encodingsPending = enc.count; + if (!encodingsPending) + handleMsg = false; + } + + if (encoder) { + delete encoder; + encoder = 0; + } + + enum Encodings { + Raw = 0, + CopyRect = 1, + RRE = 2, + CoRRE = 4, + Hextile = 5, + ZRLE = 16, + Cursor = -239, + DesktopSize = -223 + }; + + supportCursor = false; + + if (encodingsPending && (unsigned)client->bytesAvailable() >= + encodingsPending * sizeof(quint32)) { + for (int i = 0; i < encodingsPending; ++i) { + qint32 enc; + client->read((char *)&enc, sizeof(qint32)); + enc = ntohl(enc); +#ifdef QT_QWS_VNC_DEBUG + qDebug("QVNCServer::setEncodings: %d", enc); +#endif + switch (enc) { + case Raw: + if (!encoder) { + encoder = new QRfbRawEncoder(this); +#ifdef QT_QWS_VNC_DEBUG + qDebug("QVNCServer::setEncodings: using raw"); +#endif + } + break; + case CopyRect: + supportCopyRect = true; + break; + case RRE: + supportRRE = true; + break; + case CoRRE: + supportCoRRE = true; + break; + case Hextile: + supportHextile = true; + if (encoder) + break; + switch (qvnc_screen->depth()) { +#ifdef QT_QWS_DEPTH_8 + case 8: + encoder = new QRfbHextileEncoder<quint8>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_12 + case 12: + encoder = new QRfbHextileEncoder<qrgb444>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_15 + case 15: + encoder = new QRfbHextileEncoder<qrgb555>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_16 + case 16: + encoder = new QRfbHextileEncoder<quint16>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_18 + case 18: + encoder = new QRfbHextileEncoder<qrgb666>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_24 + case 24: + encoder = new QRfbHextileEncoder<qrgb888>(this); + break; +#endif +#ifdef QT_QWS_DEPTH_32 + case 32: + encoder = new QRfbHextileEncoder<quint32>(this); + break; +#endif + default: + break; + } +#ifdef QT_QWS_VNC_DEBUG + qDebug("QVNCServer::setEncodings: using hextile"); +#endif + break; + case ZRLE: + supportZRLE = true; + break; + case Cursor: + supportCursor = true; +#ifndef QT_NO_QWS_CURSOR + if (!qvnc_screen->screen() || qt_screencursor->isAccelerated()) { + delete qvnc_cursor; + qvnc_cursor = new QVNCClientCursor(this); + } +#endif + break; + case DesktopSize: + supportDesktopSize = true; + break; + default: + break; + } + } + handleMsg = false; + encodingsPending = 0; + } + + if (!encoder) { + encoder = new QRfbRawEncoder(this); +#ifdef QT_QWS_VNC_DEBUG + qDebug("QVNCServer::setEncodings: fallback using raw"); +#endif + } + + if (cursor) + cursor->setCursorMode(supportCursor); +} + +void QVNCServer::frameBufferUpdateRequest() +{ + QRfbFrameBufferUpdateRequest ev; + + if (ev.read(client)) { + if (!ev.incremental) { + QRect r(ev.rect.x, ev.rect.y, ev.rect.w, ev.rect.h); +////### r.translate(qvnc_screen->offset()); + qvnc_screen->d_ptr->setDirty(r, true); + } + wantUpdate = true; + checkUpdate(); + handleMsg = false; + } +} + +static bool buttonChange(Qt::MouseButtons before, Qt::MouseButtons after, Qt::MouseButton *button, bool *isPress) +{ + if (before == after) + return false; + for (int b = Qt::LeftButton; b <= Qt::MidButton; b<<=1) { + if ((before & b) != (after & b)) { + *button = static_cast<Qt::MouseButton>(b); + *isPress = (after & b); + return true; + } + } + return false; +} + +void QVNCServer::pointerEvent() +{ + QPoint screenOffset = this->screen()->geometry().topLeft(); + + QRfbPointerEvent ev; + if (ev.read(client)) { + QPoint eventPoint(ev.x, ev.y); + eventPoint += screenOffset; // local to global translation + + if (ev.wheelDirection == ev.WheelNone) { + QEvent::Type type = QEvent::MouseMove; + Qt::MouseButton button = Qt::NoButton; + bool isPress; + if (buttonChange(buttons, ev.buttons, &button, &isPress)) + type = isPress ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease; + QWindowSystemInterface::handleMouseEvent(0, eventPoint, eventPoint, ev.buttons); + } else { + // No buttons or motion reported at the same time as wheel events + Qt::Orientation orientation; + if (ev.wheelDirection == ev.WheelLeft || ev.wheelDirection == ev.WheelRight) + orientation = Qt::Horizontal; + else + orientation = Qt::Vertical; + int delta = 120 * ((ev.wheelDirection == ev.WheelLeft || ev.wheelDirection == ev.WheelUp) ? 1 : -1); + QWindowSystemInterface::handleWheelEvent(0, eventPoint, eventPoint, delta, orientation); + } + handleMsg = false; + } +} + +void QVNCServer::keyEvent() +{ + QRfbKeyEvent ev; + + if (ev.read(client)) { + if (ev.keycode == Qt::Key_Shift) + keymod = ev.down ? keymod | Qt::ShiftModifier : + keymod & ~Qt::ShiftModifier; + else if (ev.keycode == Qt::Key_Control) + keymod = ev.down ? keymod | Qt::ControlModifier : + keymod & ~Qt::ControlModifier; + else if (ev.keycode == Qt::Key_Alt) + keymod = ev.down ? keymod | Qt::AltModifier : + keymod & ~Qt::AltModifier; + if (ev.unicode || ev.keycode) { +// qDebug() << "keyEvent" << hex << ev.unicode << ev.keycode << keymod << ev.down; + QEvent::Type type = ev.down ? QEvent::KeyPress : QEvent::KeyRelease; + QString str; + if (ev.unicode && ev.unicode != 0xffff) + str = QString(ev.unicode); + QWindowSystemInterface::handleKeyEvent(0, type, ev.keycode, keymod, str); + } + handleMsg = false; + } +} + +void QVNCServer::clientCutText() +{ + QRfbClientCutText ev; + + if (cutTextPending == 0 && ev.read(client)) { + cutTextPending = ev.length; + if (!cutTextPending) + handleMsg = false; + } + + if (cutTextPending && client->bytesAvailable() >= cutTextPending) { + char *text = new char [cutTextPending+1]; + client->read(text, cutTextPending); + delete [] text; + cutTextPending = 0; + handleMsg = false; + } +} + +// stride in bytes +template <class SRC> +bool QRfbSingleColorHextile<SRC>::read(const uchar *data, + int width, int height, int stride) +{ + const int depth = encoder->server->screen()->depth(); + if (width % (depth / 8)) // hw: should rather fallback to simple loop + return false; + + static int alwaysFalse = qgetenv("QT_VNC_NOCHECKFILL").toInt(); + if (alwaysFalse) + return false; + + switch (depth) { + case 4: { + const quint8 *data8 = reinterpret_cast<const quint8*>(data); + if ((data8[0] & 0xf) != (data8[0] >> 4)) + return false; + width /= 2; + } // fallthrough + case 8: { + const quint8 *data8 = reinterpret_cast<const quint8*>(data); + if (data8[0] != data8[1]) + return false; + width /= 2; + } // fallthrough + case 12: + case 15: + case 16: { + const quint16 *data16 = reinterpret_cast<const quint16*>(data); + if (data16[0] != data16[1]) + return false; + width /= 2; + } // fallthrough + case 18: + case 24: + case 32: { + const quint32 *data32 = reinterpret_cast<const quint32*>(data); + const quint32 first = data32[0]; + const int linestep = (stride / sizeof(quint32)) - width; + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + if (*(data32++) != first) + return false; + } + data32 += linestep; + } + break; + } + default: + return false; + } + + SRC color = reinterpret_cast<const SRC*>(data)[0]; + encoder->newBg |= (color != encoder->bg); + encoder->bg = color; + return true; +} + +template <class SRC> +void QRfbSingleColorHextile<SRC>::write(QTcpSocket *socket) const +{ + if (true || encoder->newBg) { + const int bpp = encoder->server->clientBytesPerPixel(); + const int padding = 3; + QVarLengthArray<char> buffer(padding + 1 + bpp); + buffer[padding] = 2; // BackgroundSpecified + encoder->server->convertPixels(buffer.data() + padding + 1, + reinterpret_cast<char*>(&encoder->bg), + 1); + socket->write(buffer.data() + padding, bpp + 1); +// encoder->newBg = false; + } else { + char subenc = 0; + socket->write(&subenc, 1); + } +} + +template <class SRC> +bool QRfbDualColorHextile<SRC>::read(const uchar *data, + int width, int height, int stride) +{ + const SRC *ptr = reinterpret_cast<const SRC*>(data); + const int linestep = (stride / sizeof(SRC)) - width; + + SRC c1; + SRC c2 = 0; + int n1 = 0; + int n2 = 0; + int x = 0; + int y = 0; + + c1 = *ptr; + + // find second color + while (y < height) { + while (x < width) { + if (*ptr == c1) { + ++n1; + } else { + c2 = *ptr; + goto found_second_color; + } + ++ptr; + ++x; + } + x = 0; + ptr += linestep; + ++y; + } + +found_second_color: + // finish counting + while (y < height) { + while (x < width) { + if (*ptr == c1) { + ++n1; + } else if (*ptr == c2) { + ++n2; + } else { + return false; + } + ++ptr; + ++x; + } + x = 0; + ptr += linestep; + ++y; + } + + if (n2 > n1) { + const quint32 tmpC = c1; + c1 = c2; + c2 = tmpC; + } + + encoder->newBg |= (c1 != encoder->bg); + encoder->newFg |= (c2 != encoder->fg); + + encoder->bg = c1; + encoder->fg = c2; + + // create map + bool inRect = false; + numRects = 0; + ptr = reinterpret_cast<const SRC*>(data); + for (y = 0; y < height; ++y) { + for (x = 0; x < width; ++x) { + if (inRect && *ptr == encoder->bg) { + // rect finished + setWidth(x - lastx()); + next(); + inRect = false; + } else if (!inRect && *ptr == encoder->fg) { + // rect start + setX(x); + setY(y); + setHeight(1); + inRect = true; + } + ++ptr; + } + if (inRect) { + // finish rect + setWidth(width - lastx()); + next(); + inRect = false; + } + ptr += linestep; + } + + return true; +} + +template <class SRC> +void QRfbDualColorHextile<SRC>::write(QTcpSocket *socket) const +{ + const int bpp = encoder->server->clientBytesPerPixel(); + const int padding = 3; + QVarLengthArray<char> buffer(padding + 2 * bpp + sizeof(char) + sizeof(numRects)); + char &subenc = buffer[padding]; + int n = padding + sizeof(subenc); + + subenc = 0x8; // AnySubrects + + if (encoder->newBg) { + subenc |= 0x2; // Background + encoder->server->convertPixels(buffer.data() + n, (char*)&encoder->bg, 1); + n += bpp; +// encoder->newBg = false; + } + + if (encoder->newFg) { + subenc |= 0x4; // Foreground + encoder->server->convertPixels(buffer.data() + n, (char*)&encoder->fg, 1); + n += bpp; +// encoder->newFg = false; + } + buffer[n] = numRects; + n += sizeof(numRects); + + socket->write(buffer.data() + padding, n - padding); + socket->write((char*)rects, numRects * sizeof(Rect)); +} + +template <class SRC> +void QRfbDualColorHextile<SRC>::next() +{ + for (int r = numRects - 1; r >= 0; --r) { + if (recty(r) == lasty()) + continue; + if (recty(r) < lasty() - 1) // only search previous scanline + break; + if (rectx(r) == lastx() && width(r) == width(numRects)) { + ++rects[r].wh; + return; + } + } + ++numRects; +} + +template <class SRC> +inline void QRfbMultiColorHextile<SRC>::setColor(SRC color) +{ + encoder->server->convertPixels(reinterpret_cast<char*>(rect(numRects)), + (const char*)&color, 1); +} + +template <class SRC> +inline bool QRfbMultiColorHextile<SRC>::beginRect() +{ + if ((rects.size() + bpp + 2) > maxRectsSize) + return false; + rects.resize(rects.size() + bpp + 2); + return true; +} + +template <class SRC> +inline void QRfbMultiColorHextile<SRC>::endRect() +{ + setHeight(numRects, 1); + ++numRects; +} + +template <class SRC> +bool QRfbMultiColorHextile<SRC>::read(const uchar *data, + int width, int height, int stride) +{ + const SRC *ptr = reinterpret_cast<const SRC*>(data); + const int linestep = (stride / sizeof(SRC)) - width; + + bpp = encoder->server->clientBytesPerPixel(); + + if (encoder->newBg) + encoder->bg = ptr[0]; + + const SRC bg = encoder->bg; + SRC color = bg; + bool inRect = false; + + numRects = 0; + rects.clear(); + + for (int y = 0; y < height; ++y) { + for (int x = 0; x < width; ++x) { + if (inRect && *ptr != color) { // end rect + setWidth(numRects, x - rectx(numRects)); + endRect(); + inRect = false; + } + + if (!inRect && *ptr != bg) { // begin rect + if (!beginRect()) + return false; + inRect = true; + color = *ptr; + setColor(color); + setX(numRects, x); + setY(numRects, y); + } + ++ptr; + } + if (inRect) { // end rect + setWidth(numRects, width - rectx(numRects)); + endRect(); + inRect = false; + } + ptr += linestep; + } + + return true; +} + +template <class SRC> +void QRfbMultiColorHextile<SRC>::write(QTcpSocket *socket) const +{ + const int padding = 3; + QVarLengthArray<quint8> buffer(bpp + padding + sizeof(quint8) + sizeof(numRects)); + + quint8 &subenc = buffer[padding]; + int n = padding + sizeof(quint8); + + subenc = 8 | 16; // AnySubrects | SubrectsColoured + + if (encoder->newBg) { + subenc |= 0x2; // Background + encoder->server->convertPixels(reinterpret_cast<char*>(buffer.data() + n), + reinterpret_cast<const char*>(&encoder->bg), + 1); + n += bpp; +// encoder->newBg = false; + } + + buffer[n] = numRects; + n += sizeof(numRects); + + socket->write(reinterpret_cast<const char*>(buffer.data() + padding), + n - padding); + socket->write(reinterpret_cast<const char*>(rects.constData()), + rects.size()); +} + +bool QVNCServer::pixelConversionNeeded() const +{ + if (!sameEndian) + return true; + +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + if (qvnc_screen->swapBytes()) + return true; +#endif + + const int screendepth = qvnc_screen->depth(); + if (screendepth != pixelFormat.bitsPerPixel) + return true; + + switch (screendepth) { + case 32: + case 24: + return false; + case 18: + return (pixelFormat.redBits == 6 + && pixelFormat.greenBits == 6 + && pixelFormat.blueBits == 6); + case 16: + return (pixelFormat.redBits == 5 + && pixelFormat.greenBits == 6 + && pixelFormat.blueBits == 5); + case 15: + return (pixelFormat.redBits == 5 + && pixelFormat.greenBits == 5 + && pixelFormat.blueBits == 5); + case 12: + return (pixelFormat.redBits == 4 + && pixelFormat.greenBits == 4 + && pixelFormat.blueBits == 4); + } + return true; +} + +// count: number of pixels +void QVNCServer::convertPixels(char *dst, const char *src, int count) const +{ + const int screendepth = qvnc_screen->depth(); + const bool isBgr = false; //### qvnc_screen->pixelType() == QScreen::BGRPixel; + + // cutoffs +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + if (!swapBytes) +#endif + if (sameEndian) { + if (screendepth == pixelFormat.bitsPerPixel) { // memcpy cutoffs + + switch (screendepth) { + case 32: + memcpy(dst, src, count * sizeof(quint32)); + return; + case 16: + if (pixelFormat.redBits == 5 + && pixelFormat.greenBits == 6 + && pixelFormat.blueBits == 5) + { + memcpy(dst, src, count * sizeof(quint16)); + return; + } + } + } else if (screendepth == 16 && pixelFormat.bitsPerPixel == 32) { +#if defined(__i386__) // Currently fails on ARM if dst is not 4 byte aligned + const quint32 *src32 = reinterpret_cast<const quint32*>(src); + quint32 *dst32 = reinterpret_cast<quint32*>(dst); + int count32 = count * sizeof(quint16) / sizeof(quint32); + while (count32--) { + const quint32 s = *src32++; + quint32 result1; + quint32 result2; + + // red + result1 = ((s & 0xf8000000) | ((s & 0xe0000000) >> 5)) >> 8; + result2 = ((s & 0x0000f800) | ((s & 0x0000e000) >> 5)) << 8; + + // green + result1 |= ((s & 0x07e00000) | ((s & 0x06000000) >> 6)) >> 11; + result2 |= ((s & 0x000007e0) | ((s & 0x00000600) >> 6)) << 5; + + // blue + result1 |= ((s & 0x001f0000) | ((s & 0x001c0000) >> 5)) >> 13; + result2 |= ((s & 0x0000001f) | ((s & 0x0000001c) >> 5)) << 3; + + *dst32++ = result2; + *dst32++ = result1; + } + if (count & 0x1) { + const quint16 *src16 = reinterpret_cast<const quint16*>(src); + *dst32 = qt_conv16ToRgb(src16[count - 1]); + } + return; +#endif + } + } + + const int bytesPerPixel = (pixelFormat.bitsPerPixel + 7) / 8; + +// nibble = 0; + + for (int i = 0; i < count; ++i) { + int r, g, b; + + switch (screendepth) { +#if 0 + case 4: { + if (!nibble) { + r = ((*src) & 0x0f) << 4; + } else { + r = (*src) & 0xf0; + src++; + } + nibble = !nibble; + g = b = r; + break; + } +#endif +#if 0 + case 8: { + QRgb rgb = qvnc_screen->clut()[int(*src)]; + r = qRed(rgb); + g = qGreen(rgb); + b = qBlue(rgb); + src++; + break; + } +#endif +#ifdef QT_QWS_DEPTH_12 + case 12: { + quint32 p = quint32(*reinterpret_cast<const qrgb444*>(src)); + r = qRed(p); + g = qGreen(p); + b = qBlue(p); + src += sizeof(qrgb444); + break; + } +#endif +#ifdef QT_QWS_DEPTH_15 + case 15: { + quint32 p = quint32(*reinterpret_cast<const qrgb555*>(src)); + r = qRed(p); + g = qGreen(p); + b = qBlue(p); + src += sizeof(qrgb555); + break; + } +#endif + case 16: { + quint16 p = *reinterpret_cast<const quint16*>(src); +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + if (swapBytes) + p = ((p & 0xff) << 8) | ((p & 0xff00) >> 8); +#endif + r = (p >> 11) & 0x1f; + g = (p >> 5) & 0x3f; + b = p & 0x1f; + r <<= 3; + g <<= 2; + b <<= 3; + src += sizeof(quint16); + break; + } +#ifdef QT_QWS_DEPTH_18 + case 18: { + quint32 p = quint32(*reinterpret_cast<const qrgb666*>(src)); + r = qRed(p); + g = qGreen(p); + b = qBlue(p); + src += sizeof(qrgb666); + break; + } +#endif +#ifdef QT_QWS_DEPTH_24 + case 24: { + quint32 p = quint32(*reinterpret_cast<const qrgb888*>(src)); + r = qRed(p); + g = qGreen(p); + b = qBlue(p); + src += sizeof(qrgb888); + break; + } +#endif + case 32: { + quint32 p = *reinterpret_cast<const quint32*>(src); + r = (p >> 16) & 0xff; + g = (p >> 8) & 0xff; + b = p & 0xff; + src += sizeof(quint32); + break; + } + default: { + r = g = b = 0; + qDebug("QVNCServer: don't support %dbpp display", screendepth); + return; + } + } + +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + if (swapBytes ^ isBgr) +#else + if (isBgr) +#endif + qSwap(r, b); + + r >>= (8 - pixelFormat.redBits); + g >>= (8 - pixelFormat.greenBits); + b >>= (8 - pixelFormat.blueBits); + + int pixel = (r << pixelFormat.redShift) | + (g << pixelFormat.greenShift) | + (b << pixelFormat.blueShift); + + if (sameEndian || pixelFormat.bitsPerPixel == 8) { + memcpy(dst, &pixel, bytesPerPixel); // XXX: do a simple for-loop instead? + dst += bytesPerPixel; + continue; + } + + + if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { + switch (pixelFormat.bitsPerPixel) { + case 16: + pixel = (((pixel & 0x0000ff00) << 8) | + ((pixel & 0x000000ff) << 24)); + break; + case 32: + pixel = (((pixel & 0xff000000) >> 24) | + ((pixel & 0x00ff0000) >> 8) | + ((pixel & 0x0000ff00) << 8) | + ((pixel & 0x000000ff) << 24)); + break; + default: + qDebug("Cannot handle %d bpp client", pixelFormat.bitsPerPixel); + } + } else { // QSysInfo::ByteOrder == QSysInfo::LittleEndian + switch (pixelFormat.bitsPerPixel) { + case 16: + pixel = (((pixel & 0xff000000) >> 8) | + ((pixel & 0x00ff0000) << 8)); + break; + case 32: + pixel = (((pixel & 0xff000000) >> 24) | + ((pixel & 0x00ff0000) >> 8) | + ((pixel & 0x0000ff00) << 8) | + ((pixel & 0x000000ff) << 24)); + break; + default: + qDebug("Cannot handle %d bpp client", + pixelFormat.bitsPerPixel); + break; + } + } + memcpy(dst, &pixel, bytesPerPixel); // XXX: simple for-loop instead? + dst += bytesPerPixel; + } +} + +#ifndef QT_NO_QWS_CURSOR +static void blendCursor(QImage &image, const QRect &imageRect) +{ + const QRect cursorRect = qt_screencursor->boundingRect(); + const QRect intersection = (cursorRect & imageRect); + const QRect destRect = intersection.translated(-imageRect.topLeft()); + const QRect srcRect = intersection.translated(-cursorRect.topLeft()); + + QPainter painter(&image); + painter.drawImage(destRect, qt_screencursor->image(), srcRect); + painter.end(); +} +#endif // QT_NO_QWS_CURSOR + +QVNCDirtyMap::QVNCDirtyMap(QVNCScreen *s) + : bytesPerPixel(0), numDirty(0), screen(s) +{ + bytesPerPixel = (screen->depth() + 7) / 8; + QSize screenSize = screen->geometry().size(); + bufferWidth = screenSize.width(); + bufferHeight = screenSize.height(); + bufferStride = bufferWidth * bytesPerPixel; + buffer = new uchar[bufferHeight * bufferStride]; + + mapWidth = (bufferWidth + MAP_TILE_SIZE - 1) / MAP_TILE_SIZE; + mapHeight = (bufferHeight + MAP_TILE_SIZE - 1) / MAP_TILE_SIZE; + numTiles = mapWidth * mapHeight; + map = new uchar[numTiles]; +} + +QVNCDirtyMap::~QVNCDirtyMap() +{ + delete[] map; + delete[] buffer; +} + +void QVNCDirtyMap::reset() +{ + memset(map, 1, numTiles); + memset(buffer, 0, bufferHeight * bufferStride); + numDirty = numTiles; +} + +inline bool QVNCDirtyMap::dirty(int x, int y) const +{ + return map[y * mapWidth + x]; +} + +inline void QVNCDirtyMap::setClean(int x, int y) +{ + map[y * mapWidth + x] = 0; + --numDirty; +} + +template <class T> +void QVNCDirtyMapOptimized<T>::setDirty(int tileX, int tileY, bool force) +{ + static bool alwaysForce = qgetenv("QT_VNC_NO_COMPAREBUFFER").toInt(); + if (alwaysForce) + force = true; + + bool changed = false; + + if (!force) { + const int lstep = screen->linestep(); + const int startX = tileX * MAP_TILE_SIZE; + const int startY = tileY * MAP_TILE_SIZE; + const uchar *scrn = screen->base() + + startY * lstep + startX * bytesPerPixel; + uchar *old = buffer + startY * bufferStride + startX * sizeof(T); + + const int tileHeight = (startY + MAP_TILE_SIZE > bufferHeight ? + bufferHeight - startY : MAP_TILE_SIZE); + const int tileWidth = (startX + MAP_TILE_SIZE > bufferWidth ? + bufferWidth - startX : MAP_TILE_SIZE); + const bool doInlines = (tileWidth == MAP_TILE_SIZE); + + int y = tileHeight; + + if (doInlines) { // hw: memcmp/memcpy is inlined when using constants + while (y) { + if (memcmp(old, scrn, sizeof(T) * MAP_TILE_SIZE)) { + changed = true; + break; + } + scrn += lstep; + old += bufferStride; + --y; + } + + while (y) { + memcpy(old, scrn, sizeof(T) * MAP_TILE_SIZE); + scrn += lstep; + old += bufferStride; + --y; + } + } else { + while (y) { + if (memcmp(old, scrn, sizeof(T) * tileWidth)) { + changed = true; + break; + } + scrn += lstep; + old += bufferStride; + --y; + } + + while (y) { + memcpy(old, scrn, sizeof(T) * tileWidth); + scrn += lstep; + old += bufferStride; + --y; + } + } + } + + const int mapIndex = tileY * mapWidth + tileX; + if ((force || changed) && !map[mapIndex]) { + map[mapIndex] = 1; + ++numDirty; + } +} + +template <class SRC> +QRfbHextileEncoder<SRC>::QRfbHextileEncoder(QVNCServer *s) + : QRfbEncoder(s), + singleColorHextile(this), dualColorHextile(this), multiColorHextile(this) +{ +} + +/* + \internal + Send dirty rects using hextile encoding. +*/ +template <class SRC> +void QRfbHextileEncoder<SRC>::write() +{ +// QWSDisplay::grab(true); + + QVNCDirtyMap *map = server->dirtyMap(); + QTcpSocket *socket = server->clientSocket(); + + const quint32 encoding = htonl(5); // hextile encoding + const int bytesPerPixel = server->clientBytesPerPixel(); + + { + const char tmp[2] = { 0, 0 }; // msg type, padding + socket->write(tmp, sizeof(tmp)); + } + { + const quint16 count = htons(map->numDirty); + socket->write((char *)&count, sizeof(count)); + } + + if (map->numDirty <= 0) { +// QWSDisplay::ungrab(); + return; + } + + newBg = true; + newFg = true; + + const QImage screenImage = server->screenImage(); + QRfbRect rect(0, 0, MAP_TILE_SIZE, MAP_TILE_SIZE); + + QSize screenSize = server->screen()->geometry().size(); + + for (int y = 0; y < map->mapHeight; ++y) { + if (rect.y + MAP_TILE_SIZE > screenSize.height()) + rect.h = screenSize.height() - rect.y; + rect.w = MAP_TILE_SIZE; + for (int x = 0; x < map->mapWidth; ++x) { + if (!map->dirty(x, y)) + continue; + map->setClean(x, y); + + rect.x = x * MAP_TILE_SIZE; + if (rect.x + MAP_TILE_SIZE > screenSize.width()) //###deviceWidth ??? + rect.w = screenSize.width() - rect.x; + rect.write(socket); + + socket->write((char *)&encoding, sizeof(encoding)); + + const uchar *screendata = screenImage.scanLine(rect.y) + + rect.x * screenImage.depth() / 8; + int linestep = screenImage.bytesPerLine(); + +#ifndef QT_NO_QWS_CURSOR + // hardware cursors must be blended with the screen memory + const bool doBlendCursor = qt_screencursor + && !server->hasClientCursor() + && qt_screencursor->isAccelerated(); + QImage tileImage; + if (doBlendCursor) { + const QRect tileRect(rect.x, rect.y, rect.w, rect.h); + const QRect cursorRect = qt_screencursor->boundingRect() + .translated(-server->screen()->offset()); + if (tileRect.intersects(cursorRect)) { + tileImage = screenImage.copy(tileRect); + blendCursor(tileImage, + tileRect.translated(server->screen()->offset())); + screendata = tileImage.bits(); + linestep = tileImage.bytesPerLine(); + } + } +#endif // QT_NO_QWS_CURSOR + + if (singleColorHextile.read(screendata, rect.w, rect.h, linestep)) { + singleColorHextile.write(socket); + } else if (dualColorHextile.read(screendata, rect.w, rect.h, linestep)) { + dualColorHextile.write(socket); + } else if (multiColorHextile.read(screendata, rect.w, rect.h, linestep)) { + multiColorHextile.write(socket); + } else if (server->doPixelConversion()) { + const int bufferSize = rect.w * rect.h * bytesPerPixel + 1; + const int padding = sizeof(quint32) - sizeof(char); + buffer.resize(bufferSize + padding); + + buffer[padding] = 1; // Raw subencoding + + // convert pixels + char *b = buffer.data() + padding + 1; + const int bstep = rect.w * bytesPerPixel; + for (int i = 0; i < rect.h; ++i) { + server->convertPixels(b, (const char*)screendata, rect.w); + screendata += linestep; + b += bstep; + } + socket->write(buffer.constData() + padding, bufferSize); + } else { + quint8 subenc = 1; // Raw subencoding + socket->write((char *)&subenc, 1); + + // send pixels + for (int i = 0; i < rect.h; ++i) { + socket->write((const char*)screendata, + rect.w * bytesPerPixel); + screendata += linestep; + } + } + } + if (socket->state() == QAbstractSocket::UnconnectedState) + break; + rect.y += MAP_TILE_SIZE; + } + socket->flush(); + Q_ASSERT(map->numDirty == 0); + +// QWSDisplay::ungrab(); +} + +void QRfbRawEncoder::write() +{ +// QWSDisplay::grab(false); + + QVNCDirtyMap *map = server->dirtyMap(); + QTcpSocket *socket = server->clientSocket(); + + const int bytesPerPixel = server->clientBytesPerPixel(); + QSize screenSize = server->screen()->geometry().size(); + + // create a region from the dirty rects and send the region's merged rects. + QRegion rgn; + if (map) { + for (int y = 0; y < map->mapHeight; ++y) { + for (int x = 0; x < map->mapWidth; ++x) { + if (!map->dirty(x, y)) + continue; + rgn += QRect(x * MAP_TILE_SIZE, y * MAP_TILE_SIZE, + MAP_TILE_SIZE, MAP_TILE_SIZE); + map->setClean(x, y); + } + } + + rgn &= QRect(0, 0, screenSize.width(), + screenSize.height()); + } + const QVector<QRect> rects = rgn.rects(); + + { + const char tmp[2] = { 0, 0 }; // msg type, padding + socket->write(tmp, sizeof(tmp)); + } + + { + const quint16 count = htons(rects.size()); + socket->write((char *)&count, sizeof(count)); + } + + if (rects.size() <= 0) { +// QWSDisplay::ungrab(); + return; + } + + const QImage *screenImage = server->screenImage(); + + for (int i = 0; i < rects.size(); ++i) { + const QRect tileRect = rects.at(i); + const QRfbRect rect(tileRect.x(), tileRect.y(), + tileRect.width(), tileRect.height()); + rect.write(socket); + + const quint32 encoding = htonl(0); // raw encoding + socket->write((char *)&encoding, sizeof(encoding)); + + int linestep = screenImage->bytesPerLine(); + const uchar *screendata = screenImage->scanLine(rect.y) + + rect.x * screenImage->depth() / 8; + +#ifndef QT_NO_QWS_CURSOR + // hardware cursors must be blended with the screen memory + const bool doBlendCursor = qt_screencursor + && !server->hasClientCursor() + && qt_screencursor->isAccelerated(); + QImage tileImage; + if (doBlendCursor) { + const QRect cursorRect = qt_screencursor->boundingRect() + .translated(-server->screen()->offset()); + if (tileRect.intersects(cursorRect)) { + tileImage = screenImage->copy(tileRect); + blendCursor(tileImage, + tileRect.translated(server->screen()->offset())); + screendata = tileImage.bits(); + linestep = tileImage.bytesPerLine(); + } + } +#endif // QT_NO_QWS_CURSOR + + if (server->doPixelConversion()) { + const int bufferSize = rect.w * rect.h * bytesPerPixel; + if (bufferSize > buffer.size()) + buffer.resize(bufferSize); + + // convert pixels + char *b = buffer.data(); + const int bstep = rect.w * bytesPerPixel; + for (int i = 0; i < rect.h; ++i) { + server->convertPixels(b, (const char*)screendata, rect.w); + screendata += linestep; + b += bstep; + } + socket->write(buffer.constData(), bufferSize); + } else { + for (int i = 0; i < rect.h; ++i) { + socket->write((const char*)screendata, rect.w * bytesPerPixel); + screendata += linestep; + } + } + if (socket->state() == QAbstractSocket::UnconnectedState) + break; + } + socket->flush(); + +// QWSDisplay::ungrab(); +} + +inline QImage *QVNCServer::screenImage() const +{ + return qvnc_screen->image(); +} + +void QVNCServer::checkUpdate() +{ + if (!wantUpdate) + return; + + if (dirtyCursor) { +#ifndef QT_NO_QWS_CURSOR + Q_ASSERT(qvnc_cursor); + qvnc_cursor->write(); +#endif + cursor->sendClientCursor(); + dirtyCursor = false; + wantUpdate = false; + return; + } + + if (dirtyMap()->numDirty > 0) { + if (encoder) + encoder->write(); + wantUpdate = false; + } +} + +void QVNCServer::discardClient() +{ + timer->stop(); + state = Unconnected; + delete encoder; + encoder = 0; +#ifndef QT_NO_QWS_CURSOR + delete qvnc_cursor; + qvnc_cursor = 0; +#endif +// if (!qvnc_screen->screen()) +// QWSServer::instance()->enablePainting(false); +} + + + +QVNCScreenPrivate::QVNCScreenPrivate(QVNCScreen *parent, int screenId) + : dpiX(72), dpiY(72), doOnScreenSurface(false), refreshRate(25), + vncServer(0), q_ptr(parent) +{ +#if 0//ndef QT_NO_QWS_SIGNALHANDLER + QWSSignalHandler::instance()->addObject(this); +#endif + + vncServer = new QVNCServer(q_ptr, screenId); + vncServer->setRefreshRate(refreshRate); + + + Q_ASSERT(q_ptr->depth() == 32); + + dirty = new QVNCDirtyMapOptimized<quint32>(q_ptr); +} + +QVNCScreenPrivate::~QVNCScreenPrivate() +{ +} + + +void QVNCScreenPrivate::setDirty(const QRect& rect, bool force) +{ + if (rect.isEmpty()) + return; + +// if (q_ptr->screen()) +// q_ptr->screen()->setDirty(rect); + + if (!vncServer || !vncServer->isConnected()) { +// qDebug() << "QVNCScreenPrivate::setDirty() - Not connected"; + return; + } + const QRect r = rect; // .translated(-q_ptr->offset()); + const int x1 = r.x() / MAP_TILE_SIZE; + int y = r.y() / MAP_TILE_SIZE; + for (; (y <= r.bottom() / MAP_TILE_SIZE) && y < dirty->mapHeight; y++) + for (int x = x1; (x <= r.right() / MAP_TILE_SIZE) && x < dirty->mapWidth; x++) + dirty->setDirty(x, y, force); + + vncServer->setDirty(); +} + + + + +QT_END_NAMESPACE diff --git a/src/plugins/platforms/vnc/qvncserver.h b/src/plugins/platforms/vnc/qvncserver.h new file mode 100644 index 0000000..7244bdf --- /dev/null +++ b/src/plugins/platforms/vnc/qvncserver.h @@ -0,0 +1,533 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +#ifndef QSCREENVNC_P_H +#define QSCREENVNC_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QLibrary class. This header file may change from version to version +// without notice, or even be removed. +// +// We mean it. +// + +#include "qvncintegration.h" +#include "qvnccursor.h" +#define QT_NO_QWS_CURSOR + +#ifndef QT_NO_QWS_VNC + +#include <QtCore/qvarlengtharray.h> +#include <QtCore/qsharedmemory.h> +#include <QtNetwork/qtcpsocket.h> +#include <QtNetwork/qtcpserver.h> + +QT_BEGIN_NAMESPACE + +class QVNCServer; + +#ifndef QT_NO_QWS_CURSOR +class QVNCCursor : public QProxyScreenCursor +{ +public: + QVNCCursor(QVNCScreen *s); + ~QVNCCursor(); + + void hide(); + void show(); + void set(const QImage &image, int hotx, int hoty); + void move(int x, int y); + +private: + void setDirty(const QRect &r) const; + QVNCScreen *screen; +}; + +class QVNCClientCursor : public QProxyScreenCursor +{ +public: + QVNCClientCursor(QVNCServer *s); + ~QVNCClientCursor(); + + void set(const QImage &image, int hotx, int hoty); + void write() const; + +private: + QVNCServer *server; +}; +#endif // QT_NO_QWS_CURSOR + +#define MAP_TILE_SIZE 16 +#define MAP_WIDTH 1280 / MAP_TILE_SIZE +#define MAP_HEIGHT 1024 / MAP_TILE_SIZE + +class QVNCDirtyMap +{ +public: + QVNCDirtyMap(QVNCScreen *screen); + virtual ~QVNCDirtyMap(); + + void reset(); + bool dirty(int x, int y) const; + virtual void setDirty(int x, int y, bool force = false) = 0; + void setClean(int x, int y); + + int bytesPerPixel; + + int numDirty; + int mapWidth; + int mapHeight; + +protected: + uchar *map; + QVNCScreen *screen; + uchar *buffer; + int bufferWidth; + int bufferHeight; + int bufferStride; + int numTiles; +}; + +template <class T> +class QVNCDirtyMapOptimized : public QVNCDirtyMap +{ +public: + QVNCDirtyMapOptimized(QVNCScreen *screen) : QVNCDirtyMap(screen) {} + ~QVNCDirtyMapOptimized() {} + + void setDirty(int x, int y, bool force = false); +}; + +class QRfbRect +{ +public: + QRfbRect() {} + QRfbRect(quint16 _x, quint16 _y, quint16 _w, quint16 _h) { + x = _x; y = _y; w = _w; h = _h; + } + + void read(QTcpSocket *s); + void write(QTcpSocket *s) const; + + quint16 x; + quint16 y; + quint16 w; + quint16 h; +}; + +class QRfbPixelFormat +{ +public: + static int size() { return 16; } + + void read(QTcpSocket *s); + void write(QTcpSocket *s); + + int bitsPerPixel; + int depth; + bool bigEndian; + bool trueColor; + int redBits; + int greenBits; + int blueBits; + int redShift; + int greenShift; + int blueShift; +}; + +class QRfbServerInit +{ +public: + QRfbServerInit() { name = 0; } + ~QRfbServerInit() { delete[] name; } + + int size() const { return QRfbPixelFormat::size() + 8 + strlen(name); } + void setName(const char *n); + + void read(QTcpSocket *s); + void write(QTcpSocket *s); + + quint16 width; + quint16 height; + QRfbPixelFormat format; + char *name; +}; + +class QRfbSetEncodings +{ +public: + bool read(QTcpSocket *s); + + quint16 count; +}; + +class QRfbFrameBufferUpdateRequest +{ +public: + bool read(QTcpSocket *s); + + char incremental; + QRfbRect rect; +}; + +class QRfbKeyEvent +{ +public: + bool read(QTcpSocket *s); + + char down; + int keycode; + int unicode; +}; + +class QRfbPointerEvent +{ +public: + bool read(QTcpSocket *s); + + Qt::MouseButtons buttons; + enum { WheelNone, + WheelUp, + WheelDown, + WheelLeft, + WheelRight + } wheelDirection; + quint16 x; + quint16 y; +}; + +class QRfbClientCutText +{ +public: + bool read(QTcpSocket *s); + + quint32 length; +}; + +class QVNCScreenPrivate : public QObject +{ +public: + QVNCScreenPrivate(QVNCScreen *parent, int screenId); + ~QVNCScreenPrivate(); + + void setDirty(const QRect &rect, bool force = false); + void configure(); + + qreal dpiX; + qreal dpiY; + bool doOnScreenSurface; + QVNCDirtyMap *dirty; + int refreshRate; + QVNCServer *vncServer; + +#if !defined(QT_NO_QWS_MULTIPROCESS) && !defined(QT_NO_SHAREDMEMORY) + QSharedMemory shm; +#endif + + QVNCScreen *q_ptr; +}; + +class QRfbEncoder +{ +public: + QRfbEncoder(QVNCServer *s) : server(s) {} + virtual ~QRfbEncoder() {} + + virtual void write() = 0; + +protected: + QVNCServer *server; +}; + +class QRfbRawEncoder : public QRfbEncoder +{ +public: + QRfbRawEncoder(QVNCServer *s) : QRfbEncoder(s) {} + + void write(); + +private: + QByteArray buffer; +}; + +template <class SRC> class QRfbHextileEncoder; + +template <class SRC> +class QRfbSingleColorHextile +{ +public: + QRfbSingleColorHextile(QRfbHextileEncoder<SRC> *e) : encoder(e) {} + bool read(const uchar *data, int width, int height, int stride); + void write(QTcpSocket *socket) const; + +private: + QRfbHextileEncoder<SRC> *encoder; +}; + +template <class SRC> +class QRfbDualColorHextile +{ +public: + QRfbDualColorHextile(QRfbHextileEncoder<SRC> *e) : encoder(e) {} + bool read(const uchar *data, int width, int height, int stride); + void write(QTcpSocket *socket) const; + +private: + struct Rect { + quint8 xy; + quint8 wh; + } Q_PACKED rects[8 * 16]; + + quint8 numRects; + QRfbHextileEncoder<SRC> *encoder; + +private: + inline int lastx() const { return rectx(numRects); } + inline int lasty() const { return recty(numRects); } + inline int rectx(int r) const { return rects[r].xy >> 4; } + inline int recty(int r) const { return rects[r].xy & 0x0f; } + inline int width(int r) const { return (rects[r].wh >> 4) + 1; } + inline int height(int r) const { return (rects[r].wh & 0x0f) + 1; } + + inline void setX(int r, int x) { + rects[r].xy = (x << 4) | (rects[r].xy & 0x0f); + } + inline void setY(int r, int y) { + rects[r].xy = (rects[r].xy & 0xf0) | y; + } + inline void setWidth(int r, int width) { + rects[r].wh = ((width - 1) << 4) | (rects[r].wh & 0x0f); + } + inline void setHeight(int r, int height) { + rects[r].wh = (rects[r].wh & 0xf0) | (height - 1); + } + + inline void setWidth(int width) { setWidth(numRects, width); } + inline void setHeight(int height) { setHeight(numRects, height); } + inline void setX(int x) { setX(numRects, x); } + inline void setY(int y) { setY(numRects, y); } + void next(); +}; + +template <class SRC> +class QRfbMultiColorHextile +{ +public: + QRfbMultiColorHextile(QRfbHextileEncoder<SRC> *e) : encoder(e) {} + bool read(const uchar *data, int width, int height, int stride); + void write(QTcpSocket *socket) const; + +private: + inline quint8* rect(int r) { + return rects.data() + r * (bpp + 2); + } + inline const quint8* rect(int r) const { + return rects.constData() + r * (bpp + 2); + } + inline void setX(int r, int x) { + quint8 *ptr = rect(r) + bpp; + *ptr = (x << 4) | (*ptr & 0x0f); + } + inline void setY(int r, int y) { + quint8 *ptr = rect(r) + bpp; + *ptr = (*ptr & 0xf0) | y; + } + void setColor(SRC color); + inline int rectx(int r) const { + const quint8 *ptr = rect(r) + bpp; + return *ptr >> 4; + } + inline int recty(int r) const { + const quint8 *ptr = rect(r) + bpp; + return *ptr & 0x0f; + } + inline void setWidth(int r, int width) { + quint8 *ptr = rect(r) + bpp + 1; + *ptr = ((width - 1) << 4) | (*ptr & 0x0f); + } + inline void setHeight(int r, int height) { + quint8 *ptr = rect(r) + bpp + 1; + *ptr = (*ptr & 0xf0) | (height - 1); + } + + bool beginRect(); + void endRect(); + + static const int maxRectsSize = 16 * 16; + QVarLengthArray<quint8, maxRectsSize> rects; + + quint8 bpp; + quint8 numRects; + QRfbHextileEncoder<SRC> *encoder; +}; + +template <class SRC> +class QRfbHextileEncoder : public QRfbEncoder +{ +public: + QRfbHextileEncoder(QVNCServer *s); + void write(); + +private: + enum SubEncoding { + Raw = 1, + BackgroundSpecified = 2, + ForegroundSpecified = 4, + AnySubrects = 8, + SubrectsColoured = 16 + }; + + QByteArray buffer; + QRfbSingleColorHextile<SRC> singleColorHextile; + QRfbDualColorHextile<SRC> dualColorHextile; + QRfbMultiColorHextile<SRC> multiColorHextile; + + SRC bg; + SRC fg; + bool newBg; + bool newFg; + + friend class QRfbSingleColorHextile<SRC>; + friend class QRfbDualColorHextile<SRC>; + friend class QRfbMultiColorHextile<SRC>; +}; + +class QVNCServer : public QObject +{ + Q_OBJECT +public: + QVNCServer(QVNCScreen *screen); + QVNCServer(QVNCScreen *screen, int id); + ~QVNCServer(); + + void setDirty(); + void setDirtyCursor() { dirtyCursor = true; setDirty(); } + inline bool isConnected() const { return state == Connected; } + inline void setRefreshRate(int rate) { refreshRate = rate; } + + enum ClientMsg { SetPixelFormat = 0, + FixColourMapEntries = 1, + SetEncodings = 2, + FramebufferUpdateRequest = 3, + KeyEvent = 4, + PointerEvent = 5, + ClientCutText = 6 }; + + enum ServerMsg { FramebufferUpdate = 0, + SetColourMapEntries = 1 }; + + void convertPixels(char *dst, const char *src, int count) const; + + inline int clientBytesPerPixel() const { + return pixelFormat.bitsPerPixel / 8; + } + + inline QVNCScreen* screen() const { return qvnc_screen; } + inline QVNCDirtyMap* dirtyMap() const { return qvnc_screen->dirtyMap(); } + inline QTcpSocket* clientSocket() const { return client; } + QImage *screenImage() const; + inline bool doPixelConversion() const { return needConversion; } +#ifndef QT_NO_QWS_CURSOR + inline bool hasClientCursor() const { return qvnc_cursor != 0; } +#endif + + void setCursor(QVNCCursor * c) { cursor = c; } +private: + void setPixelFormat(); + void setEncodings(); + void frameBufferUpdateRequest(); + void pointerEvent(); + void keyEvent(); + void clientCutText(); + bool pixelConversionNeeded() const; + +private slots: + void newConnection(); + void readClient(); + void checkUpdate(); + void discardClient(); + +private: + void init(uint port); + enum ClientState { Unconnected, Protocol, Init, Connected }; + QTimer *timer; + QTcpServer *serverSocket; + QTcpSocket *client; + ClientState state; + quint8 msgType; + bool handleMsg; + QRfbPixelFormat pixelFormat; + Qt::KeyboardModifiers keymod; + Qt::MouseButtons buttons; + int encodingsPending; + int cutTextPending; + uint supportCopyRect : 1; + uint supportRRE : 1; + uint supportCoRRE : 1; + uint supportHextile : 1; + uint supportZRLE : 1; + uint supportCursor : 1; + uint supportDesktopSize : 1; + bool wantUpdate; + bool sameEndian; + bool needConversion; +#if Q_BYTE_ORDER == Q_BIG_ENDIAN + bool swapBytes; +#endif + bool dirtyCursor; + int refreshRate; + QVNCScreen *qvnc_screen; +#ifndef QT_NO_QWS_CURSOR + QVNCClientCursor *qvnc_cursor; +#endif + + QRfbEncoder *encoder; + QVNCCursor *cursor; +}; + + +QT_END_NAMESPACE +#endif // QT_NO_QWS_VNC +#endif // QSCREENVNC_P_H diff --git a/src/plugins/platforms/vnc/vnc.pro b/src/plugins/platforms/vnc/vnc.pro new file mode 100644 index 0000000..07f8d88 --- /dev/null +++ b/src/plugins/platforms/vnc/vnc.pro @@ -0,0 +1,22 @@ +TARGET = qvncgraphicssystem +include(../../qpluginbase.pri) + +QT += network + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/platforms + +SOURCES = main.cpp qvncintegration.cpp +HEADERS = qvncintegration.h + +HEADERS += qvncserver.h +SOURCES += qvncserver.cpp + +HEADERS += qvnccursor.h +SOURCES += qvnccursor.cpp + +include(../fb_base/fb_base.pri) +include(../fontdatabases/genericunix/genericunix.pri) + +target.path += $$[QT_INSTALL_PLUGINS]/platforms + +INSTALLS += target diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index bc3deb7..5b0b6f3 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -7,12 +7,12 @@ unix:!symbian { SUBDIRS *= codecs } !contains(QT_CONFIG, no-gui): SUBDIRS *= imageformats iconengines -!embedded:SUBDIRS *= graphicssystems +!embedded:!qpa:SUBDIRS *= graphicssystems embedded:SUBDIRS *= gfxdrivers decorations mousedrivers kbddrivers !win32:!embedded:!mac:!symbian:SUBDIRS *= inputmethods !symbian:!contains(QT_CONFIG, no-gui):SUBDIRS += accessible symbian:SUBDIRS += s60 contains(QT_CONFIG, phonon): SUBDIRS *= phonon contains(QT_CONFIG, multimedia): SUBDIRS *= audio - +qpa:SUBDIRS += platforms diff --git a/src/qt_install.pri b/src/qt_install.pri index f906e92..268bb86 100644 --- a/src/qt_install.pri +++ b/src/qt_install.pri @@ -38,7 +38,7 @@ qt_install_headers { } } -embedded:equals(TARGET, QtGui) { +embedded|qpa: equals(TARGET, QtGui) { # install fonts for embedded INSTALLS += fonts fonts.path = $$[QT_INSTALL_LIBS]/fonts diff --git a/src/script/script.pro b/src/script/script.pro index 4ee86d7..56d3f7a 100644 --- a/src/script/script.pro +++ b/src/script/script.pro @@ -39,10 +39,18 @@ wince* { LIBS += -lmmtimer } -mac { +!qpa:mac { DEFINES += ENABLE_JSC_MULTIPLE_THREADS=0 LIBS_PRIVATE += -framework AppKit } +qpa:mac { + DEFINES += ENABLE_JSC_MULTIPLE_THREADS=0 + contains(QT_CONFIG, coreservices) { + LIBS_PRIVATE += -framework CoreServices + } else { + LIBS_PRIVATE += -framework CoreFoundation + } +} include($$WEBKITDIR/JavaScriptCore/JavaScriptCore.pri) diff --git a/src/src.pro b/src/src.pro index 060f48b..c07d399 100644 --- a/src/src.pro +++ b/src/src.pro @@ -5,6 +5,7 @@ unset(SRC_SUBDIRS) win32:SRC_SUBDIRS += src_winmain symbian:SRC_SUBDIRS += src_s60main SRC_SUBDIRS += src_corelib src_xml src_network src_sql src_testlib +nacl: SRC_SUBDIRS -= src_network src_testlib !symbian:contains(QT_CONFIG, dbus):SRC_SUBDIRS += src_dbus !contains(QT_CONFIG, no-gui): SRC_SUBDIRS += src_gui !wince*:!symbian:!vxworks:contains(QT_CONFIG, qt3support): SRC_SUBDIRS += src_qt3support diff --git a/src/testlib/testlib.pro b/src/testlib/testlib.pro index a8186d8..c25d23d 100644 --- a/src/testlib/testlib.pro +++ b/src/testlib/testlib.pro @@ -70,8 +70,16 @@ wince*::LIBS += libcmt.lib \ coredll.lib \ winsock.lib mac:LIBS += -framework IOKit \ - -framework ApplicationServices \ -framework Security +!qpa:mac: LIBS += -framework ApplicationServices +qpa:mac: { + contains(QT_CONFIG, coreservices) { + LIBS_PRIVATE += -framework CoreServices + } else { + LIBS_PRIVATE += -framework CoreFoundation + } +} + include(../qbase.pri) QMAKE_TARGET_PRODUCT = QTestLib QMAKE_TARGET_DESCRIPTION = Qt \ |