summaryrefslogtreecommitdiffstats
path: root/src/gui/embedded
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@nokia.com>2009-03-23 10:18:55 +0100
committerSimon Hausmann <simon.hausmann@nokia.com>2009-03-23 10:18:55 +0100
commite5fcad302d86d316390c6b0f62759a067313e8a9 (patch)
treec2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/gui/embedded
Long live Qt 4.5!
Diffstat (limited to 'src/gui/embedded')
-rw-r--r--src/gui/embedded/embedded.pri226
-rw-r--r--src/gui/embedded/qcopchannel_qws.cpp608
-rw-r--r--src/gui/embedded/qcopchannel_qws.h108
-rw-r--r--src/gui/embedded/qdecoration_qws.cpp404
-rw-r--r--src/gui/embedded/qdecoration_qws.h124
-rw-r--r--src/gui/embedded/qdecorationdefault_qws.cpp803
-rw-r--r--src/gui/embedded/qdecorationdefault_qws.h101
-rw-r--r--src/gui/embedded/qdecorationfactory_qws.cpp156
-rw-r--r--src/gui/embedded/qdecorationfactory_qws.h66
-rw-r--r--src/gui/embedded/qdecorationplugin_qws.cpp116
-rw-r--r--src/gui/embedded/qdecorationplugin_qws.h80
-rw-r--r--src/gui/embedded/qdecorationstyled_qws.cpp313
-rw-r--r--src/gui/embedded/qdecorationstyled_qws.h73
-rw-r--r--src/gui/embedded/qdecorationwindows_qws.cpp407
-rw-r--r--src/gui/embedded/qdecorationwindows_qws.h77
-rw-r--r--src/gui/embedded/qdirectpainter_qws.cpp682
-rw-r--r--src/gui/embedded/qdirectpainter_qws.h112
-rw-r--r--src/gui/embedded/qkbd_qws.cpp248
-rw-r--r--src/gui/embedded/qkbd_qws.h81
-rw-r--r--src/gui/embedded/qkbddriverfactory_qws.cpp193
-rw-r--r--src/gui/embedded/qkbddriverfactory_qws.h70
-rw-r--r--src/gui/embedded/qkbddriverplugin_qws.cpp124
-rw-r--r--src/gui/embedded/qkbddriverplugin_qws.h84
-rw-r--r--src/gui/embedded/qkbdpc101_qws.cpp485
-rw-r--r--src/gui/embedded/qkbdpc101_qws.h95
-rw-r--r--src/gui/embedded/qkbdsl5000_qws.cpp356
-rw-r--r--src/gui/embedded/qkbdsl5000_qws.h79
-rw-r--r--src/gui/embedded/qkbdtty_qws.cpp263
-rw-r--r--src/gui/embedded/qkbdtty_qws.h81
-rw-r--r--src/gui/embedded/qkbdum_qws.cpp143
-rw-r--r--src/gui/embedded/qkbdum_qws.h77
-rw-r--r--src/gui/embedded/qkbdusb_qws.cpp401
-rw-r--r--src/gui/embedded/qkbdusb_qws.h77
-rw-r--r--src/gui/embedded/qkbdvfb_qws.cpp123
-rw-r--r--src/gui/embedded/qkbdvfb_qws.h86
-rw-r--r--src/gui/embedded/qkbdvr41xx_qws.cpp185
-rw-r--r--src/gui/embedded/qkbdvr41xx_qws.h73
-rw-r--r--src/gui/embedded/qkbdyopy_qws.cpp209
-rw-r--r--src/gui/embedded/qkbdyopy_qws.h73
-rw-r--r--src/gui/embedded/qlock.cpp318
-rw-r--r--src/gui/embedded/qlock_p.h100
-rw-r--r--src/gui/embedded/qmouse_qws.cpp653
-rw-r--r--src/gui/embedded/qmouse_qws.h123
-rw-r--r--src/gui/embedded/qmousebus_qws.cpp238
-rw-r--r--src/gui/embedded/qmousebus_qws.h76
-rw-r--r--src/gui/embedded/qmousedriverfactory_qws.cpp195
-rw-r--r--src/gui/embedded/qmousedriverfactory_qws.h67
-rw-r--r--src/gui/embedded/qmousedriverplugin_qws.cpp124
-rw-r--r--src/gui/embedded/qmousedriverplugin_qws.h84
-rw-r--r--src/gui/embedded/qmouselinuxtp_qws.cpp334
-rw-r--r--src/gui/embedded/qmouselinuxtp_qws.h77
-rw-r--r--src/gui/embedded/qmousepc_qws.cpp793
-rw-r--r--src/gui/embedded/qmousepc_qws.h76
-rw-r--r--src/gui/embedded/qmousetslib_qws.cpp371
-rw-r--r--src/gui/embedded/qmousetslib_qws.h80
-rw-r--r--src/gui/embedded/qmousevfb_qws.cpp132
-rw-r--r--src/gui/embedded/qmousevfb_qws.h83
-rw-r--r--src/gui/embedded/qmousevr41xx_qws.cpp250
-rw-r--r--src/gui/embedded/qmousevr41xx_qws.h80
-rw-r--r--src/gui/embedded/qmouseyopy_qws.cpp184
-rw-r--r--src/gui/embedded/qmouseyopy_qws.h80
-rw-r--r--src/gui/embedded/qscreen_qws.cpp3317
-rw-r--r--src/gui/embedded/qscreen_qws.h387
-rw-r--r--src/gui/embedded/qscreendriverfactory_qws.cpp183
-rw-r--r--src/gui/embedded/qscreendriverfactory_qws.h67
-rw-r--r--src/gui/embedded/qscreendriverplugin_qws.cpp123
-rw-r--r--src/gui/embedded/qscreendriverplugin_qws.h84
-rw-r--r--src/gui/embedded/qscreenlinuxfb_qws.cpp1324
-rw-r--r--src/gui/embedded/qscreenlinuxfb_qws.h129
-rw-r--r--src/gui/embedded/qscreenmulti_qws.cpp482
-rw-r--r--src/gui/embedded/qscreenmulti_qws_p.h114
-rw-r--r--src/gui/embedded/qscreenproxy_qws.cpp631
-rw-r--r--src/gui/embedded/qscreenproxy_qws.h153
-rw-r--r--src/gui/embedded/qscreentransformed_qws.cpp734
-rw-r--r--src/gui/embedded/qscreentransformed_qws.h103
-rw-r--r--src/gui/embedded/qscreenvfb_qws.cpp444
-rw-r--r--src/gui/embedded/qscreenvfb_qws.h86
-rw-r--r--src/gui/embedded/qsoundqss_qws.cpp1498
-rw-r--r--src/gui/embedded/qsoundqss_qws.h177
-rw-r--r--src/gui/embedded/qtransportauth_qws.cpp1562
-rw-r--r--src/gui/embedded/qtransportauth_qws.h281
-rw-r--r--src/gui/embedded/qtransportauth_qws_p.h189
-rw-r--r--src/gui/embedded/qtransportauthdefs_qws.h174
-rw-r--r--src/gui/embedded/qunixsocket.cpp1794
-rw-r--r--src/gui/embedded/qunixsocket_p.h202
-rw-r--r--src/gui/embedded/qunixsocketserver.cpp376
-rw-r--r--src/gui/embedded/qunixsocketserver_p.h98
-rw-r--r--src/gui/embedded/qvfbhdr.h89
-rw-r--r--src/gui/embedded/qwindowsystem_p.h315
-rw-r--r--src/gui/embedded/qwindowsystem_qws.cpp4947
-rw-r--r--src/gui/embedded/qwindowsystem_qws.h508
-rw-r--r--src/gui/embedded/qwscommand_qws.cpp610
-rw-r--r--src/gui/embedded/qwscommand_qws_p.h853
-rw-r--r--src/gui/embedded/qwscursor_qws.cpp654
-rw-r--r--src/gui/embedded/qwscursor_qws.h83
-rw-r--r--src/gui/embedded/qwsdisplay_qws.h185
-rw-r--r--src/gui/embedded/qwsdisplay_qws_p.h161
-rw-r--r--src/gui/embedded/qwsembedwidget.cpp227
-rw-r--r--src/gui/embedded/qwsembedwidget.h82
-rw-r--r--src/gui/embedded/qwsevent_qws.cpp216
-rw-r--r--src/gui/embedded/qwsevent_qws.h459
-rw-r--r--src/gui/embedded/qwslock.cpp243
-rw-r--r--src/gui/embedded/qwslock_p.h85
-rw-r--r--src/gui/embedded/qwsmanager_p.h122
-rw-r--r--src/gui/embedded/qwsmanager_qws.cpp535
-rw-r--r--src/gui/embedded/qwsmanager_qws.h122
-rw-r--r--src/gui/embedded/qwsproperty_qws.cpp145
-rw-r--r--src/gui/embedded/qwsproperty_qws.h96
-rw-r--r--src/gui/embedded/qwsprotocolitem_qws.h100
-rw-r--r--src/gui/embedded/qwssharedmemory.cpp185
-rw-r--r--src/gui/embedded/qwssharedmemory_p.h105
-rw-r--r--src/gui/embedded/qwssignalhandler.cpp134
-rw-r--r--src/gui/embedded/qwssignalhandler_p.h99
-rw-r--r--src/gui/embedded/qwssocket_qws.cpp280
-rw-r--r--src/gui/embedded/qwssocket_qws.h120
-rw-r--r--src/gui/embedded/qwsutils_qws.h98
116 files changed, 39150 insertions, 0 deletions
diff --git a/src/gui/embedded/embedded.pri b/src/gui/embedded/embedded.pri
new file mode 100644
index 0000000000..95c41326b4
--- /dev/null
+++ b/src/gui/embedded/embedded.pri
@@ -0,0 +1,226 @@
+# Qt for Embedded Linux
+
+embedded {
+ CONFIG -= opengl x11
+ LIBS -= -dl
+ KERNEL_P = kernel
+
+ !mac:HEADERS += embedded/qsoundqss_qws.h
+ HEADERS += \
+ embedded/qcopchannel_qws.h \
+ embedded/qdecoration_qws.h \
+ embedded/qdecorationfactory_qws.h \
+ embedded/qdecorationplugin_qws.h \
+ embedded/qdirectpainter_qws.h \
+ embedded/qlock_p.h \
+ embedded/qscreen_qws.h \
+ embedded/qscreenmulti_qws_p.h \
+ embedded/qscreenproxy_qws.h \
+ embedded/qwindowsystem_qws.h \
+ embedded/qwindowsystem_p.h \
+ embedded/qwscommand_qws_p.h \
+ embedded/qwscursor_qws.h \
+ embedded/qwsdisplay_qws.h \
+ embedded/qwsdisplay_qws_p.h \
+ embedded/qwsevent_qws.h \
+ embedded/qwsmanager_qws.h \
+ embedded/qwsmanager_p.h \
+ embedded/qwsproperty_qws.h \
+ embedded/qwsprotocolitem_qws.h \
+ embedded/qtransportauth_qws.h \
+ embedded/qtransportauth_qws_p.h \
+ embedded/qtransportauthdefs_qws.h \
+ embedded/qwssocket_qws.h \
+ embedded/qwslock_p.h \
+ embedded/qwsutils_qws.h \
+ embedded/qwssharedmemory_p.h \
+ embedded/qwssignalhandler_p.h \
+ embedded/qwsembedwidget.h
+
+ !mac:SOURCES += embedded/qsoundqss_qws.cpp
+ SOURCES += \
+ embedded/qcopchannel_qws.cpp \
+ embedded/qdecoration_qws.cpp \
+ embedded/qdecorationfactory_qws.cpp \
+ embedded/qdecorationplugin_qws.cpp \
+ embedded/qdirectpainter_qws.cpp \
+ embedded/qlock.cpp \
+ embedded/qscreen_qws.cpp \
+ embedded/qscreenmulti_qws.cpp \
+ embedded/qscreenproxy_qws.cpp \
+ embedded/qwindowsystem_qws.cpp \
+ embedded/qwscommand_qws.cpp \
+ embedded/qwscursor_qws.cpp \
+ embedded/qwsevent_qws.cpp \
+ embedded/qwsmanager_qws.cpp \
+ embedded/qwsproperty_qws.cpp \
+ embedded/qtransportauth_qws.cpp \
+ embedded/qwslock.cpp \
+ embedded/qwssharedmemory.cpp \
+ embedded/qwssocket_qws.cpp \
+ embedded/qwssignalhandler.cpp \
+ embedded/qwsembedwidget.cpp
+
+ contains(QT_CONFIG,sxe)|contains(QT_CONFIG,qtopia) {
+ SOURCES += embedded/qunixsocket.cpp embedded/qunixsocketserver.cpp
+ HEADERS += embedded/qunixsocket_p.h embedded/qunixsocketserver_p.h
+ }
+
+#
+# Decorations
+#
+ contains( decorations, default ) {
+ HEADERS += embedded/qdecorationdefault_qws.h
+ SOURCES += embedded/qdecorationdefault_qws.cpp
+ }
+ contains( decorations, styled ) {
+ HEADERS += embedded/qdecorationstyled_qws.h
+ SOURCES += embedded/qdecorationstyled_qws.cpp
+ }
+
+ contains( decorations, windows ) {
+ HEADERS += embedded/qdecorationwindows_qws.h
+ SOURCES += embedded/qdecorationwindows_qws.cpp
+ }
+
+#
+# Qt for Embedded Linux Drivers
+#
+ HEADERS += embedded/qscreendriverplugin_qws.h \
+ embedded/qscreendriverfactory_qws.h \
+ embedded/qkbd_qws.h \
+ embedded/qkbddriverplugin_qws.h \
+ embedded/qkbddriverfactory_qws.h \
+ embedded/qmouse_qws.h \
+ embedded/qmousedriverplugin_qws.h \
+ embedded/qmousedriverfactory_qws.h
+
+ SOURCES += embedded/qscreendriverplugin_qws.cpp \
+ embedded/qscreendriverfactory_qws.cpp \
+ embedded/qkbd_qws.cpp \
+ embedded/qkbddriverplugin_qws.cpp \
+ embedded/qkbddriverfactory_qws.cpp \
+ embedded/qmouse_qws.cpp \
+ embedded/qmousedriverplugin_qws.cpp \
+ embedded/qmousedriverfactory_qws.cpp
+
+#
+# Graphics drivers
+#
+ contains( gfx-drivers, linuxfb ) {
+ HEADERS += embedded/qscreenlinuxfb_qws.h
+ SOURCES += embedded/qscreenlinuxfb_qws.cpp
+ }
+
+ contains( gfx-drivers, qvfb ) {
+ HEADERS += embedded/qscreenvfb_qws.h
+ SOURCES += embedded/qscreenvfb_qws.cpp
+ }
+
+ contains( gfx-drivers, vnc ) {
+ VNCDIR = $$QT_SOURCE_TREE/src/plugins/gfxdrivers/vnc
+ INCLUDEPATH += $$VNCDIR
+ HEADERS += $$VNCDIR/qscreenvnc_qws.h \
+ $$VNCDIR/qscreenvnc_p.h
+ SOURCES += $$VNCDIR/qscreenvnc_qws.cpp
+ }
+
+ contains( gfx-drivers, transformed ) {
+ HEADERS += embedded/qscreentransformed_qws.h
+ SOURCES += embedded/qscreentransformed_qws.cpp
+ }
+
+#
+# Keyboard drivers
+#
+ contains( kbd-drivers, qvfb ) {
+ HEADERS +=embedded/qkbdvfb_qws.h
+ SOURCES +=embedded/qkbdvfb_qws.cpp
+ !contains( kbd-drivers, qvfb ) {
+ kbd-drivers += qvfb
+ }
+ }
+
+ contains( kbd-drivers, sl5000 ) {
+ HEADERS +=embedded/qkbdsl5000_qws.h
+ SOURCES +=embedded/qkbdsl5000_qws.cpp
+ !contains( kbd-drivers, tty ) {
+ kbd-drivers += tty
+ }
+ }
+
+ contains( kbd-drivers, tty ) {
+ HEADERS +=embedded/qkbdtty_qws.h
+ SOURCES +=embedded/qkbdtty_qws.cpp
+ !contains( kbd-drivers, pc101 ) {
+ kbd-drivers += pc101
+ }
+ }
+
+ contains( kbd-drivers, usb ) {
+ HEADERS +=embedded/qkbdusb_qws.h
+ SOURCES +=embedded/qkbdusb_qws.cpp
+ !contains( kbd-drivers, pc101 ) {
+ kbd-drivers += pc101
+ }
+ }
+
+ contains( kbd-drivers, um ) {
+ HEADERS +=embedded/qkbdum_qws.h
+ SOURCES +=embedded/qkbdum_qws.cpp
+ }
+
+ contains( kbd-drivers, pc101 ) {
+ HEADERS +=embedded/qkbdpc101_qws.h
+ SOURCES +=embedded/qkbdpc101_qws.cpp
+ }
+
+ contains( kbd-drivers, yopy ) {
+ HEADERS +=embedded/qkbdyopy_qws.h
+ SOURCES +=embedded/qkbdyopy_qws.cpp
+ }
+
+ contains( kbd-drivers, vr41xx ) {
+ HEADERS +=embedded/qkbdvr41xx_qws.h
+ SOURCES +=embedded/qkbdvr41xx_qws.cpp
+ }
+
+#
+# Mouse drivers
+#
+ contains( mouse-drivers, qvfb ) {
+ HEADERS +=embedded/qmousevfb_qws.h
+ SOURCES +=embedded/qmousevfb_qws.cpp
+ }
+
+ contains( mouse-drivers, pc ) {
+ HEADERS +=embedded/qmousepc_qws.h
+ SOURCES +=embedded/qmousepc_qws.cpp
+ }
+
+ contains( mouse-drivers, bus ) {
+ HEADERS +=embedded/qmousebus_qws.h
+ SOURCES +=embedded/qmousebus_qws.cpp
+ }
+
+ contains( mouse-drivers, linuxtp ) {
+ HEADERS +=embedded/qmouselinuxtp_qws.h
+ SOURCES +=embedded/qmouselinuxtp_qws.cpp
+ }
+
+ contains( mouse-drivers, vr41xx ) {
+ HEADERS +=embedded/qmousevr41xx_qws.h
+ SOURCES +=embedded/qmousevr41xx_qws.cpp
+ }
+
+ contains( mouse-drivers, yopy ) {
+ HEADERS +=embedded/qmouseyopy_qws.h
+ SOURCES +=embedded/qmouseyopy_qws.cpp
+ }
+
+ contains( mouse-drivers, tslib ) {
+ LIBS += -lts
+ HEADERS +=embedded/qmousetslib_qws.h
+ SOURCES +=embedded/qmousetslib_qws.cpp
+ }
+}
diff --git a/src/gui/embedded/qcopchannel_qws.cpp b/src/gui/embedded/qcopchannel_qws.cpp
new file mode 100644
index 0000000000..00cf5dcd9c
--- /dev/null
+++ b/src/gui/embedded/qcopchannel_qws.cpp
@@ -0,0 +1,608 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcopchannel_qws.h"
+
+#ifndef QT_NO_COP
+
+#include "qwsdisplay_qws.h"
+#include "qwscommand_qws_p.h"
+#include "qwindowsystem_qws.h"
+#include "qwindowsystem_p.h"
+#include "qlist.h"
+#include "qmap.h"
+#include "qdatastream.h"
+#include "qpointer.h"
+#include "qmutex.h"
+
+#include "qdebug.h"
+
+QT_BEGIN_NAMESPACE
+
+typedef QMap<QString, QList<QWSClient*> > QCopServerMap;
+static QCopServerMap *qcopServerMap = 0;
+
+class QCopServerRegexp
+{
+public:
+ QCopServerRegexp( const QString& channel, QWSClient *client );
+ QCopServerRegexp( const QCopServerRegexp& other );
+
+ QString channel;
+ QWSClient *client;
+ QRegExp regexp;
+};
+
+QCopServerRegexp::QCopServerRegexp( const QString& channel, QWSClient *client )
+{
+ this->channel = channel;
+ this->client = client;
+ this->regexp = QRegExp( channel, Qt::CaseSensitive, QRegExp::Wildcard );
+}
+
+QCopServerRegexp::QCopServerRegexp( const QCopServerRegexp& other )
+{
+ channel = other.channel;
+ client = other.client;
+ regexp = other.regexp;
+}
+
+typedef QList<QCopServerRegexp> QCopServerRegexpList;
+static QCopServerRegexpList *qcopServerRegexpList = 0;
+
+typedef QMap<QString, QList< QPointer<QCopChannel> > > QCopClientMap;
+static QCopClientMap *qcopClientMap = 0;
+
+Q_GLOBAL_STATIC(QMutex, qcopClientMapMutex)
+
+// Determine if a channel name contains wildcard characters.
+static bool containsWildcards( const QString& channel )
+{
+ return channel.contains(QLatin1Char('*'));
+}
+
+class QCopChannelPrivate
+{
+public:
+ QString channel;
+};
+
+/*!
+ \class QCopChannel
+ \ingroup qws
+
+ \brief The QCopChannel class provides communication capabilities
+ between clients in \l{Qt for Embedded Linux}.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ The Qt COmmunication Protocol (QCOP) is a many-to-many protocol
+ for transferring messages across registered channels. A channel is
+ registered by name, and anyone who wants to can listen to the
+ channel as well as send messages through it. The QCOP protocol
+ allows clients to communicate both within the same address space
+ and between different processes.
+
+ To send messages to a given channel, QCopChannel provides the
+ static send() function. Using this function alone, the messages
+ are queued until Qt re-enters the event loop. To immediately flush
+ all queued messages to the registered listeners, call the static
+ flush() function.
+
+ To listen to the traffic on a given channel, you typically
+ instantiate a QCopChannel object for the given channel and connect
+ to its received() signal that is emitted whenever there is
+ incoming data. Use the static isRegistered() function to query
+ the server for the existence of a given channel. QCopChannel
+ provides the channel() function returning the name of this
+ QCopChannel object's channel.
+
+ In additon, QCopChannel provides the virtual receive() function
+ that can be reimplemented to filter the incoming messages and
+ data. The default implementation simply emits the received()
+ signal.
+
+ \sa QWSServer, QWSClient, {Qt for Embedded Linux Architecture}
+*/
+
+/*!
+ Constructs a QCopChannel object for the specified \a channel, with
+ the given \a parent. Once created, the channel is registered by
+ the server.
+
+ \sa isRegistered(), channel()
+*/
+
+QCopChannel::QCopChannel(const QString& channel, QObject *parent) :
+ QObject(parent)
+{
+ init(channel);
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Use the two argument overload instead, and call the
+ QObject::setObjectName() function to \a name the instance.
+*/
+QCopChannel::QCopChannel(const QString& channel, QObject *parent, const char *name) :
+ QObject(parent)
+{
+ setObjectName(QString::fromAscii(name));
+ init(channel);
+}
+#endif
+
+void QCopChannel::init(const QString& channel)
+{
+ d = new QCopChannelPrivate;
+ d->channel = channel;
+
+ if (!qt_fbdpy) {
+ qFatal("QCopChannel: Must construct a QApplication "
+ "before QCopChannel");
+ return;
+ }
+
+ {
+ QMutexLocker locker(qcopClientMapMutex());
+
+ if (!qcopClientMap)
+ qcopClientMap = new QCopClientMap;
+
+ // do we need a new channel list ?
+ QCopClientMap::Iterator it = qcopClientMap->find(channel);
+ if (it != qcopClientMap->end()) {
+ it.value().append(this);
+ return;
+ }
+
+ it = qcopClientMap->insert(channel, QList< QPointer<QCopChannel> >());
+ it.value().append(QPointer<QCopChannel>(this));
+ }
+
+ // inform server about this channel
+ qt_fbdpy->registerChannel(channel);
+}
+
+/*!
+ \internal
+
+ Resend all channel registrations
+ */
+void QCopChannel::reregisterAll()
+{
+ if(qcopClientMap)
+ for(QCopClientMap::Iterator iter = qcopClientMap->begin();
+ iter != qcopClientMap->end();
+ ++iter)
+ qt_fbdpy->registerChannel(iter.key());
+}
+
+/*!
+ Destroys this QCopChannel object.
+
+ The server is notified that this particular listener has closed
+ its connection. The server will keep the channel open until the
+ last registered listener detaches.
+
+ \sa isRegistered(), channel()
+*/
+
+QCopChannel::~QCopChannel()
+{
+ QMutexLocker locker(qcopClientMapMutex());
+ QCopClientMap::Iterator it = qcopClientMap->find(d->channel);
+ Q_ASSERT(it != qcopClientMap->end());
+ it.value().removeAll(this);
+ // still any clients connected locally ?
+ if (it.value().isEmpty()) {
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << d->channel;
+ if (qt_fbdpy)
+ send(QLatin1String(""), QLatin1String("detach()"), data);
+ qcopClientMap->remove(d->channel);
+ }
+
+ delete d;
+}
+
+/*!
+ Returns the name of this object's channel.
+
+ \sa isRegistered()
+*/
+
+QString QCopChannel::channel() const
+{
+ return d->channel;
+}
+
+/*!
+ \fn void QCopChannel::receive(const QString& message, const QByteArray &data)
+
+ Processes the incoming \a message and \a data.
+
+ This function is called by the server when this object's channel
+ receives new messages. Note that the default implementation simply
+ emits the received() signal; reimplement this function to process
+ the incoming \a message and \a data.
+
+ Note that the format of the given \a data has to be well defined
+ in order to extract the information it contains. In addition, it
+ is recommended to use the DCOP convention. This is not a
+ requirement, but you must ensure that the sender and receiver
+ agree on the argument types. For example:
+
+ \snippet doc/src/snippets/code/src_gui_embedded_qcopchannel_qws.cpp 0
+
+ The above code assumes that the \c message is a DCOP-style
+ function signature and the \c data contains the function's
+ arguments.
+
+ \sa send(), channel(), received()
+ */
+void QCopChannel::receive(const QString& msg, const QByteArray &data)
+{
+ emit received(msg, data);
+}
+
+/*!
+ \fn void QCopChannel::received(const QString& message, const QByteArray &data)
+
+ This signal is emitted whenever this object's channel receives new
+ messages (i.e., it is emitted by the receive() function), passing
+ the incoming \a message and \a data as parameters.
+
+ \sa receive(), channel()
+*/
+
+/*!
+ Queries the server for the existence of the given \a channel. Returns true
+ if the channel is registered; otherwise returns false.
+
+ \sa channel(), send()
+*/
+
+bool QCopChannel::isRegistered(const QString& channel)
+{
+ QByteArray data;
+ QDataStream s(&data, QIODevice::WriteOnly);
+ s << channel;
+ if (!send(QLatin1String(""), QLatin1String("isRegistered()"), data))
+ return false;
+
+ QWSQCopMessageEvent *e = qt_fbdpy->waitForQCopResponse();
+ bool known = e->message == "known";
+ delete e;
+ return known;
+}
+
+/*!
+ \fn bool QCopChannel::send(const QString& channel, const QString& message)
+ \overload
+*/
+
+bool QCopChannel::send(const QString& channel, const QString& msg)
+{
+ QByteArray data;
+ return send(channel, msg, data);
+}
+
+/*!
+ \fn bool QCopChannel::send(const QString& channel, const QString& message,
+ const QByteArray &data)
+
+ Sends the given \a message on the specified \a channel with the
+ given \a data. The message will be distributed to all clients
+ subscribed to the channel. Returns true if the message is sent
+ successfully; otherwise returns false.
+
+ It is recommended to use the DCOP convention. This is not a
+ requirement, but you must ensure that the sender and receiver
+ agree on the argument types.
+
+ Note that QDataStream provides a convenient way to fill the byte
+ array with auxiliary data. For example:
+
+ \snippet doc/src/snippets/code/src_gui_embedded_qcopchannel_qws.cpp 1
+
+ In the code above the channel is \c "System/Shell". The \c message
+ is an arbitrary string, but in the example we've used the DCOP
+ convention of passing a function signature. Such a signature is
+ formatted as \c "functionname(types)" where \c types is a list of
+ zero or more comma-separated type names, with no whitespace, no
+ consts and no pointer or reference marks, i.e. no "*" or "&".
+
+ \sa receive(), isRegistered()
+*/
+
+bool QCopChannel::send(const QString& channel, const QString& msg,
+ const QByteArray &data)
+{
+ if (!qt_fbdpy) {
+ qFatal("QCopChannel::send: Must construct a QApplication "
+ "before using QCopChannel");
+ return false;
+ }
+
+ qt_fbdpy->sendMessage(channel, msg, data);
+
+ return true;
+}
+
+/*!
+ \since 4.2
+
+ Flushes all queued messages to the registered listeners.
+
+ Note that this function returns false if no QApplication has been
+ constructed, otherwise it returns true.
+
+ \sa send()
+
+*/
+bool QCopChannel::flush()
+{
+ if (!qt_fbdpy) {
+ qFatal("QCopChannel::flush: Must construct a QApplication "
+ "before using QCopChannel");
+ return false;
+ }
+
+ qt_fbdpy->flushCommands();
+
+ return true;
+}
+
+class QWSServerSignalBridge : public QObject {
+ Q_OBJECT
+
+public:
+ void emitNewChannel(const QString& channel);
+ void emitRemovedChannel(const QString& channel);
+
+ signals:
+ void newChannel(const QString& channel);
+ void removedChannel(const QString& channel);
+};
+
+void QWSServerSignalBridge::emitNewChannel(const QString& channel){
+ emit newChannel(channel);
+}
+
+void QWSServerSignalBridge::emitRemovedChannel(const QString& channel) {
+ emit removedChannel(channel);
+}
+
+/*!
+ \internal
+ Server side: subscribe client \a cl on channel \a ch.
+*/
+
+void QCopChannel::registerChannel(const QString& ch, QWSClient *cl)
+{
+ if (!qcopServerMap)
+ qcopServerMap = new QCopServerMap;
+
+ // do we need a new channel list ?
+ QCopServerMap::Iterator it = qcopServerMap->find(ch);
+ if (it == qcopServerMap->end())
+ it = qcopServerMap->insert(ch, QList<QWSClient*>());
+
+ // If the channel name contains wildcard characters, then we also
+ // register it on the server regexp matching list.
+ if (containsWildcards( ch )) {
+ QCopServerRegexp item(ch, cl);
+ if (!qcopServerRegexpList)
+ qcopServerRegexpList = new QCopServerRegexpList;
+ qcopServerRegexpList->append( item );
+ }
+
+ // If this is the first client in the channel, announce the channel as being created.
+ if (it.value().count() == 0) {
+ QWSServerSignalBridge* qwsBridge = new QWSServerSignalBridge();
+ connect(qwsBridge, SIGNAL(newChannel(QString)), qwsServer, SIGNAL(newChannel(QString)));
+ qwsBridge->emitNewChannel(ch);
+ delete qwsBridge;
+ }
+
+ it.value().append(cl);
+}
+
+/*!
+ \internal
+ Server side: unsubscribe \a cl from all channels.
+*/
+
+void QCopChannel::detach(QWSClient *cl)
+{
+ if (!qcopServerMap)
+ return;
+
+ QCopServerMap::Iterator it = qcopServerMap->begin();
+ for (; it != qcopServerMap->end(); ++it) {
+ if (it.value().contains(cl)) {
+ it.value().removeAll(cl);
+ // If this was the last client in the channel, announce the channel as dead.
+ if (it.value().count() == 0) {
+ QWSServerSignalBridge* qwsBridge = new QWSServerSignalBridge();
+ connect(qwsBridge, SIGNAL(removedChannel(QString)), qwsServer, SIGNAL(removedChannel(QString)));
+ qwsBridge->emitRemovedChannel(it.key());
+ delete qwsBridge;
+ }
+ }
+ }
+
+ if (!qcopServerRegexpList)
+ return;
+
+ QCopServerRegexpList::Iterator it2 = qcopServerRegexpList->begin();
+ while(it2 != qcopServerRegexpList->end()) {
+ if ((*it2).client == cl)
+ it2 = qcopServerRegexpList->erase(it2);
+ else
+ ++it2;
+ }
+}
+
+/*!
+ \internal
+ Server side: transmit the message to all clients registered to the
+ specified channel.
+*/
+
+void QCopChannel::answer(QWSClient *cl, const QString& ch,
+ const QString& msg, const QByteArray &data)
+{
+ // internal commands
+ if (ch.isEmpty()) {
+ if (msg == QLatin1String("isRegistered()")) {
+ QString c;
+ QDataStream s(data);
+ s >> c;
+ bool known = qcopServerMap && qcopServerMap->contains(c)
+ && !((*qcopServerMap)[c]).isEmpty();
+ // Yes, it's a typo, it's not user-visible, and we choose not to fix it for compatibility
+ QLatin1String ans = QLatin1String(known ? "known" : "unkown");
+ QWSServerPrivate::sendQCopEvent(cl, QLatin1String(""),
+ ans, data, true);
+ return;
+ } else if (msg == QLatin1String("detach()")) {
+ QString c;
+ QDataStream s(data);
+ s >> c;
+ Q_ASSERT(qcopServerMap);
+ QCopServerMap::Iterator it = qcopServerMap->find(c);
+ if (it != qcopServerMap->end()) {
+ //Q_ASSERT(it.value().contains(cl));
+ it.value().removeAll(cl);
+ if (it.value().isEmpty()) {
+ // If this was the last client in the channel, announce the channel as dead
+ QWSServerSignalBridge* qwsBridge = new QWSServerSignalBridge();
+ connect(qwsBridge, SIGNAL(removedChannel(QString)), qwsServer, SIGNAL(removedChannel(QString)));
+ qwsBridge->emitRemovedChannel(it.key());
+ delete qwsBridge;
+ qcopServerMap->erase(it);
+ }
+ }
+ if (qcopServerRegexpList && containsWildcards(c)) {
+ // Remove references to a wildcarded channel.
+ QCopServerRegexpList::Iterator it
+ = qcopServerRegexpList->begin();
+ while(it != qcopServerRegexpList->end()) {
+ if ((*it).client == cl && (*it).channel == c)
+ it = qcopServerRegexpList->erase(it);
+ else
+ ++it;
+ }
+ }
+ return;
+ }
+ qWarning("QCopChannel: unknown internal command %s", qPrintable(msg));
+ QWSServerPrivate::sendQCopEvent(cl, QLatin1String(""),
+ QLatin1String("bad"), data);
+ return;
+ }
+
+ if (qcopServerMap) {
+ QList<QWSClient*> clist = qcopServerMap->value(ch);
+ for (int i=0; i < clist.size(); ++i) {
+ QWSClient *c = clist.at(i);
+ QWSServerPrivate::sendQCopEvent(c, ch, msg, data);
+ }
+ }
+
+ if(qcopServerRegexpList && !containsWildcards(ch)) {
+ // Search for wildcard matches and forward the message on.
+ QCopServerRegexpList::ConstIterator it = qcopServerRegexpList->constBegin();
+ for (; it != qcopServerRegexpList->constEnd(); ++it) {
+ if ((*it).regexp.exactMatch(ch)) {
+ QByteArray newData;
+ {
+ QDataStream stream
+ (&newData, QIODevice::WriteOnly | QIODevice::Append);
+ stream << ch;
+ stream << msg;
+ stream << data;
+ // Stream is flushed and closed at this point.
+ }
+ QWSServerPrivate::sendQCopEvent
+ ((*it).client, (*it).channel,
+ QLatin1String("forwardedMessage(QString,QString,QByteArray)"),
+ newData);
+ }
+ }
+ }
+}
+
+/*!
+ \internal
+ Client side: distribute received event to the QCop instance managing the
+ channel.
+*/
+void QCopChannel::sendLocally(const QString& ch, const QString& msg,
+ const QByteArray &data)
+{
+ Q_ASSERT(qcopClientMap);
+
+ // filter out internal events
+ if (ch.isEmpty())
+ return;
+
+ // feed local clients with received data
+ QList< QPointer<QCopChannel> > clients;
+ {
+ QMutexLocker locker(qcopClientMapMutex());
+ clients = (*qcopClientMap)[ch];
+ }
+ for (int i = 0; i < clients.size(); ++i) {
+ QCopChannel *channel = (QCopChannel *)clients.at(i);
+ if ( channel )
+ channel->receive(msg, data);
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "qcopchannel_qws.moc"
+
+#endif
diff --git a/src/gui/embedded/qcopchannel_qws.h b/src/gui/embedded/qcopchannel_qws.h
new file mode 100644
index 0000000000..d6e6e6b5aa
--- /dev/null
+++ b/src/gui/embedded/qcopchannel_qws.h
@@ -0,0 +1,108 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOPCHANNEL_QWS_H
+#define QCOPCHANNEL_QWS_H
+
+#include <QtCore/qobject.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_COP
+
+class QWSClient;
+class QCopChannelPrivate;
+
+class Q_GUI_EXPORT QCopChannel : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QCopChannel(const QString& channel, QObject *parent=0);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QCopChannel(const QString& channel, QObject *parent, const char *name);
+#endif
+ virtual ~QCopChannel();
+
+ QString channel() const;
+
+ static bool isRegistered(const QString& channel);
+ static bool send(const QString& channel, const QString& msg);
+ static bool send(const QString& channel, const QString& msg,
+ const QByteArray &data);
+
+ static bool flush();
+
+ static void sendLocally( const QString& ch, const QString& msg,
+ const QByteArray &data);
+ static void reregisterAll();
+
+ virtual void receive(const QString& msg, const QByteArray &data);
+
+Q_SIGNALS:
+ void received(const QString& msg, const QByteArray &data);
+
+private:
+ void init(const QString& channel);
+
+ // server side
+ static void registerChannel(const QString& ch, QWSClient *cl);
+ static void detach(QWSClient *cl);
+ static void answer(QWSClient *cl, const QString& ch,
+ const QString& msg, const QByteArray &data);
+ // client side
+ QCopChannelPrivate* d;
+
+ friend class QWSServer;
+ friend class QWSServerPrivate;
+ friend class QApplication;
+};
+
+#endif // QT_NO_COP
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QCOPCHANNEL_QWS_H
diff --git a/src/gui/embedded/qdecoration_qws.cpp b/src/gui/embedded/qdecoration_qws.cpp
new file mode 100644
index 0000000000..4ac1f01d4b
--- /dev/null
+++ b/src/gui/embedded/qdecoration_qws.cpp
@@ -0,0 +1,404 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdecoration_qws.h"
+
+#include "qapplication.h"
+#include "qdrawutil.h"
+#include "qpainter.h"
+#include "qregion.h"
+#include "qwhatsthis.h"
+
+#include "qmenu.h"
+#include "private/qwidget_p.h"
+#include "qwsmanager_qws.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDecoration
+ \ingroup qws
+
+ \brief The QDecoration class is a base class for window
+ decorations in Qt for Embedded Linux
+
+ Note that this class is non-portable and only available in
+ \l{Qt for Embedded Linux}.
+
+ \l{Qt for Embedded Linux} provides window management of top level windows
+ and several ready made decorations (i.e., \c Default, \c Styled
+ and \c Windows). Custom decorations can be implemented by
+ subclassing the QDecoration class and creating a decoration plugin
+ (derived from QDecorationPlugin). The default
+ implementation of the QDecorationFactory class will automatically
+ detect the plugin, and load the decoration into the application at
+ run-time using Qt's \l {How to Create Qt Plugins}{plugin
+ system}. To actually apply a decoration, use the
+ QApplication::qwsSetDecoration() function.
+
+ When creating a custom decoration, implement the paint() function
+ to paint the border and title decoration, and the region()
+ function to return the regions the decoration
+ occupies. Reimplement the regionClicked() and
+ regionDoubleClicked() functions to respond to mouse clicks (the
+ default implementations responds to (single) clicks on items in a
+ widget's system menu and double clicks on a widget's title).
+
+ QDecoration provides the DecorationRegion enum that describes the
+ various regions of the window decoration, and the regionAt()
+ function to determine the region containing a given point. The
+ QDecoration class also provides the DecorationState enum
+ describing the state of a given region, e.g. whether it is active
+ or not.
+
+ In addition, it is possible to build the system menu for a given
+ top level widget using the buildSysMenu() function; whenever an
+ action in this menu is triggered, the menuTriggered() function is
+ called automatically.
+
+ Finally, the QDecoration class provides a couple of static
+ functions, startMove() and startResize(), which start a move or
+ resize action by making the appropriate decoration region active
+ and grabbing the mouse input.
+
+ \sa QDecorationFactory, QDecorationPlugin, {Qt for Embedded Linux
+ Architecture}
+*/
+
+/*!
+ \fn QDecoration::QDecoration()
+
+ Constructs a decoration object.
+*/
+
+/*!
+ \fn QDecoration::~QDecoration()
+
+ Destroys this decoration object.
+*/
+
+/*!
+ \enum QDecoration::DecorationRegion
+
+ This enum describes the various regions of the window decoration.
+
+ \value All The entire region used by the window decoration.
+
+ \value Top The top border used to vertically resize the window.
+ \value Bottom The bottom border used to vertically resize the window.
+ \value Left The left border used to horizontally resize the window.
+ \value Right The right border used to horizontally resize the window.
+ \value TopLeft The top-left corner of the window used to resize the
+ window both horizontally and vertically.
+ \value TopRight The top-right corner of the window used to resize the
+ window both horizontally and vertically.
+ \value BottomLeft The bottom-left corner of the window used to resize the
+ window both horizontally and vertically.
+ \value BottomRight The bottom-right corner of the window used to resize the
+ window both horizontally and vertically.
+ \value Borders All the regions used to describe the window's borders.
+
+ \value Title The region containing the window title, used
+ to move the window by dragging with the mouse cursor.
+ \value Close The region occupied by the close button. Clicking in this
+ region closes the window.
+ \value Minimize The region occupied by the minimize button. Clicking in
+ this region minimizes the window.
+ \value Maximize The region occupied by the maximize button. Clicking in
+ this region maximizes the window.
+ \value Normalize The region occupied by a button used to restore a window's
+ normal size. Clicking in this region restores a maximized
+ window to its previous size. The region used for this
+ button is often also the Maximize region.
+ \value Menu The region occupied by the window's menu button. Clicking
+ in this region opens the window operations (system) menu.
+ \value Help The region occupied by the window's help button. Clicking
+ in this region causes the context-sensitive help function
+ to be enabled.
+ \value Resize The region used to resize the window.
+ \value Move The region used to move the window.
+ \value None No region.
+
+ \sa region(), regionAt(), DecorationState
+*/
+
+/*!
+ \enum QDecoration::DecorationState
+
+ This enum describes the various states of a decoration region.
+
+ \value Normal The region is active
+ \value Disabled The region is inactive.
+ \value Hover The cursor is hovering over the region.
+ \value Pressed The region is pressed.
+
+ \sa paint(), DecorationRegion
+*/
+
+/*!
+ \fn QRegion QDecoration::region(const QWidget *widget, const QRect & rectangle, int decorationRegion)
+
+ Implement this function to return the region specified by \a
+ decorationRegion for the given top level \a widget.
+
+ The \a rectangle parameter specifies the rectangle the decoration
+ is wrapped around. The \a decorationRegion is a bitmask of the
+ values described by the DecorationRegion enum.
+
+ \sa regionAt(), paint()
+*/
+
+/*!
+ \fn QRegion QDecoration::region(const QWidget *widget, int decorationRegion)
+ \overload
+*/
+
+/*!
+ \fn bool QDecoration::paint(QPainter *painter, const QWidget *widget, int decorationRegion,
+ DecorationState state)
+
+ Implement this function to paint the border and title decoration
+ for the specified top level \a widget using the given \a painter
+ and decoration \a state. The specified \a decorationRegion is a
+ bitmask of the values described by the DecorationRegion enum.
+
+ Note that \l{Qt for Embedded Linux} expects this function to return true if
+ any of the widget's decorations are repainted; otherwise it should
+ return false.
+
+ \sa region()
+*/
+
+/*!
+ \fn int QDecoration::regionAt(const QWidget *widget, const QPoint &point)
+
+ Returns the type of the first region of the specified top level \a
+ widget containing the given \a point.
+
+ The return value is one of the DecorationRegion enum's values. Use
+ the region() function to retrieve the actual region. If none of
+ the widget's regions contain the point, this function returns \l
+ None.
+
+ \sa region()
+*/
+int QDecoration::regionAt(const QWidget *w, const QPoint &point)
+{
+ int regions[] = {
+ TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight, // Borders first
+ Menu, Title, Help, Minimize, Normalize, Maximize, Close, // then buttons
+ None
+ };
+
+// char *regions_str[] = {
+// "TopLeft", "Top", "TopRight", "Left", "Right", "BottomLeft", "Bottom", "BottomRight",
+// "Menu", "Title", "Help", "Minimize", "Normalize", "Maximize", "Close",
+// "None"
+// };
+
+ // First check to see if within all regions at all
+ QRegion reg = region(w, w->geometry(), All);
+ if (!reg.contains(point)) {
+ return None;
+ }
+
+ int i = 0;
+ while (regions[i]) {
+ reg = region(w, w->geometry(), regions[i]);
+ if (reg.contains(point)) {
+// qDebug("In region %s", regions_str[i]);
+ return regions[i];
+ }
+ ++i;
+ }
+ return None;
+}
+
+#ifndef QT_NO_MENU
+/*!
+ Builds the system menu for the given top level \a widget, adding
+ \gui Restore, \gui Move, \gui Size, \gui Minimize, \gui Maximize
+ and \gui Close actions to the given \a menu.
+
+ \sa menuTriggered()
+*/
+void QDecoration::buildSysMenu(QWidget *widget, QMenu *menu)
+{
+ QDecorationAction *act = new QDecorationAction(QLatin1String("Restore"),
+ menu, Maximize);
+ act->setEnabled(widget->windowState() & Qt::WindowMaximized);
+ menu->addAction(act);
+ act = new QDecorationAction(QLatin1String("Move"), menu, Move);
+ act->setEnabled(!(widget->windowState() & Qt::WindowMaximized));
+ menu->addAction(act);
+ menu->addAction(new QDecorationAction(QLatin1String("Size"), menu, Resize));
+ act = new QDecorationAction(QLatin1String("Minimize"), menu, Minimize);
+ menu->addAction(act);
+ act = new QDecorationAction(QLatin1String("Maximize"), menu, Maximize);
+ act->setDisabled(widget->windowState() & Qt::WindowMaximized);
+ menu->addAction(act);
+ menu->addSeparator();
+ menu->addAction(new QDecorationAction(QLatin1String("Close"), menu, Close));
+}
+
+/*!
+ This function is called whenever an action in a top level widget's
+ menu is triggered, and simply calls the regionClicked() function
+ passing the \a widget and \a action parameters as arguments.
+
+ \sa buildSysMenu()
+*/
+void QDecoration::menuTriggered(QWidget *widget, QAction *action)
+{
+ QDecorationAction *decAction = static_cast<QDecorationAction *>(action);
+ regionClicked(widget, decAction->reg);
+}
+#endif // QT_NO_MENU
+
+/*!
+ \fn void QDecoration::regionClicked(QWidget *widget, int region)
+
+ Handles the event that the specified \a region in the given top
+ level \a widget is activated by a single click (the \a region
+ parameter is described using the DecorationRegion enum).
+
+ This function is called whenever a region in a top level widget is
+ clicked; the default implementation responds to clicks on items in
+ the system menu, performing the requested actions.
+
+ \sa regionDoubleClicked(), region()
+*/
+void QDecoration::regionClicked(QWidget *widget, int reg)
+{
+ switch(reg) {
+ case Move:
+ startMove(widget);
+ break;
+ case Resize:
+ startResize(widget);
+ break;
+ case Help:
+#ifndef QT_NO_WHATSTHIS
+ if (QWhatsThis::inWhatsThisMode())
+ QWhatsThis::leaveWhatsThisMode();
+ else
+ QWhatsThis::enterWhatsThisMode();
+#endif
+ break;
+ case Close:
+ widget->close();
+ break;
+ case Normalize:
+ widget->showNormal();
+ break;
+ case Maximize:
+ if (widget->windowState() & Qt::WindowMaximized)
+ widget->showNormal();
+ else
+ widget->showMaximized();
+ break;
+ }
+}
+
+/*!
+ \fn void QDecoration::regionDoubleClicked(QWidget *widget, int region)
+
+ Handles the event that the specified \a region in the given top
+ level \a widget is activated by a double click (the region
+ parameter is described using the DecorationRegion enum).
+
+ This function is called whenever a region in a top level widget is
+ double clicked; the default implementation responds to a double
+ click on the widget's title, toggling its size between the maximum
+ and its normal size.
+
+ \sa regionClicked(), region()
+*/
+void QDecoration::regionDoubleClicked(QWidget *widget, int reg)
+{
+ switch(reg)
+ {
+ case Title: {
+ if (widget->windowState() & Qt::WindowMaximized)
+ widget->showNormal();
+ else
+ widget->showMaximized();
+ break;
+ }
+ }
+}
+
+/*!
+ Starts to move the given top level \a widget by making its \l
+ Title region active and grabbing the mouse input.
+
+ \sa startResize()
+*/
+void QDecoration::startMove(QWidget *widget)
+{
+#ifdef QT_NO_QWS_MANAGER
+ Q_UNUSED(widget);
+#else
+ QWSManager *manager = widget->d_func()->topData()->qwsManager;
+ if (manager)
+ manager->startMove();
+#endif
+}
+
+/*!
+ Starts to resize the given top level \a widget by making its \l
+ BottomRight region active and grabbing the mouse input.
+
+ \sa startMove()
+*/
+void QDecoration::startResize(QWidget *widget)
+{
+#ifdef QT_NO_QWS_MANAGER
+ Q_UNUSED(widget);
+#else
+ QWSManager *manager = widget->d_func()->topData()->qwsManager;
+ if (manager)
+ manager->startResize();
+#endif
+}
+
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qdecoration_qws.h b/src/gui/embedded/qdecoration_qws.h
new file mode 100644
index 0000000000..ff4ebac29d
--- /dev/null
+++ b/src/gui/embedded/qdecoration_qws.h
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECORATION_QWS_H
+#define QDECORATION_QWS_H
+
+#include <QtGui/qregion.h>
+#include <QtGui/qwidget.h>
+#include <QtGui/qaction.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QPopupMenu;
+class QMenu;
+
+#ifndef QT_NO_ACTION
+class QDecorationAction : public QAction
+{
+public:
+ QDecorationAction(const QString &text, QObject* parent, int region)
+ : QAction(text, parent), reg(region) {}
+ int reg;
+};
+#endif // QT_NO_ACTION
+
+/*
+ Implements decoration styles
+*/
+class Q_GUI_EXPORT QDecoration
+{
+public:
+ QDecoration() {}
+ virtual ~QDecoration() {}
+
+ /* AABBBBBBBBBBCC Items in DecorationRegion:
+ AijjjjjjjklmnC
+ A C A = TopLeft B = Top C = TopRight
+ D E D = Left E = Right
+ D E F = BottomLeft H = Bottom G = BottomRight
+ F G i = Menu j = Title k = Help
+ FFHHHHHHHHHHGG l = Minimize m = Maximize n = Close
+
+ */
+
+ enum DecorationRegion {
+ None = 0x0000000000, All = 0x7fffffff,
+ TopLeft = 0x0000000001, Top = 0x0000000002, TopRight = 0x0000000004,
+ Left = 0x0000000008, Right = 0x0000000010,
+ BottomLeft = 0x0000000020, Bottom = 0x0000000040, BottomRight = 0x0000000080,
+ Borders = 0x00000000ff,
+ Menu = 0x0000000100, Title = 0x0000000200, Help = 0x0000000400,
+ Minimize = 0x0000000800, Maximize = 0x0000001000, Normalize = 0x0000002000,
+ Close = 0x0000004000, Move = 0x0000008000, Resize = 0x0000010000
+ };
+
+ enum DecorationState { Normal = 0x04, Disabled = 0x08, Hover = 0x01, Pressed = 0x02 };
+
+ virtual QRegion region(const QWidget *w, const QRect &rect, int decorationRegion = All ) = 0;
+ QRegion region(const QWidget *w, int decorationRegion = All )
+ { return region(w, w->rect(), decorationRegion); }
+ virtual int regionAt(const QWidget *w, const QPoint &point);
+
+ virtual void regionClicked(QWidget *widget, int region);
+ virtual void regionDoubleClicked(QWidget *widget, int region);
+#ifndef QT_NO_MENU
+ virtual void buildSysMenu(QWidget *widget, QMenu *menu);
+ void menuTriggered(QWidget *widget, QAction *action);
+#endif
+
+ static void startMove(QWidget *widget);
+ static void startResize(QWidget *widget);
+
+ virtual bool paint(QPainter *p, const QWidget *w, int decorationRegion = All,
+ DecorationState state = Normal) = 0;
+
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECORATION_QWS_H
diff --git a/src/gui/embedded/qdecorationdefault_qws.cpp b/src/gui/embedded/qdecorationdefault_qws.cpp
new file mode 100644
index 0000000000..6e5314d7f2
--- /dev/null
+++ b/src/gui/embedded/qdecorationdefault_qws.cpp
@@ -0,0 +1,803 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qapplication.h>
+#include <qwidget.h>
+#include <qpainter.h>
+#include <qpaintengine.h>
+#include <qdrawutil.h>
+#include "qdecorationdefault_qws.h"
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_QWS_DECORATION_DEFAULT) || defined(QT_PLUGIN)
+
+QPixmap *QDecorationDefault::staticHelpPixmap = 0;
+QPixmap *QDecorationDefault::staticMenuPixmap = 0;
+QPixmap *QDecorationDefault::staticClosePixmap = 0;
+QPixmap *QDecorationDefault::staticMinimizePixmap = 0;
+QPixmap *QDecorationDefault::staticMaximizePixmap = 0;
+QPixmap *QDecorationDefault::staticNormalizePixmap = 0;
+
+#ifndef QT_NO_IMAGEFORMAT_XPM
+
+/* XPM */
+static const char * const default_menu_xpm[] = {
+/* width height ncolors chars_per_pixel */
+"16 16 11 1",
+/* colors */
+" c #000000",
+". c #336600",
+"X c #666600",
+"o c #99CC00",
+"O c #999933",
+"+ c #333300",
+"@ c #669900",
+"# c #999900",
+"$ c #336633",
+"% c #666633",
+"& c #99CC33",
+/* pixels */
+"oooooooooooooooo",
+"oooooooooooooooo",
+"ooooo#.++X#ooooo",
+"ooooX Xoooo",
+"oooX XO#% X&oo",
+"oo# Ooo&@O Ooo",
+"oo. Xoo#+ @X Xoo",
+"oo+ OoO+ +O# +oo",
+"oo+ #O+ +## +oo",
+"oo. %@ ++ +. Xoo",
+"oo# O@OO+ #oo",
+"oooX X##$ Ooo",
+"ooooX Xoo",
+"oooo&OX++X#OXooo",
+"oooooooooooooooo",
+"oooooooooooooooo"
+};
+
+static const char * const default_help_xpm[] = {
+"16 16 3 1",
+" s None c None",
+". c #ffffff",
+"X c #707070",
+" ",
+" ",
+" ...... ",
+" ..XXXXXX ",
+" .XX .XX ",
+" .XX .XX ",
+" ..XX ",
+" ..XX ",
+" ..XX ",
+" .XX ",
+" .XX ",
+" .. ",
+" .XX ",
+" .XX ",
+" ",
+" "};
+
+static const char * const default_close_xpm[] = {
+"16 16 3 1",
+" s None c None",
+". c #ffffff",
+"X c #707070",
+" ",
+" ",
+" .X .X ",
+" .XX .XX ",
+" .XX .XX ",
+" .XX .XX ",
+" .XX.XX ",
+" .XXX ",
+" .XXX ",
+" .XX.XX ",
+" .XX .XX ",
+" .XX .XX ",
+" .XX .XX ",
+" .X .X ",
+" ",
+" "};
+
+static const char * const default_maximize_xpm[] = {
+"16 16 3 1",
+" s None c None",
+". c #ffffff",
+"X c #707070",
+" ",
+" ",
+" ........... ",
+" .XXXXXXXXXX ",
+" .X .X ",
+" .X .X ",
+" .X .X ",
+" .X .X ",
+" .X .X ",
+" .X .X ",
+" .X .X ",
+" .X........X ",
+" .XXXXXXXXXX ",
+" ",
+" ",
+" "};
+
+static const char * const default_minimize_xpm[] = {
+"16 16 3 1",
+" s None c None",
+". c #ffffff",
+"X c #707070",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ... ",
+" . X ",
+" .XX ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" "};
+
+static const char * const default_normalize_xpm[] = {
+"16 16 3 1",
+" s None c None",
+". c #ffffff",
+"X c #707070",
+" ",
+" ",
+" ........ ",
+" .XXXXXXXX ",
+" .X .X ",
+" .X .X ",
+" ....X... .X ",
+" .XXXXXXXX .X ",
+" .X .XXXX ",
+" .X .X ",
+" .X .X ",
+" .X......X ",
+" .XXXXXXXX ",
+" ",
+" ",
+" "};
+
+#endif // QT_NO_IMAGEFORMAT_XPM
+
+/*!
+ \class QDecorationDefault
+ \since 4.4
+ \ingroup qws
+ \brief The QDecorationDefault class is a base class providing default window decorations.
+
+ See the documentation for class QDecoration for a detailed
+ description. This subclass of QDecoration provides standard
+ icons for the decoration regions.
+
+ Note that this class is non-portable and only available in
+ \l{Qt for Embedded Linux}.
+ */
+
+/*!
+ Default constructor.
+ */
+QDecorationDefault::QDecorationDefault()
+ : QDecoration()
+{
+ menu_width = 20;
+ help_width = 20;
+ close_width = 20;
+ minimize_width = 20;
+ maximize_width = 20;
+ normalize_width = 20;
+}
+
+/*!
+ The constructor deletes the static pixmaps.
+ */
+QDecorationDefault::~QDecorationDefault()
+{
+ delete staticMenuPixmap;
+ delete staticClosePixmap;
+ delete staticMinimizePixmap;
+ delete staticMaximizePixmap;
+ delete staticNormalizePixmap;
+
+ // This makes it safe to delete and then create a QDecorationDefault
+ staticMenuPixmap = 0;
+ staticClosePixmap = 0;
+ staticMinimizePixmap = 0;
+ staticMaximizePixmap = 0;
+ staticNormalizePixmap = 0;
+}
+
+/*!
+ \fn const char **QDecorationDefault::xpmForRegion(int region)
+
+ Returns a pointer to the X pixmap for the icon specified by
+ \a region. An X pixmap is an ASCII-text-based image. The value
+ of \a region must be one of a subset of the values of enum
+ DecorationRegion. The supported values are \e Help, \e Menu,
+ \e Close, \e Minimize, \e Maximize, and \e Normalize. Other
+ values of \a region cause zero to be returned.
+
+ \sa QDecoration::DecorationRegion
+ */
+const char **QDecorationDefault::xpmForRegion(int reg)
+{
+#ifdef QT_NO_IMAGEFORMAT_XPM
+ Q_UNUSED(reg);
+#else
+ switch(reg)
+ {
+ case Help:
+ return (const char **)default_help_xpm;
+ case Menu:
+ return (const char **)default_menu_xpm;
+ case Close:
+ return (const char **)default_close_xpm;
+ case Minimize:
+ return (const char **)default_minimize_xpm;
+ case Maximize:
+ return (const char **)default_maximize_xpm;
+ case Normalize:
+ return (const char **)default_normalize_xpm;
+ }
+#endif
+ return 0;
+}
+
+/*!
+ \fn QPixmap QDecorationDefault::pixmapFor(const QWidget *widget,
+ int decorationRegion, int &xoff, int &yoff)
+
+ Returns a pointer to the QPixmap for the widget specified by \a widget and
+ \a decorationRegion. The returned QPixmap is constructed from the default
+ X pixmap obtained from xpmForRegion().
+
+ \a xoff and \a yoff specify the offset for the pixmap.
+
+ The value of \a decorationRegion must be one of a subset of the values
+ of enum DecorationRegion. The supported values are \e Help,
+ \e Menu, \e Close, \e Minimize, \e Maximize, and \e Normalize.
+ Other values of \a decorationRegion return 0.
+
+ \sa QDecoration::DecorationRegion
+*/
+QPixmap QDecorationDefault::pixmapFor(const QWidget *widget,
+ int decorationRegion,
+ int &xoff,
+ int &/*yoff*/)
+{
+#ifdef QT_NO_IMAGEFORMAT_XPM
+ Q_UNUSED(widget);
+ Q_UNUSED(decorationRegion);
+ Q_UNUSED(xoff);
+ return QPixmap();
+#else
+ static const char **staticHelpPixmapXPM = 0;
+ static const char **staticMenuPixmapXPM = 0;
+ static const char **staticClosePixmapXPM = 0;
+ static const char **staticMinimizePixmapXPM = 0;
+ static const char **staticMaximizePixmapXPM = 0;
+ static const char **staticNormalizePixmapXPM = 0;
+ const char **xpm;
+
+ // Why don't we just use/extend the enum type...
+
+ if (staticHelpPixmapXPM != (xpm = xpmForRegion(Help)) || !staticHelpPixmap) {
+ staticHelpPixmapXPM = xpm;
+ staticHelpPixmap = new QPixmap(xpm);
+ }
+ if (staticMenuPixmapXPM != (xpm = xpmForRegion(Menu)) || !staticMenuPixmap) {
+ staticMenuPixmapXPM = xpm;
+ staticMenuPixmap = new QPixmap(xpm);
+ }
+ if (staticClosePixmapXPM != (xpm = xpmForRegion(Close)) || !staticClosePixmap) {
+ staticClosePixmapXPM = xpm;
+ staticClosePixmap = new QPixmap(xpm);
+ }
+ if (staticMinimizePixmapXPM != (xpm = xpmForRegion(Minimize)) || !staticMinimizePixmap) {
+ staticMinimizePixmapXPM = xpm;
+ staticMinimizePixmap = new QPixmap(xpm);
+ }
+ if (staticMaximizePixmapXPM != (xpm = xpmForRegion(Maximize)) || !staticMaximizePixmap) {
+ staticMaximizePixmapXPM = xpm;
+ staticMaximizePixmap = new QPixmap(xpm);
+ }
+ if (staticNormalizePixmapXPM != (xpm = xpmForRegion(Normalize)) || !staticNormalizePixmap) {
+ staticNormalizePixmapXPM = xpm;
+ staticNormalizePixmap = new QPixmap(xpm);
+ }
+
+ const QPixmap *pm = 0;
+
+ switch (decorationRegion) {
+ case Help:
+ pm = staticHelpPixmap;
+ break;
+ case Menu:
+ if (!widget->windowIcon().isNull())
+ return widget->windowIcon().pixmap(16,16); //##### QIcon::pixmap() needs a size !!!!!!"
+ if (!pm) {
+ xoff = 1;
+ pm = staticMenuPixmap;
+ }
+ break;
+ case Close:
+ pm = staticClosePixmap;
+ break;
+ case Maximize:
+ pm = staticMaximizePixmap;
+ break;
+ case Normalize:
+ pm = staticNormalizePixmap;
+ break;
+ case Minimize:
+ pm = staticMinimizePixmap;
+ break;
+ default:
+ break;
+ }
+ return *pm;
+#endif
+}
+
+/*!
+ \fn int QDecorationDefault::titleBarHeight(const QWidget *widget)
+
+ Returns the title bar height in pixels for the given \a widget. It is the
+ greater of 20, or the sum of the application font's line spacing value
+ plus a border width fudge factor.
+*/
+int QDecorationDefault::titleBarHeight(const QWidget *)
+{
+ return qMax(20, QApplication::fontMetrics().lineSpacing() + BORDER_WIDTH);
+}
+
+/*!
+ Returns the region specified by \a decorationRegion for the
+ top-level \a widget. \a rect specifies the rectangle the decoration
+ wraps. The value of \a decorationRegion is a combination of the
+ bitmask values of enum DecorationRegion.
+ */
+QRegion QDecorationDefault::region(const QWidget *widget,
+ const QRect &rect,
+ int decorationRegion)
+{
+ Qt::WindowFlags flags = widget->windowFlags();
+ bool hasBorder = !widget->isMaximized();
+ bool hasTitle = flags & Qt::WindowTitleHint;
+ bool hasSysMenu = flags & Qt::WindowSystemMenuHint;
+ bool hasContextHelp = flags & Qt::WindowContextHelpButtonHint;
+ bool hasMinimize = flags & Qt::WindowMinimizeButtonHint;
+ bool hasMaximize = flags & Qt::WindowMaximizeButtonHint;
+ int state = widget->windowState();
+ bool isMinimized = state & Qt::WindowMinimized;
+ bool isMaximized = state & Qt::WindowMaximized;
+
+ int titleHeight = hasTitle ? titleBarHeight(widget) : 0;
+ int bw = hasBorder ? BORDER_WIDTH : 0;
+ int bbw = hasBorder ? BOTTOM_BORDER_WIDTH : 0;
+
+ QRegion region;
+ switch (decorationRegion) {
+ case All: {
+ QRect r(rect.left() - bw,
+ rect.top() - titleHeight - bw,
+ rect.width() + 2 * bw,
+ rect.height() + titleHeight + bw + bbw);
+ region = r;
+ region -= rect;
+ }
+ break;
+
+ case Title: {
+ QRect r(rect.left()
+ + (hasSysMenu ? menu_width : 0),
+ rect.top() - titleHeight,
+ rect.width()
+ - (hasSysMenu ? menu_width : 0)
+ - close_width
+ - (hasMaximize ? maximize_width : 0)
+ - (hasMinimize ? minimize_width : 0)
+ - (hasContextHelp ? help_width : 0),
+
+ titleHeight);
+ if (r.width() > 0)
+ region = r;
+ }
+ break;
+
+ case Top: {
+ QRect r(rect.left() + CORNER_GRAB,
+ rect.top() - titleHeight - bw,
+ rect.width() - 2 * CORNER_GRAB,
+ bw);
+ region = r;
+ }
+ break;
+
+ case Left: {
+ QRect r(rect.left() - bw,
+ rect.top() - titleHeight + CORNER_GRAB,
+ bw,
+ rect.height() + titleHeight - 2 * CORNER_GRAB);
+ region = r;
+ }
+ break;
+
+ case Right: {
+ QRect r(rect.right() + 1,
+ rect.top() - titleHeight + CORNER_GRAB,
+ bw,
+ rect.height() + titleHeight - 2 * CORNER_GRAB);
+ region = r;
+ }
+ break;
+
+ case Bottom: {
+ QRect r(rect.left() + CORNER_GRAB,
+ rect.bottom() + 1,
+ rect.width() - 2 * CORNER_GRAB,
+ bw);
+ region = r;
+ }
+ break;
+
+ case TopLeft: {
+ QRect r1(rect.left() - bw,
+ rect.top() - bw - titleHeight,
+ CORNER_GRAB + bw,
+ bw);
+
+ QRect r2(rect.left() - bw,
+ rect.top() - bw - titleHeight,
+ bw,
+ CORNER_GRAB + bw);
+
+ region = QRegion(r1) + r2;
+ }
+ break;
+
+ case TopRight: {
+ QRect r1(rect.right() - CORNER_GRAB,
+ rect.top() - bw - titleHeight,
+ CORNER_GRAB + bw,
+ bw);
+
+ QRect r2(rect.right() + 1,
+ rect.top() - bw - titleHeight,
+ bw,
+ CORNER_GRAB + bw);
+
+ region = QRegion(r1) + r2;
+ }
+ break;
+
+ case BottomLeft: {
+ QRect r1(rect.left() - bw,
+ rect.bottom() + 1,
+ CORNER_GRAB + bw,
+ bw);
+
+ QRect r2(rect.left() - bw,
+ rect.bottom() - CORNER_GRAB,
+ bw,
+ CORNER_GRAB + bw);
+ region = QRegion(r1) + r2;
+ }
+ break;
+
+ case BottomRight: {
+ QRect r1(rect.right() - CORNER_GRAB,
+ rect.bottom() + 1,
+ CORNER_GRAB + bw,
+ bw);
+
+ QRect r2(rect.right() + 1,
+ rect.bottom() - CORNER_GRAB,
+ bw,
+ CORNER_GRAB + bw);
+ region = QRegion(r1) + r2;
+ }
+ break;
+
+ case Menu: {
+ if (hasSysMenu) {
+ region = QRect(rect.left(), rect.top() - titleHeight,
+ menu_width, titleHeight);
+ }
+ }
+ break;
+
+ case Help: {
+ if (hasContextHelp) {
+ QRect r(rect.right()
+ - close_width
+ - (hasMaximize ? maximize_width : 0)
+ - (hasMinimize ? minimize_width : 0)
+ - help_width + 1, rect.top() - titleHeight,
+ help_width, titleHeight);
+ if (r.left() > rect.left() + titleHeight)
+ region = r;
+ }
+ }
+ break;
+
+
+ case Minimize: {
+ if (hasMinimize && !isMinimized) {
+ QRect r(rect.right() - close_width
+ - (hasMaximize ? maximize_width : 0)
+ - minimize_width + 1, rect.top() - titleHeight,
+ minimize_width, titleHeight);
+ if (r.left() > rect.left() + titleHeight)
+ region = r;
+ }
+ }
+ break;
+
+ case Maximize: {
+ if (hasMaximize && !isMaximized) {
+ QRect r(rect.right() - close_width - maximize_width + 1,
+ rect.top() - titleHeight, maximize_width, titleHeight);
+ if (r.left() > rect.left() + titleHeight)
+ region = r;
+ }
+ }
+ break;
+
+ case Normalize: {
+ if (hasMinimize && isMinimized) {
+ QRect r(rect.right() - close_width
+ - (hasMaximize ? maximize_width : 0)
+ - minimize_width + 1, rect.top() - titleHeight,
+ minimize_width, titleHeight);
+ if (r.left() > rect.left() + titleHeight)
+ region = r;
+ } else if (hasMaximize && isMaximized) {
+ QRect r(rect.right() - close_width - maximize_width + 1,
+ rect.top() - titleHeight, maximize_width, titleHeight);
+ if (r.left() > rect.left() + titleHeight)
+ region = r;
+ }
+ }
+ break;
+
+ case Close: {
+ QRect r(rect.right() - close_width + 1, rect.top() - titleHeight,
+ close_width, titleHeight);
+ if (r.left() > rect.left() + titleHeight)
+ region = r;
+ }
+ break;
+
+ default: {
+ int i = 1;
+ while (i) {
+ if (i & decorationRegion)
+ region += this->region(widget, rect, i);
+ i <<= 1;
+ }
+ }
+ break;
+ }
+
+ return region;
+}
+
+/*!
+ Paints the border and title decoration for the top-level \a widget
+ using the \a painter provided and the decoration \a state. The value
+ of \a decorationRegion is a combination of the bitmask values of
+ enum DecorationRegion.
+
+ Note that Qt for Embedded Linux expects this function to return true if any of
+ the widget's decorations are repainted; otherwise it returns false.
+ */
+bool QDecorationDefault::paint(QPainter *painter,
+ const QWidget *widget,
+ int decorationRegion,
+ DecorationState state)
+{
+ if (decorationRegion == None)
+ return false;
+
+ const QRect titleRect = QDecoration::region(widget, Title).boundingRect();
+ const QPalette pal = QApplication::palette();
+ int titleHeight = titleRect.height();
+ int titleWidth = titleRect.width();
+ QRegion oldClipRegion = painter->clipRegion();
+
+
+ Qt::WindowFlags flags = widget->windowFlags();
+ bool hasBorder = !widget->isMaximized();
+ bool hasTitle = flags & Qt::WindowTitleHint;
+ bool hasSysMenu = flags & Qt::WindowSystemMenuHint;
+ bool hasContextHelp = flags & Qt::WindowContextHelpButtonHint;
+ bool hasMinimize = flags & Qt::WindowMinimizeButtonHint;
+ bool hasMaximize = flags & Qt::WindowMaximizeButtonHint;
+
+ bool paintAll = (decorationRegion == int(All));
+ bool handled = false;
+
+ bool porterDuff = painter->paintEngine()->hasFeature(QPaintEngine::PorterDuff);
+
+ if ((paintAll || decorationRegion & Borders) && state == Normal && hasBorder) {
+ if (hasTitle) { // reduce flicker
+ QRect rect(widget->rect());
+ QRect r(rect.left(), rect.top() - titleHeight,
+ rect.width(), titleHeight);
+ painter->setClipRegion(oldClipRegion - r);
+ }
+ QRect br = QDecoration::region(widget).boundingRect();
+ if (porterDuff)
+ painter->setCompositionMode(QPainter::CompositionMode_Source);
+ qDrawWinPanel(painter, br.x(), br.y(), br.width(),
+ br.height(), pal, false,
+ &pal.brush(QPalette::Window));
+ if (porterDuff)
+ painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
+ handled |= true;
+ }
+
+ if ((paintAll || decorationRegion & Title && titleWidth > 0) && state == Normal && hasTitle) {
+ painter->setClipRegion(oldClipRegion);
+ QBrush titleBrush;
+ QPen titlePen;
+
+ if (widget == qApp->activeWindow()) {
+ titleBrush = pal.brush(QPalette::Highlight);
+ titlePen = pal.color(QPalette::HighlightedText);
+ } else {
+ titleBrush = pal.brush(QPalette::Window);
+ titlePen = pal.color(QPalette::Text);
+ }
+
+ if (porterDuff)
+ painter->setCompositionMode(QPainter::CompositionMode_Source);
+ qDrawShadePanel(painter,
+ titleRect.x(), titleRect.y(), titleRect.width(), titleRect.height(),
+ pal, true, 1, &titleBrush);
+ if (porterDuff)
+ painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
+
+ painter->setPen(titlePen);
+ painter->drawText(titleRect.x() + 4, titleRect.y(),
+ titleRect.width() - 8, titleRect.height(),
+ Qt::AlignVCenter, windowTitleFor(widget));
+ handled |= true;
+ }
+
+ if (state != Hover) {
+ painter->setClipRegion(oldClipRegion);
+ if ((paintAll || decorationRegion & Menu) && hasSysMenu) {
+ paintButton(painter, widget, Menu, state, pal);
+ handled |= true;
+ }
+
+ if ((paintAll || decorationRegion & Help) && hasContextHelp) {
+ paintButton(painter, widget, Help, state, pal);
+ handled |= true;
+ }
+
+ if ((paintAll || decorationRegion & Minimize) && hasMinimize) {
+ paintButton(painter, widget, Minimize, state, pal);
+ handled |= true;
+ }
+
+ if ((paintAll || decorationRegion & Maximize) && hasMaximize) {
+ paintButton(painter, widget,
+ ((widget->windowState() & Qt::WindowMaximized)? Normalize : Maximize),
+ state, pal);
+ handled |= true;
+ }
+
+ if (paintAll || decorationRegion & Close) {
+ paintButton(painter, widget, Close, state, pal);
+ handled |= true;
+ }
+ }
+ return handled;
+}
+
+/*!
+ \fn void QDecorationDefault::paintButton(QPainter *painter, const
+ QWidget *widget, int buttonRegion, DecorationState state,
+ const QPalette &palette)
+
+ Paints a region of the top-level \a widget. The region is
+ painted in the specified decoration \a state using the
+ \a painter and \a palette provided. The region to be painted is specified
+ by \a buttonRegion, which is a combination of the bitmask values of
+ DecorationRegion. If the value of \a buttonRegion is one of \e Help,
+ \e Menu, \e Close, \e Minimize, \e Maximize, and \e Normalize, the
+ button pixmap for that region is painted.
+
+ \sa pixmapFor()
+ */
+void QDecorationDefault::paintButton(QPainter *painter,
+ const QWidget *widget,
+ int buttonRegion,
+ DecorationState state,
+ const QPalette &pal)
+{
+ int xoff = 2;
+ int yoff = 2;
+
+ const QPixmap pm = pixmapFor(widget, buttonRegion, xoff, yoff);
+ QRect brect(QDecoration::region(widget, buttonRegion).boundingRect());
+ bool porterDuff = painter->paintEngine()->hasFeature(QPaintEngine::PorterDuff);
+
+ if (state & QDecoration::Pressed) {
+ if (porterDuff)
+ painter->setCompositionMode(QPainter::CompositionMode_Source);
+ qDrawWinPanel(painter, brect, pal, true, &pal.brush(QPalette::Window));
+ if (porterDuff)
+ painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
+ ++xoff;
+ ++yoff;
+ } else {
+ painter->fillRect(brect, pal.brush(QPalette::Window));
+ }
+
+ if (!pm.isNull())
+ painter->drawPixmap(brect.x() + xoff, brect.y() + yoff, pm);
+}
+
+extern QString qt_setWindowTitle_helperHelper(const QString&, const QWidget*);
+
+/*!
+ \internal
+ */
+QString QDecorationDefault::windowTitleFor(const QWidget *widget) const
+{
+ return qt_setWindowTitle_helperHelper(widget->windowTitle(), widget);
+}
+
+#endif // QT_NO_QWS_DECORATION_DEFAULT
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qdecorationdefault_qws.h b/src/gui/embedded/qdecorationdefault_qws.h
new file mode 100644
index 0000000000..4cc3703484
--- /dev/null
+++ b/src/gui/embedded/qdecorationdefault_qws.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECORATIONDEFAULT_QWS_H
+#define QDECORATIONDEFAULT_QWS_H
+
+#include <QtGui/qdecoration_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if !defined(QT_NO_QWS_DECORATION_DEFAULT) || defined(QT_PLUGIN)
+
+#define CORNER_GRAB 16
+#define BORDER_WIDTH 4
+#define BOTTOM_BORDER_WIDTH BORDER_WIDTH
+
+class Q_GUI_EXPORT QDecorationDefault : public QDecoration
+{
+public:
+ QDecorationDefault();
+ virtual ~QDecorationDefault();
+
+ virtual QRegion region(const QWidget *widget, const QRect &rect, int decorationRegion = All);
+ virtual bool paint(QPainter *painter, const QWidget *widget, int decorationRegion = All,
+ DecorationState state = Normal);
+
+protected:
+ virtual int titleBarHeight(const QWidget *widget);
+
+ virtual void paintButton(QPainter *painter, const QWidget *widget, int buttonRegion,
+ DecorationState state, const QPalette &pal);
+ virtual QPixmap pixmapFor(const QWidget *widget, int decorationRegion, int &xoff, int &yoff);
+ virtual const char **xpmForRegion(int region);
+
+ QString windowTitleFor(const QWidget *widget) const;
+
+ int menu_width;
+ int help_width;
+ int close_width;
+ int minimize_width;
+ int maximize_width;
+ int normalize_width;
+
+private:
+ static QPixmap *staticHelpPixmap;
+ static QPixmap *staticMenuPixmap;
+ static QPixmap *staticClosePixmap;
+ static QPixmap *staticMinimizePixmap;
+ static QPixmap *staticMaximizePixmap;
+ static QPixmap *staticNormalizePixmap;
+
+};
+
+
+QT_END_NAMESPACE
+#endif // QT_NO_QWS_DECORATION_DEFAULT
+QT_END_HEADER
+
+#endif // QDECORATIONDEFAULT_QWS_H
diff --git a/src/gui/embedded/qdecorationfactory_qws.cpp b/src/gui/embedded/qdecorationfactory_qws.cpp
new file mode 100644
index 0000000000..999e346505
--- /dev/null
+++ b/src/gui/embedded/qdecorationfactory_qws.cpp
@@ -0,0 +1,156 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdecorationfactory_qws.h"
+#include "qdecorationplugin_qws.h"
+#include "private/qfactoryloader_p.h"
+#include "qmutex.h"
+
+#include "qapplication.h"
+#include "qdecorationdefault_qws.h"
+#include "qdecorationwindows_qws.h"
+#include "qdecorationstyled_qws.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_LIBRARY
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QDecorationFactoryInterface_iid,
+ QLatin1String("/decorations"), Qt::CaseInsensitive))
+#endif
+
+
+
+/*!
+ \class QDecorationFactory
+ \ingroup qws
+ \ingroup appearance
+
+ \brief The QDecorationFactory class creates window decorations in
+ Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ QDecorationFactory is used to detect and instantiate the available
+ decorations, allowing \l{Qt for Embedded Linux} to load the preferred
+ decoration into the application at runtime. The create() function
+ returns a QDecoration object representing the decoration
+ identified by a given key. The valid keys (i.e. the supported
+ decorations) can be retrieved using the keys() function.
+
+ \l{Qt for Embedded Linux} provides three built-in decorations: \c Default,
+ \c Styled and \c Windows. In addition, custom decorations can be
+ added using Qt's \l {How to Create Qt Plugins}{plugin mechanism},
+ i.e. by subclassing the QDecoration class and creating a mouse
+ driver plugin (QDecorationPlugin).
+
+ \sa QDecoration, QDecorationPlugin
+*/
+
+/*!
+ Creates the decoration specified by the given \a key. Note that
+ the keys are case-insensitive.
+
+ \sa keys()
+*/
+
+QDecoration *QDecorationFactory::create(const QString& key)
+{
+ QDecoration *ret = 0;
+ QString decoration = key.toLower();
+#ifndef QT_NO_QWS_DECORATION_DEFAULT
+ if (decoration == QLatin1String("default"))
+ ret = new QDecorationDefault;
+ else
+#endif
+#ifndef QT_NO_QWS_DECORATION_WINDOWS
+ if (decoration == QLatin1String("windows"))
+ ret = new QDecorationWindows;
+ else
+#endif
+#ifndef QT_NO_QWS_DECORATION_STYLED
+ if (decoration == QLatin1String("styled"))
+ ret = new QDecorationStyled;
+ else
+#endif
+ { } // Keep these here - they make the #ifdefery above work
+#ifndef QT_NO_LIBRARY
+ if (!ret) {
+ if (QDecorationFactoryInterface *factory = qobject_cast<QDecorationFactoryInterface*>(loader()->instance(decoration))) {
+ ret = factory->create(decoration);
+ }
+ }
+#endif
+ return ret;
+}
+
+/*!
+ Returns the list of valid keys, i.e., the available decorations.
+
+ \sa create()
+*/
+QStringList QDecorationFactory::keys()
+{
+ QStringList list;
+#ifndef QT_NO_QWS_DECORATION_STYLED
+ list << QLatin1String("Styled");
+#endif
+#ifndef QT_NO_QWS_DECORATION_DEFAULT
+ list << QLatin1String("Default");
+#endif
+#ifndef QT_NO_QWS_DECORATION_WINDOWS
+ list << QLatin1String("Windows");
+#endif
+
+#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/embedded/qdecorationfactory_qws.h b/src/gui/embedded/qdecorationfactory_qws.h
new file mode 100644
index 0000000000..7397c78826
--- /dev/null
+++ b/src/gui/embedded/qdecorationfactory_qws.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECORATIONFACTORY_QWS_H
+#define QDECORATIONFACTORY_QWS_H
+
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QDecoration;
+
+class Q_GUI_EXPORT QDecorationFactory
+{
+public:
+ static QStringList keys();
+ static QDecoration *create(const QString&);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECORATIONFACTORY_QWS_H
diff --git a/src/gui/embedded/qdecorationplugin_qws.cpp b/src/gui/embedded/qdecorationplugin_qws.cpp
new file mode 100644
index 0000000000..eb37e2143c
--- /dev/null
+++ b/src/gui/embedded/qdecorationplugin_qws.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdecorationplugin_qws.h"
+#include "qdecoration_qws.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QDecorationPlugin
+ \ingroup qws
+ \ingroup plugins
+
+ \brief The QDecorationPlugin class is an abstract base class for
+ window decoration plugins in Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ \l{Qt for Embedded Linux} provides three ready-made decoration styles: \c
+ Default, \c Styled and \c Windows. Custom decorations can be
+ implemented by subclassing the QDecoration class and creating a
+ decoration plugin.
+
+ A decoration plugin can be created by subclassing
+ QDecorationPlugin and implementing the pure virtual keys() and
+ create() functions. By exporting the derived class using the
+ Q_EXPORT_PLUGIN2() macro, the default implementation of the
+ QDecorationFactory class will automatically detect the plugin and
+ load the driver into the application at run-time. See \l{How to
+ Create Qt Plugins} for details.
+
+ To actually apply a decoration, use the
+ QApplication::qwsSetDecoration() function.
+
+ \sa QDecoration, QDecorationFactory
+*/
+
+/*!
+ \fn QStringList QDecorationPlugin::keys() const
+
+ Returns the list of valid keys, i.e., the decorations supported by
+ this plugin.
+
+ \sa create()
+*/
+
+/*!
+ \fn QDecoration *QDecorationPlugin::create(const QString &key)
+
+ Creates a decoration matching the given \a key. Note that keys are
+ case-insensitive.
+
+ \sa keys()
+*/
+
+/*!
+ Constructs a decoration 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.
+*/
+QDecorationPlugin::QDecorationPlugin(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ Destroys the decoration plugin.
+
+ Note that Qt destroys a plugin automatically when it is no longer
+ used, so there is no need for calling the destructor explicitly.
+*/
+QDecorationPlugin::~QDecorationPlugin()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qdecorationplugin_qws.h b/src/gui/embedded/qdecorationplugin_qws.h
new file mode 100644
index 0000000000..c58aaab4f1
--- /dev/null
+++ b/src/gui/embedded/qdecorationplugin_qws.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECORATIONPLUGIN_QWS_H
+#define QDECORATIONPLUGIN_QWS_H
+
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QDecoration;
+
+struct Q_GUI_EXPORT QDecorationFactoryInterface : public QFactoryInterface
+{
+ virtual QDecoration *create(const QString &key) = 0;
+};
+
+#define QDecorationFactoryInterface_iid "com.trolltech.Qt.QDecorationFactoryInterface"
+Q_DECLARE_INTERFACE(QDecorationFactoryInterface, QDecorationFactoryInterface_iid)
+
+class Q_GUI_EXPORT QDecorationPlugin : public QObject, public QDecorationFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QDecorationFactoryInterface:QFactoryInterface)
+ public:
+ explicit QDecorationPlugin(QObject *parent = 0);
+ ~QDecorationPlugin();
+
+ virtual QStringList keys() const = 0;
+ virtual QDecoration *create(const QString &key) = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECORATIONPLUGIN_QWS_H
diff --git a/src/gui/embedded/qdecorationstyled_qws.cpp b/src/gui/embedded/qdecorationstyled_qws.cpp
new file mode 100644
index 0000000000..847881b5c8
--- /dev/null
+++ b/src/gui/embedded/qdecorationstyled_qws.cpp
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qapplication.h>
+#include <qwidget.h>
+#include <qpainter.h>
+#include <qdrawutil.h>
+#include "qdecorationstyled_qws.h"
+#include "qstyle.h"
+#include "qstyleoption.h"
+#include "qpaintengine.h"
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_QWS_DECORATION_STYLED) || defined(QT_PLUGIN)
+
+QDecorationStyled::QDecorationStyled()
+ : QDecorationDefault()
+{
+}
+
+QDecorationStyled::~QDecorationStyled()
+{
+}
+
+int QDecorationStyled::titleBarHeight(const QWidget *widget)
+{
+ QStyleOptionTitleBar opt;
+ opt.subControls = QStyle::SC_TitleBarLabel
+ | QStyle::SC_TitleBarSysMenu
+ | QStyle::SC_TitleBarNormalButton
+ | QStyle::SC_TitleBarContextHelpButton
+ | QStyle::SC_TitleBarMinButton
+ | QStyle::SC_TitleBarMaxButton
+ | QStyle::SC_TitleBarCloseButton;
+ opt.titleBarFlags = widget->windowFlags();
+ opt.direction = QApplication::layoutDirection();
+ opt.text = windowTitleFor(widget);
+ opt.icon = widget->windowIcon();
+ opt.rect = widget->rect();
+
+ QStyle *style = QApplication::style();
+ if (!style)
+ return 18;
+
+ return style->pixelMetric(QStyle::PM_TitleBarHeight, &opt, 0);
+}
+
+bool QDecorationStyled::paint(QPainter *painter, const QWidget *widget, int decorationRegion,
+ DecorationState state)
+{
+ if (decorationRegion == None)
+ return false;
+
+ bool isActive = (widget == qApp->activeWindow());
+ QPalette pal = qApp->palette();
+ //ideally, the difference between Active and Inactive should be enough, so we shouldn't need to test this
+ if (!isActive) {
+ //pal.setCurrentColorGroup(QPalette::Disabled); //Can't do this either, because of palette limitations
+ //copied from Q3TitleBar:
+ pal.setColor(QPalette::Inactive, QPalette::Highlight,
+ pal.color(QPalette::Inactive, QPalette::Dark));
+ pal.setColor(QPalette::Inactive, QPalette::Base,
+ pal.color(QPalette::Inactive, QPalette::Dark));
+ pal.setColor(QPalette::Inactive, QPalette::HighlightedText,
+ pal.color(QPalette::Inactive, QPalette::Window));
+ }
+
+ Qt::WindowFlags flags = widget->windowFlags();
+ bool hasBorder = !widget->isMaximized();
+ bool hasTitle = flags & Qt::WindowTitleHint;
+ bool hasSysMenu = flags & Qt::WindowSystemMenuHint;
+ bool hasContextHelp = flags & Qt::WindowContextHelpButtonHint;
+ bool hasMinimize = flags & Qt::WindowMinimizeButtonHint;
+ bool hasMaximize = flags & Qt::WindowMaximizeButtonHint;
+
+ bool paintAll = (DecorationRegion(decorationRegion) == All);
+ bool handled = false;
+
+ QStyle *style = QApplication::style();
+
+ // In the case of a borderless title bar, the title bar must be expanded one
+ // borderWidth to the left, right and up.
+ bool noTitleBorder = style->styleHint(QStyle::SH_TitleBar_NoBorder, 0, widget);
+ int borderWidth = style->pixelMetric(QStyle::PM_MDIFrameWidth, 0, 0);
+ int titleHeight = titleBarHeight(widget) + (noTitleBorder ? borderWidth : 0);
+ int titleExtra = noTitleBorder ? borderWidth : 0;
+
+ if ((paintAll || decorationRegion & Borders) && state == Normal && hasBorder) {
+ QRegion newClip = painter->clipRegion();
+ if (hasTitle) { // reduce flicker
+ QRect rect(widget->rect());
+ QRect r(rect.left() - titleExtra, rect.top() - titleHeight,
+ rect.width() + 2 * titleExtra, titleHeight);
+ newClip -= r;
+ }
+ if (!newClip.isEmpty()) {
+ QRect br = QDecoration::region(widget).boundingRect();
+ painter->save();
+ painter->setClipRegion(newClip);
+
+ QStyleOptionFrame opt;
+ opt.palette = pal;
+ opt.rect = br;
+ opt.lineWidth = borderWidth;
+
+ if (isActive)
+ opt.state |= QStyle::State_Active;
+ bool porterDuff = painter->paintEngine()->hasFeature(QPaintEngine::PorterDuff);
+ if (porterDuff)
+ painter->setCompositionMode(QPainter::CompositionMode_Source);
+ painter->fillRect(br, pal.window());
+ if (porterDuff)
+ painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
+ style->drawPrimitive(QStyle::PE_FrameWindow, &opt, painter, 0);
+ painter->restore();
+
+ decorationRegion &= (~Borders);
+ handled |= true;
+ }
+ }
+
+ if (hasTitle) {
+ painter->save();
+
+ QStyleOptionTitleBar opt;
+ opt.subControls = (decorationRegion & Title
+ ? QStyle::SC_TitleBarLabel : QStyle::SubControl(0))
+ | (decorationRegion & Menu
+ ? QStyle::SC_TitleBarSysMenu : QStyle::SubControl(0))
+ | (decorationRegion & Help
+ ? QStyle::SC_TitleBarContextHelpButton : QStyle::SubControl(0))
+ | (decorationRegion & Minimize
+ ? QStyle::SC_TitleBarMinButton : QStyle::SubControl(0))
+ | (decorationRegion & Maximize
+ ? QStyle::SC_TitleBarMaxButton : QStyle::SubControl(0))
+ | (decorationRegion & (Minimize | Maximize)
+ ? QStyle::SC_TitleBarNormalButton : QStyle::SubControl(0))
+ | (decorationRegion & Close
+ ? QStyle::SC_TitleBarCloseButton : QStyle::SubControl(0));
+ opt.titleBarFlags = widget->windowFlags();
+ opt.titleBarState = widget->windowState();
+ if (isActive)
+ opt.titleBarState |= QStyle::State_Active;
+ opt.text = windowTitleFor(widget);
+ opt.icon = widget->windowIcon();
+ opt.palette = pal;
+ opt.rect = QRect(widget->rect().x() - titleExtra, -titleHeight,
+ widget->rect().width() + 2 * titleExtra, titleHeight);
+
+ if (paintAll) {
+ painter->setClipRegion(opt.rect);
+ } else {
+ const QRect widgetRect = widget->rect();
+ QRegion newClip = opt.rect;
+ if (!(decorationRegion & Menu) && hasSysMenu)
+ newClip -= region(widget, widgetRect, Menu);
+ if (!(decorationRegion & Title) && hasTitle)
+ newClip -= region(widget, widgetRect, Title);
+ if (!(decorationRegion & Help) && hasContextHelp)
+ newClip -= region(widget, widgetRect, Help);
+ if (!(decorationRegion & Minimize) && hasMinimize)
+ newClip -= region(widget, widgetRect, Minimize);
+ if (!(decorationRegion & Maximize) && hasMaximize)
+ newClip -= region(widget, widgetRect, Maximize);
+ if (!(decorationRegion & (Minimize | Maximize)) && (hasMaximize | hasMinimize))
+ newClip -= region(widget, widgetRect, Normal);
+ if (!(decorationRegion & Close))
+ newClip -= region(widget, widgetRect, Close);
+ painter->setClipRegion(newClip);
+ }
+
+ if (state == Pressed)
+ opt.activeSubControls = opt.subControls;
+
+ style->drawComplexControl(QStyle::CC_TitleBar, &opt, painter, 0);
+ painter->restore();
+
+ decorationRegion &= ~(Title | Menu | Help | Normalize | Minimize | Maximize | Close);
+ handled |= true;
+ }
+
+ return handled;
+}
+
+QRegion QDecorationStyled::region(const QWidget *widget, const QRect &rect, int decorationRegion)
+{
+ QStyle *style = QApplication::style();
+
+ // In the case of a borderless title bar, the title bar must be expanded one
+ // borderWidth to the left, right and up.
+ bool noTitleBorder = style->styleHint(QStyle::SH_TitleBar_NoBorder, 0, widget);
+ int borderWidth = style->pixelMetric(QStyle::PM_MDIFrameWidth, 0, 0);
+ int titleHeight = titleBarHeight(widget) + (noTitleBorder ? borderWidth : 0);
+ int titleExtra = noTitleBorder ? borderWidth : 0;
+
+ QRect inside = QRect(rect.x() - titleExtra, rect.top() - titleHeight,
+ rect.width() + 2 * titleExtra, titleHeight);
+
+ Qt::WindowFlags flags = widget->windowFlags();
+ bool hasSysMenu = flags & Qt::WindowSystemMenuHint;
+ bool hasContextHelp = flags & Qt::WindowContextHelpButtonHint;
+ bool hasMinimize = flags & Qt::WindowMinimizeButtonHint;
+ bool hasMaximize = flags & Qt::WindowMaximizeButtonHint;
+
+ QStyleOptionTitleBar opt;
+ opt.subControls = QStyle::SC_TitleBarLabel
+ | QStyle::SC_TitleBarSysMenu
+ | QStyle::SC_TitleBarNormalButton
+ | QStyle::SC_TitleBarMinButton
+ | QStyle::SC_TitleBarMaxButton
+ | QStyle::SC_TitleBarCloseButton;
+ opt.titleBarFlags = widget->windowFlags();
+ opt.direction = QApplication::layoutDirection();
+ opt.text = windowTitleFor(widget);
+ opt.icon = widget->windowIcon();
+ opt.rect = inside;
+
+ QRegion region;
+ switch (decorationRegion) {
+ case Title:
+ region = style->subControlRect(QStyle::CC_TitleBar, &opt,
+ QStyle::SC_TitleBarLabel, 0);
+ break;
+ case Menu:
+ if (hasSysMenu)
+ region = style->subControlRect(QStyle::CC_TitleBar, &opt,
+ QStyle::SC_TitleBarSysMenu, 0);
+ break;
+ case Help:
+ if (hasContextHelp)
+ region = style->subControlRect(QStyle::CC_TitleBar, &opt,
+ QStyle::SC_TitleBarContextHelpButton,
+ 0);
+ break;
+ case Normalize:
+ if (hasMaximize | hasMinimize)
+ region = style->subControlRect(QStyle::CC_TitleBar, &opt,
+ QStyle::SC_TitleBarNormalButton,
+ 0);
+ break;
+ case Minimize:
+ if (hasMinimize)
+ region = style->subControlRect(QStyle::CC_TitleBar, &opt,
+ QStyle::SC_TitleBarMinButton,
+ 0);
+ break;
+ case Maximize:
+ if (hasMaximize)
+ region = style->subControlRect(QStyle::CC_TitleBar, &opt,
+ QStyle::SC_TitleBarMaxButton,
+ 0);
+ break;
+ case Close:
+ region = style->subControlRect(QStyle::CC_TitleBar, &opt,
+ QStyle::SC_TitleBarCloseButton, 0);
+ break;
+
+ default:
+ region = QDecorationDefault::region(widget, rect, decorationRegion);
+ }
+
+ opt.rect = QRect(rect.x() - titleExtra, rect.top() - titleHeight,
+ rect.width() + 2 * titleExtra,
+ rect.height() + titleHeight + titleExtra);
+
+ QStyleHintReturnMask mask;
+ style->styleHint(QStyle::SH_WindowFrame_Mask, &opt, 0, &mask);
+
+ return (mask.region.isEmpty() ? region : (region & mask.region));
+}
+
+#endif // QT_NO_QWS_DECORATION_STYLED
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qdecorationstyled_qws.h b/src/gui/embedded/qdecorationstyled_qws.h
new file mode 100644
index 0000000000..583c3f281b
--- /dev/null
+++ b/src/gui/embedded/qdecorationstyled_qws.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECORATIONSTYLED_QWS_H
+#define QDECORATIONSTYLED_QWS_H
+
+#include <QtGui/qdecorationdefault_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if !defined(QT_NO_QWS_DECORATION_STYLED) || defined(QT_PLUGIN)
+
+class Q_GUI_EXPORT QDecorationStyled : public QDecorationDefault
+{
+public:
+ QDecorationStyled();
+ virtual ~QDecorationStyled();
+
+ QRegion region(const QWidget *widget, const QRect &rect, int decorationRegion = All);
+ bool paint(QPainter *painter, const QWidget *widget, int decorationRegion = All,
+ DecorationState state = Normal);
+ int titleBarHeight(const QWidget *widget);
+};
+
+#endif // QT_NO_QWS_DECORATION_STYLED
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECORATIONSTYLED_QWS_H
diff --git a/src/gui/embedded/qdecorationwindows_qws.cpp b/src/gui/embedded/qdecorationwindows_qws.cpp
new file mode 100644
index 0000000000..374f45eebf
--- /dev/null
+++ b/src/gui/embedded/qdecorationwindows_qws.cpp
@@ -0,0 +1,407 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qapplication.h>
+#include <qwidget.h>
+#include <qpainter.h>
+#include <qdrawutil.h>
+#include "qdecorationwindows_qws.h"
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_QWS_DECORATION_WINDOWS) || defined(QT_PLUGIN)
+
+#ifndef QT_NO_IMAGEFORMAT_XPM
+
+/* XPM */
+static const char * const win_close_xpm[] = {
+"16 16 4 1",
+" s None c None",
+". c #000000",
+"X c #FFFFFF",
+"Y c #707070",
+" ",
+" ",
+" ",
+" Y. .Y ",
+" .. .. ",
+" .. .. ",
+" .YY. ",
+" Y..Y ",
+" .YY. ",
+" .. .. ",
+" .. .. ",
+" Y. .Y ",
+" ",
+" ",
+" ",
+" "};
+
+static const char * const win_help_xpm[] = {
+"16 16 3 1",
+" s None c None",
+". c #ffffff",
+"X c #000000",
+" ",
+" ",
+" ",
+" XXXXXX ",
+" XX XX ",
+" XX XX ",
+" XX ",
+" XX ",
+" XX ",
+" XX ",
+" ",
+" XX ",
+" XX ",
+" ",
+" ",
+" "};
+
+static const char * const win_maximize_xpm[] = {
+"16 16 4 1",
+" s None c None",
+". c #000000",
+"X c #FFFFFF",
+"Y c #707070",
+" ",
+" ",
+" ",
+" .......... ",
+" .......... ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" . . ",
+" .......... ",
+" ",
+" ",
+" ",
+" "};
+
+static const char * const win_minimize_xpm[] = {
+"16 16 4 1",
+" s None c None",
+". c #000000",
+"X c #FFFFFF",
+"Y c #707070",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ",
+" ........ ",
+" ........ ",
+" ",
+" ",
+" ",
+" "};
+
+static const char * const win_normalize_xpm[] = {
+"16 16 4 1",
+" s None c None",
+". c #000000",
+"X c #FFFFFF",
+"Y c #707070",
+" ",
+" ",
+" ......... ",
+" ......... ",
+" . . ",
+" . . ",
+" ......... . ",
+" ......... . ",
+" . . . ",
+" . .... ",
+" . . ",
+" . . ",
+" ......... ",
+" ",
+" ",
+" "};
+
+#endif // QT_NO_IMAGEFORMAT_XPM
+
+
+QDecorationWindows::QDecorationWindows()
+ : QDecorationDefault()
+{
+ menu_width = 16;
+ help_width = 18;
+ minimize_width = 18;
+ maximize_width = 18;
+ close_width = 18;
+}
+
+QDecorationWindows::~QDecorationWindows()
+{
+}
+
+const char **QDecorationWindows::xpmForRegion(int reg)
+{
+#ifdef QT_NO_IMAGEFORMAT_XPM
+ Q_UNUSED(reg);
+#else
+ switch(reg)
+ {
+ case Close:
+ return (const char **)win_close_xpm;
+ case Help:
+ return (const char **)win_help_xpm;
+ case Minimize:
+ return (const char **)win_minimize_xpm;
+ case Maximize:
+ return (const char **)win_maximize_xpm;
+ case Normalize:
+ return (const char **)win_normalize_xpm;
+ default:
+ return QDecorationDefault::xpmForRegion(reg);
+ }
+#endif
+ return 0;
+}
+
+QRegion QDecorationWindows::region(const QWidget *widget, const QRect &rect, int type)
+{
+ Qt::WindowFlags flags = widget->windowFlags();
+ bool hasTitle = flags & Qt::WindowTitleHint;
+ bool hasSysMenu = flags & Qt::WindowSystemMenuHint;
+ bool hasContextHelp = flags & Qt::WindowContextHelpButtonHint;
+ bool hasMinimize = flags & Qt::WindowMinimizeButtonHint;
+ bool hasMaximize = flags & Qt::WindowMaximizeButtonHint;
+ const QFontMetrics fontMetrics = QApplication::fontMetrics();
+ int titleHeight = hasTitle ? qMax(20, fontMetrics.lineSpacing()) : 0;
+ int state = widget->windowState();
+ bool isMinimized = state & Qt::WindowMinimized;
+ bool isMaximized = state & Qt::WindowMaximized;
+
+ QRegion region;
+ switch (type) {
+ case Menu: {
+ if (hasSysMenu) {
+ region = QRect(rect.left() + 2, rect.top() - titleHeight,
+ menu_width, titleHeight);
+ }
+ }
+ break;
+
+ case Title: {
+ QRect r(rect.left()
+ + (hasSysMenu ? menu_width + 4: 0),
+ rect.top() - titleHeight,
+ rect.width()
+ - (hasSysMenu ? menu_width : 0)
+ - close_width
+ - (hasMaximize ? maximize_width : 0)
+ - (hasMinimize ? minimize_width : 0)
+ - (hasContextHelp ? help_width : 0)
+ - 3,
+ titleHeight);
+ if (r.width() > 0)
+ region = r;
+ }
+ break;
+ case Help: {
+ if (hasContextHelp) {
+ QRect r(rect.right()
+ - close_width
+ - (hasMaximize ? maximize_width : 0)
+ - (hasMinimize ? minimize_width : 0)
+ - help_width - 3, rect.top() - titleHeight,
+ help_width, titleHeight);
+ if (r.left() > rect.left() + titleHeight)
+ region = r;
+ }
+ }
+ break;
+
+ case Minimize: {
+ if (hasMinimize && !isMinimized) {
+ QRect r(rect.right() - close_width
+ - (hasMaximize ? maximize_width : 0)
+ - minimize_width - 3, rect.top() - titleHeight,
+ minimize_width, titleHeight);
+ if (r.left() > rect.left() + titleHeight)
+ region = r;
+ }
+ }
+ break;
+
+ case Maximize: {
+ if (hasMaximize && !isMaximized) {
+ QRect r(rect.right() - close_width - maximize_width - 3,
+ rect.top() - titleHeight, maximize_width, titleHeight);
+ if (r.left() > rect.left() + titleHeight)
+ region = r;
+ }
+ }
+ break;
+
+ case Normalize: {
+ if (hasMinimize && isMinimized) {
+ QRect r(rect.right() - close_width
+ - (hasMaximize ? maximize_width : 0)
+ - minimize_width - 3, rect.top() - titleHeight,
+ minimize_width, titleHeight);
+ if (r.left() > rect.left() + titleHeight)
+ region = r;
+ } else if (hasMaximize && isMaximized) {
+ QRect r(rect.right() - close_width - maximize_width - 3,
+ rect.top() - titleHeight, maximize_width, titleHeight);
+ if (r.left() > rect.left() + titleHeight)
+ region = r;
+ }
+ }
+ break;
+
+ case Close: {
+ QRect r(rect.right() - close_width - 1, rect.top() - titleHeight,
+ close_width, titleHeight);
+ if (r.left() > rect.left() + titleHeight)
+ region = r;
+ }
+ break;
+
+ default:
+ region = QDecorationDefault::region(widget, rect, type);
+ break;
+ }
+
+ return region;
+}
+
+bool QDecorationWindows::paint(QPainter *painter, const QWidget *widget, int decorationRegion,
+ DecorationState state)
+{
+ if (decorationRegion == None)
+ return false;
+
+ const QRect titleRect = QDecoration::region(widget, Title).boundingRect();
+ const QPalette pal = QApplication::palette();
+ QRegion oldClipRegion = painter->clipRegion();
+
+ bool paintAll = (decorationRegion == int(All));
+ if ((paintAll || decorationRegion & Title && titleRect.width() > 0) && state == Normal
+ && (widget->windowFlags() & Qt::WindowTitleHint) ) {
+ painter->setClipRegion(oldClipRegion);
+ QColor fromBrush, toBrush;
+ QPen titlePen;
+
+ if (widget == qApp->activeWindow() || qApp->activeWindow() == qApp->activePopupWidget()) {
+ fromBrush = pal.color(QPalette::Highlight);
+ titlePen = pal.color(QPalette::HighlightedText);
+ } else {
+ fromBrush = pal.color(QPalette::Window);
+ titlePen = pal.color(QPalette::Text);
+ }
+ toBrush = fromBrush.lighter(300);
+
+ painter->setPen(Qt::NoPen);
+ QPoint p1(titleRect.x(), titleRect.y() + titleRect.height()/2);
+ QPoint p2(titleRect.right(), titleRect.y() + titleRect.height()/2);
+ QLinearGradient lg(p1, p2);
+ lg.setColorAt(0, fromBrush);
+ lg.setColorAt(1, toBrush);
+ painter->fillRect(titleRect, lg);
+
+ painter->setPen(titlePen);
+ painter->drawText(titleRect, Qt::AlignVCenter, windowTitleFor(widget));
+ decorationRegion ^= Title;
+ }
+
+ return QDecorationDefault::paint(painter, widget, decorationRegion, state);
+}
+
+void QDecorationWindows::paintButton(QPainter *painter, const QWidget *widget, int buttonRegion,
+ DecorationState state, const QPalette &pal)
+{
+ QBrush fromBrush, toBrush;
+ QPen titlePen;
+
+ if (widget == qApp->activeWindow() || qApp->activeWindow() == qApp->activePopupWidget()) {
+ fromBrush = pal.brush(QPalette::Highlight);
+ titlePen = pal.color(QPalette::HighlightedText);
+ } else {
+ fromBrush = pal.brush(QPalette::Window);
+ titlePen = pal.color(QPalette::Text);
+ }
+ toBrush = fromBrush.color().lighter(300);
+
+ QRect brect(QDecoration::region(widget, buttonRegion).boundingRect());
+ if (buttonRegion != Close && buttonRegion != Menu)
+ painter->fillRect(brect, toBrush);
+ else
+ painter->fillRect(brect.x() - 2, brect.y(), brect.width() + 4, brect.height(),
+ buttonRegion == Menu ? fromBrush : toBrush);
+
+ int xoff = 1;
+ int yoff = 2;
+ const QPixmap pm = pixmapFor(widget, buttonRegion, xoff, yoff);
+ if (buttonRegion != Menu) {
+ if (state & Normal) {
+ qDrawWinPanel(painter, brect.x(), brect.y() + 2, brect.width(),
+ brect.height() - 4, pal, false, &pal.brush(QPalette::Window));
+ } else if (state & Pressed) {
+ qDrawWinPanel(painter, brect.x(), brect.y() + 2, brect.width(),
+ brect.height() - 4, pal, true, &pal.brush(QPalette::Window));
+ ++xoff;
+ ++yoff;
+ }
+ } else {
+ xoff = 0;
+ yoff = 2;
+ }
+
+ if (!pm.isNull())
+ painter->drawPixmap(brect.x() + xoff, brect.y() + yoff, pm);
+}
+
+#endif // QT_NO_QWS_DECORATION_WINDOWS || QT_PLUGIN
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qdecorationwindows_qws.h b/src/gui/embedded/qdecorationwindows_qws.h
new file mode 100644
index 0000000000..c7eb80ece9
--- /dev/null
+++ b/src/gui/embedded/qdecorationwindows_qws.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECORATIONWINDOWS_QWS_H
+#define QDECORATIONWINDOWS_QWS_H
+
+#include <QtGui/qdecorationdefault_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if !defined(QT_NO_QWS_DECORATION_WINDOWS) || defined(QT_PLUGIN)
+
+class Q_GUI_EXPORT QDecorationWindows : public QDecorationDefault
+{
+public:
+ QDecorationWindows();
+ virtual ~QDecorationWindows();
+
+ QRegion region(const QWidget *widget, const QRect &rect, int decorationRegion = All);
+ bool paint(QPainter *painter, const QWidget *widget, int decorationRegion = All,
+ DecorationState state = Normal);
+
+protected:
+ void paintButton(QPainter *painter, const QWidget *widget, int buttonRegion,
+ DecorationState state, const QPalette &pal);
+ const char **xpmForRegion(int reg);
+};
+
+#endif // QT_NO_QWS_DECORATION_WINDOWS
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDECORATIONWINDOWS_QWS_H
diff --git a/src/gui/embedded/qdirectpainter_qws.cpp b/src/gui/embedded/qdirectpainter_qws.cpp
new file mode 100644
index 0000000000..113e60747c
--- /dev/null
+++ b/src/gui/embedded/qdirectpainter_qws.cpp
@@ -0,0 +1,682 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdirectpainter_qws.h"
+
+#include "qscreen_qws.h"
+#include "private/qobject_p.h"
+#include "private/qapplication_p.h"
+#include "qwsdisplay_qws.h"
+#include "qwidget.h"
+#include "qimage.h"
+#include <qwsevent_qws.h>
+#include <private/qwindowsurface_qws_p.h>
+#include <private/qwsdisplay_qws_p.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef Q_WS_QWS
+#ifndef QT_NO_DIRECTPAINTER
+
+/*!
+ \class QDirectPainter
+ \ingroup multimedia
+ \ingroup qws
+
+ \brief The QDirectPainter class provides direct access to the
+ underlying hardware in Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ QDirectPainter allows a client application to reserve a region of
+ the framebuffer and render directly onto the screen. There are two
+ ways of using the QDirectPainter class: You can either reserve a
+ region using the provided static functions, or you can instantiate
+ an object and make use of its more dynamic API.
+
+ \tableofcontents
+
+ \section1 Dynamic Allocation
+
+ By instantiating a QDirectPainter object using the default
+ QDirectPainter::NonReserved surface flag, the client application
+ only gets some control over the reserved region, i.e., it can
+ still render directly onto the screen but the allocated region may
+ change (for example, if a window with a higher focus requests
+ parts of the same region). The currently allocated region can be
+ retrieved using the allocatedRegion() function, while the
+ requestedRegion() function returns the originally reserved
+ region.
+
+
+ \section1 Static Allocation
+
+
+ Using the static approach, the client application gets complete
+ control over the reserved region, i.e., the affected region will
+ never be modified by the screen driver.
+
+ To create a static region, pass the QDirectPainter::Reserved
+ surface flag to the constructor. After the reserved region is
+ reported through regionChanged(), the allocated region will not
+ change, unless setRegion() is called.
+
+ If QDirectPainter::ReservedSynchronous is passed to the
+ constructor, calls to setRegion() will block until the region is
+ reserved, meaning that allocatedRegion() will be available immediately.
+ Note that in the current version setRegion() will cause the application
+ event loop to be entered, potentially causing reentrancy issues.
+
+ \section1 Rendering
+
+ To draw on a given region, the application must first get hold of
+ a pointer to the framebuffer. In most cases, this pointer can be
+ retrieved using the QDirectPainter::frameBuffer() function. But
+ note that if the current screen has subscreens, you must query the
+ screen driver instead to identify the correct subscreen. A pointer
+ to the current screen driver can always be retrieved using the
+ static QScreen::instance() function. Then use QScreen's \l
+ {QScreen::}{subScreenIndexAt()} and \l {QScreen::}{subScreens()}
+ functions to access the correct subscreen, and the subscreen's \l
+ {QScreen::}{base()} function to retrieve a pointer to the
+ framebuffer.
+
+ Depending on the hardware, it might be necessary to lock the
+ framebuffer for exclusive use while writing to it. This is
+ possible using the lock() and unlock() functions. Note that
+ calling lock() will prevent all other applications from working
+ until unlock() is called.
+
+ In addition, QDirectPainter provides several functions returning
+ information about the framebuffer: the linestep() function returns
+ the length (in bytes) of each scanline of the framebuffer while
+ the screenDepth(), screenWidth() and screenHeight() function
+ return the screen metrics.
+
+ \sa QScreen, QWSEmbedWidget, {Qt for Embedded Linux Architecture}
+*/
+
+/*!
+ \enum QDirectPainter::SurfaceFlag
+
+ This enum describes the behavior of the region reserved by this
+ QDirectPainter object.
+
+ \value NonReserved The allocated region may change, e.g., if a
+ window with a higher focus requests parts of the same region. See
+ also \l {Dynamic Allocation}.
+
+ \value Reserved The allocated region will never change. See also
+ \l {Static Allocation}.
+
+ \value ReservedSynchronous The allocated region will never change and
+ each function that changes the allocated region will be blocking.
+
+ \sa reservedRegion(), allocatedRegion()
+*/
+
+/*!
+ \fn QRegion QDirectPainter::region()
+ \obsolete
+
+ Use QDirectPainter::reservedRegion() instead.
+*/
+
+static inline QScreen *getPrimaryScreen()
+{
+ QScreen *screen = QScreen::instance();
+ if (!screen->base()) {
+ QList<QScreen*> subScreens = screen->subScreens();
+ if (subScreens.size() < 1)
+ return 0;
+ screen = subScreens.at(0);
+ }
+ return screen;
+}
+
+static inline QSize screenS()
+{
+ QScreen *screen = getPrimaryScreen();
+ if (!screen)
+ return QSize();
+ return QSize(screen->width(), screen->height());
+}
+
+static inline QSize devS()
+{
+ QScreen *screen = getPrimaryScreen();
+ if (!screen)
+ return QSize();
+ return QSize(screen->deviceWidth(), screen->deviceHeight());
+}
+
+
+class QDirectPainterPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QDirectPainter);
+public:
+
+ QDirectPainterPrivate() : surface(0), seenRegion(false) {}
+
+ ~QDirectPainterPrivate() {
+ if (QPaintDevice::qwsDisplay()) { // make sure not in QApplication destructor
+ qApp->d_func()->directPainters->remove(surface->windowId());
+ surface->setGeometry(QRect());
+ }
+ delete surface;
+ }
+
+ QWSDirectPainterSurface *surface;
+ QRegion requested_region;
+
+ static QDirectPainter *staticPainter;
+ bool seenRegion;
+};
+
+QDirectPainter *QDirectPainterPrivate::staticPainter = 0;
+
+void qt_directpainter_region(QDirectPainter *dp, const QRegion &alloc, int type)
+{
+ QDirectPainterPrivate *d = dp->d_func();
+
+ QRegion r = alloc;
+ QScreen *screen = d->surface->screen();
+ if (screen->isTransformed()) {
+ const QSize screenSize(screen->width(), screen->height());
+ r = screen->mapToDevice(r, screenSize);
+ }
+ if (type == QWSRegionEvent::Allocation) {
+ d->surface->setClipRegion(alloc);
+ d->seenRegion = true;
+ if (dp != QDirectPainterPrivate::staticPainter) {
+ if (!d->surface->flushingRegionEvents) // recursion guard
+ dp->regionChanged(r);
+ }
+ }
+}
+
+#ifndef QT_NO_QWSEMBEDWIDGET
+void qt_directpainter_embedevent(QDirectPainter *dp, const QWSEmbedEvent *event)
+{
+ if (event->type | QWSEmbedEvent::Region) {
+ QScreen *screen = dp->d_func()->surface->screen();
+ QRegion r = event->region;
+ if (screen->isTransformed()) {
+ const QSize screenSize(screen->width(), screen->height());
+ r = screen->mapToDevice(r, screenSize);
+ }
+ dp->setRegion(r);
+ }
+}
+#endif
+
+/*!
+ Constructs a QDirectPainter object with the given \a parent and
+ surface \a flag.
+*/
+QDirectPainter::QDirectPainter(QObject *parent, SurfaceFlag flag)
+ :QObject(*new QDirectPainterPrivate, parent)
+{
+ Q_D(QDirectPainter);
+ d->surface = new QWSDirectPainterSurface(true, flag);
+
+ if (flag != NonReserved)
+ d->surface->setReserved();
+
+ QApplicationPrivate *ad = qApp->d_func();
+ if (!ad->directPainters)
+ ad->directPainters = new QMap<WId, QDirectPainter*>;
+ ad->directPainters->insert(d->surface->windowId(), this);
+}
+
+/*!
+ Destroys this QDirectPainter object, releasing the reserved region.
+
+ \sa allocatedRegion()
+*/
+QDirectPainter::~QDirectPainter()
+{
+ /* should not be necessary
+ if (this == QDirectPainterPrivate::staticPainter)
+ QDirectPainterPrivate::staticPainter = 0;
+ */
+}
+
+/*!
+ \fn void QDirectPainter::setGeometry(const QRect &rectangle)
+ \since 4.2
+
+ Request to reserve the given \a rectangle of the framebuffer.
+
+ Note that the actually allocated region might differ from the
+ requested one, e.g., if the given region overlaps with the
+ region of another QDirectPainter object.
+
+ \sa geometry(), allocatedRegion(), setRegion()
+*/
+void QDirectPainter::setGeometry(const QRect &rect)
+{
+ setRegion(rect);
+}
+
+/*!
+ \since 4.2
+
+ Returns the bounding rectangle of the requested region.
+
+ \sa setGeometry(), requestedRegion()
+*/
+QRect QDirectPainter::geometry() const
+{
+ Q_D(const QDirectPainter);
+ return d->requested_region.boundingRect();
+}
+
+/*!
+ \since 4.2
+
+ Requests to reserve the given \a region of the framebuffer.
+
+ Note that the actually allocated region might differ from the
+ requested one, e.g., if the given region overlaps with the region
+ of another QDirectPainter object.
+
+ \sa requestedRegion(), allocatedRegion(), {Dynamic Allocation}
+*/
+void QDirectPainter::setRegion(const QRegion &region)
+{
+ Q_D(QDirectPainter);
+ d->requested_region = region;
+
+ const QScreen *screen = d->surface->screen();
+ if (screen->isTransformed()) {
+ const QSize devSize(screen->deviceWidth(), screen->deviceHeight());
+ const QRegion r = screen->mapFromDevice(region, devSize);
+ d->surface->setRegion(r);
+ } else {
+ d->surface->setRegion(region);
+ }
+}
+
+/*!
+ \since 4.2
+
+ Returns the region requested by this QDirectPainter.
+
+ Note that if the QDirectPainter::Reserved flag is set, the region
+ returned by this function will always be equivalent to the region
+ returned by the allocatedRegion() function. Otherwise they might
+ differ (see \l {Dynamic Allocation} for details).
+
+ \sa geometry(), setRegion()
+*/
+QRegion QDirectPainter::requestedRegion() const
+{
+ Q_D(const QDirectPainter);
+ return d->requested_region;
+}
+
+/*!
+ \since 4.2
+
+ Returns the currently reserved region.
+
+ Note that if the QDirectPainter::Reserved flag is set, the region
+ returned by this function will always be equivalent to the region
+ returned by the requestedRegion() function. Otherwise they might
+ differ (see \l {Dynamic Allocation} for details).
+
+ \sa requestedRegion(), geometry()
+*/
+QRegion QDirectPainter::allocatedRegion() const
+{
+ Q_D(const QDirectPainter);
+ const QScreen *screen = d->surface->screen();
+ if (screen->isTransformed()) {
+ const QSize screenSize(screen->width(), screen->height());
+ return screen->mapToDevice(d->surface->region(), screenSize);
+ } else {
+ return d->surface->region();
+ }
+}
+
+/*!
+ \since 4.2
+
+ Returns the window system identifier of the widget.
+*/
+WId QDirectPainter::winId() const
+{
+ Q_D(const QDirectPainter);
+ return d->surface->windowId();
+}
+
+/*!
+ \fn void QDirectPainter::regionChanged(const QRegion &newRegion)
+ \since 4.2
+
+ This function is called when the allocated region changes.
+
+ This function is not called for region changes that happen while the
+ startPainting() function is executing.
+
+ Note that the given region, \a newRegion, is not guaranteed to be correct at the
+ time you access the display. To prevent reentrancy problems you should
+ always call startPainting() before updating the display and then use
+ allocatedRegion() to retrieve the correct region.
+
+ \sa allocatedRegion(), startPainting(), {Dynamic Allocation}
+*/
+void QDirectPainter::regionChanged(const QRegion &region)
+{
+ Q_UNUSED(region);
+}
+
+/*!
+ \since 4.2
+
+ Call this function before you start updating the pixels in the
+ allocated region. The hardware will be notified, if necessary,
+ that you are about to start painting operations.
+
+ Set \a lockDisplay if you want startPainting() and endPainting()
+ to lock() and unlock() the display automatically.
+
+ Note that for a NonReserved direct painter, you must call
+ allocatedRegion() after calling this function, since the allocated
+ region is only guaranteed to be correct after this function has
+ returned.
+
+ The regionChanged() function will not be called between startPainting()
+ and endPainting().
+
+ \sa endPainting(), flush()
+*/
+void QDirectPainter::startPainting(bool lockDisplay)
+{
+ Q_D(QDirectPainter);
+ d->surface->setLocking(lockDisplay);
+
+ const QScreen *screen = d->surface->screen();
+ if (screen->isTransformed()) {
+ const QSize devSize(screen->deviceWidth(), screen->deviceHeight());
+ const QRegion r = screen->mapFromDevice(d->surface->region(), devSize);
+ d->surface->beginPaint(r);
+ } else {
+ d->surface->beginPaint(d->surface->region());
+ }
+}
+
+/*!
+ \since 4.2
+
+ Call this function when you are done updating the screen. It will
+ notify the hardware, if necessary, that your painting operations
+ have ended.
+*/
+void QDirectPainter::endPainting()
+{
+ Q_D(QDirectPainter);
+
+ const QScreen *screen = d->surface->screen();
+ if (screen->isTransformed()) {
+ const QSize devSize(screen->deviceWidth(), screen->deviceHeight());
+ const QRegion r = screen->mapFromDevice(d->surface->region(), devSize);
+ d->surface->endPaint(r);
+ } else {
+ d->surface->endPaint(d->surface->region());
+ }
+}
+
+/*!
+ \since 4.3
+ \overload
+
+ This function will automatically call flush() to flush the
+ \a region to the display before notifying the hardware, if
+ necessary, that painting operations have ended.
+*/
+void QDirectPainter::endPainting(const QRegion &region)
+{
+ endPainting();
+ flush(region);
+}
+
+/*!
+ \since 4.3
+
+ Flushes the \a region onto the screen.
+*/
+void QDirectPainter::flush(const QRegion &region)
+{
+ Q_D(QDirectPainter);
+
+ const QScreen *screen = d->surface->screen();
+ if (screen->isTransformed()) {
+ const QSize devSize(screen->deviceWidth(), screen->deviceHeight());
+ const QRegion r = screen->mapFromDevice(region, devSize);
+ d->surface->flush(0, r, QPoint());
+ } else {
+ d->surface->flush(0, region, QPoint());
+ }
+}
+
+/*!
+ \since 4.2
+
+ Raises the reserved region to the top of the widget stack.
+
+ After this call the reserved region will be visually in front of
+ any overlapping widgets.
+
+ \sa lower(), requestedRegion()
+*/
+void QDirectPainter::raise()
+{
+ QWidget::qwsDisplay()->setAltitude(winId(),QWSChangeAltitudeCommand::Raise);
+}
+
+/*!
+ \since 4.2
+
+ Lowers the reserved region to the bottom of the widget stack.
+
+ After this call the reserved region will be visually behind (and
+ therefore obscured by) any overlapping widgets.
+
+ \sa raise(), requestedRegion()
+*/
+void QDirectPainter::lower()
+{
+ QWidget::qwsDisplay()->setAltitude(winId(),QWSChangeAltitudeCommand::Lower);
+}
+
+
+/*!
+ \fn QRegion QDirectPainter::reserveRegion(const QRegion &region)
+
+ Attempts to reserve the \a region and returns the region that is
+ actually reserved.
+
+ This function also releases the previously reserved region if
+ any. If not released explicitly, the region will be released on
+ application exit.
+
+ \sa reservedRegion(), {Static Allocation}
+
+ \obsolete
+
+ Construct a QDirectPainter using QDirectPainter::ReservedSynchronous instead.
+*/
+QRegion QDirectPainter::reserveRegion(const QRegion &reg)
+{
+ if (!QDirectPainterPrivate::staticPainter)
+ QDirectPainterPrivate::staticPainter = new QDirectPainter(qApp, ReservedSynchronous);
+
+ QDirectPainter *dp = QDirectPainterPrivate::staticPainter;
+ dp->setRegion(reg);
+
+ return dp->allocatedRegion();
+}
+
+/*!
+ Returns a pointer to the beginning of the display memory.
+
+ Note that it is the application's responsibility to limit itself
+ to modifying only the reserved region.
+
+ Do not use this pointer if the current screen has subscreens,
+ query the screen driver instead: A pointer to the current screen
+ driver can always be retrieved using the static
+ QScreen::instance() function. Then use QScreen's \l
+ {QScreen::}{subScreenIndexAt()} and \l {QScreen::}{subScreens()}
+ functions to access the correct subscreen, and the subscreen's \l
+ {QScreen::}{base()} function to retrieve a pointer to the
+ framebuffer.
+
+ \sa requestedRegion(), allocatedRegion(), linestep()
+*/
+uchar* QDirectPainter::frameBuffer()
+{
+ QScreen *screen = getPrimaryScreen();
+ if (!screen)
+ return 0;
+ return screen->base();
+}
+
+/*!
+ \since 4.2
+
+ Returns the reserved region.
+
+ \sa reserveRegion(), frameBuffer()
+
+ \obsolete
+
+ Use allocatedRegion() instead.
+*/
+QRegion QDirectPainter::reservedRegion()
+{
+ return QDirectPainterPrivate::staticPainter
+ ? QDirectPainterPrivate::staticPainter->allocatedRegion() : QRegion();
+}
+
+/*!
+ Returns the bit depth of the display.
+
+ \sa screenHeight(), screenWidth()
+*/
+int QDirectPainter::screenDepth()
+{
+ QScreen *screen = getPrimaryScreen();
+ if (!screen)
+ return 0;
+ return screen->depth();
+}
+
+/*!
+ Returns the width of the display in pixels.
+
+ \sa screenHeight(), screenDepth()
+*/
+int QDirectPainter::screenWidth()
+{
+ QScreen *screen = getPrimaryScreen();
+ if (!screen)
+ return 0;
+ return screen->deviceWidth();
+}
+
+/*!
+ Returns the height of the display in pixels.
+
+ \sa screenWidth(), screenDepth()
+*/
+int QDirectPainter::screenHeight()
+{
+ QScreen *screen = getPrimaryScreen();
+ if (!screen)
+ return 0;
+ return screen->deviceHeight();
+}
+
+/*!
+ Returns the length (in bytes) of each scanline of the framebuffer.
+
+ \sa frameBuffer()
+*/
+int QDirectPainter::linestep()
+{
+ QScreen *screen = getPrimaryScreen();
+ if (!screen)
+ return 0;
+ return screen->linestep();
+}
+
+
+/*!
+ Locks access to the framebuffer.
+
+ Note that calling this function will prevent all other
+ applications from updating the display until unlock() is called.
+
+ \sa unlock()
+*/
+void QDirectPainter::lock()
+{
+ QWSDisplay::grab(true);
+}
+/*!
+ Unlocks the lock on the framebuffer (set using the lock()
+ function), allowing other applications to access the screen.
+
+ \sa lock()
+ */
+void QDirectPainter::unlock()
+{
+ QWSDisplay::ungrab();
+}
+
+#endif //QT_NO_DIRECTPAINTER
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qdirectpainter_qws.h b/src/gui/embedded/qdirectpainter_qws.h
new file mode 100644
index 0000000000..8c5c30f5b0
--- /dev/null
+++ b/src/gui/embedded/qdirectpainter_qws.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDIRECTPAINTER_QWS_H
+#define QDIRECTPAINTER_QWS_H
+
+#include <QtCore/qobject.h>
+#include <QtGui/qregion.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_DIRECTPAINTER
+class QDirectPainterPrivate;
+class QWSEmbedEvent;
+
+class Q_GUI_EXPORT QDirectPainter : public QObject {
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QDirectPainter)
+public:
+
+ enum SurfaceFlag { NonReserved = 0,
+ Reserved = 1,
+ ReservedSynchronous = 3 };
+
+ explicit QDirectPainter(QObject *parentObject = 0, SurfaceFlag flag = NonReserved);
+ ~QDirectPainter();
+
+ void setRegion(const QRegion&);
+ QRegion requestedRegion() const;
+ QRegion allocatedRegion() const;
+
+ void setGeometry(const QRect&);
+ QRect geometry() const;
+
+ WId winId() const;
+ virtual void regionChanged(const QRegion &exposedRegion);
+
+ void startPainting(bool lockDisplay = true);
+ void endPainting();
+ void endPainting(const QRegion &region);
+ void flush(const QRegion &region);
+
+ void raise();
+ void lower();
+
+
+ static QRegion reserveRegion(const QRegion&);
+ static QRegion reservedRegion();
+ static QRegion region() { return reservedRegion(); }
+
+ static uchar* frameBuffer();
+ static int screenDepth();
+ static int screenWidth();
+ static int screenHeight();
+ static int linestep();
+
+ static void lock();
+ static void unlock();
+private:
+ friend void qt_directpainter_region(QDirectPainter *dp, const QRegion &alloc, int type);
+ friend void qt_directpainter_embedevent(QDirectPainter*, const QWSEmbedEvent*);
+};
+
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QDIRECTPAINTER_QWS_H
diff --git a/src/gui/embedded/qkbd_qws.cpp b/src/gui/embedded/qkbd_qws.cpp
new file mode 100644
index 0000000000..8cf87db0e8
--- /dev/null
+++ b/src/gui/embedded/qkbd_qws.cpp
@@ -0,0 +1,248 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkbd_qws.h"
+
+#ifndef QT_NO_QWS_KEYBOARD
+
+#include "qwindowsystem_qws.h"
+#include "qscreen_qws.h"
+#include "qtimer.h"
+#include <stdlib.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWSKbPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QWSKbPrivate(QWSKeyboardHandler *h) {
+ handler = h;
+ arTimer = new QTimer(this);
+ arTimer->setSingleShot(true);
+ connect(arTimer, SIGNAL(timeout()), SLOT(autoRepeat()));
+ repeatdelay = 400;
+ repeatperiod = 80;
+ }
+
+ void beginAutoRepeat(int uni, int code, Qt::KeyboardModifiers mod) {
+ unicode = uni;
+ keycode = code;
+ modifier = mod;
+ arTimer->start(repeatdelay);
+ }
+ void endAutoRepeat() {
+ arTimer->stop();
+ }
+
+private slots:
+ void autoRepeat() {
+ handler->processKeyEvent(unicode, keycode, modifier, false, true);
+ handler->processKeyEvent(unicode, keycode, modifier, true, true);
+ arTimer->start(repeatperiod);
+ }
+
+private:
+ QWSKeyboardHandler *handler;
+ int unicode;
+ int keycode;
+ Qt::KeyboardModifiers modifier;
+ int repeatdelay;
+ int repeatperiod;
+ QTimer *arTimer;
+};
+
+/*!
+ \class QWSKeyboardHandler
+ \ingroup qws
+
+ \brief The QWSKeyboardHandler class is a base class for keyboard
+ drivers in Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ \l{Qt for Embedded Linux} provides ready-made drivers for several keyboard
+ protocols, see the \l{Qt for Embedded Linux Character Input}{character
+ input} documentation for details. Custom keyboard drivers can be
+ implemented by subclassing the QWSKeyboardHandler class and
+ creating a keyboard driver plugin (derived from
+ QKbdDriverPlugin). The default implementation of the
+ QKbdDriverFactory class will automatically detect the plugin, and
+ load the driver into the server application at run-time using Qt's
+ \l{How to Create Qt Plugins}{plugin system}.
+
+ The keyboard driver receives keyboard events from the system
+ device and encapsulates each event with an instance of the
+ QWSEvent class which it then passes to the server application (the
+ server is responsible for propagating the event to the appropriate
+ client). To receive keyboard events, a QWSKeyboardHandler object
+ will usually create a QSocketNotifier object for the given
+ device. The QSocketNotifier class provides support for monitoring
+ activity on a file descriptor. When the socket notifier receives
+ data, it will call the keyboard driver's processKeyEvent()
+ function to send the event to the \l{Qt for Embedded Linux} server
+ application for relaying to clients.
+
+
+ QWSKeyboardHandler also provides functions to control
+ auto-repetion of key sequences, beginAutoRepeat() and
+ endAutoRepeat(), and the transformDirKey() function enabling
+ transformation of arrow keys according to the display orientation.
+
+ \sa QKbdDriverPlugin, QKbdDriverFactory, {Qt for Embedded Linux Character Input}
+*/
+
+
+/*!
+ Constructs a keyboard driver.
+
+ Call the QWSServer::setKeyboardHandler() function to make the
+ newly created keyboard driver, the primary driver. Note that the
+ primary driver is controlled by the system, i.e., the system will
+ delete it upon exit.
+*/
+QWSKeyboardHandler::QWSKeyboardHandler()
+{
+ d = new QWSKbPrivate(this);
+}
+
+/*!
+ Destroys this keyboard driver.
+
+ Do not call this function if this driver is the primary keyboard
+ handler, i.e., if QWSServer::setKeyboardHandler() function has
+ been called passing this driver as argument. The primary keyboard
+ driver is deleted by the system.
+*/
+QWSKeyboardHandler::~QWSKeyboardHandler()
+{
+ delete d;
+}
+
+
+/*!
+ Sends a key event to the \l{Qt for Embedded Linux} server application.
+
+ The key event is identified by its \a unicode value and the \a
+ keycode, \a modifiers, \a isPress and \a autoRepeat parameters.
+
+ The \a keycode parameter is the Qt keycode value as defined by the
+ Qt::Key enum. The \a modifiers is an OR combination of
+ Qt::KeyboardModifier values, indicating whether \gui
+ Shift/Alt/Ctrl keys are pressed. The \a isPress parameter is true
+ if the event is a key press event and \a autoRepeat is true if the
+ event is caused by an auto-repeat mechanism and not an actual key
+ press.
+
+ \sa beginAutoRepeat(), endAutoRepeat(), transformDirKey()
+*/
+void QWSKeyboardHandler::processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
+ bool isPress, bool autoRepeat)
+{
+ qwsServer->processKeyEvent(unicode, keycode, modifiers, isPress, autoRepeat);
+}
+
+/*!
+ \fn int QWSKeyboardHandler::transformDirKey(int keycode)
+
+ Transforms the arrow key specified by the given \a keycode, to the
+ orientation of the display and returns the transformed keycode.
+
+ The \a keycode is a Qt::Key value. The values identifying arrow
+ keys are:
+
+ \list
+ \o Qt::Key_Left
+ \o Qt::Key_Up
+ \o Qt::Key_Right
+ \o Qt::Key_Down
+ \endlist
+
+ \sa processKeyEvent()
+ */
+int QWSKeyboardHandler::transformDirKey(int key)
+{
+ static int dir_keyrot = -1;
+ if (dir_keyrot < 0) {
+ // get the rotation
+ switch (qgetenv("QWS_CURSOR_ROTATION").toInt()) {
+ case 90: dir_keyrot = 1; break;
+ case 180: dir_keyrot = 2; break;
+ case 270: dir_keyrot = 3; break;
+ default: dir_keyrot = 0; break;
+ }
+ }
+ int xf = qt_screen->transformOrientation() + dir_keyrot;
+ return (key-Qt::Key_Left+xf)%4+Qt::Key_Left;
+}
+
+/*!
+ \fn void QWSKeyboardHandler::beginAutoRepeat(int unicode, int keycode, Qt::KeyboardModifiers modifier)
+
+ Begins auto-repeating the specified key press; after a short delay
+ the key press is sent periodically until the endAutoRepeat()
+ function is called.
+
+ The key press is specified by its \a unicode, \a keycode and \a
+ modifier state.
+
+ \sa endAutoRepeat(), processKeyEvent()
+*/
+void QWSKeyboardHandler::beginAutoRepeat(int uni, int code, Qt::KeyboardModifiers mod)
+{
+ d->beginAutoRepeat(uni, code, mod);
+}
+
+/*!
+ Stops auto-repeating a key press.
+
+ \sa beginAutoRepeat(), processKeyEvent()
+*/
+void QWSKeyboardHandler::endAutoRepeat()
+{
+ d->endAutoRepeat();
+}
+
+QT_END_NAMESPACE
+
+#include "qkbd_qws.moc"
+
+#endif // QT_NO_QWS_KEYBOARD
diff --git a/src/gui/embedded/qkbd_qws.h b/src/gui/embedded/qkbd_qws.h
new file mode 100644
index 0000000000..8809f0a5b5
--- /dev/null
+++ b/src/gui/embedded/qkbd_qws.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKBD_QWS_H
+#define QKBD_QWS_H
+
+#include <QtGui/qapplication.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_KEYBOARD
+
+class QWSKbPrivate;
+
+class Q_GUI_EXPORT QWSKeyboardHandler
+{
+public:
+ QWSKeyboardHandler();
+ virtual ~QWSKeyboardHandler();
+
+ virtual void processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
+ bool isPress, bool autoRepeat);
+
+protected:
+ int transformDirKey(int key);
+ void beginAutoRepeat(int uni, int code, Qt::KeyboardModifiers mod);
+ void endAutoRepeat();
+
+private:
+ QWSKbPrivate *d;
+};
+
+#endif // QT_NO_QWS_KEYBOARD
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QKBD_QWS_H
diff --git a/src/gui/embedded/qkbddriverfactory_qws.cpp b/src/gui/embedded/qkbddriverfactory_qws.cpp
new file mode 100644
index 0000000000..1ade652a9c
--- /dev/null
+++ b/src/gui/embedded/qkbddriverfactory_qws.cpp
@@ -0,0 +1,193 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkbddriverfactory_qws.h"
+
+#ifndef QT_NO_QWS_KEYBOARD
+
+#include "qapplication.h"
+#include "qkbdtty_qws.h"
+#include "qkbdusb_qws.h"
+#include "qkbdum_qws.h"
+#include "qkbdsl5000_qws.h"
+#include "qkbdvfb_qws.h"
+#include "qkbdyopy_qws.h"
+#include "qkbdvr41xx_qws.h"
+#include <stdlib.h>
+#include "private/qfactoryloader_p.h"
+#include "qkbddriverplugin_qws.h"
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL)
+#ifndef QT_NO_LIBRARY
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QWSKeyboardHandlerFactoryInterface_iid,
+ QLatin1String("/kbddrivers"), Qt::CaseInsensitive))
+
+#endif //QT_NO_LIBRARY
+#endif //QT_MAKEDLL
+
+/*!
+ \class QKbdDriverFactory
+ \ingroup qws
+
+ \brief The QKbdDriverFactory class creates keyboard drivers in
+ Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ QKbdDriverFactory is used to detect and instantiate the available
+ keyboard drivers, allowing \l{Qt for Embedded Linux} to load the preferred
+ driver into the server application at runtime. The create()
+ function returns a QWSKeyboardHandler object representing the
+ keyboard driver identified by a given key. The valid keys
+ (i.e. the supported drivers) can be retrieved using the keys()
+ function.
+
+ \l{Qt for Embedded Linux} provides several built-in keyboard drivers. In
+ addition, custom keyboard drivers can be added using Qt's plugin
+ mechanism, i.e. by subclassing the QWSKeyboardHandler class and
+ creating a keyboard driver plugin (QKbdDriverPlugin). See the
+ \l{Qt for Embedded Linux Character Input}{character input} documentation
+ for details.
+
+ \sa QWSKeyboardHandler, QKbdDriverPlugin
+*/
+
+/*!
+ Creates the keyboard driver specified by the given \a key, using
+ the display specified by the given \a device.
+
+ Note that the keys are case-insensitive.
+
+ \sa keys()
+*/
+QWSKeyboardHandler *QKbdDriverFactory::create(const QString& key, const QString& device)
+{
+ QString driver = key.toLower();
+#ifndef QT_NO_QWS_KBD_SL5000
+ if (driver == QLatin1String("sl5000") || driver.isEmpty())
+ return new QWSSL5000KeyboardHandler(device);
+#endif
+#ifndef QT_NO_QWS_KBD_YOPY
+ if (driver == QLatin1String("yopy") || driver.isEmpty())
+ return new QWSYopyKeyboardHandler(device);
+#endif
+#ifndef QT_NO_QWS_KBD_VR41XX
+ if (driver == QLatin1String("vr41xx") || driver.isEmpty())
+ return new QWSVr41xxKeyboardHandler(device);
+#endif
+#ifndef QT_NO_QWS_KEYBOARD
+# ifndef QT_NO_QWS_KBD_TTY
+ if (driver == QLatin1String("tty") || driver.isEmpty())
+ return new QWSTtyKeyboardHandler(device);
+# endif
+# ifndef QT_NO_QWS_KBD_USB
+ if (driver == QLatin1String("usb"))
+ return new QWSUsbKeyboardHandler(device);
+# endif
+# ifndef QT_NO_QWS_KBD_UM
+ if (driver == QLatin1String("um") || driver == QLatin1String("qvfbkeyboard"))
+ return new QWSUmKeyboardHandler(device);
+# endif
+# ifndef QT_NO_QWS_KBD_QVFB
+ if (driver == QLatin1String("qvfbkbd")
+ || driver == QLatin1String("qvfbkeyboard")
+ || driver == QLatin1String("qvfb"))
+ return new QVFbKeyboardHandler(device);
+# endif
+#endif
+
+#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL)
+#ifndef QT_NO_LIBRARY
+ if (QWSKeyboardHandlerFactoryInterface *factory = qobject_cast<QWSKeyboardHandlerFactoryInterface*>(loader()->instance(driver)))
+ return factory->create(driver, device);
+#endif
+#endif
+ return 0;
+}
+
+/*!
+ Returns the list of valid keys, i.e. the available keyboard
+ drivers.
+
+ \sa create()
+*/
+QStringList QKbdDriverFactory::keys()
+{
+ QStringList list;
+
+#ifndef QT_NO_QWS_KBD_SL5000
+ list << QLatin1String("SL5000");
+#endif
+#ifndef QT_NO_QWS_KBD_YOPY
+ list << QLatin1String("YOPY");
+#endif
+#ifndef QT_NO_QWS_KBD_VR41XX
+ list << QLatin1String("VR41xx");
+#endif
+#ifndef QT_NO_QWS_KBD_TTY
+ list << QLatin1String("TTY");
+#endif
+#ifndef QT_NO_QWS_KBD_USB
+ list << QLatin1String("USB");
+#endif
+#ifndef QT_NO_QWS_KBD_UM
+ list << QLatin1String("UM");
+#endif
+
+#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
+
+#endif // QT_NO_QWS_KEYBOARD
diff --git a/src/gui/embedded/qkbddriverfactory_qws.h b/src/gui/embedded/qkbddriverfactory_qws.h
new file mode 100644
index 0000000000..45e5664428
--- /dev/null
+++ b/src/gui/embedded/qkbddriverfactory_qws.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKBDDRIVERFACTORY_QWS_H
+#define QKBDDRIVERFACTORY_QWS_H
+
+#include <QtCore/qstringlist.h>
+
+#ifndef QT_NO_QWS_KEYBOARD
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QString;
+class QWSKeyboardHandler;
+
+class Q_GUI_EXPORT QKbdDriverFactory
+{
+public:
+ static QStringList keys();
+ static QWSKeyboardHandler *create(const QString&, const QString&);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_QWS_KEYBOARD
+#endif // QKBDDRIVERFACTORY_QWS_H
diff --git a/src/gui/embedded/qkbddriverplugin_qws.cpp b/src/gui/embedded/qkbddriverplugin_qws.cpp
new file mode 100644
index 0000000000..93dd9df458
--- /dev/null
+++ b/src/gui/embedded/qkbddriverplugin_qws.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkbddriverplugin_qws.h"
+
+#ifndef QT_NO_LIBRARY
+
+#include "qkbd_qws.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QKbdDriverPlugin
+ \ingroup plugins
+ \ingroup qws
+
+ \brief The QKbdDriverPlugin class is an abstract base class for
+ keyboard driver plugins in Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ \l{Qt for Embedded Linux} provides ready-made drivers for several keyboard
+ protocols, see the \l{Qt for Embedded Linux Character Input}{character
+ input} documentation for details. Custom keyboard drivers can be
+ implemented by subclassing the QWSKeyboardHandler class and
+ creating a keyboard driver plugin.
+
+ A keyboard driver plugin can be created by subclassing
+ QKbdDriverPlugin 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
+ QKbdDriverFactory 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 QKbdDriverFactory, QWSKeyboardHandler
+*/
+
+/*!
+ \fn QStringList QKbdDriverPlugin::keys() const
+
+ Implement this function to return the list of valid keys, i.e. the
+ keyboard drivers supported by this plugin.
+
+ \l{Qt for Embedded Linux} provides ready-made drivers for several keyboard
+ protocols, see the \l{Qt for Embedded Linux Character Input}{character
+ input} documentation for details.
+
+ \sa create()
+*/
+
+/*!
+ Constructs a keyboard driver 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.
+*/
+QKbdDriverPlugin::QKbdDriverPlugin(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ Destroys the keyboard driver plugin.
+
+ Note that Qt destroys a plugin automatically when it is no longer
+ used, so there is no need for calling the destructor explicitly.
+*/
+QKbdDriverPlugin::~QKbdDriverPlugin()
+{
+}
+
+/*!
+ \fn QScreen *QKbdDriverPlugin::create(const QString &key, const QString &device)
+
+ Implement this function to create a driver matching the type
+ specified by the given \a key and \a device parameters. Note that
+ keys are case-insensitive.
+
+ \sa keys()
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
diff --git a/src/gui/embedded/qkbddriverplugin_qws.h b/src/gui/embedded/qkbddriverplugin_qws.h
new file mode 100644
index 0000000000..e320b17b8c
--- /dev/null
+++ b/src/gui/embedded/qkbddriverplugin_qws.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKBDDRIVERPLUGIN_QWS_H
+#define QKBDDRIVERPLUGIN_QWS_H
+
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_LIBRARY
+
+class QWSKeyboardHandler;
+
+struct Q_GUI_EXPORT QWSKeyboardHandlerFactoryInterface : public QFactoryInterface
+{
+ virtual QWSKeyboardHandler* create(const QString &name, const QString &device) = 0;
+};
+
+#define QWSKeyboardHandlerFactoryInterface_iid "com.trolltech.Qt.QWSKeyboardHandlerFactoryInterface"
+Q_DECLARE_INTERFACE(QWSKeyboardHandlerFactoryInterface, QWSKeyboardHandlerFactoryInterface_iid)
+
+class Q_GUI_EXPORT QKbdDriverPlugin : public QObject, public QWSKeyboardHandlerFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QWSKeyboardHandlerFactoryInterface:QFactoryInterface)
+public:
+ explicit QKbdDriverPlugin(QObject *parent = 0);
+ ~QKbdDriverPlugin();
+
+ virtual QStringList keys() const = 0;
+ virtual QWSKeyboardHandler* create(const QString& driver, const QString &device) = 0;
+};
+
+#endif // QT_NO_LIBRARY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QKBDDRIVERPLUGIN_QWS_H
diff --git a/src/gui/embedded/qkbdpc101_qws.cpp b/src/gui/embedded/qkbdpc101_qws.cpp
new file mode 100644
index 0000000000..3173645785
--- /dev/null
+++ b/src/gui/embedded/qkbdpc101_qws.cpp
@@ -0,0 +1,485 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkbdpc101_qws.h"
+
+#ifndef QT_NO_QWS_KEYBOARD
+
+#include "qscreen_qws.h"
+#include "qwindowsystem_qws.h"
+#include "qnamespace.h"
+#include "qapplication.h"
+
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#ifdef Q_OS_LINUX
+#include <sys/kd.h>
+#include <sys/vt.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static const QWSKeyMap pc101KeyM[] = {
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_Escape, 27 , 27 , 0xffff },
+ { Qt::Key_1, '1' , '!' , 0xffff },
+ { Qt::Key_2, '2' , '@' , 0xffff },
+ { Qt::Key_3, '3' , '#' , 0xffff },
+ { Qt::Key_4, '4' , '$' , 0xffff },
+ { Qt::Key_5, '5' , '%' , 0xffff },
+ { Qt::Key_6, '6' , '^' , 0xffff },
+ { Qt::Key_7, '7' , '&' , 0xffff },
+ { Qt::Key_8, '8' , '*' , 0xffff },
+ { Qt::Key_9, '9' , '(' , 0xffff }, // 10
+ { Qt::Key_0, '0' , ')' , 0xffff },
+ { Qt::Key_Minus, '-' , '_' , 0xffff },
+ { Qt::Key_Equal, '=' , '+' , 0xffff },
+ { Qt::Key_Backspace, 8 , 8 , 0xffff },
+ { Qt::Key_Tab, 9 , 9 , 0xffff },
+ { Qt::Key_Q, 'q' , 'Q' , 'Q'-64 },
+ { Qt::Key_W, 'w' , 'W' , 'W'-64 },
+ { Qt::Key_E, 'e' , 'E' , 'E'-64 },
+ { Qt::Key_R, 'r' , 'R' , 'R'-64 },
+ { Qt::Key_T, 't' , 'T' , 'T'-64 }, // 20
+ { Qt::Key_Y, 'y' , 'Y' , 'Y'-64 },
+ { Qt::Key_U, 'u' , 'U' , 'U'-64 },
+ { Qt::Key_I, 'i' , 'I' , 'I'-64 },
+ { Qt::Key_O, 'o' , 'O' , 'O'-64 },
+ { Qt::Key_P, 'p' , 'P' , 'P'-64 },
+ { Qt::Key_BraceLeft, '[' , '{' , 0xffff },
+ { Qt::Key_BraceRight, ']' , '}' , 0xffff },
+ { Qt::Key_Return, 13 , 13 , 0xffff },
+ { Qt::Key_Control, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_A, 'a' , 'A' , 'A'-64 }, // 30
+ { Qt::Key_S, 's' , 'S' , 'S'-64 },
+ { Qt::Key_D, 'd' , 'D' , 'D'-64 },
+ { Qt::Key_F, 'f' , 'F' , 'F'-64 },
+ { Qt::Key_G, 'g' , 'G' , 'G'-64 },
+ { Qt::Key_H, 'h' , 'H' , 'H'-64 },
+ { Qt::Key_J, 'j' , 'J' , 'J'-64 },
+ { Qt::Key_K, 'k' , 'K' , 'K'-64 },
+ { Qt::Key_L, 'l' , 'L' , 'L'-64 },
+ { Qt::Key_Semicolon, ';' , ':' , 0xffff },
+ { Qt::Key_Apostrophe, '\'' , '"' , 0xffff }, // 40
+ { Qt::Key_QuoteLeft, '`' , '~' , 0xffff },
+ { Qt::Key_Shift, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_Backslash, '\\' , '|' , 0xffff },
+ { Qt::Key_Z, 'z' , 'Z' , 'Z'-64 },
+ { Qt::Key_X, 'x' , 'X' , 'X'-64 },
+ { Qt::Key_C, 'c' , 'C' , 'C'-64 },
+ { Qt::Key_V, 'v' , 'V' , 'V'-64 },
+ { Qt::Key_B, 'b' , 'B' , 'B'-64 },
+ { Qt::Key_N, 'n' , 'N' , 'N'-64 },
+ { Qt::Key_M, 'm' , 'M' , 'M'-64 }, // 50
+ { Qt::Key_Comma, ',' , '<' , 0xffff },
+ { Qt::Key_Period, '.' , '>' , 0xffff },
+ { Qt::Key_Slash, '/' , '?' , 0xffff },
+ { Qt::Key_Shift, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_Asterisk, '*' , '*' , 0xffff },
+ { Qt::Key_Alt, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_Space, ' ' , ' ' , 0xffff },
+ { Qt::Key_CapsLock, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_F1, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_F2, 0xffff , 0xffff , 0xffff }, // 60
+ { Qt::Key_F3, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_F4, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_F5, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_F6, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_F7, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_F8, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_F9, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_F10, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_NumLock, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_ScrollLock, 0xffff , 0xffff , 0xffff }, // 70
+ { Qt::Key_7, '7' , '7' , 0xffff },
+ { Qt::Key_8, '8' , '8' , 0xffff },
+ { Qt::Key_9, '9' , '9' , 0xffff },
+ { Qt::Key_Minus, '-' , '-' , 0xffff },
+ { Qt::Key_4, '4' , '4' , 0xffff },
+ { Qt::Key_5, '5' , '5' , 0xffff },
+ { Qt::Key_6, '6' , '6' , 0xffff },
+ { Qt::Key_Plus, '+' , '+' , 0xffff },
+ { Qt::Key_1, '1' , '1' , 0xffff },
+ { Qt::Key_2, '2' , '2' , 0xffff }, // 80
+ { Qt::Key_3, '3' , '3' , 0xffff },
+ { Qt::Key_0, '0' , '0' , 0xffff },
+ { Qt::Key_Period, '.' , '.' , 0xffff },
+ { Qt::Key_SysReq, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_Less, '<' , '>' , 0xffff },
+ { Qt::Key_F11, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_F12, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 90
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_Enter, 13 , 13 , 0xffff },
+ { Qt::Key_Control, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_Slash, '/' , '/' , 0xffff },
+ { Qt::Key_SysReq, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_Meta, 0xffff , 0xffff , 0xffff }, // 100
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // break
+ { Qt::Key_Home, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_Up, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_PageUp, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_Left, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_Right, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_End, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_Down, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_PageDown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_Insert, 0xffff , 0xffff , 0xffff }, // 110
+ { Qt::Key_Delete, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // macro
+ { Qt::Key_F13, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_F14, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_Help, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // do
+ { Qt::Key_F17, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_Plus, '+' , '-' , 0xffff },
+ { Qt::Key_Pause, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff },
+ { 0, 0xffff , 0xffff , 0xffff }
+};
+
+static const int keyMSize = sizeof(pc101KeyM)/sizeof(QWSKeyMap)-1;
+
+//===========================================================================
+
+//
+// PC-101 type keyboards
+//
+
+/*!
+ \class QWSPC101KeyboardHandler
+ \ingroup qws
+
+ \internal
+*/
+
+QWSPC101KeyboardHandler::QWSPC101KeyboardHandler(const QString&)
+{
+ shift = false;
+ alt = false;
+ ctrl = false;
+ extended = 0;
+ prevuni = 0;
+ prevkey = 0;
+ caps = false;
+#if defined(QT_QWS_IPAQ)
+ // iPAQ Action Key has ScanCode 0x60: 0x60|0x80 = 0xe0 == extended mode 1 !
+ ipaq_return_pressed = false;
+#endif
+}
+
+QWSPC101KeyboardHandler::~QWSPC101KeyboardHandler()
+{
+}
+
+const QWSKeyMap *QWSPC101KeyboardHandler::keyMap() const
+{
+ return pc101KeyM;
+}
+
+void QWSPC101KeyboardHandler::doKey(uchar code)
+{
+
+ int keyCode = Qt::Key_unknown;
+ bool release = false;
+ int keypad = 0;
+ bool softwareRepeat = false;
+
+#ifndef QT_QWS_USE_KEYCODES
+ // extended?
+ if (code == 224
+#if defined(QT_QWS_IPAQ)
+ && !ipaq_return_pressed
+#endif
+ ) {
+ extended = 1;
+ return;
+ } else if (code == 225) {
+ extended = 2;
+ return;
+ }
+#endif
+
+ if (code & 0x80) {
+ release = true;
+ code &= 0x7f;
+ }
+
+#ifndef QT_QWS_USE_KEYCODES
+ if (extended == 1) {
+ switch (code) {
+ case 72:
+ keyCode = Qt::Key_Up;
+ break;
+ case 75:
+ keyCode = Qt::Key_Left;
+ break;
+ case 77:
+ keyCode = Qt::Key_Right;
+ break;
+ case 80:
+ keyCode = Qt::Key_Down;
+ break;
+ case 82:
+ keyCode = Qt::Key_Insert;
+ break;
+ case 71:
+ keyCode = Qt::Key_Home;
+ break;
+ case 73:
+ keyCode = Qt::Key_PageUp;
+ break;
+ case 83:
+ keyCode = Qt::Key_Delete;
+ break;
+ case 79:
+ keyCode = Qt::Key_End;
+ break;
+ case 81:
+ keyCode = Qt::Key_PageDown;
+ break;
+ case 28:
+ keyCode = Qt::Key_Enter;
+ break;
+ case 53:
+ keyCode = Qt::Key_Slash;
+ break;
+ case 0x1d:
+ keyCode = Qt::Key_Control;
+ break;
+ case 0x2a:
+ keyCode = Qt::Key_Print;
+ break;
+ case 0x38:
+ keyCode = Qt::Key_Alt;
+ break;
+ case 0x5b:
+ keyCode = Qt::Key_Super_L;
+ break;
+ case 0x5c:
+ keyCode = Qt::Key_Super_R;
+ break;
+ case 0x5d:
+ keyCode = Qt::Key_Menu;
+ break;
+#if 0
+ default:
+ qDebug("extended1 code %x release %d", code, release);
+ break;
+#endif
+ }
+ } else if (extended == 2) {
+ switch (code) {
+ case 0x1d:
+ return;
+ case 0x45:
+ keyCode = Qt::Key_Pause;
+ break;
+ }
+ } else
+#endif
+ {
+ if (code < keyMSize) {
+ keyCode = pc101KeyM[code].key_code;
+ }
+
+#if defined(QT_QWS_IPAQ) || defined(QT_QWS_EBX)
+ softwareRepeat = true;
+
+ switch (code) {
+ case 0x7a: case 0x7b: case 0x7c: case 0x7d:
+ keyCode = code - 0x7a + Qt::Key_F9;
+ softwareRepeat = false;
+ break;
+ case 0x79:
+ keyCode = Qt::Key_SysReq;
+ softwareRepeat = false;
+ break;
+ case 0x78:
+# ifdef QT_QWS_IPAQ
+ keyCode = Qt::Key_F24; // record
+# else
+ keyCode = Qt::Key_Escape;
+# endif
+ softwareRepeat = false;
+ break;
+ case 0x60:
+ keyCode = Qt::Key_Return;
+# ifdef QT_QWS_IPAQ
+ ipaq_return_pressed = !release;
+# endif
+ break;
+ case 0x67:
+ keyCode = Qt::Key_Right;
+ break;
+ case 0x69:
+ keyCode = Qt::Key_Up;
+ break;
+ case 0x6a:
+ keyCode = Qt::Key_Down;
+ break;
+ case 0x6c:
+ keyCode = Qt::Key_Left;
+ break;
+ }
+
+ if (qt_screen->isTransformed()
+ && keyCode >= Qt::Key_Left && keyCode <= Qt::Key_Down)
+ {
+ keyCode = transformDirKey(keyCode);
+ }
+#endif
+ /*
+ Translate shift+Qt::Key_Tab to Qt::Key_Backtab
+ */
+ if ((keyCode == Qt::Key_Tab) && shift)
+ keyCode = Qt::Key_Backtab;
+ }
+
+#ifndef QT_QWS_USE_KEYCODES
+ /*
+ Qt::Keypad consists of extended keys 53 and 28,
+ and non-extended keys 55 and 71 through 83.
+ */
+ if ((extended == 1) ? (code == 53 || code == 28) :
+ (code == 55 || (code >= 71 && code <= 83)))
+#else
+ if (code == 55 || code >= 71 && code <= 83 || code == 96
+ || code == 98 || code == 118)
+#endif
+ {
+ keypad = Qt::KeypadModifier;
+ }
+
+ // Ctrl-Alt-Backspace exits qws
+ if (ctrl && alt && keyCode == Qt::Key_Backspace) {
+ qApp->quit();
+ }
+
+ if (keyCode == Qt::Key_Alt) {
+ alt = !release;
+ } else if (keyCode == Qt::Key_Control) {
+ ctrl = !release;
+ } else if (keyCode == Qt::Key_Shift) {
+ shift = !release;
+ } else if (keyCode == Qt::Key_CapsLock && release) {
+ caps = !caps;
+#if defined(Q_OS_LINUX)
+ char leds;
+ ioctl(0, KDGETLED, &leds);
+ leds = leds & ~LED_CAP;
+ if (caps) leds |= LED_CAP;
+ ioctl(0, KDSETLED, leds);
+#endif
+ }
+ if (keyCode != Qt::Key_unknown) {
+ bool bAlt = alt;
+ bool bCtrl = ctrl;
+ bool bShift = shift;
+ int unicode = 0;
+ if (code < keyMSize) {
+ if (!extended) {
+ bool bCaps = shift ||
+ (caps ? QChar(keyMap()[code].unicode).isLetter() : false);
+ if (bCtrl)
+ unicode = keyMap()[code].ctrl_unicode ? keyMap()[code].ctrl_unicode : 0xffff;
+ else if (bCaps)
+ unicode = keyMap()[code].shift_unicode ? keyMap()[code].shift_unicode : 0xffff;
+ else
+ unicode = keyMap()[code].unicode ? keyMap()[code].unicode : 0xffff;
+#ifndef QT_QWS_USE_KEYCODES
+ } else if (extended==1) {
+ if (code == 53)
+ unicode = '/';
+#endif
+ }
+ }
+
+ modifiers = 0;
+ if (bAlt) modifiers |= Qt::AltModifier;
+ if (bCtrl) modifiers |= Qt::ControlModifier;
+ if (bShift) modifiers |= Qt::ShiftModifier;
+ if (keypad) modifiers |= Qt::KeypadModifier;
+
+ // looks wrong -- WWA
+ bool repeat = false;
+ if (prevuni == unicode && prevkey == keyCode && !release)
+ repeat = true;
+
+ processKeyEvent(unicode, keyCode, modifiers, !release, repeat);
+
+ if (!release) {
+ prevuni = unicode;
+ prevkey = keyCode;
+ } else {
+ prevkey = prevuni = 0;
+ }
+ }
+
+ if (softwareRepeat && !release)
+ beginAutoRepeat(prevuni, prevkey, modifiers);
+ else
+ endAutoRepeat();
+
+ extended = 0;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QWS_KEYBOARD
diff --git a/src/gui/embedded/qkbdpc101_qws.h b/src/gui/embedded/qkbdpc101_qws.h
new file mode 100644
index 0000000000..f9f0104d4c
--- /dev/null
+++ b/src/gui/embedded/qkbdpc101_qws.h
@@ -0,0 +1,95 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKBDPC101_QWS_H
+#define QKBDPC101_QWS_H
+
+#include <QtGui/qkbd_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_KEYBOARD
+
+#ifndef QT_NO_QWS_KBD_PC101
+
+struct QWSKeyMap {
+ uint key_code;
+ ushort unicode;
+ ushort shift_unicode;
+ ushort ctrl_unicode;
+};
+
+class QWSPC101KeyboardHandler : public QWSKeyboardHandler
+{
+public:
+ explicit QWSPC101KeyboardHandler(const QString&);
+ virtual ~QWSPC101KeyboardHandler();
+
+ virtual void doKey(uchar scancode);
+ virtual const QWSKeyMap *keyMap() const;
+
+protected:
+ bool shift;
+ bool alt;
+ bool ctrl;
+ bool caps;
+#if defined(QT_QWS_IPAQ)
+ uint ipaq_return_pressed:1;
+#endif
+ uint extended:2;
+ Qt::KeyboardModifiers modifiers;
+ int prevuni;
+ int prevkey;
+};
+
+#endif // QT_NO_QWS_KBD_PC101
+
+#endif // QT_NO_QWS_KEYBOARD
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QKBDPC101_QWS_H
diff --git a/src/gui/embedded/qkbdsl5000_qws.cpp b/src/gui/embedded/qkbdsl5000_qws.cpp
new file mode 100644
index 0000000000..bc412b6ee8
--- /dev/null
+++ b/src/gui/embedded/qkbdsl5000_qws.cpp
@@ -0,0 +1,356 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkbdsl5000_qws.h"
+
+#ifndef QT_NO_QWS_KBD_SL5000
+
+#include "qwindowsystem_qws.h"
+#include "qwsutils_qws.h"
+#include "qscreen_qws.h"
+
+#include "qapplication.h"
+#include "qnamespace.h"
+#include "qtimer.h"
+
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <asm/sharp_char.h>
+
+#include <string.h>
+
+QT_BEGIN_NAMESPACE
+
+static const QWSKeyMap sl5000KeyMap[] = {
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 00
+ { Qt::Key_A, 'a' , 'A' , 'A'-64 }, // 01
+ { Qt::Key_B, 'b' , 'B' , 'B'-64 }, // 02
+ { Qt::Key_C, 'c' , 'C' , 'C'-64 }, // 03
+ { Qt::Key_D, 'd' , 'D' , 'D'-64 }, // 04
+ { Qt::Key_E, 'e' , 'E' , 'E'-64 }, // 05
+ { Qt::Key_F, 'f' , 'F' , 'F'-64 }, // 06
+ { Qt::Key_G, 'g' , 'G' , 'G'-64 }, // 07
+ { Qt::Key_H, 'h' , 'H' , 'H'-64 }, // 08
+ { Qt::Key_I, 'i' , 'I' , 'I'-64 }, // 09
+ { Qt::Key_J, 'j' , 'J' , 'J'-64 }, // 0a 10
+ { Qt::Key_K, 'k' , 'K' , 'K'-64 }, // 0b
+ { Qt::Key_L, 'l' , 'L' , 'L'-64 }, // 0c
+ { Qt::Key_M, 'm' , 'M' , 'M'-64 }, // 0d
+ { Qt::Key_N, 'n' , 'N' , 'N'-64 }, // 0e
+ { Qt::Key_O, 'o' , 'O' , 'O'-64 }, // 0f
+ { Qt::Key_P, 'p' , 'P' , 'P'-64 }, // 10
+ { Qt::Key_Q, 'q' , 'Q' , 'Q'-64 }, // 11
+ { Qt::Key_R, 'r' , 'R' , 'R'-64 }, // 12
+ { Qt::Key_S, 's' , 'S' , 'S'-64 }, // 13
+ { Qt::Key_T, 't' , 'T' , 'T'-64 }, // 14 20
+ { Qt::Key_U, 'u' , 'U' , 'U'-64 }, // 15
+ { Qt::Key_V, 'v' , 'V' , 'V'-64 }, // 16
+ { Qt::Key_W, 'w' , 'W' , 'W'-64 }, // 17
+ { Qt::Key_X, 'x' , 'X' , 'X'-64 }, // 18
+ { Qt::Key_Y, 'y' , 'Y' , 'Y'-64 }, // 19
+ { Qt::Key_Z, 'z' , 'Z' , 'Z'-64 }, // 1a
+ { Qt::Key_Shift, 0xffff , 0xffff , 0xffff }, // 1b
+ { Qt::Key_Return, 13 , 13 , 0xffff }, // 1c
+ { Qt::Key_F11, 0xffff , 0xffff , 0xffff }, // 1d todo
+ { Qt::Key_F22, 0xffff , 0xffff , 0xffff }, // 1e 30
+ { Qt::Key_Backspace, 8 , 8 , 0xffff }, // 1f
+ { Qt::Key_F31, 0xffff , 0xffff , 0xffff }, // 20
+ { Qt::Key_F35, 0xffff , 0xffff , 0xffff }, // 21 light
+ { Qt::Key_Escape, 0xffff , 0xffff , 0xffff }, // 22
+
+ // Direction key code are for *UNROTATED* display.
+ { Qt::Key_Up, 0xffff , 0xffff , 0xffff }, // 23
+ { Qt::Key_Right, 0xffff , 0xffff , 0xffff }, // 24
+ { Qt::Key_Left, 0xffff , 0xffff , 0xffff }, // 25
+ { Qt::Key_Down, 0xffff , 0xffff , 0xffff }, // 26
+
+ { Qt::Key_F33, 0xffff , 0xffff , 0xffff }, // 27 OK
+ { Qt::Key_F12, 0xffff , 0xffff , 0xffff }, // 28 40 home
+ { Qt::Key_1, '1' , 'q' , 'Q'-64 }, // 29
+ { Qt::Key_2, '2' , 'w' , 'W'-64 }, // 2a
+ { Qt::Key_3, '3' , 'e' , 'E'-64 }, // 2b
+ { Qt::Key_4, '4' , 'r' , 'R'-64 }, // 2c
+ { Qt::Key_5, '5' , 't' , 'T'-64 }, // 2d
+ { Qt::Key_6, '6' , 'y' , 'Y'-64 }, // 2e
+ { Qt::Key_7, '7' , 'u' , 'U'-64 }, // 2f
+ { Qt::Key_8, '8' , 'i' , 'I'-64 }, // 30
+ { Qt::Key_9, '9' , 'o' , 'O'-64 }, // 31
+ { Qt::Key_0, '0' , 'p' , 'P'-64 }, // 32 50
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 33
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 34
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 35
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 36
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 37
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 38
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 39
+ { Qt::Key_Minus, '-' , 'b' , 'B'-64 }, // 3a
+ { Qt::Key_Plus, '+' , 'n' , 'N'-64 }, // 3b
+ { Qt::Key_CapsLock, 0xffff , 0xffff , 0xffff }, // 3c 60
+ { Qt::Key_At, '@' , 's' , 'S'-64 }, // 3d
+ { Qt::Key_Question, '?' , '?' , 0xffff }, // 3e
+ { Qt::Key_Comma, ',' , ',' , 0xffff }, // 3f
+ { Qt::Key_Period, '.' , '.' , 0xffff }, // 40
+ { Qt::Key_Tab, 9 , '\\' , 0xffff }, // 41
+ { Qt::Key_X, 0xffff , 'x' , 'X'-64 }, // 42
+ { Qt::Key_C, 0xffff , 'c' , 'C'-64 }, // 43
+ { Qt::Key_V, 0xffff , 'v' , 'V'-64 }, // 44
+ { Qt::Key_Slash, '/' , '/' , 0xffff }, // 45
+ { Qt::Key_Apostrophe, '\'' , '\'' , 0xffff }, // 46 70
+ { Qt::Key_Semicolon, ';' , ';' , 0xffff }, // 47
+ { Qt::Key_QuoteDbl, '\"' , '\"' , 0xffff }, // 48
+ { Qt::Key_Colon, ':' , ':' , 0xffff }, // 49
+ { Qt::Key_NumberSign, '#' , 'd' , 'D'-64 }, // 4a
+ { Qt::Key_Dollar, '$' , 'f' , 'F'-64 }, // 4b
+ { Qt::Key_Percent, '%' , 'g' , 'G'-64 }, // 4c
+ { Qt::Key_Underscore, '_' , 'h' , 'H'-64 }, // 4d
+ { Qt::Key_Ampersand, '&' , 'j' , 'J'-64 }, // 4e
+ { Qt::Key_Asterisk, '*' , 'k' , 'K'-64 }, // 4f
+ { Qt::Key_ParenLeft, '(' , 'l' , 'L'-64 }, // 50 80
+ { Qt::Key_Delete, '[' , '[' , '[' }, // 51
+ { Qt::Key_Z, 0xffff , 'z' , 'Z'-64 }, // 52
+ { Qt::Key_Equal, '=' , 'm' , 'M'-64 }, // 53
+ { Qt::Key_ParenRight, ')' , ']' , ']' }, // 54
+ { Qt::Key_AsciiTilde, '~' , '^' , '^' }, // 55
+ { Qt::Key_Less, '<' , '{' , '{' }, // 56
+ { Qt::Key_Greater, '>' , '}' , '}' }, // 57
+ { Qt::Key_F9, 0xffff , 0xffff , 0xffff }, // 58 datebook
+ { Qt::Key_F10, 0xffff , 0xffff , 0xffff }, // 59 address
+ { Qt::Key_F13, 0xffff , 0xffff , 0xffff }, // 5a 90 email
+ { Qt::Key_F30, ' ' , ' ' , 0xffff }, // 5b select
+ { Qt::Key_Space, ' ' , '|' , '`' }, // 5c
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 5d
+ { Qt::Key_Exclam, '!' , 'a' , 'A'-64 }, // 5e
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 5f
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 60
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 61
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 62
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 63
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 64
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 65
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 66
+ { Qt::Key_Meta, 0xffff , 0xffff , 0xffff }, // 67
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 68
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 69
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 6a
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 6b
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 6c
+ { Qt::Key_F34, 0xffff , 0xffff , 0xffff }, // 6d power
+ { Qt::Key_F13, 0xffff , 0xffff , 0xffff }, // 6e mail long
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 6f
+ { Qt::Key_NumLock, 0xffff , 0xffff , 0xffff }, // 70
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 71
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 72
+ { 0x20ac, 0xffff , 0x20ac , 0x20ac }, // 73 Euro sign
+ { Qt::Key_unknown, 0xffff , 0xffff , 0xffff }, // 74
+ { Qt::Key_F32, 0xffff , 0xffff , 0xffff }, // 75 Sync
+ { 0, 0xffff , 0xffff , 0xffff }
+};
+
+static const int keyMSize = sizeof(sl5000KeyMap)/sizeof(QWSKeyMap)-1;
+
+QWSSL5000KeyboardHandler::QWSSL5000KeyboardHandler(const QString &device)
+ : QWSTtyKeyboardHandler(device)
+{
+ meta = false;
+ fn = false;
+ numLock = false;
+
+ sharp_kbdctl_modifstat st;
+ int dev = ::open(device.isEmpty()?"/dev/sharp_kbdctl":device.toLocal8Bit().constData(), O_RDWR);
+ if (dev >= 0) {
+ memset(&st, 0, sizeof(st));
+ st.which = 3;
+ int ret = ioctl(dev, SHARP_KBDCTL_GETMODIFSTAT, (char*)&st);
+ if(!ret)
+ numLock = (bool)st.stat;
+ ::close(dev);
+ }
+}
+
+QWSSL5000KeyboardHandler::~QWSSL5000KeyboardHandler()
+{
+}
+
+const QWSKeyMap *QWSSL5000KeyboardHandler::keyMap() const
+{
+ return sl5000KeyMap;
+}
+
+void QWSSL5000KeyboardHandler::doKey(uchar code)
+{
+ int keyCode = Qt::Key_unknown;
+ bool release = false;
+
+ if (code & 0x80) {
+ release = true;
+ code &= 0x7f;
+ }
+
+ if (fn && !meta && (code >= 0x42 && code <= 0x52)) {
+ ushort unicode=0;
+ int scan=0;
+ if (code == 0x42) { unicode='X'-'@'; scan=Qt::Key_X; } // Cut
+ else if (code == 0x43) { unicode='C'-'@'; scan=Qt::Key_C; } // Copy
+ else if (code == 0x44) { unicode='V'-'@'; scan=Qt::Key_V; } // Paste
+ else if (code == 0x52) { unicode='Z'-'@'; scan=Qt::Key_Z; } // Undo
+ if (scan) {
+ processKeyEvent(unicode, scan, Qt::ControlModifier, !release, false);
+ return;
+ }
+ }
+
+ if (code < keyMSize) {
+ keyCode = keyMap()[code].key_code;
+ }
+
+ bool repeatable = true;
+
+ if (release && (keyCode == Qt::Key_F34 || keyCode == Qt::Key_F35))
+ return; // no release for power and light keys
+ if (keyCode >= Qt::Key_F1 && keyCode <= Qt::Key_F35
+ || keyCode == Qt::Key_Escape || keyCode == Qt::Key_Home
+ || keyCode == Qt::Key_Shift || keyCode == Qt::Key_Meta)
+ repeatable = false;
+
+ if (qt_screen->isTransformed()
+ && keyCode >= Qt::Key_Left && keyCode <= Qt::Key_Down)
+ {
+ keyCode = transformDirKey(keyCode);
+ }
+
+ // Ctrl-Alt-Delete exits qws
+ if (ctrl && alt && keyCode == Qt::Key_Delete) {
+ qApp->quit();
+ }
+
+ if (keyCode == Qt::Key_F22) { /* Fn key */
+ fn = !release;
+ } else if (keyCode == Qt::Key_NumLock) {
+ if (release)
+ numLock = !numLock;
+ } else if (keyCode == Qt::AltModifier) {
+ alt = !release;
+ } else if (keyCode == Qt::ControlModifier) {
+ ctrl = !release;
+ } else if (keyCode == Qt::ShiftModifier) {
+ shift = !release;
+ } else if (keyCode == Qt::MetaModifier) {
+ meta = !release;
+ } else if (keyCode == Qt::Key_CapsLock && release) {
+ caps = !caps;
+ }
+ if (keyCode != Qt::Key_unknown) {
+ bool bAlt = alt;
+ bool bCtrl = ctrl;
+ bool bShift = shift;
+ int unicode = 0;
+ if (code < keyMSize) {
+ bool bCaps = caps ^ shift;
+ if (fn) {
+ if (shift) {
+ bCaps = bShift = false;
+ bCtrl = true;
+ }
+ if (meta) {
+ bCaps = bShift = true;
+ bAlt = true;
+ }
+ } else if (meta) {
+ bCaps = bShift = true;
+ }
+ if (code > 40 && caps) {
+ // fn-keys should only react to shift, not caps
+ bCaps = bShift = shift;
+ }
+ if (numLock) {
+ if (keyCode != Qt::Key_Space && keyCode != Qt::Key_Tab)
+ bCaps = bShift = false;
+ }
+ if (keyCode == Qt::Key_Delete && (bAlt || bCtrl)) {
+ keyCode = Qt::Key_BraceLeft;
+ unicode = '[';
+ bCaps = bShift = bAlt = bCtrl = false;
+ } else if (keyCode == Qt::Key_F31 && bCtrl) {
+ keyCode = Qt::Key_QuoteLeft;
+ unicode = '`';
+ } else if (bCtrl)
+ unicode = keyMap()[code].ctrl_unicode ? keyMap()[code].ctrl_unicode : 0xffff;
+ else if (bCaps)
+ unicode = keyMap()[code].shift_unicode ? keyMap()[code].shift_unicode : 0xffff;
+ else
+ unicode = keyMap()[code].unicode ? keyMap()[code].unicode : 0xffff;
+ }
+
+ modifiers = 0;
+ if (bAlt) modifiers |= Qt::AltModifier;
+ if (bCtrl) modifiers |= Qt::ControlModifier;
+ if (bShift) modifiers |= Qt::ShiftModifier;
+
+ // looks wrong -- WWA
+ bool repeat = false;
+ if (prevuni == unicode && prevkey == keyCode && !release)
+ repeat = true;
+
+ processKeyEvent(unicode, keyCode, modifiers, !release, repeat);
+
+ if (!release) {
+ prevuni = unicode;
+ prevkey = keyCode;
+ } else {
+ prevkey = prevuni = 0;
+ }
+ }
+
+ if (repeatable && !release)
+ beginAutoRepeat(prevuni, prevkey, modifiers);
+ else
+ endAutoRepeat();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QWS_KBD_SL5000
diff --git a/src/gui/embedded/qkbdsl5000_qws.h b/src/gui/embedded/qkbdsl5000_qws.h
new file mode 100644
index 0000000000..514d6028c7
--- /dev/null
+++ b/src/gui/embedded/qkbdsl5000_qws.h
@@ -0,0 +1,79 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKBDSL5000_QWS_H
+#define QKBDSL5000_QWS_H
+
+#include <QtGui/qkbdtty_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_KBD_SL5000
+
+class QWSSL5000KbPrivate;
+
+class QWSSL5000KeyboardHandler : public QWSTtyKeyboardHandler
+{
+public:
+ explicit QWSSL5000KeyboardHandler(const QString&);
+ virtual ~QWSSL5000KeyboardHandler();
+
+ virtual void doKey(uchar scancode);
+ virtual const QWSKeyMap *keyMap() const;
+
+private:
+ bool meta;
+ bool fn;
+ bool numLock;
+ QWSSL5000KbPrivate *d;
+};
+
+#endif // QT_NO_QWS_KBD_SL5000
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QKBDSL5000_QWS_H
diff --git a/src/gui/embedded/qkbdtty_qws.cpp b/src/gui/embedded/qkbdtty_qws.cpp
new file mode 100644
index 0000000000..b588e55d7b
--- /dev/null
+++ b/src/gui/embedded/qkbdtty_qws.cpp
@@ -0,0 +1,263 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkbdtty_qws.h"
+
+#if !defined(QT_NO_QWS_KEYBOARD) && !defined(QT_NO_QWS_KBD_TTY)
+
+#include "qscreen_qws.h"
+
+#include "qwindowsystem_qws.h"
+#include "qapplication.h"
+#include "qsocketnotifier.h"
+#include "qnamespace.h"
+#include "qtimer.h"
+#include <private/qwssignalhandler_p.h>
+#include <private/qwindowsurface_qws_p.h>
+
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+#include <termios.h>
+
+#include <qeventloop.h>
+
+#ifdef Q_OS_LINUX
+#include <sys/kd.h>
+#include <sys/vt.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#define VTACQSIG SIGUSR1
+#define VTRELSIG SIGUSR2
+
+static int vtQws = 0;
+static int kbdFD = -1;
+
+//===========================================================================
+
+//
+// Tty keyboard
+//
+
+class QWSTtyKbPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QWSTtyKbPrivate(QWSPC101KeyboardHandler *, const QString &device);
+ ~QWSTtyKbPrivate();
+
+private slots:
+ void readKeyboardData();
+ void handleTtySwitch(int);
+
+private:
+ QWSPC101KeyboardHandler *handler;
+ struct termios origTermData;
+};
+
+QWSTtyKeyboardHandler::QWSTtyKeyboardHandler(const QString &device)
+ : QWSPC101KeyboardHandler(device)
+{
+ d = new QWSTtyKbPrivate(this, device);
+}
+
+QWSTtyKeyboardHandler::~QWSTtyKeyboardHandler()
+{
+ delete d;
+}
+
+void QWSTtyKeyboardHandler::processKeyEvent(int unicode, int keycode,
+ Qt::KeyboardModifiers modifiers, bool isPress,
+ bool autoRepeat)
+{
+#if defined(Q_OS_LINUX)
+ // Virtual console switching
+ int term = 0;
+ bool ctrl = modifiers & Qt::ControlModifier;
+ bool alt = modifiers & Qt::AltModifier;
+ if (ctrl && alt && keycode >= Qt::Key_F1 && keycode <= Qt::Key_F10)
+ term = keycode - Qt::Key_F1 + 1;
+ else if (ctrl && alt && keycode == Qt::Key_Left)
+ term = qMax(vtQws - 1, 1);
+ else if (ctrl && alt && keycode == Qt::Key_Right)
+ term = qMin(vtQws + 1, 10);
+ if (term && isPress) {
+ ioctl(kbdFD, VT_ACTIVATE, term);
+ return;
+ }
+#endif
+
+ QWSPC101KeyboardHandler::processKeyEvent(unicode, keycode, modifiers,
+ isPress, autoRepeat);
+}
+
+
+QWSTtyKbPrivate::QWSTtyKbPrivate(QWSPC101KeyboardHandler *h, const QString &device) : handler(h)
+{
+ kbdFD = ::open(device.isEmpty()?"/dev/tty0":device.toLatin1().constData(), O_RDWR|O_NDELAY, 0);
+#ifndef QT_NO_QWS_SIGNALHANDLER
+ QWSSignalHandler::instance()->addObject(this);
+#endif
+
+ if (kbdFD >= 0) {
+ QSocketNotifier *notifier;
+ notifier = new QSocketNotifier(kbdFD, QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)),this,
+ SLOT(readKeyboardData()));
+
+ // save for restore.
+ tcgetattr(kbdFD, &origTermData);
+
+ struct termios termdata;
+ tcgetattr(kbdFD, &termdata);
+
+#if defined(Q_OS_LINUX)
+# ifdef QT_QWS_USE_KEYCODES
+ ioctl(kbdFD, KDSKBMODE, K_MEDIUMRAW);
+# else
+ ioctl(kbdFD, KDSKBMODE, K_RAW);
+# endif
+#endif
+
+ 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(kbdFD, TCSANOW, &termdata);
+
+#if defined(Q_OS_LINUX)
+
+ connect(QApplication::instance(), SIGNAL(unixSignal(int)), this, SLOT(handleTtySwitch(int)));
+ QApplication::instance()->watchUnixSignal(VTACQSIG, true);
+ QApplication::instance()->watchUnixSignal(VTRELSIG, true);
+
+ struct vt_mode vtMode;
+ ioctl(kbdFD, VT_GETMODE, &vtMode);
+
+ // let us control VT switching
+ vtMode.mode = VT_PROCESS;
+ vtMode.relsig = VTRELSIG;
+ vtMode.acqsig = VTACQSIG;
+ ioctl(kbdFD, VT_SETMODE, &vtMode);
+
+ struct vt_stat vtStat;
+ ioctl(kbdFD, VT_GETSTATE, &vtStat);
+ vtQws = vtStat.v_active;
+#endif
+ } else {
+ qCritical("Cannot open keyboard: %s", strerror(errno));
+ }
+
+}
+
+QWSTtyKbPrivate::~QWSTtyKbPrivate()
+{
+ if (kbdFD >= 0) {
+#if defined(Q_OS_LINUX)
+ ioctl(kbdFD, KDSKBMODE, K_XLATE);
+#endif
+ tcsetattr(kbdFD, TCSANOW, &origTermData);
+ ::close(kbdFD);
+ kbdFD = -1;
+ }
+}
+
+void QWSTtyKbPrivate::handleTtySwitch(int sig)
+{
+#if defined(Q_OS_LINUX)
+ if (sig == VTACQSIG) {
+ if (ioctl(kbdFD, VT_RELDISP, VT_ACKACQ) == 0) {
+ qwsServer->enablePainting(true);
+ qt_screen->restore();
+ qwsServer->resumeMouse();
+ qwsServer->refresh();
+ }
+ } else if (sig == VTRELSIG) {
+ qwsServer->enablePainting(false);
+
+ // Check for reserved surfaces which might still do painting
+ bool allWindowsHidden = true;
+ const QList<QWSWindow*> windows = QWSServer::instance()->clientWindows();
+ for (int i = 0; i < windows.size(); ++i) {
+ const QWSWindow *w = windows.at(i);
+ QWSWindowSurface *s = w->windowSurface();
+ if (s && s->isRegionReserved() && !w->allocatedRegion().isEmpty()) {
+ allWindowsHidden = false;
+ break;
+ }
+ }
+
+ if (!allWindowsHidden) {
+ ioctl(kbdFD, VT_RELDISP, 0); // abort console switch
+ qwsServer->enablePainting(true);
+ } else if (ioctl(kbdFD, VT_RELDISP, 1) == 0) {
+ qt_screen->save();
+ qwsServer->suspendMouse();
+ } else {
+ qwsServer->enablePainting(true);
+ }
+ }
+#endif
+}
+
+void QWSTtyKbPrivate::readKeyboardData()
+{
+ unsigned char buf[81];
+ int n = read(kbdFD, buf, 80);
+ for (int loop = 0; loop < n; loop++)
+ handler->doKey(buf[loop]);
+}
+
+QT_END_NAMESPACE
+
+#include "qkbdtty_qws.moc"
+
+#endif // QT_NO_QWS_KEYBOARD || QT_NO_QWS_KBD_TTY
diff --git a/src/gui/embedded/qkbdtty_qws.h b/src/gui/embedded/qkbdtty_qws.h
new file mode 100644
index 0000000000..4f93d6cbbb
--- /dev/null
+++ b/src/gui/embedded/qkbdtty_qws.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKBDTTY_QWS_H
+#define QKBDTTY_QWS_H
+
+#include <QtGui/qkbdpc101_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_KEYBOARD
+
+#ifndef QT_NO_QWS_KBD_TTY
+
+class QWSTtyKbPrivate;
+
+class QWSTtyKeyboardHandler : public QWSPC101KeyboardHandler
+{
+public:
+ explicit QWSTtyKeyboardHandler(const QString&);
+ virtual ~QWSTtyKeyboardHandler();
+
+protected:
+ virtual void processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
+ bool isPress, bool autoRepeat);
+
+private:
+ QWSTtyKbPrivate *d;
+};
+
+#endif // QT_NO_QWS_KBD_TTY
+
+#endif // QT_NO_QWS_KEYBOARD
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QKBDTTY_QWS_H
diff --git a/src/gui/embedded/qkbdum_qws.cpp b/src/gui/embedded/qkbdum_qws.cpp
new file mode 100644
index 0000000000..d525c667c9
--- /dev/null
+++ b/src/gui/embedded/qkbdum_qws.cpp
@@ -0,0 +1,143 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkbdum_qws.h"
+#include "qvfbhdr.h"
+
+#if !defined(QT_NO_QWS_KEYBOARD) && !defined(QT_NO_QWS_KBD_UM)
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <qstring.h>
+#include <qwindowsystem_qws.h>
+#include <qsocketnotifier.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWSUmKeyboardHandlerPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ QWSUmKeyboardHandlerPrivate(const QString&);
+ ~QWSUmKeyboardHandlerPrivate();
+
+private slots:
+ void readKeyboardData();
+
+private:
+ int kbdFD;
+ int kbdIdx;
+ const int kbdBufferLen;
+ unsigned char *kbdBuffer;
+ QSocketNotifier *notifier;
+};
+
+QWSUmKeyboardHandlerPrivate::QWSUmKeyboardHandlerPrivate(const QString &device)
+ : kbdFD(-1), kbdIdx(0), kbdBufferLen(sizeof(QVFbKeyData)*5)
+{
+ kbdBuffer = new unsigned char [kbdBufferLen];
+
+ if ((kbdFD = open((const char *)device.toLocal8Bit(), O_RDONLY | O_NDELAY)) < 0) {
+ qDebug("Cannot open %s (%s)", (const char *)device.toLocal8Bit(),
+ strerror(errno));
+ } else {
+ // Clear pending input
+ char buf[2];
+ while (read(kbdFD, buf, 1) > 0) { }
+
+ notifier = new QSocketNotifier(kbdFD, QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)),this, SLOT(readKeyboardData()));
+ }
+}
+
+QWSUmKeyboardHandlerPrivate::~QWSUmKeyboardHandlerPrivate()
+{
+ if (kbdFD >= 0)
+ close(kbdFD);
+ delete [] kbdBuffer;
+}
+
+
+void QWSUmKeyboardHandlerPrivate::readKeyboardData()
+{
+ int n;
+ do {
+ n = 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);
+ // Qtopia Key filters must still work.
+ QWSServer::processKeyEvent(kd->unicode, kd->keycode, kd->modifiers, kd->press, kd->repeat);
+ idx += sizeof(QVFbKeyData);
+ }
+
+ int surplus = kbdIdx - idx;
+ for (int i = 0; i < surplus; i++)
+ kbdBuffer[i] = kbdBuffer[idx+i];
+ kbdIdx = surplus;
+}
+
+QWSUmKeyboardHandler::QWSUmKeyboardHandler(const QString &device)
+ : QWSKeyboardHandler()
+{
+ d = new QWSUmKeyboardHandlerPrivate(device);
+}
+
+QWSUmKeyboardHandler::~QWSUmKeyboardHandler()
+{
+ delete d;
+}
+
+QT_END_NAMESPACE
+
+#include "qkbdum_qws.moc"
+
+#endif // QT_NO_QWS_KEYBOARD && QT_NO_QWS_KBD_UM
diff --git a/src/gui/embedded/qkbdum_qws.h b/src/gui/embedded/qkbdum_qws.h
new file mode 100644
index 0000000000..96aaef6349
--- /dev/null
+++ b/src/gui/embedded/qkbdum_qws.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKBDUM_QWS_H
+#define QKBDUM_QWS_H
+
+#include <QtGui/qkbd_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_KEYBOARD
+
+#ifndef QT_NO_QWS_KBD_UM
+
+class QWSUmKeyboardHandlerPrivate;
+
+class QWSUmKeyboardHandler : public QWSKeyboardHandler
+{
+public:
+ QWSUmKeyboardHandler(const QString &);
+ virtual ~QWSUmKeyboardHandler();
+
+private:
+
+ QWSUmKeyboardHandlerPrivate *d;
+};
+#endif // QT_NO_QWS_KBD_UM
+
+#endif // QT_NO_QWS_KEYBOARD
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QKBDUM_QWS_H
diff --git a/src/gui/embedded/qkbdusb_qws.cpp b/src/gui/embedded/qkbdusb_qws.cpp
new file mode 100644
index 0000000000..e35ac55ff5
--- /dev/null
+++ b/src/gui/embedded/qkbdusb_qws.cpp
@@ -0,0 +1,401 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkbdusb_qws.h"
+
+#ifndef QT_NO_QWS_KEYBOARD
+
+#include "qscreen_qws.h"
+
+#include "qwindowsystem_qws.h"
+#include "qapplication.h"
+#include "qsocketnotifier.h"
+#include "qnamespace.h"
+#include "qtimer.h"
+
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <signal.h>
+
+#include <linux/input.h>
+
+#ifdef Q_OS_LINUX
+#include <sys/kd.h>
+#include <sys/vt.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+/* USB driver */
+
+
+class QWSUsbKbPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QWSUsbKbPrivate(QWSPC101KeyboardHandler *, const QString &);
+ ~QWSUsbKbPrivate();
+
+private slots:
+ void readKeyboardData();
+
+private:
+ QWSPC101KeyboardHandler *handler;
+ int fd;
+#ifdef QT_QWS_ZYLONITE
+ bool shift;
+#endif
+};
+
+QWSUsbKeyboardHandler::QWSUsbKeyboardHandler(const QString &device)
+ : QWSPC101KeyboardHandler(device)
+{
+ d = new QWSUsbKbPrivate(this, device);
+}
+
+QWSUsbKeyboardHandler::~QWSUsbKeyboardHandler()
+{
+ delete d;
+}
+
+QWSUsbKbPrivate::QWSUsbKbPrivate(QWSPC101KeyboardHandler *h, const QString &device) : handler(h)
+{
+#ifdef QT_QWS_ZYLONITE
+ shift = FALSE;
+#endif
+ fd = ::open(device.isEmpty()?"/dev/input/event1":device.toLocal8Bit(),O_RDONLY, 0);
+ if (fd >= 0) {
+ QSocketNotifier *notifier;
+ notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)),this,
+ SLOT(readKeyboardData()));
+ }
+}
+
+QWSUsbKbPrivate::~QWSUsbKbPrivate()
+{
+ ::close(fd);
+}
+
+void QWSUsbKbPrivate::readKeyboardData()
+{
+ input_event event;
+ if (read(fd, &event, sizeof(input_event)) != sizeof(input_event))
+ return;
+
+ if (event.type != EV_KEY)
+ return;
+
+#ifdef QT_QWS_ZYLONITE
+ qDebug("keypressed: code=%03d (%s)\n",event.code,((event.value)!=0) ? "Down":"Up");
+ int modifiers=0;
+ int unicode=0xffff;
+ int key_code=0;
+
+ switch(event.code)
+ {
+ case 0xA2:
+ key_code = ((!shift) ? Qt::Key_0 : Qt::Key_Plus );
+ unicode = ((!shift) ? 0x30 : 0x2B );
+ break;
+ case 0x70:
+ key_code = ((!shift) ? Qt::Key_1 : Qt::Key_At );
+ unicode = ((!shift) ? 0x31 : 0x40 );
+ break;
+ case 0x72:
+ key_code = ((!shift) ? Qt::Key_2 : Qt::Key_Ampersand );
+ unicode = ((!shift) ? 0x32 : 0x26 );
+ break;
+ case 0x74:
+ key_code = ((!shift) ? Qt::Key_3 : Qt::Key_At );
+ unicode = ((!shift) ? 0x33 : 0x3F );
+ break;
+ case 0x80:
+ key_code = ((!shift) ? Qt::Key_4 : Qt::Key_Minus );
+ unicode = ((!shift) ? 0x34 : 0x2D );
+ break;
+ case 0x82:
+ key_code = ((!shift) ? Qt::Key_5 : Qt::Key_Apostrophe);
+ unicode = ((!shift) ? 0x35 : 0x27 );
+ break;
+ case 0x84:
+ key_code = ((!shift) ? Qt::Key_6 : Qt::Key_Slash );
+ unicode = ((!shift) ? 0x36 : 0x5C );
+ break;
+ case 0x90:
+ key_code = ((!shift) ? Qt::Key_7 : Qt::Key_Colon );
+ unicode = ((!shift) ? 0x37 : 0x3A );
+ break;
+ case 0x92:
+ key_code = ((!shift) ? Qt::Key_8 : Qt::Key_Semicolon );
+ unicode = ((!shift) ? 0x38 : 0x3B );
+ break;
+ case 0x94:
+ key_code = ((!shift) ? Qt::Key_9 : Qt::Key_QuoteDbl );
+ unicode = ((!shift) ? 0x39 : 0x22 );
+ break;
+ case 0x0:
+ key_code = Qt::Key_A;
+ unicode = ((!shift) ? 0x61 : 0x41 );
+ break;
+ case 0x10:
+ key_code = Qt::Key_B;
+ unicode = ((!shift) ? 0x62 : 0x42 );
+ break;
+ case 0x20:
+ key_code = Qt::Key_C;
+ unicode = ((!shift) ? 0x63 : 0x43 );
+ break;
+ case 0x30:
+ key_code = Qt::Key_D;
+ unicode = ((!shift) ? 0x64 : 0x44 );
+ break;
+ case 0x40:
+ key_code = Qt::Key_E;
+ unicode = ((!shift) ? 0x65 : 0x45 );
+ break;
+ case 0x50:
+ key_code = Qt::Key_F;
+ unicode = ((!shift) ? 0x66 : 0x46 );
+ break;
+ case 0x01:
+ key_code = Qt::Key_G;
+ unicode = ((!shift) ? 0x67 : 0x47 );
+ break;
+ case 0x11:
+ key_code = Qt::Key_H;
+ unicode = ((!shift) ? 0x68 : 0x48 );
+ break;
+ case 0x21:
+ key_code = Qt::Key_I;
+ unicode = ((!shift) ? 0x69 : 0x49 );
+ break;
+ case 0x31:
+ key_code = Qt::Key_J;
+ unicode = ((!shift) ? 0x6A : 0x4A );
+ break;
+ case 0x41:
+ key_code = Qt::Key_K;
+ unicode = ((!shift) ? 0x6B : 0x4B );
+ break;
+ case 0x51:
+ key_code = Qt::Key_L;
+ unicode = ((!shift) ? 0x6C : 0x4C );
+ break;
+ case 0x02:
+ key_code = Qt::Key_M;
+ unicode = ((!shift) ? 0x6D : 0x4D );
+ break;
+ case 0x12:
+ key_code = Qt::Key_N;
+ unicode = ((!shift) ? 0x6E : 0x4E );
+ break;
+ case 0x22:
+ key_code = Qt::Key_O;
+ unicode = ((!shift) ? 0x6F : 0x4F );
+ break;
+ case 0x32:
+ key_code = Qt::Key_P;
+ unicode = ((!shift) ? 0x70 : 0x50 );
+ break;
+ case 0x42:
+ key_code = Qt::Key_Q;
+ unicode = ((!shift) ? 0x71 : 0x51 );
+ break;
+ case 0x52:
+ key_code = Qt::Key_R;
+ unicode = ((!shift) ? 0x72 : 0x52 );
+ break;
+ case 0x03:
+ key_code = Qt::Key_S;
+ unicode = ((!shift) ? 0x73 : 0x53 );
+ break;
+ case 0x13:
+ key_code = Qt::Key_T;
+ unicode = ((!shift) ? 0x74 : 0x54 );
+ break;
+ case 0x23:
+ key_code = Qt::Key_U;
+ unicode = ((!shift) ? 0x75 : 0x55 );
+ break;
+ case 0x33:
+ key_code = Qt::Key_V;
+ unicode = ((!shift) ? 0x76 : 0x56 );
+ break;
+ case 0x43:
+ key_code = Qt::Key_W;
+ unicode = ((!shift) ? 0x77 : 0x57 );
+ break;
+ case 0x53:
+ key_code = Qt::Key_X;
+ unicode = ((!shift) ? 0x78 : 0x58 );
+ break;
+ case 0x24:
+ key_code = Qt::Key_Y;
+ unicode = ((!shift) ? 0x79 : 0x59 );
+ break;
+ case 0x34:
+ key_code = Qt::Key_Z;
+ unicode = ((!shift) ? 0x7A : 0x5A );
+ break;
+ case 0xA4:
+ key_code = ((!shift) ? Qt::Key_NumberSign : Qt::Key_Period);
+ unicode = ((!shift) ? 0x23 : 0x2E );
+ break;
+ case 0xA0:
+ key_code = ((!shift) ? Qt::Key_Asterisk : Qt::Key_NumberSign );
+ unicode = ((!shift) ? 0x2A : 0x2C );
+ break;
+ case 0x25:
+ key_code = Qt::Key_Space;
+ unicode = 0x20;
+ break;
+ case 0x06:
+ key_code = Qt::Key_Up;
+ unicode = 0xffff; modifiers |= Qt::KeypadModifier;
+ break;
+ case 0x16:
+ key_code = Qt::Key_Down;
+ unicode = 0xffff; modifiers |= Qt::KeypadModifier;
+ break;
+ case 0x26:
+ key_code = Qt::Key_Left;
+ unicode = 0xffff; modifiers |= Qt::KeypadModifier;
+ break;
+ case 0x36:
+ key_code = Qt::Key_Right;
+ unicode = 0xffff; modifiers |= Qt::KeypadModifier;
+ break;
+ case 0x46:
+ key_code = Qt::Key_Select;
+ unicode = 0xffff; modifiers |= Qt::KeypadModifier;
+ break;
+ case 0x61:
+ key_code = Qt::Key_No;
+ unicode = 0xffff; modifiers |= Qt::KeypadModifier;
+ break;
+ case 0x60:
+ key_code = Qt::Key_Call;
+ unicode = 0xffff; modifiers |= Qt::KeypadModifier;
+ break;
+ case 0x55:
+ key_code = Qt::Key_Hangup;
+ unicode = 0xffff; modifiers |= Qt::KeypadModifier;
+ break;
+ case 0x62:
+ key_code = Qt::Key_Context1;
+ unicode = 0xffff; modifiers |= Qt::KeypadModifier;
+ break;
+ case 0x63:
+ key_code = Qt::Key_No;
+ unicode = 0xffff; modifiers |= Qt::KeypadModifier;
+ break;
+ case 0x05:
+ key_code = Qt::Key_Home;
+ unicode = 0xffff; modifiers |= Qt::KeypadModifier;
+ break;
+ case 0x15:
+ key_code = Qt::Key_Shift;
+ unicode = 0xffff; modifiers |= Qt::ShiftModifier;
+ if(event.value==0) break;
+ if(shift) {
+ shift = FALSE;
+ qWarning("Caps Off!");
+ } else {
+ shift = TRUE;
+ qWarning("Caps On!");
+ }
+ break;
+ case 0x1C:
+ key_code = ((!shift) ? Qt::Key_Back : Qt::Key_Enter );
+ unicode = 0xffff; modifiers |= Qt::KeypadModifier;
+ break;
+ case 0x19:
+ key_code = Qt::Key_Context2;
+ unicode = 0xffff; modifiers |= Qt::KeypadModifier;
+ break;
+ case 0x1A:
+ key_code = Qt::Key_Context3;
+ unicode = 0xffff; modifiers |= Qt::KeypadModifier;
+ break;
+ case 0x1B:
+ key_code = Qt::Key_Context4;
+ unicode = 0xffff; modifiers |= Qt::KeypadModifier;
+ break;
+ }
+ if(shift) modifiers |= Qt::ShiftModifier;
+ handler->processKeyEvent(unicode, key_code, (Qt::KeyboardModifiers)modifiers, event.value!=0, false);
+#else
+
+ int key=event.code;
+#ifndef QT_QWS_USE_KEYCODES
+ // Handle SOME keys, otherwise it's useless.
+
+ if(key==103) {
+ handler->processKeyEvent(0, Qt::Key_Up, 0, event.value!=0, false);
+ } else if(key==106) {
+ handler->processKeyEvent(0, Qt::Key_Right, 0, event.value!=0, false );
+ } else if(key==108) {
+ handler->processKeyEvent(0, Qt::Key_Down, 0, event.value!=0, false);
+ } else if(key==105) {
+ handler->processKeyEvent(0, Qt::Key_Left, 0, event.value!=0, false);
+ } else
+
+#endif
+
+ {
+ if(event.value == 0) {
+ key=key | 0x80;
+ }
+ handler->doKey(key);
+ }
+#endif
+}
+
+QT_END_NAMESPACE
+
+#include "qkbdusb_qws.moc"
+
+#endif // QT_NO_QWS_KEYBOARD
diff --git a/src/gui/embedded/qkbdusb_qws.h b/src/gui/embedded/qkbdusb_qws.h
new file mode 100644
index 0000000000..81d0103b47
--- /dev/null
+++ b/src/gui/embedded/qkbdusb_qws.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKBDUSB_QWS_H
+#define QKBDUSB_QWS_H
+
+#include <QtGui/qkbdpc101_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_KEYBOARD
+
+#ifndef QT_NO_QWS_KBD_USB
+
+class QWSUsbKbPrivate;
+
+class QWSUsbKeyboardHandler : public QWSPC101KeyboardHandler
+{
+public:
+ QWSUsbKeyboardHandler(const QString&);
+ virtual ~QWSUsbKeyboardHandler();
+
+private:
+ QWSUsbKbPrivate *d;
+};
+
+#endif // QT_NO_QWS_KBD_USB
+
+#endif // QT_NO_QWS_KEYBOARD
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QKBDUSB_QWS_H
diff --git a/src/gui/embedded/qkbdvfb_qws.cpp b/src/gui/embedded/qkbdvfb_qws.cpp
new file mode 100644
index 0000000000..1d53ce9150
--- /dev/null
+++ b/src/gui/embedded/qkbdvfb_qws.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <qvfbhdr.h>
+#include <qkbdvfb_qws.h>
+
+#ifndef QT_NO_QWS_KEYBOARD
+#ifndef QT_NO_QWS_KBD_QVFB
+
+#include <qwindowsystem_qws.h>
+#include <qsocketnotifier.h>
+#include <qapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+QVFbKeyboardHandler::QVFbKeyboardHandler(const QString &device)
+ : QObject()
+{
+ terminalName = device;
+ if (terminalName.isEmpty())
+ terminalName = QLatin1String("/dev/vkdb");
+ kbdFD = -1;
+ kbdIdx = 0;
+ kbdBufferLen = sizeof(QVFbKeyData) * 5;
+ kbdBuffer = new unsigned char [kbdBufferLen];
+
+ if ((kbdFD = open(terminalName.toLatin1().constData(), O_RDONLY | O_NDELAY)) < 0) {
+ qWarning("Cannot open %s (%s)", terminalName.toLatin1().constData(),
+ strerror(errno));
+ } else {
+ // Clear pending input
+ char buf[2];
+ while (read(kbdFD, buf, 1) > 0) { }
+
+ notifier = new QSocketNotifier(kbdFD, QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)),this, SLOT(readKeyboardData()));
+ }
+}
+
+QVFbKeyboardHandler::~QVFbKeyboardHandler()
+{
+ if (kbdFD >= 0)
+ close(kbdFD);
+ delete [] kbdBuffer;
+}
+
+
+void QVFbKeyboardHandler::readKeyboardData()
+{
+ int n;
+ do {
+ n = 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);
+ idx += sizeof(QVFbKeyData);
+ }
+
+ int surplus = kbdIdx - idx;
+ for (int i = 0; i < surplus; i++)
+ kbdBuffer[i] = kbdBuffer[idx+i];
+ kbdIdx = surplus;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QWS_KBD_QVFB
+#endif // QT_NO_QWS_KEYBOARD
diff --git a/src/gui/embedded/qkbdvfb_qws.h b/src/gui/embedded/qkbdvfb_qws.h
new file mode 100644
index 0000000000..47fa5d37cb
--- /dev/null
+++ b/src/gui/embedded/qkbdvfb_qws.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKBDVFB_QWS_H
+#define QKBDVFB_QWS_H
+
+#include <QtGui/qkbd_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_KEYBOARD
+
+#ifndef QT_NO_QWS_KBD_QVFB
+
+class QSocketNotifier;
+
+class QVFbKeyboardHandler : public QObject, public QWSKeyboardHandler
+{
+ Q_OBJECT
+public:
+ QVFbKeyboardHandler(const QString &device);
+ virtual ~QVFbKeyboardHandler();
+
+private Q_SLOTS:
+ void readKeyboardData();
+
+private:
+ QString terminalName;
+ int kbdFD;
+ int kbdIdx;
+ int kbdBufferLen;
+ unsigned char *kbdBuffer;
+ QSocketNotifier *notifier;
+};
+
+#endif // QT_NO_QWS_KBD_QVFB
+
+#endif // QT_NO_QWS_KEYBOARD
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QKBDVFB_QWS_H
diff --git a/src/gui/embedded/qkbdvr41xx_qws.cpp b/src/gui/embedded/qkbdvr41xx_qws.cpp
new file mode 100644
index 0000000000..4613891416
--- /dev/null
+++ b/src/gui/embedded/qkbdvr41xx_qws.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qkbdvr41xx_qws.h"
+
+#if !defined(QT_NO_QWS_KEYBOARD) && !defined(QT_NO_QWS_KBD_VR41XX)
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <qsocketnotifier.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWSVr41xxKbPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QWSVr41xxKbPrivate(QWSVr41xxKeyboardHandler *h, const QString&);
+ virtual ~QWSVr41xxKbPrivate();
+
+ bool isOpen() { return buttonFD > 0; }
+
+private slots:
+ void readKeyboardData();
+
+private:
+ QString terminalName;
+ int buttonFD;
+ int kbdIdx;
+ int kbdBufferLen;
+ unsigned char *kbdBuffer;
+ QSocketNotifier *notifier;
+ QWSVr41xxKeyboardHandler *handler;
+};
+
+QWSVr41xxKeyboardHandler::QWSVr41xxKeyboardHandler(const QString &device)
+{
+ d = new QWSVr41xxKbPrivate(this, device);
+}
+
+QWSVr41xxKeyboardHandler::~QWSVr41xxKeyboardHandler()
+{
+ delete d;
+}
+
+QWSVr41xxKbPrivate::QWSVr41xxKbPrivate(QWSVr41xxKeyboardHandler *h, const QString &device) : handler(h)
+{
+ terminalName = device;
+ if (terminalName.isEmpty())
+ terminalName = QLatin1String("/dev/buttons");
+ buttonFD = -1;
+ notifier = 0;
+
+ buttonFD = open(terminalName.toLatin1().constData(), O_RDWR | O_NDELAY, 0);;
+ if (buttonFD < 0) {
+ qWarning("Cannot open %s\n", qPrintable(terminalName));
+ return;
+ }
+
+ if (buttonFD >= 0) {
+ notifier = new QSocketNotifier(buttonFD, QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)),this,
+ SLOT(readKeyboardData()));
+ }
+
+ kbdBufferLen = 80;
+ kbdBuffer = new unsigned char [kbdBufferLen];
+ kbdIdx = 0;
+}
+
+QWSVr41xxKbPrivate::~QWSVr41xxKbPrivate()
+{
+ if (buttonFD > 0) {
+ ::close(buttonFD);
+ buttonFD = -1;
+ }
+ delete notifier;
+ notifier = 0;
+ delete [] kbdBuffer;
+}
+
+void QWSVr41xxKbPrivate::readKeyboardData()
+{
+ int n = 0;
+ do {
+ n = read(buttonFD, kbdBuffer+kbdIdx, kbdBufferLen - kbdIdx);
+ if (n > 0)
+ kbdIdx += n;
+ } while (n > 0);
+
+ int idx = 0;
+ while (kbdIdx - idx >= 2) {
+ unsigned char *next = kbdBuffer + idx;
+ unsigned short *code = (unsigned short *)next;
+ int keycode = Qt::Key_unknown;
+ switch ((*code) & 0x0fff) {
+ case 0x7:
+ keycode = Qt::Key_Up;
+ break;
+ case 0x9:
+ keycode = Qt::Key_Right;
+ break;
+ case 0x8:
+ keycode = Qt::Key_Down;
+ break;
+ case 0xa:
+ keycode = Qt::Key_Left;
+ break;
+ case 0x3:
+ keycode = Qt::Key_Up;
+ break;
+ case 0x4:
+ keycode = Qt::Key_Down;
+ break;
+ case 0x1:
+ keycode = Qt::Key_Return;
+ break;
+ case 0x2:
+ keycode = Qt::Key_F4;
+ break;
+ default:
+ qDebug("Unrecognised key sequence %d", *code);
+ }
+ if ((*code) & 0x8000)
+ handler->processKeyEvent(0, keycode, 0, false, false);
+ else
+ handler->processKeyEvent(0, keycode, 0, true, false);
+ idx += 2;
+ }
+
+ int surplus = kbdIdx - idx;
+ for (int i = 0; i < surplus; i++)
+ kbdBuffer[i] = kbdBuffer[idx+i];
+ kbdIdx = surplus;
+}
+
+QT_END_NAMESPACE
+
+#include "qkbdvr41xx_qws.moc"
+
+#endif // QT_NO_QWS_KBD_VR41XX
diff --git a/src/gui/embedded/qkbdvr41xx_qws.h b/src/gui/embedded/qkbdvr41xx_qws.h
new file mode 100644
index 0000000000..51719cf64e
--- /dev/null
+++ b/src/gui/embedded/qkbdvr41xx_qws.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKBDVR41XX_QWS_H
+#define QKBDVR41XX_QWS_H
+
+#include <QtGui/qkbd_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if !defined(QT_NO_QWS_KEYBOARD) && !defined(QT_NO_QWS_KBD_VR41XX)
+
+class QWSVr41xxKbPrivate;
+
+class QWSVr41xxKeyboardHandler : public QWSKeyboardHandler
+{
+public:
+ explicit QWSVr41xxKeyboardHandler(const QString&);
+ virtual ~QWSVr41xxKeyboardHandler();
+
+private:
+ QWSVr41xxKbPrivate *d;
+};
+
+#endif // QT_NO_QWS_KBD_VR41XX
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QKBDVR41XX_QWS_H
diff --git a/src/gui/embedded/qkbdyopy_qws.cpp b/src/gui/embedded/qkbdyopy_qws.cpp
new file mode 100644
index 0000000000..bfa8c647ac
--- /dev/null
+++ b/src/gui/embedded/qkbdyopy_qws.cpp
@@ -0,0 +1,209 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+/*
+ * YOPY buttons driver
+ * Contributed by Ron Victorelli (victorrj at icubed.com)
+ */
+
+#include "qkbdyopy_qws.h"
+
+#ifndef QT_NO_QWS_KBD_YOPY
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <termios.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <linux/kd.h>
+#include <linux/fb.h>
+#include <linux/yopy_button.h>
+
+extern "C" {
+ int getpgid(int);
+}
+
+#include <qwidget.h>
+#include <qsocketnotifier.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWSYopyKbPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QWSYopyKbPrivate(QWSYopyKeyboardHandler *h, const QString&);
+ virtual ~QWSYopyKbPrivate();
+
+ bool isOpen() { return buttonFD > 0; }
+
+private slots:
+ void readKeyboardData();
+
+private:
+ QString terminalName;
+ int buttonFD;
+ struct termios newT, oldT;
+ QSocketNotifier *notifier;
+ QWSYopyKeyboardHandler *handler;
+};
+
+QWSYopyKeyboardHandler::QWSYopyKeyboardHandler(const QString &device)
+{
+ d = new QWSYopyKbPrivate(this, device);
+}
+
+QWSYopyKeyboardHandler::~QWSYopyKeyboardHandler()
+{
+ delete d;
+}
+
+QWSYopyKbPrivate::QWSYopyKbPrivate(QWSYopyKeyboardHandler *h, const QString &device) : handler(h)
+{
+ terminalName = device.isEmpty()?"/dev/tty1":device.toLatin1().constData();
+ buttonFD = -1;
+ notifier = 0;
+
+ buttonFD = ::open(terminalName.toLatin1().constData(), O_RDWR | O_NDELAY, 0);
+ if (buttonFD < 0) {
+ qWarning("Cannot open %s\n", qPrintable(terminalName));
+ return;
+ } else {
+
+ tcsetpgrp(buttonFD, getpgid(0));
+
+ /* put tty into "straight through" mode.
+ */
+ if (tcgetattr(buttonFD, &oldT) < 0) {
+ qFatal("Linux-kbd: tcgetattr failed");
+ }
+
+ newT = oldT;
+ newT.c_lflag &= ~(ICANON | ECHO | ISIG);
+ newT.c_iflag &= ~(ISTRIP | IGNCR | ICRNL | INLCR | IXOFF | IXON);
+ newT.c_iflag |= IGNBRK;
+ newT.c_cc[VMIN] = 0;
+ newT.c_cc[VTIME] = 0;
+
+
+ if (tcsetattr(buttonFD, TCSANOW, &newT) < 0) {
+ qFatal("Linux-kbd: TCSANOW tcsetattr failed");
+ }
+
+ if (ioctl(buttonFD, KDSKBMODE, K_MEDIUMRAW) < 0) {
+ qFatal("Linux-kbd: KDSKBMODE tcsetattr failed");
+ }
+
+ notifier = new QSocketNotifier(buttonFD, QSocketNotifier::Read, this);
+ connect(notifier, SIGNAL(activated(int)),this,
+ SLOT(readKeyboardData()));
+ }
+}
+
+QWSYopyKbPrivate::~QWSYopyKbPrivate()
+{
+ if (buttonFD > 0) {
+ ::close(buttonFD);
+ buttonFD = -1;
+ }
+}
+
+void QWSYopyKbPrivate::readKeyboardData()
+{
+ uchar buf[1];
+ char c='1';
+ int fd;
+
+ int n=read(buttonFD,buf,1);
+ if (n<0) {
+ qDebug("Keyboard read error %s",strerror(errno));
+ } else {
+ uint code = buf[0]&YPBUTTON_CODE_MASK;
+ bool press = !(buf[0]&0x80);
+ // printf("Key=%d/%d/%d\n",buf[1],code,press);
+ int k=(-1);
+ switch(code) {
+ case 39: k=Qt::Key_Up; break;
+ case 44: k=Qt::Key_Down; break;
+ case 41: k=Qt::Key_Left; break;
+ case 42: k=Qt::Key_Right; break;
+ case 56: k=Qt::Key_F1; break; //windows
+ case 29: k=Qt::Key_F2; break; //cycle
+ case 24: k=Qt::Key_F3; break; //record
+ case 23: k=Qt::Key_F4; break; //mp3
+ case 4: k=Qt::Key_F5; break; // PIMS
+ case 1: k=Qt::Key_Escape; break; // Escape
+ case 40: k=Qt::Key_Up; break; // prev
+ case 45: k=Qt::Key_Down; break; // next
+ case 35: if(!press) {
+ fd = open("/proc/sys/pm/sleep",O_RDWR,0);
+ if(fd >= 0) {
+ write(fd,&c,sizeof(c));
+ close(fd);
+ //
+ // Updates all widgets.
+ //
+ QWidgetList list = QApplication::allWidgets();
+ for (int i = 0; i < list.size(); ++i) {
+ QWidget *w = list.at(i);
+ w->update();
+ }
+ }
+ }
+ break;
+
+ default: k=(-1); break;
+ }
+
+ if (k >= 0) {
+ handler->processKeyEvent(0, k, 0, press, false);
+ }
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "qkbdyopy_qws.moc"
+
+#endif // QT_NO_QWS_KBD_YOPY
diff --git a/src/gui/embedded/qkbdyopy_qws.h b/src/gui/embedded/qkbdyopy_qws.h
new file mode 100644
index 0000000000..81c1c4d505
--- /dev/null
+++ b/src/gui/embedded/qkbdyopy_qws.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QKBDYOPY_QWS_H
+#define QKBDYOPY_QWS_H
+
+#include <QtGui/qkbd_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_KBD_YOPY
+
+class QWSYopyKbPrivate;
+
+class QWSYopyKeyboardHandler : public QWSKeyboardHandler
+{
+public:
+ explicit QWSYopyKeyboardHandler(const QString&);
+ virtual ~QWSYopyKeyboardHandler();
+
+private:
+ QWSYopyKbPrivate *d;
+};
+
+#endif // QT_NO_QWS_KBD_YOPY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QKBDYOPY_QWS_H
diff --git a/src/gui/embedded/qlock.cpp b/src/gui/embedded/qlock.cpp
new file mode 100644
index 0000000000..874ca7d205
--- /dev/null
+++ b/src/gui/embedded/qlock.cpp
@@ -0,0 +1,318 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qlock_p.h"
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+
+#include "qwssignalhandler_p.h"
+#include <unistd.h>
+#include <sys/types.h>
+#if defined(Q_OS_DARWIN)
+# define Q_NO_SEMAPHORE
+# include <sys/stat.h>
+# include <sys/file.h>
+#else // Q_OS_DARWIN
+# include <sys/sem.h>
+# if (defined(__GNU_LIBRARY__) && !defined(_SEM_SEMUN_UNDEFINED) && !defined(QT_LINUXBASE)) \
+ || defined(Q_OS_FREEBSD) || defined(Q_OS_OPENBSD) || defined(Q_OS_NETBSD) \
+ || defined(Q_OS_BSDI)
+ /* union semun is defined by including <sys/sem.h> */
+# else
+/* according to X/OPEN we have to define it ourselves */
+union semun {
+ int val; /* value for SETVAL */
+ struct semid_ds *buf; /* buffer for IPC_STAT, IPC_SET */
+ unsigned short *array; /* array for GETALL, SETALL */
+};
+# endif
+#endif // Q_OS_DARWIN
+#include <sys/ipc.h>
+#include <string.h>
+#include <errno.h>
+#include <qdebug.h>
+#include <signal.h>
+
+#endif // QT_NO_QWS_MULTIPROCESS
+
+#define MAX_LOCKS 200 // maximum simultaneous read locks
+
+QT_BEGIN_NAMESPACE
+
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+class QLockData
+{
+public:
+#ifdef Q_NO_SEMAPHORE
+ QByteArray file;
+#endif // Q_NO_SEMAPHORE
+ int id;
+ int count;
+ bool owned;
+};
+#endif // QT_NO_QWS_MULTIPROCESS
+
+/*!
+ \class QLock
+ \brief The QLock class is a wrapper for a System V shared semaphore.
+
+ \ingroup qws
+ \ingroup io
+
+ \internal
+
+ It is used by \l{Qt for Embedded Linux} for synchronizing access to the graphics
+ card and shared memory region between processes.
+*/
+
+/*!
+ \enum QLock::Type
+
+ \value Read
+ \value Write
+*/
+
+/*!
+ \fn QLock::QLock(const QString &filename, char id, bool create)
+
+ Creates a lock. \a filename is the file path of the Unix-domain
+ socket the \l{Qt for Embedded Linux} client is using. \a id is the name of the
+ particular lock to be created on that socket. If \a create is true
+ the lock is to be created (as the Qt for Embedded Linux server does); if \a
+ create is false the lock should exist already (as the Qt for Embedded Linux
+ client expects).
+*/
+
+QLock::QLock(const QString &filename, char id, bool create)
+{
+#ifdef QT_NO_QWS_MULTIPROCESS
+ Q_UNUSED(filename);
+ Q_UNUSED(id);
+ Q_UNUSED(create);
+#else
+ data = new QLockData;
+ data->count = 0;
+#ifdef Q_NO_SEMAPHORE
+ data->file = QString(filename+id).toLocal8Bit().constData();
+ for(int x = 0; x < 2; x++) {
+ data->id = open(data->file, O_RDWR | (x ? O_CREAT : 0), S_IRWXU);
+ if(data->id != -1 || !create) {
+ data->owned = x;
+ break;
+ }
+ }
+#else
+ key_t semkey = ftok(filename.toLocal8Bit().constData(), id);
+ data->id = semget(semkey,0,0);
+ data->owned = create;
+ if (create) {
+ semun arg; arg.val = 0;
+ if (data->id != -1)
+ semctl(data->id,0,IPC_RMID,arg);
+ data->id = semget(semkey,1,IPC_CREAT|0600);
+ arg.val = MAX_LOCKS;
+ semctl(data->id,0,SETVAL,arg);
+
+ QWSSignalHandler::instance()->addSemaphore(data->id);
+ }
+#endif
+ if (data->id == -1) {
+ int eno = errno;
+ qWarning("Cannot %s semaphore %s '%c'", (create ? "create" : "get"),
+ qPrintable(filename), id);
+ qDebug() << "Error" << eno << strerror(eno);
+ }
+#endif
+}
+
+/*!
+ \fn QLock::~QLock()
+
+ Destroys a lock
+*/
+
+QLock::~QLock()
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (locked())
+ unlock();
+#ifdef Q_NO_SEMAPHORE
+ if(isValid()) {
+ close(data->id);
+ if(data->owned)
+ unlink(data->file);
+ }
+#else
+ if(data->owned)
+ QWSSignalHandler::instance()->removeSemaphore(data->id);
+#endif
+ delete data;
+#endif
+}
+
+/*!
+ \fn bool QLock::isValid() const
+
+ Returns true if the lock constructor was successful; returns false if
+ the lock could not be created or was not available to connect to.
+*/
+
+bool QLock::isValid() const
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ return (data->id != -1);
+#else
+ return true;
+#endif
+}
+
+/*!
+ Locks the semaphore with a lock of type \a t. Locks can either be
+ \c Read or \c Write. If a lock is \c Read, attempts by other
+ processes to obtain \c Read locks will succeed, and \c Write
+ attempts will block until the lock is unlocked. If locked as \c
+ Write, all attempts to lock by other processes will block until
+ the lock is unlocked. Locks are stacked: i.e. a given QLock can be
+ locked multiple times by the same process without blocking, and
+ will only be unlocked after a corresponding number of unlock()
+ calls.
+*/
+
+void QLock::lock(Type t)
+{
+#ifdef QT_NO_QWS_MULTIPROCESS
+ Q_UNUSED(t);
+#else
+ if (!data->count) {
+#ifdef Q_NO_SEMAPHORE
+ int op = LOCK_SH;
+ if(t == Write)
+ op = LOCK_EX;
+ for(int rv=1; rv;) {
+ rv = flock(data->id, op);
+ if (rv == -1 && errno != EINTR)
+ qDebug("Semop lock failure %s",strerror(errno));
+ }
+#else
+ sembuf sops;
+ sops.sem_num = 0;
+ sops.sem_flg = SEM_UNDO;
+
+ if (t == Write) {
+ sops.sem_op = -MAX_LOCKS;
+ type = Write;
+ } else {
+ sops.sem_op = -1;
+ type = Read;
+ }
+
+ int rv;
+ do {
+ rv = semop(data->id,&sops,1);
+ if (rv == -1 && errno != EINTR)
+ qDebug("Semop lock failure %s",strerror(errno));
+ } while (rv == -1 && errno == EINTR);
+#endif
+ }
+ data->count++;
+#endif
+}
+
+/*!
+ \fn void QLock::unlock()
+
+ Unlocks the semaphore. If other processes were blocking waiting to
+ lock() the semaphore, one of them will wake up and succeed in
+ lock()ing.
+*/
+
+void QLock::unlock()
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if(data->count) {
+ data->count--;
+ if(!data->count) {
+#ifdef Q_NO_SEMAPHORE
+ for(int rv=1; rv;) {
+ rv = flock(data->id, LOCK_UN);
+ if (rv == -1 && errno != EINTR)
+ qDebug("Semop lock failure %s",strerror(errno));
+ }
+#else
+ sembuf sops;
+ sops.sem_num = 0;
+ sops.sem_op = 1;
+ sops.sem_flg = SEM_UNDO;
+ if (type == Write)
+ sops.sem_op = MAX_LOCKS;
+
+ int rv;
+ do {
+ rv = semop(data->id,&sops,1);
+ if (rv == -1 && errno != EINTR)
+ qDebug("Semop unlock failure %s",strerror(errno));
+ } while (rv == -1 && errno == EINTR);
+#endif
+ }
+ } else {
+ qDebug("Unlock without corresponding lock");
+ }
+#endif
+}
+
+/*!
+ \fn bool QLock::locked() const
+
+ Returns true if the lock is currently held by the current process;
+ otherwise returns false.
+*/
+
+bool QLock::locked() const
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ return (data->count > 0);
+#else
+ return false;
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qlock_p.h b/src/gui/embedded/qlock_p.h
new file mode 100644
index 0000000000..92e0704e56
--- /dev/null
+++ b/src/gui/embedded/qlock_p.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QLOCK_P_H
+#define QLOCK_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. This header file may
+// change from version to version without notice, or even be
+// removed.
+//
+// We mean it.
+//
+
+#include "QtCore/qstring.h"
+
+QT_BEGIN_NAMESPACE
+
+class QLockData;
+
+class Q_GUI_EXPORT QLock
+{
+public:
+ QLock(const QString &filename, char id, bool create = false);
+ ~QLock();
+
+ enum Type { Read, Write };
+
+ bool isValid() const;
+ void lock(Type type);
+ void unlock();
+ bool locked() const;
+
+private:
+ Type type;
+ QLockData *data;
+};
+
+
+// Nice class for ensuring the lock is released.
+// Just create one on the stack and the lock is automatically released
+// when QLockHandle is destructed.
+class Q_GUI_EXPORT QLockHandle
+{
+public:
+ QLockHandle(QLock *l, QLock::Type type) : qlock(l) { qlock->lock(type); }
+ ~QLockHandle() { if (locked()) qlock->unlock(); }
+
+ void lock(QLock::Type type) { qlock->lock(type); }
+ void unlock() { qlock->unlock(); }
+ bool locked() const { return qlock->locked(); }
+
+private:
+ QLock *qlock;
+};
+
+QT_END_NAMESPACE
+
+#endif // QLOCK_P_H
diff --git a/src/gui/embedded/qmouse_qws.cpp b/src/gui/embedded/qmouse_qws.cpp
new file mode 100644
index 0000000000..044a574444
--- /dev/null
+++ b/src/gui/embedded/qmouse_qws.cpp
@@ -0,0 +1,653 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmouse_qws.h"
+#include "qwindowsystem_qws.h"
+#include "qscreen_qws.h"
+#include "qapplication.h"
+#include "qtextstream.h"
+#include "qfile.h"
+#include "qdebug.h"
+#include "qscreen_qws.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWSPointerCalibrationData
+ \ingroup qws
+
+ \brief The QWSPointerCalibrationData class is a container for
+ mouse calibration data in Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ QWSPointerCalibrationData stores device and screen coordinates in
+ the devPoints and screenPoints variables, respectively.
+
+ A calibration program should create a QWSPointerCalibrationData
+ object, fill the devPoints and screenPoints variables with its
+ device and screen coordinates, and pass the object to the mouse
+ driver using the QWSMouseHandler::calibrate() function.
+
+ \sa QWSCalibratedMouseHandler, {Mouse Calibration Example}
+*/
+
+/*!
+ \variable QWSPointerCalibrationData::devPoints
+ \brief the raw device coordinates for each value of the Location enum.
+*/
+
+/*!
+ \variable QWSPointerCalibrationData::screenPoints
+ \brief the logical screen coordinates for each value of the Location enum.
+*/
+
+/*!
+ \enum QWSPointerCalibrationData::Location
+
+ This enum describes the various logical positions that can be
+ specified by the devPoints and screenPoints variables.
+
+ \value TopLeft Index of the top left corner of the screen.
+ \value BottomLeft Index of the bottom left corner of the screen.
+ \value BottomRight Index of the bottom right corner of the screen.
+ \value TopRight Index of the top right corner of the screen.
+ \value Center Index of the center of the screen.
+ \value LastLocation Last index in the pointer arrays.
+*/
+
+class QWSMouseHandlerPrivate
+{
+public:
+ QWSMouseHandlerPrivate() : screen(qt_screen) {}
+
+ const QScreen *screen;
+};
+
+/*!
+ \class QWSMouseHandler
+ \ingroup qws
+
+ \brief The QWSMouseHandler class is a base class for mouse drivers in
+ Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ \l{Qt for Embedded Linux} provides ready-made drivers for several mouse
+ protocols, see the \l{Qt for Embedded Linux Pointer Handling}{pointer
+ handling} documentation for details. Custom mouse drivers can be
+ implemented by subclassing the QWSMouseHandler class and creating
+ a mouse driver plugin (derived from QMouseDriverPlugin).
+ The default implementation of the QMouseDriverFactory class
+ will automatically detect the plugin, and load the driver into the
+ server application at run-time using Qt's \l {How to Create Qt
+ Plugins}{plugin system}.
+
+ The mouse driver receives mouse events from the system device and
+ encapsulates each event with an instance of the QWSEvent class
+ which it then passes to the server application (the server is
+ responsible for propagating the event to the appropriate
+ client). To receive mouse events, a QWSMouseHandler object will
+ usually create a QSocketNotifier object for the given device. The
+ QSocketNotifier class provides support for monitoring activity on
+ a file descriptor. When the socket notifier receives data, it will
+ call the mouse driver's mouseChanged() function to send the event
+ to the \l{Qt for Embedded Linux} server application for relaying to
+ clients.
+
+ If you are creating a driver for a device that needs calibration
+ or noise reduction, such as a touchscreen, use the
+ QWSCalibratedMouseHandler subclass instead to take advantage of
+ the calibrate() and clearCalibration() functions. The \l
+ {qws/mousecalibration}{Mouse Calibration}
+ demonstrates how to write a simple program using the mechanisms
+ provided by the QWSMouseHandler class to calibrate a mouse driver.
+
+ Note that when deriving from the QWSMouseHandler class, the
+ resume() and suspend() functions must be reimplemented to control
+ the flow of mouse input, i.e., the default implementation does
+ nothing. Reimplementations of these functions typically call the
+ QSocketNotifier::setEnabled() function to enable or disable the
+ socket notifier, respectively.
+
+ In addition, QWSMouseHandler provides the setScreen() function
+ that allows you to specify a screen for your mouse driver and the
+ limitToScreen() function that ensures that a given position is
+ within this screen's boundaries (changing the position if
+ necessary). Finally, QWSMouseHandler provides the pos() function
+ returning the current mouse position.
+
+ \sa QMouseDriverPlugin, QMouseDriverFactory, {Qt for Embedded Linux Pointer
+ Handling}
+*/
+
+
+/*!
+ \fn void QWSMouseHandler::suspend()
+
+ Implement this function to suspend reading and handling of mouse
+ events, e.g., call the QSocketNotifier::setEnabled() function to
+ disable the socket notifier.
+
+ \sa resume()
+*/
+
+/*!
+ \fn void QWSMouseHandler::resume()
+
+ Implement this function to resume reading and handling mouse
+ events, e.g., call the QSocketNotifier::setEnabled() function to
+ enable the socket notifier.
+
+ \sa suspend()
+*/
+
+/*!
+ \fn const QPoint &QWSMouseHandler::pos() const
+
+ Returns the current mouse position.
+
+ \sa mouseChanged(), limitToScreen()
+*/
+
+/*!
+ Constructs a mouse driver. The \a driver and \a device arguments
+ are passed by the QWS_MOUSE_PROTO environment variable.
+
+ Call the QWSServer::setMouseHandler() function to make the newly
+ created mouse driver, the primary driver. Note that the primary
+ driver is controlled by the system, i.e., the system will delete
+ it upon exit.
+*/
+QWSMouseHandler::QWSMouseHandler(const QString &, const QString &)
+ : mousePos(QWSServer::mousePosition), d_ptr(new QWSMouseHandlerPrivate)
+{
+}
+
+/*!
+ Destroys this mouse driver.
+
+ Do not call this function if this driver is the primary mouse
+ driver, i.e., if QWSServer::setMouseHandler() function has been
+ called passing this driver as argument. The primary mouse
+ driver is deleted by the system.
+*/
+QWSMouseHandler::~QWSMouseHandler()
+{
+ delete d_ptr;
+}
+
+/*!
+ Ensures that the given \a position is within the screen's
+ boundaries, changing the \a position if necessary.
+
+ \sa pos(), setScreen()
+*/
+
+void QWSMouseHandler::limitToScreen(QPoint &position)
+{
+ position.setX(qMin(d_ptr->screen->deviceWidth() - 1, qMax(0, position.x())));
+ position.setY(qMin(d_ptr->screen->deviceHeight() - 1, qMax(0, position.y())));
+}
+
+/*!
+ \since 4.2
+
+ Sets the screen for this mouse driver to be the given \a screen.
+
+ \sa limitToScreen()
+*/
+void QWSMouseHandler::setScreen(const QScreen *screen)
+{
+ d_ptr->screen = (screen ? screen : qt_screen);
+}
+
+/*!
+ Notifies the system of a new mouse event.
+
+ This function updates the current mouse position and sends the
+ event to the \l{Qt for Embedded Linux} server application for
+ delivery to the correct widget. Note that a custom mouse driver must call
+ this function whenever it wants to deliver a new mouse event.
+
+ The given \a position is the global position of the mouse cursor.
+ The \a state parameter is a bitmask of the Qt::MouseButton enum's
+ values, indicating which mouse buttons are pressed. The \a wheel
+ parameter is the delta value of the mouse wheel as returned by
+ QWheelEvent::delta().
+
+ \sa pos()
+*/
+void QWSMouseHandler::mouseChanged(const QPoint &position, int state, int wheel)
+{
+ mousePos = position + d_ptr->screen->offset();
+ QWSServer::sendMouseEvent(mousePos, state, wheel);
+}
+
+/*!
+ \fn QWSMouseHandler::clearCalibration()
+
+ This virtual function allows subclasses of QWSMouseHandler to
+ clear the calibration information. Note that the default
+ implementation does nothing.
+
+ \sa QWSCalibratedMouseHandler::clearCalibration(), calibrate()
+*/
+
+/*!
+ \fn QWSMouseHandler::calibrate(const QWSPointerCalibrationData *data)
+
+ This virtual function allows subclasses of QWSMouseHandler to set
+ the calibration information passed in the given \a data. Note that
+ the default implementation does nothing.
+
+ \sa QWSCalibratedMouseHandler::calibrate(), clearCalibration()
+*/
+
+/*! \fn QWSMouseHandler::getCalibration(QWSPointerCalibrationData *data) const
+ This virtual function allows subclasses of QWSMouseHandler
+ to fill in the device coordinates in \a data with values
+ that correspond to screen coordinates that are already in
+ \a data. Note that the default implementation does nothing.
+ */
+
+/*!
+ \class QWSCalibratedMouseHandler
+ \ingroup qws
+
+ \brief The QWSCalibratedMouseHandler class provides mouse
+ calibration and noise reduction in Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ \l{Qt for Embedded Linux} provides ready-made drivers for several mouse
+ protocols, see the \l{Qt for Embedded Linux Pointer Handling}{pointer
+ handling} documentation for details. In general, custom mouse
+ drivers can be implemented by subclassing the QWSMouseHandler
+ class. But when the system device does not have a fixed mapping
+ between device and screen coordinates and/or produces noisy events
+ (e.g., a touchscreen), you should derive from the
+ QWSCalibratedMouseHandler class instead to take advantage of its
+ calibration functionality. As always, you must also create a mouse
+ driver plugin (derived from QMouseDriverPlugin);
+ the implementation of the QMouseDriverFactory class will then
+ automatically detect the plugin, and load the driver into the
+ server application at run-time using Qt's
+ \l{How to Create Qt Plugins}{plugin system}.
+
+ QWSCalibratedMouseHandler provides an implementation of the
+ calibrate() function to update the calibration parameters based on
+ coordinate mapping of the given calibration data. The calibration
+ data is represented by an QWSPointerCalibrationData object. The
+ linear transformation between device coordinates and screen
+ coordinates is performed by calling the transform() function
+ explicitly on the points passed to the
+ QWSMouseHandler::mouseChanged() function. Use the
+ clearCalibration() function to make the mouse driver return mouse
+ events in raw device coordinates and not in screen coordinates.
+
+ The calibration parameters are recalculated whenever calibrate()
+ is called, and they can be stored using the writeCalibration()
+ function. Previously written parameters can be retrieved at any
+ time using the readCalibration() function (calibration parameters
+ are always read when the class is instantiated). Note that the
+ calibration parameters is written to and read from the file
+ currently specified by the POINTERCAL_FILE environment variable;
+ the default file is \c /etc/pointercal.
+
+ To achieve noise reduction, QWSCalibratedMouseHandler provides the
+ sendFiltered() function. Use this function instead of
+ mouseChanged() whenever a mouse event occurs. The filter's size
+ can be manipulated using the setFilterSize() function.
+
+ \sa QWSMouseHandler, QWSPointerCalibrationData,
+ {Mouse Calibration Example}
+*/
+
+
+/*!
+ \internal
+ */
+
+QWSCalibratedMouseHandler::QWSCalibratedMouseHandler(const QString &, const QString &)
+ : samples(5), currSample(0), numSamples(0)
+{
+ clearCalibration();
+ readCalibration();
+}
+
+/*!
+ Fills \a cd with the device coordinates corresponding to the given
+ screen coordinates.
+
+ \internal
+*/
+void QWSCalibratedMouseHandler::getCalibration(QWSPointerCalibrationData *cd) const
+{
+ const qint64 scale = qint64(a) * qint64(e) - qint64(b) * qint64(d);
+ const qint64 xOff = qint64(b) * qint64(f) - qint64(c) * qint64(e);
+ const qint64 yOff = qint64(c) * qint64(d) - qint64(a) * qint64(f);
+ for (int i = 0; i <= QWSPointerCalibrationData::LastLocation; ++i) {
+ const qint64 sX = cd->screenPoints[i].x();
+ const qint64 sY = cd->screenPoints[i].y();
+ const qint64 dX = (s*(e*sX - b*sY) + xOff) / scale;
+ const qint64 dY = (s*(a*sY - d*sX) + yOff) / scale;
+ cd->devPoints[i] = QPoint(dX, dY);
+ }
+}
+
+/*!
+ Clears the current calibration, i.e., makes the mouse
+ driver return mouse events in raw device coordinates instead of
+ screen coordinates.
+
+ \sa calibrate()
+*/
+void QWSCalibratedMouseHandler::clearCalibration()
+{
+ a = 1;
+ b = 0;
+ c = 0;
+ d = 0;
+ e = 1;
+ f = 0;
+ s = 1;
+}
+
+
+/*!
+ Saves the current calibration parameters in \c /etc/pointercal
+ (separated by whitespace and in alphabetical order).
+
+ You can override the default \c /etc/pointercal by specifying
+ another file using the POINTERCAL_FILE environment variable.
+
+ \sa readCalibration()
+*/
+void QWSCalibratedMouseHandler::writeCalibration()
+{
+ QString calFile;
+ calFile = QString::fromLocal8Bit(qgetenv("POINTERCAL_FILE"));
+ if (calFile.isEmpty())
+ calFile = QLatin1String("/etc/pointercal");
+
+#ifndef QT_NO_TEXTSTREAM
+ QFile file(calFile);
+ if (file.open(QIODevice::WriteOnly)) {
+ QTextStream t(&file);
+ t << a << " " << b << " " << c << " ";
+ t << d << " " << e << " " << f << " " << s << endl;
+ } else
+#endif
+ {
+ qCritical("QWSCalibratedMouseHandler::writeCalibration: "
+ "Could not save calibration into %s", qPrintable(calFile));
+ }
+}
+
+/*!
+ Reads previously written calibration parameters which are stored
+ in \c /etc/pointercal (separated by whitespace and in alphabetical
+ order).
+
+ You can override the default \c /etc/pointercal by specifying
+ another file using the POINTERCAL_FILE environment variable.
+
+
+ \sa writeCalibration()
+*/
+void QWSCalibratedMouseHandler::readCalibration()
+{
+ QString calFile = QString::fromLocal8Bit(qgetenv("POINTERCAL_FILE"));
+ if (calFile.isEmpty())
+ calFile = QLatin1String("/etc/pointercal");
+
+#ifndef QT_NO_TEXTSTREAM
+ QFile file(calFile);
+ if (file.open(QIODevice::ReadOnly)) {
+ QTextStream t(&file);
+ t >> a >> b >> c >> d >> e >> f >> s;
+ if (s == 0 || t.status() != QTextStream::Ok) {
+ qCritical("Corrupt calibration data");
+ clearCalibration();
+ }
+ } else
+#endif
+ {
+ qDebug() << "Could not read calibration:" <<calFile;
+ }
+}
+
+static int ilog2(quint32 n)
+{
+ int result = 0;
+
+ if (n & 0xffff0000) {
+ n >>= 16;
+ result += 16;
+ }
+ if (n & 0xff00) {
+ n >>= 8;
+ result += 8;}
+ if (n & 0xf0) {
+ n >>= 4;
+ result += 4;
+ }
+ if (n & 0xc) {
+ n >>= 2;
+ result += 2;
+ }
+ if (n & 0x2)
+ result += 1;
+
+ return result;
+}
+
+/*!
+ Updates the calibration parameters based on coordinate mapping of
+ the given \a data.
+
+ Create an instance of the QWSPointerCalibrationData class, fill in
+ the device and screen coordinates and pass that object to the mouse
+ driver using this function.
+
+ \sa clearCalibration(), transform()
+*/
+void QWSCalibratedMouseHandler::calibrate(const QWSPointerCalibrationData *data)
+{
+ // Algorithm derived from
+ // "How To Calibrate Touch Screens" by Carlos E. Vidales,
+ // printed in Embedded Systems Programming, Vol. 15 no 6, June 2002
+ // URL: http://www.embedded.com/showArticle.jhtml?articleID=9900629
+
+ const QPoint pd0 = data->devPoints[QWSPointerCalibrationData::TopLeft];
+ const QPoint pd1 = data->devPoints[QWSPointerCalibrationData::TopRight];
+ const QPoint pd2 = data->devPoints[QWSPointerCalibrationData::BottomRight];
+ const QPoint p0 = data->screenPoints[QWSPointerCalibrationData::TopLeft];
+ const QPoint p1 = data->screenPoints[QWSPointerCalibrationData::TopRight];
+ const QPoint p2 = data->screenPoints[QWSPointerCalibrationData::BottomRight];
+
+ const qint64 xd0 = pd0.x();
+ const qint64 xd1 = pd1.x();
+ const qint64 xd2 = pd2.x();
+ const qint64 yd0 = pd0.y();
+ const qint64 yd1 = pd1.y();
+ const qint64 yd2 = pd2.y();
+ const qint64 x0 = p0.x();
+ const qint64 x1 = p1.x();
+ const qint64 x2 = p2.x();
+ const qint64 y0 = p0.y();
+ const qint64 y1 = p1.y();
+ const qint64 y2 = p2.y();
+
+ qint64 scale = ((xd0 - xd2)*(yd1 - yd2) - (xd1 - xd2)*(yd0 - yd2));
+ int shift = 0;
+ qint64 absScale = qAbs(scale);
+ // use maximum 16 bit precision to reduce risk of integer overflow
+ if (absScale > (1 << 16)) {
+ shift = ilog2(absScale >> 16) + 1;
+ scale >>= shift;
+ }
+
+ s = scale;
+ a = ((x0 - x2)*(yd1 - yd2) - (x1 - x2)*(yd0 - yd2)) >> shift;
+ b = ((xd0 - xd2)*(x1 - x2) - (x0 - x2)*(xd1 - xd2)) >> shift;
+ c = (yd0*(xd2*x1 - xd1*x2) + yd1*(xd0*x2 - xd2*x0) + yd2*(xd1*x0 - xd0*x1)) >> shift;
+ d = ((y0 - y2)*(yd1 - yd2) - (y1 - y2)*(yd0 - yd2)) >> shift;
+ e = ((xd0 - xd2)*(y1 - y2) - (y0 - y2)*(xd1 - xd2)) >> shift;
+ f = (yd0*(xd2*y1 - xd1*y2) + yd1*(xd0*y2 - xd2*y0) + yd2*(xd1*y0 - xd0*y1)) >> shift;
+
+ writeCalibration();
+}
+
+/*!
+ Transforms the given \a position from device coordinates to screen
+ coordinates, and returns the transformed position.
+
+ This function is typically called explicitly on the points passed
+ to the QWSMouseHandler::mouseChanged() function.
+
+ This implementation is a linear transformation using 7 parameters
+ (\c a, \c b, \c c, \c d, \c e, \c f and \c s) to transform the
+ device coordinates (\c Xd, \c Yd) into screen coordinates (\c Xs,
+ \c Ys) using the following equations:
+
+ \snippet doc/src/snippets/code/src_gui_embedded_qmouse_qws.cpp 0
+
+ \sa mouseChanged()
+*/
+QPoint QWSCalibratedMouseHandler::transform(const QPoint &position)
+{
+ QPoint tp;
+
+ tp.setX((a * position.x() + b * position.y() + c) / s);
+ tp.setY((d * position.x() + e * position.y() + f) / s);
+
+ return tp;
+}
+
+/*!
+ Sets the size of the filter used in noise reduction to the given
+ \a size.
+
+ The sendFiltered() function reduces noice by calculating an
+ average position from a collection of mouse event positions. The
+ filter size determines the number of positions that forms the
+ basis for these calculations.
+
+ \sa sendFiltered()
+*/
+void QWSCalibratedMouseHandler::setFilterSize(int size)
+{
+ samples.resize(qMax(1, size));
+ numSamples = 0;
+ currSample = 0;
+}
+
+/*!
+ \fn bool QWSCalibratedMouseHandler::sendFiltered(const QPoint &position, int state)
+
+ Notifies the system of a new mouse event \e after applying a noise
+ reduction filter. Returns true if the filtering process is
+ successful; otherwise returns false. Note that if the filtering
+ process failes, the system is not notified about the event.
+
+ The given \a position is the global position of the mouse. The \a
+ state parameter is a bitmask of the Qt::MouseButton enum's values
+ indicating which mouse buttons are pressed.
+
+ The noice is reduced by calculating an average position from a
+ collection of mouse event positions and then calling the
+ mouseChanged() function with the new position. The number of
+ positions that is used is determined by the filter size.
+
+ \sa mouseChanged(), setFilterSize()
+*/
+bool QWSCalibratedMouseHandler::sendFiltered(const QPoint &position, int button)
+{
+ if (!button) {
+ if (numSamples >= samples.count())
+ mouseChanged(transform(position), 0);
+ currSample = 0;
+ numSamples = 0;
+ return true;
+ }
+
+ bool sent = false;
+ samples[currSample] = position;
+ numSamples++;
+ if (numSamples >= samples.count()) {
+
+ int ignore = -1;
+ if (samples.count() > 2) { // throw away the "worst" sample
+ int maxd = 0;
+ for (int i = 0; i < samples.count(); i++) {
+ int d = (mousePos - samples[i]).manhattanLength();
+ if (d > maxd) {
+ maxd = d;
+ ignore = i;
+ }
+ }
+ }
+
+ // average the rest
+ QPoint pos(0, 0);
+ int numAveraged = 0;
+ for (int i = 0; i < samples.count(); i++) {
+ if (ignore == i)
+ continue;
+ pos += samples[i];
+ ++numAveraged;
+ }
+ if (numAveraged)
+ pos /= numAveraged;
+
+ mouseChanged(transform(pos), button);
+ sent = true;
+ }
+ currSample++;
+ if (currSample >= samples.count())
+ currSample = 0;
+
+ return sent;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qmouse_qws.h b/src/gui/embedded/qmouse_qws.h
new file mode 100644
index 0000000000..d003b4ee92
--- /dev/null
+++ b/src/gui/embedded/qmouse_qws.h
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOUSE_QWS_H
+#define QMOUSE_QWS_H
+
+#include <QtCore/qobject.h>
+#include <QtGui/qpolygon.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QWSMouseHandlerPrivate;
+class QScreen;
+
+class Q_GUI_EXPORT QWSPointerCalibrationData
+{
+public:
+ enum Location { TopLeft = 0, BottomLeft = 1, BottomRight = 2, TopRight = 3,
+ Center = 4, LastLocation = Center };
+ QPoint devPoints[5];
+ QPoint screenPoints[5];
+};
+
+class Q_GUI_EXPORT QWSMouseHandler
+{
+public:
+ explicit QWSMouseHandler(const QString &driver = QString(),
+ const QString &device = QString());
+ virtual ~QWSMouseHandler();
+
+ virtual void clearCalibration() {}
+ virtual void calibrate(const QWSPointerCalibrationData *) {}
+ virtual void getCalibration(QWSPointerCalibrationData *) const {}
+
+ virtual void resume() = 0;
+ virtual void suspend() = 0;
+
+ void limitToScreen(QPoint &pt);
+ void mouseChanged(const QPoint& pos, int bstate, int wheel = 0);
+ const QPoint &pos() const { return mousePos; }
+
+ void setScreen(const QScreen *screen);
+
+protected:
+ QPoint &mousePos;
+ QWSMouseHandlerPrivate *d_ptr;
+};
+
+
+class Q_GUI_EXPORT QWSCalibratedMouseHandler : public QWSMouseHandler
+{
+public:
+ explicit QWSCalibratedMouseHandler(const QString &driver = QString(),
+ const QString &device = QString());
+
+ virtual void clearCalibration();
+ virtual void calibrate(const QWSPointerCalibrationData *);
+ virtual void getCalibration(QWSPointerCalibrationData *) const;
+
+protected:
+ bool sendFiltered(const QPoint &, int button);
+ QPoint transform(const QPoint &);
+
+ void readCalibration();
+ void writeCalibration();
+ void setFilterSize(int);
+
+private:
+ int a, b, c;
+ int d, e, f;
+ int s;
+ QPolygon samples;
+ int currSample;
+ int numSamples;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMOUSE_QWS_H
diff --git a/src/gui/embedded/qmousebus_qws.cpp b/src/gui/embedded/qmousebus_qws.cpp
new file mode 100644
index 0000000000..6b26349cb5
--- /dev/null
+++ b/src/gui/embedded/qmousebus_qws.cpp
@@ -0,0 +1,238 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmousebus_qws.h"
+
+#ifndef QT_NO_QWS_MOUSE_BUS
+
+#include "qwindowsystem_qws.h"
+#include "qsocketnotifier.h"
+
+#include "qapplication.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <termios.h>
+
+QT_BEGIN_NAMESPACE
+
+/*
+ * bus mouse driver (a.k.a. Logitech busmouse)
+ */
+
+class QWSBusMouseHandlerPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QWSBusMouseHandlerPrivate(QWSBusMouseHandler *h, const QString &driver, const QString &device);
+ ~QWSBusMouseHandlerPrivate();
+
+ void suspend();
+ void resume();
+
+private slots:
+ void readMouseData();
+
+protected:
+ enum { mouseBufSize = 128 };
+ QWSBusMouseHandler *handler;
+ QSocketNotifier *mouseNotifier;
+ int mouseFD;
+ int mouseIdx;
+ int obstate;
+ uchar mouseBuf[mouseBufSize];
+};
+
+QWSBusMouseHandler::QWSBusMouseHandler(const QString &driver, const QString &device)
+ : QWSMouseHandler(driver, device)
+{
+ d = new QWSBusMouseHandlerPrivate(this, driver, device);
+}
+
+QWSBusMouseHandler::~QWSBusMouseHandler()
+{
+ delete d;
+}
+
+void QWSBusMouseHandler::suspend()
+{
+ d->suspend();
+}
+
+void QWSBusMouseHandler::resume()
+{
+ d->resume();
+}
+
+
+QWSBusMouseHandlerPrivate::QWSBusMouseHandlerPrivate(QWSBusMouseHandler *h,
+ const QString &, const QString &device)
+ : handler(h)
+
+{
+ QString mouseDev = device;
+ if (mouseDev.isEmpty())
+ mouseDev = QLatin1String("/dev/mouse");
+ obstate = -1;
+ mouseFD = -1;
+ mouseFD = open(mouseDev.toLocal8Bit(), O_RDWR | O_NDELAY);
+ if (mouseFD < 0)
+ mouseFD = open(mouseDev.toLocal8Bit(), O_RDONLY | O_NDELAY);
+ if (mouseFD < 0)
+ qDebug("Cannot open %s (%s)", qPrintable(mouseDev), strerror(errno));
+
+ // Clear pending input
+ tcflush(mouseFD,TCIFLUSH);
+ usleep(50000);
+
+ char buf[100]; // busmouse driver will not read if bufsize < 3, YYD
+ while (read(mouseFD, buf, 100) > 0) { } // eat unwanted replies
+
+ mouseIdx = 0;
+
+ mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read, this);
+ connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));
+}
+
+QWSBusMouseHandlerPrivate::~QWSBusMouseHandlerPrivate()
+{
+ if (mouseFD >= 0) {
+ tcflush(mouseFD,TCIFLUSH); // yyd.
+ close(mouseFD);
+ }
+}
+
+
+void QWSBusMouseHandlerPrivate::suspend()
+{
+ mouseNotifier->setEnabled(false);
+}
+
+
+void QWSBusMouseHandlerPrivate::resume()
+{
+ mouseIdx = 0;
+ obstate = -1;
+ mouseNotifier->setEnabled(true);
+}
+
+void QWSBusMouseHandlerPrivate::readMouseData()
+{
+ int n;
+ // It'll only read 3 bytes a time and return all other buffer zeroed, thus cause protocol errors
+ for (;;) {
+ if (mouseBufSize - mouseIdx < 3)
+ break;
+ n = read(mouseFD, mouseBuf+mouseIdx, 3);
+ if (n != 3)
+ break;
+ mouseIdx += 3;
+ }
+
+ static const int accel_limit = 5;
+ static const int accel = 2;
+
+ int idx = 0;
+ int bstate = 0;
+ int dx = 0, dy = 0;
+ bool sendEvent = false;
+ int tdx = 0, tdy = 0;
+
+ while (mouseIdx-idx >= 3) {
+#if 0 // debug
+ qDebug("Got mouse data");
+#endif
+ uchar *mb = mouseBuf+idx;
+ bstate = 0;
+ dx = 0;
+ dy = 0;
+ sendEvent = false;
+ if (((mb[0] & 0x04)))
+ bstate |= Qt::LeftButton;
+ if (((mb[0] & 0x01)))
+ bstate |= Qt::RightButton;
+
+ dx=(signed char)mb[1];
+ dy=(signed char)mb[2];
+ sendEvent=true;
+
+ if (sendEvent) {
+ if (qAbs(dx) > accel_limit || qAbs(dy) > accel_limit) {
+ dx *= accel;
+ dy *= accel;
+ }
+ tdx += dx;
+ tdy += dy;
+ if (bstate != obstate) {
+ QPoint pos = handler->pos() + QPoint(tdx,-tdy);
+ handler->limitToScreen(pos);
+ handler->mouseChanged(pos,bstate);
+ sendEvent = false;
+ tdx = 0;
+ tdy = 0;
+ obstate = bstate;
+ }
+ }
+ idx += 3;
+ }
+ if (sendEvent) {
+ QPoint pos = handler->pos() + QPoint(tdx,-tdy);
+ handler->limitToScreen(pos);
+ handler->mouseChanged(pos,bstate);
+ }
+
+ int surplus = mouseIdx - idx;
+ for (int i = 0; i < surplus; i++)
+ mouseBuf[i] = mouseBuf[idx+i];
+ mouseIdx = surplus;
+}
+
+QT_END_NAMESPACE
+
+#include "qmousebus_qws.moc"
+
+#endif // QT_NO_QWS_MOUSE_BUS
diff --git a/src/gui/embedded/qmousebus_qws.h b/src/gui/embedded/qmousebus_qws.h
new file mode 100644
index 0000000000..636b466374
--- /dev/null
+++ b/src/gui/embedded/qmousebus_qws.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOUSEBUS_QWS_H
+#define QMOUSEBUS_QWS_H
+
+#include <QtGui/qmouse_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_MOUSE_BUS
+
+class QWSBusMouseHandlerPrivate;
+
+class QWSBusMouseHandler : public QWSMouseHandler
+{
+public:
+ explicit QWSBusMouseHandler(const QString & = QString(),
+ const QString & = QString());
+ ~QWSBusMouseHandler();
+
+ void suspend();
+ void resume();
+protected:
+ QWSBusMouseHandlerPrivate *d;
+};
+
+#endif // QT_NO_QWS_MOUSE_BUS
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMOUSEBUS_QWS_H
diff --git a/src/gui/embedded/qmousedriverfactory_qws.cpp b/src/gui/embedded/qmousedriverfactory_qws.cpp
new file mode 100644
index 0000000000..db1d7a4262
--- /dev/null
+++ b/src/gui/embedded/qmousedriverfactory_qws.cpp
@@ -0,0 +1,195 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmousedriverfactory_qws.h"
+
+#include "qapplication.h"
+#include "qmousepc_qws.h"
+#include "qmousebus_qws.h"
+#include "qmousevr41xx_qws.h"
+#include "qmouseyopy_qws.h"
+#include "qmouselinuxtp_qws.h"
+#include "qmousevfb_qws.h"
+#include "qmousetslib_qws.h"
+#include <stdlib.h>
+#include "private/qfactoryloader_p.h"
+#include "qmousedriverplugin_qws.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,
+ (QWSMouseHandlerFactoryInterface_iid,
+ QLatin1String("/mousedrivers"), Qt::CaseInsensitive))
+
+#endif //QT_NO_LIBRARY
+#endif //QT_MAKEDLL
+
+/*!
+ \class QMouseDriverFactory
+ \ingroup qws
+
+ \brief The QMouseDriverFactory class creates mouse drivers in
+ Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ QMouseDriverFactory is used to detect and instantiate the
+ available mouse drivers, allowing \l{Qt for Embedded Linux} to load the
+ preferred driver into the server application at runtime. The
+ create() function returns a QWSMouseHandler object representing
+ the mouse driver identified by a given key. The valid keys
+ (i.e. the supported drivers) can be retrieved using the keys()
+ function.
+
+ \l{Qt for Embedded Linux} provides several built-in mouse drivers. In
+ addition, custom mouse drivers can be added using Qt's plugin
+ mechanism, i.e. by subclassing the QWSMouseHandler class and
+ creating a mouse driver plugin (QMouseDriverPlugin). See the
+ \l{Qt for Embedded Linux Pointer Handling}{pointer handling}
+ documentation for details.
+
+ \sa QWSMouseHandler, QMouseDriverPlugin
+*/
+
+/*!
+ Creates the mouse driver specified by the given \a key, using the
+ display specified by the given \a device.
+
+ Note that the keys are case-insensitive.
+
+ \sa keys()
+*/
+QWSMouseHandler *QMouseDriverFactory::create(const QString& key, const QString &device)
+{
+ QString driver = key.toLower();
+#ifndef QT_NO_QWS_MOUSE_LINUXTP
+ if (driver == QLatin1String("linuxtp") || driver.isEmpty())
+ return new QWSLinuxTPMouseHandler(key, device);
+#endif
+#ifndef QT_NO_QWS_MOUSE_YOPY
+ if (driver == QLatin1String("yopy") || driver.isEmpty())
+ return new QWSYopyMouseHandler(key, device);
+#endif
+#ifndef QT_NO_QWS_MOUSE_VR41XX
+ if (driver == QLatin1String("vr41xx") || driver.isEmpty())
+ return new QWSVr41xxMouseHandler(key, device);
+#endif
+#ifndef QT_NO_QWS_MOUSE_PC
+ if (driver == QLatin1String("auto")
+ || driver == QLatin1String("intellimouse")
+ || driver == QLatin1String("microsoft")
+ || driver == QLatin1String("mousesystems")
+ || driver == QLatin1String("mouseman")
+ || driver.isEmpty()) {
+ return new QWSPcMouseHandler(key, device);
+ }
+#endif
+#ifndef QT_NO_QWS_MOUSE_BUS
+ if (driver == QLatin1String("bus"))
+ return new QWSBusMouseHandler(key, device);
+#endif
+#ifndef QT_NO_QWS_MOUSE_TSLIB
+ if (driver == QLatin1String("tslib") || driver.isEmpty())
+ return new QWSTslibMouseHandler(key, device);
+#endif
+#ifndef QT_NO_QWS_MOUSE_QVFB
+ if (driver == QLatin1String("qvfbmouse") || driver == QLatin1String("qvfb"))
+ return new QVFbMouseHandler(key, device);
+#endif
+
+#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL)
+#ifndef QT_NO_LIBRARY
+ if (QWSMouseHandlerFactoryInterface *factory = qobject_cast<QWSMouseHandlerFactoryInterface*>(loader()->instance(driver)))
+ return factory->create(driver, device);
+#endif
+#endif
+ return 0;
+}
+
+/*!
+ Returns the list of valid keys, i.e. the available mouse drivers.
+
+ \sa create()
+*/
+QStringList QMouseDriverFactory::keys()
+{
+ QStringList list;
+
+#ifndef QT_NO_QWS_MOUSE_LINUXTP
+ list << QLatin1String("LinuxTP");
+#endif
+#ifndef QT_NO_QWS_MOUSE_YOPY
+ list << QLatin1String("Yopy");
+#endif
+#ifndef QT_NO_QWS_MOUSE_VR41XX
+ list << QLatin1String("VR41xx");
+#endif
+#ifndef QT_NO_QWS_MOUSE_PC
+ list << QLatin1String("Auto")
+ << QLatin1String("IntelliMouse")
+ << QLatin1String("Microsoft")
+ << QLatin1String("MouseSystems")
+ << QLatin1String("MouseMan");
+#endif
+#ifndef QT_NO_QWS_MOUSE_BUS
+ list << QLatin1String("Bus");
+#endif
+#ifndef QT_NO_QWS_MOUSE_TSLIB
+ list << QLatin1String("Tslib");
+#endif
+
+#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/embedded/qmousedriverfactory_qws.h b/src/gui/embedded/qmousedriverfactory_qws.h
new file mode 100644
index 0000000000..6a13bb71d5
--- /dev/null
+++ b/src/gui/embedded/qmousedriverfactory_qws.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOUSEDRIVERFACTORY_QWS_H
+#define QMOUSEDRIVERFACTORY_QWS_H
+
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QString;
+class QWSMouseHandler;
+
+class Q_GUI_EXPORT QMouseDriverFactory
+{
+public:
+ static QStringList keys();
+ static QWSMouseHandler *create(const QString&, const QString &);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMOUSEDRIVERFACTORY_QWS_H
diff --git a/src/gui/embedded/qmousedriverplugin_qws.cpp b/src/gui/embedded/qmousedriverplugin_qws.cpp
new file mode 100644
index 0000000000..e7f11b372d
--- /dev/null
+++ b/src/gui/embedded/qmousedriverplugin_qws.cpp
@@ -0,0 +1,124 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmousedriverplugin_qws.h"
+
+#ifndef QT_NO_LIBRARY
+
+#include "qmouse_qws.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QMouseDriverPlugin
+ \ingroup plugins
+ \ingroup qws
+
+ \brief The QMouseDriverPlugin class is an abstract base class for
+ mouse driver plugins in Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ \l{Qt for Embedded Linux} provides ready-made drivers for several mouse
+ protocols, see the \l{Qt for Embedded Linux Pointer Handling}{pointer
+ handling} documentation for details. Custom mouse drivers can be
+ implemented by subclassing the QWSMouseHandler class and creating
+ a mouse driver plugin.
+
+ A mouse driver plugin can be created by subclassing
+ QMouseDriverPlugin 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
+ QMouseDriverFactory 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 QWSMouseHandler, QMouseDriverFactory
+*/
+
+/*!
+ \fn QStringList QMouseDriverPlugin::keys() const
+
+ Implement this function to return the list of valid keys, i.e. the
+ mouse drivers supported by this plugin.
+
+ \l{Qt for Embedded Linux} provides ready-made drivers for several mouse
+ protocols, see the \l {Qt for Embedded Linux Pointer Handling}{pointer
+ handling} documentation for details.
+
+ \sa create()
+*/
+
+/*!
+ Constructs a mouse driver 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.
+*/
+QMouseDriverPlugin::QMouseDriverPlugin(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ Destroys the mouse driver plugin.
+
+ Note that Qt destroys a plugin automatically when it is no longer
+ used, so there is no need for calling the destructor explicitly.
+*/
+QMouseDriverPlugin::~QMouseDriverPlugin()
+{
+}
+
+/*!
+ \fn QScreen* QMouseDriverPlugin::create(const QString &key, const QString& device)
+
+ Implement this function to create a driver matching the type
+ specified by the given \a key and \a device parameters. Note that
+ keys are case-insensitive.
+
+ \sa keys()
+*/
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_LIBRARY
diff --git a/src/gui/embedded/qmousedriverplugin_qws.h b/src/gui/embedded/qmousedriverplugin_qws.h
new file mode 100644
index 0000000000..4a864f98a3
--- /dev/null
+++ b/src/gui/embedded/qmousedriverplugin_qws.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOUSEDRIVERPLUGIN_QWS_H
+#define QMOUSEDRIVERPLUGIN_QWS_H
+
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_LIBRARY
+
+class QWSMouseHandler;
+
+struct Q_GUI_EXPORT QWSMouseHandlerFactoryInterface : public QFactoryInterface
+{
+ virtual QWSMouseHandler* create(const QString &name, const QString &device) = 0;
+};
+
+#define QWSMouseHandlerFactoryInterface_iid "com.trolltech.Qt.QWSMouseHandlerFactoryInterface"
+Q_DECLARE_INTERFACE(QWSMouseHandlerFactoryInterface, QWSMouseHandlerFactoryInterface_iid)
+
+class Q_GUI_EXPORT QMouseDriverPlugin : public QObject, public QWSMouseHandlerFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QWSMouseHandlerFactoryInterface:QFactoryInterface)
+public:
+ explicit QMouseDriverPlugin(QObject *parent = 0);
+ ~QMouseDriverPlugin();
+
+ virtual QStringList keys() const = 0;
+ virtual QWSMouseHandler* create(const QString& driver, const QString &device) = 0;
+};
+
+#endif // QT_NO_LIBRARY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMOUSEDRIVERPLUGIN_QWS_H
diff --git a/src/gui/embedded/qmouselinuxtp_qws.cpp b/src/gui/embedded/qmouselinuxtp_qws.cpp
new file mode 100644
index 0000000000..7683be3ba4
--- /dev/null
+++ b/src/gui/embedded/qmouselinuxtp_qws.cpp
@@ -0,0 +1,334 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmouselinuxtp_qws.h"
+
+#ifndef QT_NO_QWS_MOUSE_LINUXTP
+#include "qwindowsystem_qws.h"
+#include "qsocketnotifier.h"
+#include "qtimer.h"
+#include "qapplication.h"
+#include "qscreen_qws.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <termios.h>
+
+QT_BEGIN_NAMESPACE
+
+#if defined(QT_QWS_IPAQ)
+ #define QT_QWS_IPAQ_RAW
+ #define QT_QWS_SCREEN_COORDINATES
+ typedef struct {
+ unsigned short pressure;
+ unsigned short x;
+ unsigned short y;
+ unsigned short pad;
+ } TS_EVENT;
+#elif defined(QT_QWS_EBX)
+ #define QT_QWS_EBX_RAW
+ #define QT_QWS_SCREEN_COORDINATES
+#ifndef QT_QWS_SHARP
+ typedef struct {
+ unsigned short pressure;
+ unsigned short x;
+ unsigned short y;
+ unsigned short pad;
+ } TS_EVENT;
+ #else
+ typedef struct {
+ long y;
+ long x;
+ long pressure;
+ long long millisecs;
+ } TS_EVENT;
+ #define QT_QWS_TP_SAMPLE_SIZE 10
+ #define QT_QWS_TP_MINIMUM_SAMPLES 4
+ #define QT_QWS_TP_PRESSURE_THRESHOLD 500
+ #define QT_QWS_TP_MOVE_LIMIT 50
+ #define QT_QWS_TP_JITTER_LIMIT 2
+ #endif
+#else // not IPAQ, not SHARP
+ typedef struct {
+ unsigned short pressure;
+ unsigned short x;
+ unsigned short y;
+ unsigned short pad;
+ } TS_EVENT;
+#endif
+
+#ifndef QT_QWS_TP_SAMPLE_SIZE
+#define QT_QWS_TP_SAMPLE_SIZE 5
+#endif
+
+#ifndef QT_QWS_TP_MINIMUM_SAMPLES
+#define QT_QWS_TP_MINIMUM_SAMPLES 5
+#endif
+
+#ifndef QT_QWS_TP_PRESSURE_THRESHOLD
+#define QT_QWS_TP_PRESSURE_THRESHOLD 1
+#endif
+
+#ifndef QT_QWS_TP_MOVE_LIMIT
+#define QT_QWS_TP_MOVE_LIMIT 100
+#endif
+
+#ifndef QT_QWS_TP_JITTER_LIMIT
+#define QT_QWS_TP_JITTER_LIMIT 2
+#endif
+
+class QWSLinuxTPMouseHandlerPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QWSLinuxTPMouseHandlerPrivate(QWSLinuxTPMouseHandler *h, const QString &);
+ ~QWSLinuxTPMouseHandlerPrivate();
+
+ void suspend();
+ void resume();
+private:
+ static const int mouseBufSize = 2048;
+ int mouseFD;
+ QPoint oldmouse;
+ QPoint oldTotalMousePos;
+ bool waspressed;
+ QPolygon samples;
+ int currSample;
+ int lastSample;
+ int numSamples;
+ int skipCount;
+ int mouseIdx;
+ uchar mouseBuf[mouseBufSize];
+ QWSLinuxTPMouseHandler *handler;
+ QSocketNotifier *mouseNotifier;
+
+private slots:
+ void readMouseData();
+};
+
+QWSLinuxTPMouseHandler::QWSLinuxTPMouseHandler(const QString &driver, const QString &device)
+ : QWSCalibratedMouseHandler(driver, device)
+{
+ d = new QWSLinuxTPMouseHandlerPrivate(this, device);
+}
+
+QWSLinuxTPMouseHandler::~QWSLinuxTPMouseHandler()
+{
+ delete d;
+}
+
+void QWSLinuxTPMouseHandler::suspend()
+{
+ d->suspend();
+}
+
+void QWSLinuxTPMouseHandler::resume()
+{
+ d->resume();
+}
+
+QWSLinuxTPMouseHandlerPrivate::QWSLinuxTPMouseHandlerPrivate(QWSLinuxTPMouseHandler *h,
+ const QString &device)
+ : samples(QT_QWS_TP_SAMPLE_SIZE), currSample(0), lastSample(0),
+ numSamples(0), skipCount(0), handler(h)
+{
+ QString mousedev;
+ if (device.isEmpty()) {
+#if defined(QT_QWS_IPAQ)
+# ifdef QT_QWS_IPAQ_RAW
+ mousedev = QLatin1String("/dev/h3600_tsraw");
+# else
+ mousedev = QLatin1String("/dev/h3600_ts");
+# endif
+#else
+ mousedev = QLatin1String("/dev/ts");
+#endif
+ } else {
+ mousedev = device;
+ }
+ if ((mouseFD = open(mousedev.toLatin1().constData(), O_RDONLY | O_NDELAY)) < 0) {
+ qWarning("Cannot open %s (%s)", qPrintable(mousedev), strerror(errno));
+ return;
+ }
+
+ mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read,
+ this);
+ connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));
+ waspressed=false;
+ mouseIdx = 0;
+}
+
+QWSLinuxTPMouseHandlerPrivate::~QWSLinuxTPMouseHandlerPrivate()
+{
+ if (mouseFD >= 0)
+ close(mouseFD);
+}
+
+void QWSLinuxTPMouseHandlerPrivate::suspend()
+{
+ if (mouseNotifier)
+ mouseNotifier->setEnabled(false);
+}
+
+void QWSLinuxTPMouseHandlerPrivate::resume()
+{
+ mouseIdx=0;
+ currSample=0;
+ lastSample=0;
+ numSamples=0;
+ skipCount=0;
+ if (mouseNotifier)
+ mouseNotifier->setEnabled(true);
+}
+
+
+void QWSLinuxTPMouseHandlerPrivate::readMouseData()
+{
+ if(!qt_screen)
+ return;
+
+ int n;
+ do {
+ n = read(mouseFD, mouseBuf+mouseIdx, mouseBufSize-mouseIdx);
+ if (n > 0)
+ mouseIdx += n;
+ } while (n > 0 && mouseIdx < mouseBufSize);
+
+ //qDebug("readMouseData()");
+
+ TS_EVENT *data;
+ int idx = 0;
+
+ // perhaps we shouldn't be reading EVERY SAMPLE.
+ while (mouseIdx-idx >= (int)sizeof(TS_EVENT)) {
+ uchar *mb = mouseBuf+idx;
+ data = (TS_EVENT *) mb;
+
+ if(data->pressure >= QT_QWS_TP_PRESSURE_THRESHOLD) {
+#ifdef QT_QWS_SHARP
+ samples[currSample] = QPoint(1000 - data->x, data->y);
+#else
+ samples[currSample] = QPoint(data->x, data->y);
+#endif
+ numSamples++;
+ if (numSamples >= QT_QWS_TP_MINIMUM_SAMPLES) {
+ int sampleCount = qMin(numSamples + 1,samples.count());
+
+ // average the rest
+ QPoint mousePos = QPoint(0, 0);
+ QPoint totalMousePos = oldTotalMousePos;
+ totalMousePos += samples[currSample];
+ if(numSamples >= samples.count())
+ totalMousePos -= samples[lastSample];
+
+ mousePos = totalMousePos / (sampleCount - 1);
+#if defined(QT_QWS_SCREEN_COORDINATES)
+ mousePos = handler->transform(mousePos);
+#endif
+ if(!waspressed)
+ oldmouse = mousePos;
+ QPoint dp = mousePos - oldmouse;
+ int dxSqr = dp.x() * dp.x();
+ int dySqr = dp.y() * dp.y();
+ if (dxSqr + dySqr < (QT_QWS_TP_MOVE_LIMIT * QT_QWS_TP_MOVE_LIMIT)) {
+ if (waspressed) {
+ if ((dxSqr + dySqr > (QT_QWS_TP_JITTER_LIMIT * QT_QWS_TP_JITTER_LIMIT)) || skipCount > 2) {
+ handler->mouseChanged(mousePos,Qt::LeftButton);
+ oldmouse = mousePos;
+ skipCount = 0;
+ } else {
+ skipCount++;
+ }
+ } else {
+ handler->mouseChanged(mousePos,Qt::LeftButton);
+ oldmouse=mousePos;
+ waspressed=true;
+ }
+
+ // save recuring information
+ currSample++;
+ if (numSamples >= samples.count())
+ lastSample++;
+ oldTotalMousePos = totalMousePos;
+ } else {
+ numSamples--; // don't use this sample, it was bad.
+ }
+ } else {
+ // build up the average
+ oldTotalMousePos += samples[currSample];
+ currSample++;
+ }
+ if (currSample >= samples.count())
+ currSample = 0;
+ if (lastSample >= samples.count())
+ lastSample = 0;
+ } else {
+ currSample = 0;
+ lastSample = 0;
+ numSamples = 0;
+ skipCount = 0;
+ oldTotalMousePos = QPoint(0,0);
+ if (waspressed) {
+ handler->mouseChanged(oldmouse,0);
+ oldmouse = QPoint(-100, -100);
+ waspressed=false;
+ }
+ }
+ idx += sizeof(TS_EVENT);
+ }
+
+ int surplus = mouseIdx - idx;
+ for (int i = 0; i < surplus; i++)
+ mouseBuf[i] = mouseBuf[idx+i];
+ mouseIdx = surplus;
+}
+
+QT_END_NAMESPACE
+
+#include "qmouselinuxtp_qws.moc"
+
+#endif //QT_NO_QWS_MOUSE_LINUXTP
diff --git a/src/gui/embedded/qmouselinuxtp_qws.h b/src/gui/embedded/qmouselinuxtp_qws.h
new file mode 100644
index 0000000000..2385455c19
--- /dev/null
+++ b/src/gui/embedded/qmouselinuxtp_qws.h
@@ -0,0 +1,77 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOUSELINUXTP_QWS_H
+#define QMOUSELINUXTP_QWS_H
+
+#include <QtGui/qmouse_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_MOUSE_LINUXTP
+
+class QWSLinuxTPMouseHandlerPrivate;
+
+class QWSLinuxTPMouseHandler : public QWSCalibratedMouseHandler
+{
+ friend class QWSLinuxTPMouseHandlerPrivate;
+public:
+ explicit QWSLinuxTPMouseHandler(const QString & = QString(),
+ const QString & = QString());
+ ~QWSLinuxTPMouseHandler();
+
+ void suspend();
+ void resume();
+protected:
+ QWSLinuxTPMouseHandlerPrivate *d;
+};
+
+#endif // QT_NO_QWS_MOUSE_LINUXTP
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMOUSELINUXTP_QWS_H
diff --git a/src/gui/embedded/qmousepc_qws.cpp b/src/gui/embedded/qmousepc_qws.cpp
new file mode 100644
index 0000000000..a0cb032b60
--- /dev/null
+++ b/src/gui/embedded/qmousepc_qws.cpp
@@ -0,0 +1,793 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmousepc_qws.h"
+
+#ifndef QT_NO_QWS_MOUSE_PC
+
+#include "qwindowsystem_qws.h"
+#include "qsocketnotifier.h"
+#include "qwsevent_qws.h"
+#include "qwscommand_qws_p.h"
+#include "qwsutils_qws.h"
+
+#include "qapplication.h"
+#include "qpolygon.h"
+#include "qtimer.h"
+#include "qfile.h"
+#include "qtextstream.h"
+#include "qstringlist.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <termios.h>
+
+#include <qscreen_qws.h>
+
+QT_BEGIN_NAMESPACE
+
+//#define QWS_MOUSE_DEBUG
+
+/*
+ * Automatic-detection mouse driver
+ */
+
+class QWSPcMouseSubHandler {
+protected:
+ enum { max_buf=32 };
+
+ int fd;
+
+ uchar buffer[max_buf];
+ int nbuf;
+
+ QPoint motion;
+ int bstate;
+ int wheel;
+
+ int goodness;
+ int badness;
+
+ virtual int tryData()=0;
+
+public:
+ QWSPcMouseSubHandler(int f) : fd(f)
+ {
+ initState();
+ }
+ virtual ~QWSPcMouseSubHandler() {}
+
+ int file() const { return fd; }
+
+ void closeIfNot(int& f)
+ {
+ if (fd != f) {
+ f = fd;
+ close(fd);
+ }
+ }
+
+ void initState() { nbuf = bstate = goodness = badness = 0; }
+
+ void worse(int by=1) { badness+=by; }
+ bool reliable() const { return goodness >= 5 && badness < 50; }
+ int buttonState() const { return bstate; }
+ bool motionPending() const { return motion!=QPoint(0,0); }
+ QPoint takeMotion() { QPoint r=motion; motion=QPoint(0,0); return r; }
+ int takeWheel() { int result = wheel; wheel = 0; return result; }
+
+ void appendData(uchar* data, int length)
+ {
+ memcpy(buffer+nbuf, data, length);
+ nbuf += length;
+ }
+
+ enum UsageResult { Insufficient, Motion, Button };
+
+ UsageResult useData()
+ {
+ int pbstate = bstate;
+ int n = tryData();
+#ifdef QWS_MOUSE_DEBUG
+ if (n) {
+ fprintf(stderr, "QWSPcMouseSubHandler tryData read %d bytes:", n);
+ for (int i=0; i<n; ++i)
+ fprintf(stderr, " %02x", buffer[i]);
+ fprintf(stderr, "\n");
+ }
+#endif
+ if (n > 0) {
+ if (n<nbuf)
+ memmove(buffer, buffer+n, nbuf-n);
+ nbuf -= n;
+ return (wheel || pbstate != bstate) ? Button : Motion;
+ }
+ return Insufficient;
+ }
+};
+
+class QWSPcMouseSubHandler_intellimouse : public QWSPcMouseSubHandler {
+ int packetsize;
+public:
+ QWSPcMouseSubHandler_intellimouse(int f) : QWSPcMouseSubHandler(f)
+ {
+ init();
+ }
+
+ void init()
+ {
+ int n;
+ uchar reply[20];
+
+ if (tcflush(fd,TCIOFLUSH) == -1) {
+#ifdef QWS_MOUSE_DEBUG
+ perror("QWSPcMouseSubHandler_intellimouse: pre-init tcflush");
+#endif
+ }
+ static const uchar initseq[] = { 243, 200, 243, 100, 243, 80 };
+ static const uchar query[] = { 0xf2 };
+ if (write(fd, initseq, sizeof(initseq))!=sizeof(initseq)) {
+ badness = 100;
+ return;
+ }
+ usleep(10000);
+ if (tcflush(fd,TCIOFLUSH) == -1) {
+#ifdef QWS_MOUSE_DEBUG
+ perror("QWSPcMouseSubHandler_intellimouse: post-init tcflush");
+#endif
+ }
+ if (write(fd, query, sizeof(query))!=sizeof(query)) {
+ badness = 100;
+ return;
+ }
+ usleep(10000);
+ n = read(fd, reply, 20);
+ if (n > 0) {
+ goodness = 10;
+ switch (reply[n-1]) {
+ case 3:
+ case 4:
+ packetsize = 4;
+ break;
+ default:
+ packetsize = 3;
+ }
+ } else {
+ badness = 100;
+ }
+ }
+
+ int tryData()
+ {
+ if (nbuf >= packetsize) {
+ //int overflow = (buffer[0]>>6)& 0x03;
+
+ if (/*overflow ||*/ !(buffer[0] & 8)) {
+#ifdef QWS_MOUSE_DEBUG
+ qDebug("Intellimouse: skipping (overflow)");
+#endif
+ badness++;
+ return 1;
+ } else {
+ QPoint delta((buffer[0] & 0x10) ? buffer[1]-256 : buffer[1],
+ (buffer[0] & 0x20) ? 256-buffer[2] : -buffer[2]);
+ motion += delta;
+ int nbstate = buffer[0] & 0x7;
+#ifdef QWS_MOUSE_DEBUG
+ int debugwheel =
+#endif
+ wheel = packetsize > 3 ? -(signed char)buffer[3] : 0;
+ if (wheel < -2 || wheel > 2)
+ wheel = 0;
+ wheel *= 120; // WHEEL_DELTA?
+#ifdef QWS_MOUSE_DEBUG
+ qDebug("Intellimouse: motion %d,%d, state %d, raw wheel %d, wheel %d", motion.x(), motion.y(), nbstate, debugwheel, wheel);
+#endif
+ if (motion.x() || motion.y() || bstate != nbstate || wheel) {
+ bstate = nbstate;
+ goodness++;
+ } else {
+ badness++;
+ return 1;
+ }
+ }
+ return packetsize;
+ }
+ return 0;
+ }
+};
+
+class QWSPcMouseSubHandler_mouseman : public QWSPcMouseSubHandler {
+ int packetsize;
+public:
+ QWSPcMouseSubHandler_mouseman(int f) : QWSPcMouseSubHandler(f)
+ {
+ init();
+ }
+
+ void init()
+ {
+ if (tcflush(fd,TCIOFLUSH) == -1) {
+#ifdef QWS_MOUSE_DEBUG
+ perror("QWSPcMouseSubHandler_mouseman: initial tcflush");
+#endif
+ }
+ write(fd,"",1);
+ usleep(50000);
+ write(fd,"@EeI!",5);
+ usleep(10000);
+ static const char ibuf[] = { 246, 244 };
+ write(fd,ibuf,1);
+ write(fd,ibuf+1,1);
+ if (tcflush(fd,TCIOFLUSH) == -1) {
+#ifdef QWS_MOUSE_DEBUG
+ perror("QWSPcMouseSubHandler_mouseman: tcflush");
+#endif
+ }
+ usleep(10000);
+
+ char buf[100];
+ while (read(fd, buf, 100) > 0) { } // eat unwanted replies
+ }
+
+ int tryData()
+ {
+ if (nbuf >= 3) {
+ int nbstate = 0;
+ if (buffer[0] & 0x01)
+ nbstate |= Qt::LeftButton;
+ if (buffer[0] & 0x02)
+ nbstate |= Qt::RightButton;
+ if (buffer[0] & 0x04)
+ nbstate |= Qt::MidButton;
+
+ int overflow = (buffer[0]>>6)& 0x03;
+ if (overflow) {
+ //### wheel events signalled with overflow bit, ignore for now
+ badness++;
+ return 1;
+ } else {
+ bool xs = buffer[0] & 0x10;
+ bool ys = buffer[0] & 0x20;
+ int dx = xs ? buffer[1]-256 : buffer[1];
+ int dy = ys ? buffer[2]-256 : buffer[2];
+
+ motion += QPoint(dx, -dy);
+ if (motion.x() || motion.y() || bstate != nbstate) {
+ bstate = nbstate;
+ goodness++;
+ } else {
+ badness++;
+ return 1;
+ }
+ }
+ return 3;
+ }
+ return 0;
+ }
+};
+
+class QWSPcMouseSubHandler_serial : public QWSPcMouseSubHandler {
+public:
+ QWSPcMouseSubHandler_serial(int f) : QWSPcMouseSubHandler(f)
+ {
+ initSerial();
+ }
+
+protected:
+ void setflags(int f)
+ {
+ termios tty;
+ if (tcgetattr(fd, &tty) == -1) {
+#ifdef QWS_MOUSE_DEBUG
+ perror("QWSPcMouseSubHandler_serial: tcgetattr");
+#endif
+ }
+ tty.c_iflag = IGNBRK | IGNPAR;
+ tty.c_oflag = 0;
+ tty.c_lflag = 0;
+ tty.c_cflag = f | CREAD | CLOCAL | HUPCL;
+#if !defined(Q_OS_DARWIN) && !defined(Q_OS_SOLARIS) && !defined(Q_OS_INTEGRITY)
+ tty.c_line = 0;
+#endif
+ tty.c_cc[VTIME] = 0;
+ tty.c_cc[VMIN] = 1;
+ if (tcsetattr(fd, TCSANOW, &tty) == -1) {
+#ifdef QWS_MOUSE_DEBUG
+ perror("QWSPcMouseSubHandler_serial: tcgetattr");
+#endif
+ }
+ }
+
+private:
+ void initSerial()
+ {
+ int speed[4] = { B9600, B4800, B2400, B1200 };
+
+ for (int n = 0; n < 4; n++) {
+ setflags(CSTOPB | speed[n]);
+ write(fd, "*q", 2);
+ usleep(10000);
+ }
+ }
+};
+
+class QWSPcMouseSubHandler_mousesystems : public QWSPcMouseSubHandler_serial {
+public:
+ // ##### This driver has not been tested
+
+ QWSPcMouseSubHandler_mousesystems(int f) : QWSPcMouseSubHandler_serial(f)
+ {
+ init();
+ }
+
+ void init()
+ {
+ setflags(B1200|CS8|CSTOPB);
+ // 60Hz
+ if (write(fd, "R", 1)!=1) {
+ badness = 100;
+ return;
+ }
+ if (tcflush(fd,TCIOFLUSH) == -1) {
+#ifdef QT_QWS_VNC_DEBUG
+ perror("QWSPcMouseSubHandler_mousesystems: tcflush");
+#endif
+ }
+ }
+
+ int tryData()
+ {
+ if (nbuf >= 5) {
+ if ((buffer[0] & 0xf8) != 0x80) {
+ badness++;
+ return 1;
+ }
+ motion +=
+ QPoint((signed char)buffer[1] + (signed char)buffer[3],
+ -(signed char)buffer[2] + (signed char)buffer[4]);
+ int t = ~buffer[0];
+ int nbstate = ((t&3) << 1) | ((t&4) >> 2);
+ if (motion.x() || motion.y() || bstate != nbstate) {
+ bstate = nbstate;
+ goodness++;
+ } else {
+ badness++;
+ return 1;
+ }
+ return 5;
+ }
+ return 0;
+ }
+};
+
+class QWSPcMouseSubHandler_ms : public QWSPcMouseSubHandler_serial {
+ int mman;
+public:
+ QWSPcMouseSubHandler_ms(int f) : QWSPcMouseSubHandler_serial(f)
+ {
+ mman=0;
+ init();
+ }
+
+ void init()
+ {
+ setflags(B1200|CS7);
+ // 60Hz
+ if (write(fd, "R", 1)!=1) {
+ badness = 100;
+ return;
+ }
+ if (tcflush(fd,TCIOFLUSH) == -1) {
+#ifdef QWS_MOUSE_DEBUG
+ perror("QWSPcMouseSubHandler_ms: tcflush");
+#endif
+ }
+ }
+
+ int tryData()
+ {
+ if (!(buffer[0] & 0x40)) {
+ if (buffer[0] == 0x20 && (bstate & Qt::MidButton)) {
+ mman=1; // mouseman extension
+ }
+ return 1;
+ }
+ int extra = mman&&(bstate & Qt::MidButton);
+ if (nbuf >= 3+extra) {
+ int nbstate = 0;
+ if (buffer[0] == 0x40 && !bstate && !buffer[1] && !buffer[2]) {
+ nbstate = Qt::MidButton;
+ } else {
+ nbstate = ((buffer[0] & 0x20) >> 5)
+ | ((buffer[0] & 0x10) >> 3);
+ if (extra && buffer[3] == 0x20)
+ nbstate = Qt::MidButton;
+ }
+
+ if (buffer[1] & 0x40) {
+ badness++;
+ return 1;
+ } else {
+ motion +=
+ QPoint((signed char)((buffer[0]&0x3)<<6)
+ |(signed char)(buffer[1]&0x3f),
+ (signed char)((buffer[0]&0xc)<<4)
+ |(signed char)(buffer[2]&0x3f));
+ if (motion.x() || motion.y() || bstate != nbstate) {
+ bstate = nbstate;
+ goodness++;
+ } else {
+ badness++;
+ return 1;
+ }
+ return 3+extra;
+ }
+ }
+ return 0;
+ }
+};
+
+//===========================================================================
+
+class QWSPcMouseHandlerPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QWSPcMouseHandlerPrivate(QWSPcMouseHandler *h, const QString &, const QString &);
+ ~QWSPcMouseHandlerPrivate();
+
+ void suspend();
+ void resume();
+
+private:
+ enum { max_dev=32 };
+ QWSPcMouseSubHandler *sub[max_dev];
+ QList<QSocketNotifier*> notifiers;
+ int nsub;
+ int retries;
+
+private slots:
+ void readMouseData(int);
+
+private:
+ void openDevices();
+ void closeDevices();
+ void notify(int fd);
+ bool sendEvent(QWSPcMouseSubHandler& h);
+
+private:
+ QWSPcMouseHandler *handler;
+ QString driver;
+ QString device;
+ qreal accel;
+ int accel_limit;
+};
+
+QWSPcMouseHandler::QWSPcMouseHandler(const QString &driver, const QString &device)
+ : QWSMouseHandler(driver, device)
+{
+ d = new QWSPcMouseHandlerPrivate(this, driver, device);
+}
+
+QWSPcMouseHandler::~QWSPcMouseHandler()
+{
+ delete d;
+}
+
+void QWSPcMouseHandler::suspend()
+{
+ d->suspend();
+}
+
+void QWSPcMouseHandler::resume()
+{
+ d->resume();
+}
+
+
+QWSPcMouseHandlerPrivate::QWSPcMouseHandlerPrivate(QWSPcMouseHandler *h,
+ const QString &drv, const QString &arg)
+ : handler(h), driver(drv)
+{
+ QStringList args = arg.split(QLatin1Char(':'), QString::SkipEmptyParts);
+
+ int index;
+
+ accel = qreal(2.0);
+ QRegExp accelRegex(QLatin1String("^accel=(\\d+\\.?\\d*)$"));
+ index = args.indexOf(accelRegex);
+ if (index >= 0) {
+ accel = qreal(accelRegex.cap(1).toDouble());
+ args.removeAt(index);
+ }
+
+ accel_limit = 5;
+ QRegExp accelLimitRegex(QLatin1String("^accel_limit=(\\d+)$"));
+ index = args.indexOf(accelLimitRegex);
+ if (index >= 0) {
+ accel_limit = accelLimitRegex.cap(1).toInt();
+ args.removeAt(index);
+ }
+
+ device = args.join(QString());
+
+ retries = 0;
+ openDevices();
+}
+
+QWSPcMouseHandlerPrivate::~QWSPcMouseHandlerPrivate()
+{
+ closeDevices();
+}
+
+/*
+QWSPcMouseHandler::UsageResult QWSPcMouseHandler::useDev(Dev& d)
+{
+ if (d.nbuf >= mouseData[d.protocol].bytesPerPacket) {
+ uchar *mb = d.buf;
+ int bstate = 0;
+ int dx = 0;
+ int dy = 0;
+
+ switch (mouseProtocol) {
+ case MouseMan:
+ case IntelliMouse:
+ {
+ bstate = mb[0] & 0x7; // assuming Qt::*Button order
+
+ int overflow = (mb[0]>>6)& 0x03;
+ if (mouseProtocol == MouseMan && overflow) {
+ //### wheel events signalled with overflow bit, ignore for now
+ }
+ else {
+ bool xs = mb[0] & 0x10;
+ bool ys = mb[0] & 0x20;
+ dx = xs ? mb[1]-256 : mb[1];
+ dy = ys ? mb[2]-256 : mb[2];
+ }
+ break;
+ }
+ case Microsoft:
+ if (((mb[0] & 0x20) >> 3)) {
+ bstate |= Qt::LeftButton;
+ }
+ if (((mb[0] & 0x10) >> 4)) {
+ bstate |= Qt::RightButton;
+ }
+
+ dx=(signed char)(((mb[0] & 0x03) << 6) | (mb[1] & 0x3f));
+ dy=-(signed char)(((mb[0] & 0x0c) << 4) | (mb[2] & 0x3f));
+
+ break;
+ }
+ }
+ }
+*/
+
+
+bool QWSPcMouseHandlerPrivate::sendEvent(QWSPcMouseSubHandler& h)
+{
+ if (h.reliable()) {
+ QPoint motion = h.takeMotion();
+ if (qAbs(motion.x()) > accel_limit || qAbs(motion.y()) > accel_limit)
+ motion *= accel;
+ QPoint newPos = handler->pos() + motion;
+ if (qt_screen->isTransformed()) {
+ QSize s = QSize(qt_screen->width(), qt_screen->height());
+ newPos = qt_screen->mapToDevice(newPos, s);
+ }
+ handler->limitToScreen(newPos);
+
+ handler->mouseChanged(newPos, h.buttonState(), h.takeWheel());
+ return true;
+ } else {
+ h.takeMotion();
+ if (h.buttonState() & (Qt::RightButton|Qt::MidButton)) {
+ // Strange for the user to press right or middle without
+ // a moving mouse!
+ h.worse();
+ }
+ return false;
+ }
+}
+
+void QWSPcMouseHandlerPrivate::openDevices()
+{
+ nsub=0;
+ int fd = -1;
+
+ QString drv = driver.toLower();
+ if (!drv.isEmpty() && drv != QLatin1String("auto")) {
+ // Manually specified mouse
+ QByteArray dev = device.toLatin1();
+ if (drv == QLatin1String("intellimouse")) {
+ if (dev.isEmpty())
+ dev = "/dev/psaux";
+ fd = open(dev, O_RDWR | O_NDELAY);
+ if (fd >= 0)
+ sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd);
+ } else if (drv == QLatin1String("microsoft")) {
+ if (dev.isEmpty())
+ dev = "/dev/ttyS0";
+ fd = open(dev, O_RDWR | O_NDELAY);
+ if (fd >= 0)
+ sub[nsub++] = new QWSPcMouseSubHandler_ms(fd);
+ } else if (drv == QLatin1String("mousesystems")) {
+ if (dev.isEmpty())
+ dev = "/dev/ttyS0";
+ fd = open(dev, O_RDWR | O_NDELAY);
+ if (fd >= 0)
+ sub[nsub++] = new QWSPcMouseSubHandler_mousesystems(fd);
+ } else if (drv == QLatin1String("mouseman")) {
+ if (dev.isEmpty())
+ dev = "/dev/psaux";
+ fd = open(dev, O_RDWR | O_NDELAY);
+ if (fd >= 0)
+ sub[nsub++] = new QWSPcMouseSubHandler_mouseman(fd);
+ }
+ if (fd >= 0)
+ notify(fd);
+ else
+ qCritical("Error opening mouse device '%s': %s",
+ dev.constData(), strerror(errno));
+ } else {
+ // Try automatically
+ fd = open("/dev/psaux", O_RDWR | O_NDELAY);
+ if (fd >= 0) {
+ sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd);
+ notify(fd);
+ }
+ fd = open("/dev/input/mice", O_RDWR | O_NDELAY);
+ if (fd >= 0) {
+ sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd);
+ notify(fd);
+ //qDebug("/dev/input/mice fd %d #%d", fd, nsub-1);
+ }
+
+// include the code below to auto-detect serial mice, and to mess up
+// any sort of serial communication
+#if 0
+ const char fn[4][11] = { "/dev/ttyS0", "/dev/ttyS1", "/dev/ttyS2", "/dev/ttyS3" };
+ for (int ch = 0; ch < 4; ++ch) {
+ fd = open(fn[ch], O_RDWR | O_NDELAY);
+ if (fd >= 0) {
+ //sub[nsub++] = new QWSPcMouseSubHandler_intellimouse(fd);
+ sub[nsub++] = new QWSPcMouseSubHandler_mousesystems(fd);
+ sub[nsub++] = new QWSPcMouseSubHandler_ms(fd);
+ notify(fd);
+ }
+ }
+#endif
+ }
+}
+
+void QWSPcMouseHandlerPrivate::closeDevices()
+{
+ int pfd=-1;
+ for (int i=0; i<nsub; i++) {
+ sub[i]->closeIfNot(pfd);
+ delete sub[i];
+ }
+ qDeleteAll(notifiers);
+ notifiers.clear();
+}
+
+void QWSPcMouseHandlerPrivate::suspend()
+{
+ for (int i=0; i<notifiers.size(); ++i)
+ notifiers.at(i)->setEnabled(false);
+}
+
+void QWSPcMouseHandlerPrivate::resume()
+{
+ for (int i=0; i<nsub; i++)
+ sub[i]->initState();
+
+ for (int i=0; i<notifiers.size(); ++i)
+ notifiers.at(i)->setEnabled(true);
+}
+
+
+
+void QWSPcMouseHandlerPrivate::notify(int fd)
+{
+ QSocketNotifier *mouseNotifier
+ = new QSocketNotifier(fd, QSocketNotifier::Read, this);
+ connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData(int)));
+ notifiers.append(mouseNotifier);
+}
+
+void QWSPcMouseHandlerPrivate::readMouseData(int fd)
+{
+ for (;;) {
+ uchar buf[8];
+ int n = read(fd, buf, 8);
+ if (n<=0)
+ break;
+ for (int i=0; i<nsub; i++) {
+ QWSPcMouseSubHandler& h = *sub[i];
+ if (h.file() == fd) {
+ h.appendData(buf,n);
+ for (;;) {
+ switch (h.useData()) {
+ case QWSPcMouseSubHandler::Button:
+ sendEvent(h);
+ break;
+ case QWSPcMouseSubHandler::Insufficient:
+ goto breakbreak;
+ case QWSPcMouseSubHandler::Motion:
+ break;
+ }
+ }
+ breakbreak:
+ ;
+ }
+ }
+ }
+ bool any_reliable=false;
+ for (int i=0; i<nsub; i++) {
+ QWSPcMouseSubHandler& h = *sub[i];
+ if (h.motionPending())
+ sendEvent(h);
+ any_reliable = any_reliable || h.reliable();
+ }
+ if (any_reliable) {
+ // ... get rid of all unreliable ones? All bad ones?
+ } else if (retries < 2) {
+ // Try again - maybe the mouse was being moved when we tried to init.
+ closeDevices();
+ openDevices();
+ retries++;
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "qmousepc_qws.moc"
+
+#endif // QT_NO_MOUSE_PC
diff --git a/src/gui/embedded/qmousepc_qws.h b/src/gui/embedded/qmousepc_qws.h
new file mode 100644
index 0000000000..6a088780ca
--- /dev/null
+++ b/src/gui/embedded/qmousepc_qws.h
@@ -0,0 +1,76 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOUSEPC_QWS_H
+#define QMOUSEPC_QWS_H
+
+#include <QtGui/qmouse_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_MOUSE_PC
+
+class QWSPcMouseHandlerPrivate;
+
+class QWSPcMouseHandler : public QWSMouseHandler
+{
+public:
+ explicit QWSPcMouseHandler(const QString & = QString(),
+ const QString & = QString());
+ ~QWSPcMouseHandler();
+
+ void suspend();
+ void resume();
+protected:
+ QWSPcMouseHandlerPrivate *d;
+};
+
+#endif // QT_NO_QWS_MOUSE_PC
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMOUSEPC_QWS_H
diff --git a/src/gui/embedded/qmousetslib_qws.cpp b/src/gui/embedded/qmousetslib_qws.cpp
new file mode 100644
index 0000000000..8edbc62245
--- /dev/null
+++ b/src/gui/embedded/qmousetslib_qws.cpp
@@ -0,0 +1,371 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmousetslib_qws.h"
+
+#if !defined(QT_NO_QWS_MOUSE_TSLIB) || defined(QT_PLUGIN)
+
+#include <QtCore/qregexp.h>
+#include <QtCore/qstringlist.h>
+#include "qsocketnotifier.h"
+#include "qscreen_qws.h"
+
+#include <tslib.h>
+#include <errno.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef TSLIBMOUSEHANDLER_DEBUG
+# include <QtCore/QDebug>
+#endif
+
+/*!
+ \internal
+
+ \class QWSTslibMouseHandler
+ \ingroup qws
+
+ \brief The QWSTslibMouseHandler class implements a mouse driver
+ for the Universal Touch Screen Library, tslib.
+
+ QWSTslibMouseHandler inherits the QWSCalibratedMouseHandler class,
+ providing calibration and noise reduction functionality in
+ addition to generating mouse events, for devices using the
+ Universal Touch Screen Library.
+
+ To be able to compile this mouse handler, \l{Qt for Embedded Linux}
+ must be configured with the \c -qt-mouse-tslib option, see the
+ \l{Pointer Handling} documentation for details. In addition, the tslib
+ headers and library must be present in the build environment. The
+ tslib sources can be downloaded from \l
+ {http://tslib.berlios.de/}. Use the \c -L and \c -I options
+ with \c configure to explicitly specify the location of the
+ library and its headers:
+
+ \snippet doc/src/snippets/code/src_gui_embedded_qmousetslib_qws.cpp 0
+
+ In order to use this mouse handler, tslib must also be correctly
+ installed on the target machine. This includes providing a \c
+ ts.conf configuration file and setting the necessary environment
+ variables, see the README file provided with tslib for details.
+
+ The ts.conf file will usually contain the following two lines
+
+ \snippet doc/src/snippets/code/src_gui_embedded_qmousetslib_qws.cpp 1
+
+ To make \l{Qt for Embedded Linux} explicitly choose the tslib mouse
+ handler, set the QWS_MOUSE_PROTO environment variable.
+
+ \sa {Pointer Handling}, {Qt for Embedded Linux}
+*/
+
+class QWSTslibMouseHandlerPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QWSTslibMouseHandlerPrivate(QWSTslibMouseHandler *h,
+ const QString &device);
+ ~QWSTslibMouseHandlerPrivate();
+
+ void suspend();
+ void resume();
+
+ void calibrate(const QWSPointerCalibrationData *data);
+ void clearCalibration();
+
+private:
+ QWSTslibMouseHandler *handler;
+ struct tsdev *dev;
+ QSocketNotifier *mouseNotifier;
+ int jitter_limit;
+
+ struct ts_sample lastSample;
+ bool wasPressed;
+ int lastdx;
+ int lastdy;
+
+ bool calibrated;
+ QString devName;
+
+ bool open();
+ void close();
+ inline bool get_sample(struct ts_sample *sample);
+
+private slots:
+ void readMouseData();
+};
+
+QWSTslibMouseHandlerPrivate::QWSTslibMouseHandlerPrivate(QWSTslibMouseHandler *h,
+ const QString &device)
+ : handler(h), dev(0), mouseNotifier(0), jitter_limit(3)
+{
+ QStringList args = device.split(QLatin1Char(':'), QString::SkipEmptyParts);
+ QRegExp jitterRegex(QLatin1String("^jitter_limit=(\\d+)$"));
+ int index = args.indexOf(jitterRegex);
+ if (index >= 0) {
+ jitter_limit = jitterRegex.cap(1).toInt();
+ args.removeAt(index);
+ }
+
+ devName = args.join(QString());
+
+ if (devName.isNull()) {
+ const char *str = getenv("TSLIB_TSDEVICE");
+ if (str)
+ devName = QString::fromLocal8Bit(str);
+ }
+
+ if (devName.isNull())
+ devName = QLatin1String("/dev/ts");
+
+ if (!open())
+ return;
+
+ calibrated = true;
+
+ int fd = ts_fd(dev);
+ mouseNotifier = new QSocketNotifier(fd, QSocketNotifier::Read, this);
+ connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));
+ resume();
+}
+
+QWSTslibMouseHandlerPrivate::~QWSTslibMouseHandlerPrivate()
+{
+ close();
+}
+
+bool QWSTslibMouseHandlerPrivate::open()
+{
+ dev = ts_open(devName.toLocal8Bit().constData(), 1);
+ if (!dev) {
+ qCritical("QWSTslibMouseHandlerPrivate: ts_open() failed"
+ " with error: '%s'", strerror(errno));
+ qCritical("Please check your tslib installation!");
+ return false;
+ }
+
+ if (ts_config(dev)) {
+ qCritical("QWSTslibMouseHandlerPrivate: ts_config() failed"
+ " with error: '%s'", strerror(errno));
+ qCritical("Please check your tslib installation!");
+ close();
+ return false;
+ }
+
+ return true;
+}
+
+void QWSTslibMouseHandlerPrivate::close()
+{
+ if (dev)
+ ts_close(dev);
+}
+
+void QWSTslibMouseHandlerPrivate::suspend()
+{
+ if (mouseNotifier)
+ mouseNotifier->setEnabled(false);
+}
+
+void QWSTslibMouseHandlerPrivate::resume()
+{
+ memset(&lastSample, 0, sizeof(lastSample));
+ wasPressed = false;
+ lastdx = 0;
+ lastdy = 0;
+ if (mouseNotifier)
+ mouseNotifier->setEnabled(true);
+}
+
+bool QWSTslibMouseHandlerPrivate::get_sample(struct ts_sample *sample)
+{
+ if (!calibrated)
+ return (ts_read_raw(dev, sample, 1) == 1);
+
+ return (ts_read(dev, sample, 1) == 1);
+}
+
+void QWSTslibMouseHandlerPrivate::readMouseData()
+{
+ if (!qt_screen)
+ return;
+
+ for(;;) {
+ struct ts_sample sample = lastSample;
+ bool pressed = wasPressed;
+
+ // Fast return if there's no events.
+ if (!get_sample(&sample))
+ return;
+ pressed = (sample.pressure > 0);
+
+ // Only return last sample unless there's a press/release event.
+ while (pressed == wasPressed) {
+ if (!get_sample(&sample))
+ break;
+ pressed = (sample.pressure > 0);
+ }
+
+ // work around missing coordinates on mouse release in raw mode
+ if (!calibrated && !pressed && sample.x == 0 && sample.y == 0) {
+ sample.x = lastSample.x;
+ sample.y = lastSample.y;
+ }
+
+ int dx = sample.x - lastSample.x;
+ int dy = sample.y - lastSample.y;
+
+ // Remove small movements in oppsite direction
+ if (dx * lastdx < 0 && qAbs(dx) < jitter_limit) {
+ sample.x = lastSample.x;
+ dx = 0;
+ }
+ if (dy * lastdy < 0 && qAbs(dy) < jitter_limit) {
+ sample.y = lastSample.y;
+ dy = 0;
+ }
+
+ if (wasPressed == pressed && dx == 0 && dy == 0)
+ return;
+
+#ifdef TSLIBMOUSEHANDLER_DEBUG
+ qDebug() << "last" << QPoint(lastSample.x, lastSample.y)
+ << "curr" << QPoint(sample.x, sample.y)
+ << "dx,dy" << QPoint(dx, dy)
+ << "ddx,ddy" << QPoint(dx*lastdx, dy*lastdy)
+ << "pressed" << wasPressed << pressed;
+#endif
+
+ lastSample = sample;
+ wasPressed = pressed;
+ if (dx != 0)
+ lastdx = dx;
+ if (dy != 0)
+ lastdy = dy;
+
+ const QPoint p(sample.x, sample.y);
+ if (calibrated) {
+ // tslib should do all the translation and filtering, so we send a
+ // "raw" mouse event
+ handler->QWSMouseHandler::mouseChanged(p, pressed);
+ } else {
+ handler->sendFiltered(p, pressed);
+ }
+ }
+}
+
+void QWSTslibMouseHandlerPrivate::clearCalibration()
+{
+ suspend();
+ close();
+ handler->QWSCalibratedMouseHandler::clearCalibration();
+ calibrated = false;
+ open();
+ resume();
+}
+
+void QWSTslibMouseHandlerPrivate::calibrate(const QWSPointerCalibrationData *data)
+{
+ suspend();
+ close();
+ // default implementation writes to /etc/pointercal
+ // using the same format as the tslib linear module.
+ handler->QWSCalibratedMouseHandler::calibrate(data);
+ calibrated = true;
+ open();
+ resume();
+}
+
+/*!
+ \internal
+*/
+QWSTslibMouseHandler::QWSTslibMouseHandler(const QString &driver,
+ const QString &device)
+ : QWSCalibratedMouseHandler(driver, device)
+{
+ d = new QWSTslibMouseHandlerPrivate(this, device);
+}
+
+/*!
+ \internal
+*/
+QWSTslibMouseHandler::~QWSTslibMouseHandler()
+{
+ delete d;
+}
+
+/*!
+ \reimp
+*/
+void QWSTslibMouseHandler::suspend()
+{
+ d->suspend();
+}
+
+/*!
+ \reimp
+*/
+void QWSTslibMouseHandler::resume()
+{
+ d->resume();
+}
+
+/*!
+ \reimp
+*/
+void QWSTslibMouseHandler::clearCalibration()
+{
+ d->clearCalibration();
+}
+
+/*!
+ \reimp
+*/
+void QWSTslibMouseHandler::calibrate(const QWSPointerCalibrationData *data)
+{
+ d->calibrate(data);
+}
+
+QT_END_NAMESPACE
+
+#include "qmousetslib_qws.moc"
+
+#endif //QT_NO_QWS_MOUSE_TSLIB
diff --git a/src/gui/embedded/qmousetslib_qws.h b/src/gui/embedded/qmousetslib_qws.h
new file mode 100644
index 0000000000..07bacde31f
--- /dev/null
+++ b/src/gui/embedded/qmousetslib_qws.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOUSETSLIB_QWS_H
+#define QMOUSETSLIB_QWS_H
+
+#include <QtGui/qmouse_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if !defined(QT_NO_QWS_MOUSE_TSLIB) || defined(QT_PLUGIN)
+
+class QWSTslibMouseHandlerPrivate;
+
+class QWSTslibMouseHandler : public QWSCalibratedMouseHandler
+{
+public:
+ explicit QWSTslibMouseHandler(const QString &driver = QString(),
+ const QString &device = QString());
+ ~QWSTslibMouseHandler();
+
+ void suspend();
+ void resume();
+
+ void calibrate(const QWSPointerCalibrationData *data);
+ void clearCalibration();
+
+protected:
+ friend class QWSTslibMouseHandlerPrivate;
+ QWSTslibMouseHandlerPrivate *d;
+};
+
+
+QT_END_NAMESPACE
+#endif // QT_NO_QWS_MOUSE_TSLIB
+QT_END_HEADER
+
+#endif // QMOUSETSLIB_QWS_H
diff --git a/src/gui/embedded/qmousevfb_qws.cpp b/src/gui/embedded/qmousevfb_qws.cpp
new file mode 100644
index 0000000000..9d81201f70
--- /dev/null
+++ b/src/gui/embedded/qmousevfb_qws.cpp
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_NO_QWS_MOUSE_QVFB
+
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+
+#include <qvfbhdr.h>
+#include <qmousevfb_qws.h>
+#include <qwindowsystem_qws.h>
+#include <qsocketnotifier.h>
+#include <qapplication.h>
+#include <qtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+QVFbMouseHandler::QVFbMouseHandler(const QString &driver, const QString &device)
+ : QObject(), QWSMouseHandler(driver, device)
+{
+ QString mouseDev = device;
+ if (device.isEmpty())
+ mouseDev = QLatin1String("/dev/vmouse");
+
+ mouseFD = 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 (read(mouseFD, buf, 1) > 0) { }
+
+ mouseIdx = 0;
+
+ mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read, this);
+ connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));
+}
+
+QVFbMouseHandler::~QVFbMouseHandler()
+{
+ if (mouseFD >= 0)
+ close(mouseFD);
+}
+
+void QVFbMouseHandler::resume()
+{
+ mouseNotifier->setEnabled(true);
+}
+
+void QVFbMouseHandler::suspend()
+{
+ mouseNotifier->setEnabled(false);
+}
+
+void QVFbMouseHandler::readMouseData()
+{
+ int n;
+ do {
+ n = 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);
+// limitToScreen(mousePos);
+ mouseChanged(mousePos, bstate, wheel);
+ idx += packetsize;
+ }
+
+ int surplus = mouseIdx - idx;
+ for (int i = 0; i < surplus; i++)
+ mouseBuf[i] = mouseBuf[idx+i];
+ mouseIdx = surplus;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QWS_MOUSE_QVFB
diff --git a/src/gui/embedded/qmousevfb_qws.h b/src/gui/embedded/qmousevfb_qws.h
new file mode 100644
index 0000000000..fbf1efe817
--- /dev/null
+++ b/src/gui/embedded/qmousevfb_qws.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOUSEVFB_QWS_H
+#define QMOUSEVFB_QWS_H
+
+#include <QtGui/qmouse_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_MOUSE_QVFB
+
+class QSocketNotifier;
+
+class QVFbMouseHandler : public QObject, public QWSMouseHandler {
+ Q_OBJECT
+public:
+ QVFbMouseHandler(const QString &driver = QString(),
+ const QString &device = QString());
+ ~QVFbMouseHandler();
+
+ void resume();
+ void suspend();
+
+private:
+ int mouseFD;
+ int mouseIdx;
+ enum {mouseBufSize = 128};
+ uchar mouseBuf[mouseBufSize];
+ QSocketNotifier *mouseNotifier;
+
+private Q_SLOTS:
+ void readMouseData();
+};
+#endif // QT_NO_QWS_MOUSE_QVFB
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMOUSEVFB_QWS_H
diff --git a/src/gui/embedded/qmousevr41xx_qws.cpp b/src/gui/embedded/qmousevr41xx_qws.cpp
new file mode 100644
index 0000000000..b4828bf9ba
--- /dev/null
+++ b/src/gui/embedded/qmousevr41xx_qws.cpp
@@ -0,0 +1,250 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmousevr41xx_qws.h"
+
+#ifndef QT_NO_QWS_MOUSE_VR41XX
+#include "qwindowsystem_qws.h"
+#include "qsocketnotifier.h"
+#include "qtimer.h"
+#include "qapplication.h"
+#include "qscreen_qws.h"
+#include <qstringlist.h>
+#include <qvarlengtharray.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <termios.h>
+
+QT_BEGIN_NAMESPACE
+
+static const int defaultFilterSize = 3;
+
+class QWSVr41xxMouseHandlerPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QWSVr41xxMouseHandlerPrivate(QWSVr41xxMouseHandler *, const QString &, const QString &);
+ ~QWSVr41xxMouseHandlerPrivate();
+
+ void resume();
+ void suspend();
+
+private slots:
+ void sendRelease();
+ void readMouseData();
+
+private:
+ bool getSample();
+ ushort currSample[6];
+ uint currLength;
+
+ int mouseFD;
+ int mouseIdx;
+ QTimer *rtimer;
+ QSocketNotifier *mouseNotifier;
+ QWSVr41xxMouseHandler *handler;
+ QPoint lastPos;
+ bool isPressed;
+ int filterSize;
+ int pressLimit;
+};
+
+QWSVr41xxMouseHandler::QWSVr41xxMouseHandler(const QString &drv, const QString &dev)
+ : QWSCalibratedMouseHandler(drv, dev)
+{
+ d = new QWSVr41xxMouseHandlerPrivate(this, drv, dev);
+}
+
+QWSVr41xxMouseHandler::~QWSVr41xxMouseHandler()
+{
+ delete d;
+}
+
+void QWSVr41xxMouseHandler::resume()
+{
+ d->resume();
+}
+
+void QWSVr41xxMouseHandler::suspend()
+{
+ d->suspend();
+}
+
+QWSVr41xxMouseHandlerPrivate::QWSVr41xxMouseHandlerPrivate(QWSVr41xxMouseHandler *h, const QString &, const QString &device)
+ : currLength(0), handler(h)
+{
+ QStringList options = device.split(QLatin1String(":"));
+ int index = -1;
+
+ filterSize = defaultFilterSize;
+ QRegExp filterRegExp(QLatin1String("filter=(\\d+)"));
+ index = options.indexOf(filterRegExp);
+ if (index != -1) {
+ filterSize = qMax(1, filterRegExp.cap(1).toInt());
+ options.removeAt(index);
+ }
+ handler->setFilterSize(filterSize);
+
+ pressLimit = 750;
+ QRegExp pressRegExp(QLatin1String("press=(\\d+)"));
+ index = options.indexOf(pressRegExp);
+ if (index != -1) {
+ pressLimit = filterRegExp.cap(1).toInt();
+ options.removeAt(index);
+ }
+
+ QString dev;
+ if (options.isEmpty())
+ dev = QLatin1String("/dev/vrtpanel");
+ else
+ dev = options.first();
+
+ if ((mouseFD = open(dev.toLocal8Bit().constData(), O_RDONLY)) < 0) {
+ qWarning("Cannot open %s (%s)", qPrintable(dev), strerror(errno));
+ return;
+ }
+ sleep(1);
+
+ if (fcntl(mouseFD, F_SETFL, O_NONBLOCK) < 0) {
+ qWarning("Error initializing touch panel.");
+ return;
+ }
+
+ mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read, this);
+ connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));
+
+ rtimer = new QTimer(this);
+ rtimer->setSingleShot(true);
+ connect(rtimer, SIGNAL(timeout()), this, SLOT(sendRelease()));
+ mouseIdx = 0;
+}
+
+QWSVr41xxMouseHandlerPrivate::~QWSVr41xxMouseHandlerPrivate()
+{
+ if (mouseFD >= 0)
+ close(mouseFD);
+}
+
+void QWSVr41xxMouseHandlerPrivate::suspend()
+{
+ mouseNotifier->setEnabled(false);
+}
+
+
+void QWSVr41xxMouseHandlerPrivate::resume()
+{
+ mouseIdx = 0;
+ mouseNotifier->setEnabled(true);
+}
+
+void QWSVr41xxMouseHandlerPrivate::sendRelease()
+{
+ handler->sendFiltered(lastPos, Qt::NoButton);
+ isPressed = false;
+}
+
+bool QWSVr41xxMouseHandlerPrivate::getSample()
+{
+ const int n = read(mouseFD,
+ reinterpret_cast<uchar*>(currSample) + currLength,
+ sizeof(currSample) - currLength);
+
+ if (n > 0)
+ currLength += n;
+
+ if (currLength < sizeof(currSample))
+ return false;
+
+ currLength = 0;
+ return true;
+}
+
+void QWSVr41xxMouseHandlerPrivate::readMouseData()
+{
+ const int sampleLength = sizeof(currSample) / sizeof(ushort);
+ QVarLengthArray<ushort, sampleLength * defaultFilterSize> samples(sampleLength * filterSize);
+
+ // Only return last 'filterSize' samples
+ int head = 0;
+ int tail = 0;
+ int nSamples = 0;
+ while (getSample()) {
+ if (!(currSample[0] & 0x8000) || (currSample[5] < pressLimit))
+ continue;
+
+ ushort *data = samples.data() + head * sampleLength;
+ memcpy(data, currSample, sizeof(currSample));
+ ++nSamples;
+ head = (head + 1) % filterSize;
+ if (nSamples >= filterSize)
+ tail = (tail + 1) % filterSize;
+ }
+
+ if (nSamples == 0)
+ return;
+
+ // send mouse events
+ while (tail != head || filterSize == 1) {
+ const ushort *data = samples.data() + tail * sampleLength;
+ lastPos = QPoint(data[3] - data[4], data[2] - data[1]);
+ handler->sendFiltered(lastPos, Qt::LeftButton);
+ isPressed = true;
+ tail = (tail + 1) % filterSize;
+ if (filterSize == 1)
+ break;
+ }
+
+ if (isPressed)
+ rtimer->start(50); // release unreliable
+}
+
+QT_END_NAMESPACE
+
+#include "qmousevr41xx_qws.moc"
+
+#endif //QT_NO_QWS_MOUSE_VR41
diff --git a/src/gui/embedded/qmousevr41xx_qws.h b/src/gui/embedded/qmousevr41xx_qws.h
new file mode 100644
index 0000000000..ad21013903
--- /dev/null
+++ b/src/gui/embedded/qmousevr41xx_qws.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOUSEVR41XX_QWS_H
+#define QMOUSEVR41XX_QWS_H
+
+#include <QtGui/qmouse_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_MOUSE_VR41XX
+
+class QWSVr41xxMouseHandlerPrivate;
+
+class QWSVr41xxMouseHandler : public QWSCalibratedMouseHandler
+{
+public:
+ explicit QWSVr41xxMouseHandler(const QString & = QString(),
+ const QString & = QString());
+ ~QWSVr41xxMouseHandler();
+
+ void resume();
+ void suspend();
+
+protected:
+ QWSVr41xxMouseHandlerPrivate *d;
+
+private:
+ friend class QWSVr41xxMouseHandlerPrivate;
+};
+
+#endif // QT_NO_QWS_MOUSE_VR41XX
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMOUSEVR41XX_QWS_H
diff --git a/src/gui/embedded/qmouseyopy_qws.cpp b/src/gui/embedded/qmouseyopy_qws.cpp
new file mode 100644
index 0000000000..fcf5193f25
--- /dev/null
+++ b/src/gui/embedded/qmouseyopy_qws.cpp
@@ -0,0 +1,184 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qmouseyopy_qws.h"
+
+#ifndef QT_NO_QWS_MOUSE_YOPY
+#include "qwindowsystem_qws.h"
+#include "qsocketnotifier.h"
+#include "qapplication.h"
+#include "qscreen_qws.h"
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <termios.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWSYopyMouseHandlerPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QWSYopyMouseHandlerPrivate(QWSYopyMouseHandler *h);
+ ~QWSYopyMouseHandlerPrivate();
+
+ void suspend();
+ void resume();
+
+private slots:
+ void readMouseData();
+
+private:
+ int mouseFD;
+ int prevstate;
+ QSocketNotifier *mouseNotifier;
+ QWSYopyMouseHandler *handler;
+};
+
+QWSYopyMouseHandler::QWSYopyMouseHandler(const QString &driver, const QString &device)
+ : QWSMouseHandler(driver, device)
+{
+ d = new QWSYopyMouseHandlerPrivate(this);
+}
+
+QWSYopyMouseHandler::~QWSYopyMouseHandler()
+{
+ delete d;
+}
+
+void QWSYopyMouseHandler::resume()
+{
+ d->resume();
+}
+
+void QWSYopyMouseHandler::suspend()
+{
+ d->suspend();
+}
+
+QWSYopyMouseHandlerPrivate::QWSYopyMouseHandlerPrivate(QWSYopyMouseHandler *h)
+ : handler(h)
+{
+ if ((mouseFD = open("/dev/ts", O_RDONLY)) < 0) {
+ qWarning("Cannot open /dev/ts (%s)", strerror(errno));
+ return;
+ } else {
+ sleep(1);
+ }
+ prevstate=0;
+ mouseNotifier = new QSocketNotifier(mouseFD, QSocketNotifier::Read,
+ this);
+ connect(mouseNotifier, SIGNAL(activated(int)),this, SLOT(readMouseData()));
+}
+
+QWSYopyMouseHandlerPrivate::~QWSYopyMouseHandlerPrivate()
+{
+ if (mouseFD >= 0)
+ close(mouseFD);
+}
+
+#define YOPY_XPOS(d) (d[1]&0x3FF)
+#define YOPY_YPOS(d) (d[2]&0x3FF)
+#define YOPY_PRES(d) (d[0]&0xFF)
+#define YOPY_STAT(d) (d[3]&0x01)
+
+struct YopyTPdata {
+
+ unsigned char status;
+ unsigned short xpos;
+ unsigned short ypos;
+
+};
+
+void QWSYopyMouseHandlerPrivate::suspend()
+{
+ mouseNotifier->setEnabled(false);
+}
+
+
+void QWSYopyMouseHandlerPrivate::resume()
+{
+ prevstate = 0;
+ mouseNotifier->setEnabled(true);
+}
+
+void QWSYopyMouseHandlerPrivate::readMouseData()
+{
+ if(!qt_screen)
+ return;
+ YopyTPdata data;
+
+ unsigned int yopDat[4];
+
+ int ret;
+
+ ret=read(mouseFD,&yopDat,sizeof(yopDat));
+
+ if(ret) {
+ data.status= (YOPY_PRES(yopDat)) ? 1 : 0;
+ data.xpos=YOPY_XPOS(yopDat);
+ data.ypos=YOPY_YPOS(yopDat);
+ QPoint q;
+ q.setX(data.xpos);
+ q.setY(data.ypos);
+ if (data.status && !prevstate) {
+ handler->mouseChanged(q,Qt::LeftButton);
+ } else if(!data.status && prevstate) {
+ handler->mouseChanged(q,0);
+ }
+ prevstate = data.status;
+ }
+ if(ret<0) {
+ qDebug("Error %s",strerror(errno));
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "qmouseyopy_qws.moc"
+
+#endif //QT_NO_QWS_MOUSE_YOPY
diff --git a/src/gui/embedded/qmouseyopy_qws.h b/src/gui/embedded/qmouseyopy_qws.h
new file mode 100644
index 0000000000..0209f104f6
--- /dev/null
+++ b/src/gui/embedded/qmouseyopy_qws.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMOUSEYOPY_QWS_H
+#define QMOUSEYOPY_QWS_H
+
+#include <QtGui/qmouse_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_MOUSE_YOPY
+
+// YOPY touch panel support based on changes contributed by Ron Victorelli
+// (victorrj at icubed.com) to Custom TP driver.
+
+class QWSYopyMouseHandlerPrivate;
+
+class QWSYopyMouseHandler : public QWSMouseHandler
+{
+public:
+ explicit QWSYopyMouseHandler(const QString & = QString(),
+ const QString & = QString());
+ ~QWSYopyMouseHandler();
+
+ void resume();
+ void suspend();
+
+protected:
+ QWSYopyMouseHandlerPrivate *d;
+};
+
+#endif // QT_NO_QWS_MOUSE_YOPY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QMOUSEYOPY_QWS_H
diff --git a/src/gui/embedded/qscreen_qws.cpp b/src/gui/embedded/qscreen_qws.cpp
new file mode 100644
index 0000000000..6741f2cedc
--- /dev/null
+++ b/src/gui/embedded/qscreen_qws.cpp
@@ -0,0 +1,3317 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscreen_qws.h"
+
+#include "qcolormap.h"
+#include "qscreendriverfactory_qws.h"
+#include "qwindowsystem_qws.h"
+#include "qwidget.h"
+#include "qcolor.h"
+#include "qpixmap.h"
+#include "qvarlengtharray.h"
+#include "qwsdisplay_qws.h"
+#include <private/qdrawhelper_p.h>
+#include <private/qpaintengine_raster_p.h>
+#include <private/qpixmap_raster_p.h>
+#include <private/qwindowsurface_qws_p.h>
+#include <private/qpainter_p.h>
+#include <private/qwidget_p.h>
+#include <private/qgraphicssystem_qws_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// #define QT_USE_MEMCPY_DUFF
+
+#ifndef QT_NO_QWS_CURSOR
+bool qt_sw_cursor=false;
+Q_GUI_EXPORT QScreenCursor * qt_screencursor = 0;
+#endif
+Q_GUI_EXPORT QScreen * qt_screen = 0;
+
+ClearCacheFunc QScreen::clearCacheFunc = 0;
+
+#ifndef QT_NO_QWS_CURSOR
+/*!
+ \class QScreenCursor
+ \ingroup qws
+
+ \brief The QScreenCursor class is a base class for screen cursors
+ in Qt for Embedded Linux.
+
+ Note that this class is non-portable, and that it is only
+ available in \l{Qt for Embedded Linux}.
+
+ QScreenCursor implements a software cursor, but can be subclassed
+ to support hardware cursors as well. When deriving from the
+ QScreenCursor class it is important to maintain the cursor's
+ image, position, hot spot (the point within the cursor's image
+ that will be the position of the associated mouse events) and
+ visibility as well as informing whether it is hardware accelerated
+ or not.
+
+ Note that there may only be one screen cursor at a time. Use the
+ static instance() function to retrieve a pointer to the current
+ screen cursor. Typically, the cursor is constructed by the QScreen
+ class or one of its descendants when it is initializing the
+ device; the QScreenCursor class should never be instantiated
+ explicitly.
+
+ Use the move() function to change the position of the cursor, and
+ the set() function to alter its image or its hot spot. In
+ addition, you can find out whether the cursor is accelerated or
+ not, using the isAccelerated() function, and the boundingRect()
+ function returns the cursor's bounding rectangle.
+
+ The cursor's appearance can be controlled using the isVisible(),
+ hide() and show() functions; alternatively the QWSServer class
+ provides some means of controlling the cursor's appearance using
+ the QWSServer::isCursorVisible() and QWSServer::setCursorVisible()
+ functions.
+
+ \sa QScreen, QWSServer
+*/
+
+/*!
+ \fn static QScreenCursor* QScreenCursor::instance()
+ \since 4.2
+
+ Returns a pointer to the application's unique screen cursor.
+*/
+
+extern bool qws_sw_cursor;
+
+/*!
+ Constructs a screen cursor
+*/
+QScreenCursor::QScreenCursor()
+{
+ pos = QPoint(qt_screen->deviceWidth()/2, qt_screen->deviceHeight()/2);
+ size = QSize(0,0);
+ enable = true;
+ hwaccel = false;
+ supportsAlpha = true;
+}
+
+/*!
+ Destroys the screen cursor.
+*/
+QScreenCursor::~QScreenCursor()
+{
+}
+
+/*!
+ Hides the cursor from the screen.
+
+ \sa show()
+*/
+void QScreenCursor::hide()
+{
+ if (enable) {
+ enable = false;
+ if (!hwaccel)
+ qt_screen->exposeRegion(boundingRect(), 0);
+ }
+}
+
+/*!
+ Shows the mouse cursor.
+
+ \sa hide()
+*/
+void QScreenCursor::show()
+{
+ if (!enable) {
+ enable = true;
+ if (!hwaccel)
+ qt_screen->exposeRegion(boundingRect(), 0);
+ }
+}
+
+/*!
+ Sets the cursor's image to be the given \a image.
+
+ The \a hotx and \a hoty parameters define the cursor's hot spot,
+ i.e., the point within the cursor's image that will be the
+ position of the associated mouse events.
+
+ \sa move()
+*/
+void QScreenCursor::set(const QImage &image, int hotx, int hoty)
+{
+ const QRect r = boundingRect();
+
+ hotspot = QPoint(hotx, hoty);
+ cursor = image;
+ size = image.size();
+
+ if (enable && !hwaccel)
+ qt_screen->exposeRegion(r | boundingRect(), 0);
+}
+
+/*!
+ Moves the mouse cursor to the given position, i.e., (\a x, \a y).
+
+ Note that the given position defines the top-left corner of the
+ cursor's image, i.e., not the cursor's hot spot (the position of
+ the associated mouse events).
+
+ \sa set()
+*/
+void QScreenCursor::move(int x, int y)
+{
+ const QRegion r = boundingRect();
+ pos = QPoint(x,y);
+ if (enable && !hwaccel)
+ qt_screen->exposeRegion(r | boundingRect(), 0);
+}
+
+
+/*!
+ \fn void QScreenCursor::initSoftwareCursor ()
+
+ Initializes the screen cursor.
+
+ This function is typically called from the screen driver when
+ initializing the device. Alternatively, the cursor can be set
+ directly using the pointer returned by the static instance()
+ function.
+
+ \sa QScreen::initDevice()
+*/
+void QScreenCursor::initSoftwareCursor()
+{
+ qt_screencursor = new QScreenCursor;
+}
+
+
+#endif // QT_NO_QWS_CURSOR
+
+
+/*!
+ \fn QRect QScreenCursor::boundingRect () const
+
+ Returns the cursor's bounding rectangle.
+*/
+
+/*!
+ \internal
+ \fn bool QScreenCursor::enabled ()
+*/
+
+/*!
+ \fn QImage QScreenCursor::image () const
+
+ Returns the cursor's image.
+*/
+
+
+/*!
+ \fn bool QScreenCursor::isAccelerated () const
+
+ Returns true if the cursor is accelerated; otherwise false.
+*/
+
+/*!
+ \fn bool QScreenCursor::isVisible () const
+
+ Returns true if the cursor is visible; otherwise false.
+*/
+
+/*!
+ \internal
+ \fn bool QScreenCursor::supportsAlphaCursor () const
+*/
+
+/*
+ \variable QScreenCursor::cursor
+
+ \brief the cursor's image.
+
+ \sa image()
+*/
+
+/*
+ \variable QScreenCursor::size
+
+ \brief the cursor's size
+*/
+
+/*
+ \variable QScreenCursor::pos
+
+ \brief the cursor's position, i.e., the position of the top-left
+ corner of the crsor's image
+
+ \sa set(), move()
+*/
+
+/*
+ \variable QScreenCursor::hotspot
+
+ \brief the cursor's hotspot, i.e., the point within the cursor's
+ image that will be the position of the associated mouse events.
+
+ \sa set(), move()
+*/
+
+/*
+ \variable QScreenCursor::enable
+
+ \brief whether the cursor is visible or not
+
+ \sa isVisible()
+*/
+
+/*
+ \variable QScreenCursor::hwaccel
+
+ \brief holds whether the cursor is accelerated or not
+
+ If the cursor is not accelerated, its image will be included by
+ the screen when it composites the window surfaces.
+
+ \sa isAccelerated()
+
+*/
+
+/*
+ \variable QScreenCursor::supportsAlpha
+*/
+
+/*!
+ \internal
+ \macro qt_screencursor
+ \relates QScreenCursor
+
+ A global pointer referring to the unique screen cursor. It is
+ equivalent to the pointer returned by the
+ QScreenCursor::instance() function.
+*/
+
+
+
+class QScreenPrivate
+{
+public:
+ QScreenPrivate(QScreen *parent, QScreen::ClassId id = QScreen::CustomClass);
+ ~QScreenPrivate();
+
+ inline QImage::Format preferredImageFormat() const;
+
+ typedef void (*SolidFillFunc)(QScreen*, const QColor&, const QRegion&);
+ typedef void (*BlitFunc)(QScreen*, const QImage&, const QPoint&, const QRegion&);
+
+ SolidFillFunc solidFill;
+ BlitFunc blit;
+
+ QPoint offset;
+ QList<QScreen*> subScreens;
+ QPixmapDataFactory* pixmapFactory;
+ QGraphicsSystem* graphicsSystem;
+ QWSGraphicsSystem defaultGraphicsSystem; //###
+ QImage::Format pixelFormat;
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ bool fb_is_littleEndian;
+#endif
+#ifdef QT_QWS_CLIENTBLIT
+ bool supportsBlitInClients;
+#endif
+ int classId;
+ QScreen *q_ptr;
+};
+
+template <typename T>
+static void solidFill_template(QScreen *screen, const QColor &color,
+ const QRegion &region)
+{
+ T *dest = reinterpret_cast<T*>(screen->base());
+ const T c = qt_colorConvert<T, quint32>(color.rgba(), 0);
+ const int stride = screen->linestep();
+ const QVector<QRect> rects = region.rects();
+
+ for (int i = 0; i < rects.size(); ++i) {
+ const QRect r = rects.at(i);
+ qt_rectfill(dest, c, r.x(), r.y(), r.width(), r.height(), stride);
+ }
+}
+
+#ifdef QT_QWS_DEPTH_GENERIC
+static void solidFill_rgb_32bpp(QScreen *screen, const QColor &color,
+ const QRegion &region)
+{
+ quint32 *dest = reinterpret_cast<quint32*>(screen->base());
+ const quint32 c = qt_convertToRgb<quint32>(color.rgba());
+
+ const int stride = screen->linestep();
+ const QVector<QRect> rects = region.rects();
+
+ for (int i = 0; i < rects.size(); ++i) {
+ const QRect r = rects.at(i);
+ qt_rectfill(dest, c, r.x(), r.y(), r.width(), r.height(), stride);
+ }
+}
+
+static void solidFill_rgb_16bpp(QScreen *screen, const QColor &color,
+ const QRegion &region)
+{
+ quint16 *dest = reinterpret_cast<quint16*>(screen->base());
+ const quint16 c = qt_convertToRgb<quint32>(color.rgba());
+
+ const int stride = screen->linestep();
+ const QVector<QRect> rects = region.rects();
+
+ for (int i = 0; i < rects.size(); ++i) {
+ const QRect r = rects.at(i);
+ qt_rectfill(dest, c, r.x(), r.y(), r.width(), r.height(), stride);
+ }
+}
+#endif // QT_QWS_DEPTH_GENERIC
+
+#ifdef QT_QWS_DEPTH_4
+static inline void qt_rectfill_gray4(quint8 *dest, quint8 value,
+ int x, int y, int width, int height,
+ int stride)
+{
+ const int pixelsPerByte = 2;
+ dest += y * stride + x / pixelsPerByte;
+ const int doAlign = x & 1;
+ const int doTail = (width - doAlign) & 1;
+ const int width8 = (width - doAlign) / pixelsPerByte;
+
+ for (int j = 0; j < height; ++j) {
+ if (doAlign)
+ *dest = (*dest & 0xf0) | (value & 0x0f);
+ if (width8)
+ qt_memfill<quint8>(dest + doAlign, value, width8);
+ if (doTail) {
+ quint8 *d = dest + doAlign + width8;
+ *d = (*d & 0x0f) | (value & 0xf0);
+ }
+ dest += stride;
+ }
+}
+
+static void solidFill_gray4(QScreen *screen, const QColor &color,
+ const QRegion &region)
+{
+ quint8 *dest = reinterpret_cast<quint8*>(screen->base());
+ const quint8 c = qGray(color.rgba()) >> 4;
+ const quint8 c8 = (c << 4) | c;
+
+ const int stride = screen->linestep();
+ const QVector<QRect> rects = region.rects();
+
+ for (int i = 0; i < rects.size(); ++i) {
+ const QRect r = rects.at(i);
+ qt_rectfill_gray4(dest, c8, r.x(), r.y(), r.width(), r.height(),
+ stride);
+ }
+}
+#endif // QT_QWS_DEPTH_4
+
+#ifdef QT_QWS_DEPTH_1
+static inline void qt_rectfill_mono(quint8 *dest, quint8 value,
+ int x, int y, int width, int height,
+ int stride)
+{
+ const int pixelsPerByte = 8;
+ const int alignWidth = qMin(width, (8 - (x & 7)) & 7);
+ const int doAlign = (alignWidth > 0 ? 1 : 0);
+ const int alignStart = pixelsPerByte - 1 - (x & 7);
+ const int alignStop = alignStart - (alignWidth - 1);
+ const quint8 alignMask = ((1 << alignWidth) - 1) << alignStop;
+ const int tailWidth = (width - alignWidth) & 7;
+ const int doTail = (tailWidth > 0 ? 1 : 0);
+ const quint8 tailMask = (1 << (pixelsPerByte - tailWidth)) - 1;
+ const int width8 = (width - alignWidth) / pixelsPerByte;
+
+ dest += y * stride + x / pixelsPerByte;
+ stride -= (doAlign + width8);
+
+ for (int j = 0; j < height; ++j) {
+ if (doAlign) {
+ *dest = (*dest & ~alignMask) | (value & alignMask);
+ ++dest;
+ }
+ if (width8) {
+ qt_memfill<quint8>(dest, value, width8);
+ dest += width8;
+ }
+ if (doTail)
+ *dest = (*dest & tailMask) | (value & ~tailMask);
+ dest += stride;
+ }
+}
+
+static void solidFill_mono(QScreen *screen, const QColor &color,
+ const QRegion &region)
+{
+ quint8 *dest = reinterpret_cast<quint8*>(screen->base());
+ const quint8 c8 = (qGray(color.rgba()) >> 7) * 0xff;
+
+ const int stride = screen->linestep();
+ const QVector<QRect> rects = region.rects();
+
+ for (int i = 0; i < rects.size(); ++i) {
+ const QRect r = rects.at(i);
+ qt_rectfill_mono(dest, c8, r.x(), r.y(), r.width(), r.height(),
+ stride);
+ }
+}
+#endif // QT_QWS_DEPTH_1
+
+void qt_solidFill_setup(QScreen *screen, const QColor &color,
+ const QRegion &region)
+{
+ switch (screen->depth()) {
+#ifdef QT_QWS_DEPTH_32
+ case 32:
+ if (screen->pixelType() == QScreen::NormalPixel)
+ screen->d_ptr->solidFill = solidFill_template<quint32>;
+ else
+ screen->d_ptr->solidFill = solidFill_template<qabgr8888>;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_24
+ case 24:
+ if (screen->pixelType() == QScreen::NormalPixel)
+ screen->d_ptr->solidFill = solidFill_template<qrgb888>;
+ else
+ screen->d_ptr->solidFill = solidFill_template<quint24>;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_18
+ case 18:
+ screen->d_ptr->solidFill = solidFill_template<quint18>;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_16
+ case 16:
+ if (screen->pixelType() == QScreen::NormalPixel)
+ screen->d_ptr->solidFill = solidFill_template<quint16>;
+ else
+ screen->d_ptr->solidFill = solidFill_template<qbgr565>;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_15
+ case 15:
+ if (screen->pixelType() == QScreen::NormalPixel)
+ screen->d_ptr->solidFill = solidFill_template<qrgb555>;
+ else
+ screen->d_ptr->solidFill = solidFill_template<qbgr555>;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_12
+ case 12:
+ screen->d_ptr->solidFill = solidFill_template<qrgb444>;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_8
+ case 8:
+ screen->d_ptr->solidFill = solidFill_template<quint8>;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_4
+ case 4:
+ screen->d_ptr->solidFill = solidFill_gray4;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_1
+ case 1:
+ screen->d_ptr->solidFill = solidFill_mono;
+ break;
+#endif
+ default:
+ qFatal("solidFill_setup(): Screen depth %d not supported!",
+ screen->depth());
+ screen->d_ptr->solidFill = 0;
+ break;
+ }
+ screen->d_ptr->solidFill(screen, color, region);
+}
+
+template <typename DST, typename SRC>
+static void blit_template(QScreen *screen, const QImage &image,
+ const QPoint &topLeft, const QRegion &region)
+{
+ DST *dest = reinterpret_cast<DST*>(screen->base());
+ const int screenStride = screen->linestep();
+ const int imageStride = image.bytesPerLine();
+
+ if (region.numRects() == 1) {
+ const QRect r = region.boundingRect();
+ const SRC *src = reinterpret_cast<const SRC*>(image.scanLine(r.y()))
+ + r.x();
+ qt_rectconvert<DST, SRC>(dest, src,
+ r.x() + topLeft.x(), r.y() + topLeft.y(),
+ r.width(), r.height(),
+ screenStride, imageStride);
+ } else {
+ const QVector<QRect> rects = region.rects();
+
+ for (int i = 0; i < rects.size(); ++i) {
+ const QRect r = rects.at(i);
+ const SRC *src = reinterpret_cast<const SRC*>(image.scanLine(r.y()))
+ + r.x();
+ qt_rectconvert<DST, SRC>(dest, src,
+ r.x() + topLeft.x(), r.y() + topLeft.y(),
+ r.width(), r.height(),
+ screenStride, imageStride);
+ }
+ }
+}
+
+#ifdef QT_QWS_DEPTH_32
+static void blit_32(QScreen *screen, const QImage &image,
+ const QPoint &topLeft, const QRegion &region)
+{
+ switch (image.format()) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ blit_template<quint32, quint32>(screen, image, topLeft, region);
+ return;
+#ifdef QT_QWS_DEPTH_16
+ case QImage::Format_RGB16:
+ blit_template<quint32, quint16>(screen, image, topLeft, region);
+ return;
+#endif
+ default:
+ qCritical("blit_32(): Image format %d not supported!", image.format());
+ }
+}
+#endif // QT_QWS_DEPTH_32
+
+#ifdef QT_QWS_DEPTH_24
+static void blit_24(QScreen *screen, const QImage &image,
+ const QPoint &topLeft, const QRegion &region)
+{
+ switch (image.format()) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ blit_template<quint24, quint32>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_RGB888:
+ blit_template<quint24, qrgb888>(screen, image, topLeft, region);
+ return;
+#ifdef QT_QWS_DEPTH_16
+ case QImage::Format_RGB16:
+ blit_template<quint24, quint16>(screen, image, topLeft, region);
+ return;
+#endif
+ default:
+ qCritical("blit_24(): Image format %d not supported!", image.format());
+ }
+}
+
+static void blit_qrgb888(QScreen *screen, const QImage &image,
+ const QPoint &topLeft, const QRegion &region)
+{
+ switch (image.format()) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ blit_template<qrgb888, quint32>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_RGB888:
+ blit_template<qrgb888, qrgb888>(screen, image, topLeft, region);
+ return;
+#ifdef QT_QWS_DEPTH_16
+ case QImage::Format_RGB16:
+ blit_template<qrgb888, quint16>(screen, image, topLeft, region);
+ return;
+#endif
+ default:
+ qCritical("blit_24(): Image format %d not supported!", image.format());
+ break;
+ }
+}
+#endif // QT_QWS_DEPTH_24
+
+#ifdef QT_QWS_DEPTH_18
+static void blit_18(QScreen *screen, const QImage &image,
+ const QPoint &topLeft, const QRegion &region)
+{
+ switch (image.format()) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ blit_template<qrgb666, quint32>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_RGB666:
+ blit_template<qrgb666, qrgb666>(screen, image, topLeft, region);
+ return;
+#ifdef QT_QWS_DEPTH_16
+ case QImage::Format_RGB16:
+ blit_template<qrgb666, quint16>(screen, image, topLeft, region);
+ return;
+#endif
+ default:
+ qCritical("blit_18(): Image format %d not supported!", image.format());
+ }
+}
+#endif // QT_QWS_DEPTH_18
+
+#if (Q_BYTE_ORDER == Q_BIG_ENDIAN) && (defined(QT_QWS_DEPTH_16) || defined(QT_QWS_DEPTH_15))
+class quint16LE
+{
+public:
+ inline quint16LE(quint32 v) {
+ data = ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8);
+ }
+
+ inline quint16LE(int v) {
+ data = ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8);
+ }
+
+ inline quint16LE(quint16 v) {
+ data = ((v & 0xff00) >> 8) | ((v & 0x00ff) << 8);
+ }
+
+ inline quint16LE(qrgb555 v) {
+ data = (( (quint16)v & 0xff00) >> 8) |
+ (( (quint16)v & 0x00ff) << 8);
+ }
+
+ inline bool operator==(const quint16LE &v) const
+ {
+ return data == v.data;
+ }
+
+private:
+ quint16 data;
+};
+#endif
+
+#ifdef QT_QWS_DEPTH_16
+static void blit_16(QScreen *screen, const QImage &image,
+ const QPoint &topLeft, const QRegion &region)
+{
+ switch (image.format()) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ // ### This probably doesn't work but it's a case which should never happen
+ blit_template<quint16, quint32>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_RGB16:
+ blit_template<quint16, quint16>(screen, image, topLeft, region);
+ return;
+ default:
+ qCritical("blit_16(): Image format %d not supported!", image.format());
+ }
+}
+
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+static void blit_16_bigToLittleEndian(QScreen *screen, const QImage &image,
+ const QPoint &topLeft,
+ const QRegion &region)
+{
+ switch (image.format()) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ blit_template<quint16LE, quint32>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_RGB16:
+ blit_template<quint16LE, quint16>(screen, image, topLeft, region);
+ return;
+ default:
+ qCritical("blit_16_bigToLittleEndian(): Image format %d not supported!", image.format());
+ }
+}
+
+#endif // Q_BIG_ENDIAN
+#endif // QT_QWS_DEPTH_16
+
+#ifdef QT_QWS_DEPTH_15
+static void blit_15(QScreen *screen, const QImage &image,
+ const QPoint &topLeft, const QRegion &region)
+{
+ switch (image.format()) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ blit_template<qrgb555, quint32>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_RGB555:
+ blit_template<qrgb555, qrgb555>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_RGB16:
+ blit_template<qrgb555, quint16>(screen, image, topLeft, region);
+ return;
+ default:
+ qCritical("blit_15(): Image format %d not supported!", image.format());
+ }
+}
+
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+static void blit_15_bigToLittleEndian(QScreen *screen, const QImage &image,
+ const QPoint &topLeft,
+ const QRegion &region)
+{
+ switch (image.format()) {
+ case QImage::Format_RGB555:
+ blit_template<quint16LE, qrgb555>(screen, image, topLeft, region);
+ return;
+ default:
+ qCritical("blit_15_bigToLittleEndian(): Image format %d not supported!", image.format());
+ }
+}
+#endif // Q_BIG_ENDIAN
+#endif // QT_QWS_DEPTH_15
+
+
+#ifdef QT_QWS_DEPTH_12
+static void blit_12(QScreen *screen, const QImage &image,
+ const QPoint &topLeft, const QRegion &region)
+{
+ switch (image.format()) {
+ case QImage::Format_ARGB4444_Premultiplied:
+ blit_template<qrgb444, qargb4444>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_RGB444:
+ blit_template<qrgb444, qrgb444>(screen, image, topLeft, region);
+ return;
+ default:
+ qCritical("blit_12(): Image format %d not supported!", image.format());
+ }
+}
+#endif // QT_QWS_DEPTH_12
+
+#ifdef QT_QWS_DEPTH_8
+static void blit_8(QScreen *screen, const QImage &image,
+ const QPoint &topLeft, const QRegion &region)
+{
+ switch (image.format()) {
+ case QImage::Format_RGB32:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ blit_template<quint8, quint32>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_RGB16:
+ blit_template<quint8, quint16>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_ARGB4444_Premultiplied:
+ blit_template<quint8, qargb4444>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_RGB444:
+ blit_template<quint8, qrgb444>(screen, image, topLeft, region);
+ return;
+ default:
+ qCritical("blit_8(): Image format %d not supported!", image.format());
+ }
+}
+#endif // QT_QWS_DEPTH_8
+
+#ifdef QT_QWS_DEPTH_4
+
+struct qgray4 { quint8 dummy; } Q_PACKED;
+
+template <typename SRC>
+Q_STATIC_TEMPLATE_FUNCTION inline quint8 qt_convertToGray4(SRC color);
+
+template <>
+inline quint8 qt_convertToGray4(quint32 color)
+{
+ return qGray(color) >> 4;
+}
+
+template <>
+inline quint8 qt_convertToGray4(quint16 color)
+{
+ const int r = (color & 0xf800) >> 11;
+ const int g = (color & 0x07e0) >> 6; // only keep 5 bit
+ const int b = (color & 0x001f);
+ return (r * 11 + g * 16 + b * 5) >> 6;
+}
+
+template <>
+inline quint8 qt_convertToGray4(qrgb444 color)
+{
+ return qt_convertToGray4(quint32(color));
+}
+
+template <>
+inline quint8 qt_convertToGray4(qargb4444 color)
+{
+ return qt_convertToGray4(quint32(color));
+}
+
+template <typename SRC>
+Q_STATIC_TEMPLATE_FUNCTION inline void qt_rectconvert_gray4(qgray4 *dest4, const SRC *src,
+ int x, int y, int width, int height,
+ int dstStride, int srcStride)
+{
+ const int pixelsPerByte = 2;
+ quint8 *dest8 = reinterpret_cast<quint8*>(dest4)
+ + y * dstStride + x / pixelsPerByte;
+ const int doAlign = x & 1;
+ const int doTail = (width - doAlign) & 1;
+ const int width8 = (width - doAlign) / pixelsPerByte;
+ const int count8 = (width8 + 3) / 4;
+
+ srcStride = srcStride / sizeof(SRC) - width;
+ dstStride -= (width8 + doAlign);
+
+ for (int i = 0; i < height; ++i) {
+ if (doAlign) {
+ *dest8 = (*dest8 & 0xf0) | qt_convertToGray4<SRC>(*src++);
+ ++dest8;
+ }
+ if (count8) {
+ int n = count8;
+ switch (width8 & 0x03) // duff's device
+ {
+ case 0: do { *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
+ | qt_convertToGray4<SRC>(src[1]);
+ src += 2;
+ case 3: *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
+ | qt_convertToGray4<SRC>(src[1]);
+ src += 2;
+ case 2: *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
+ | qt_convertToGray4<SRC>(src[1]);
+ src += 2;
+ case 1: *dest8++ = qt_convertToGray4<SRC>(src[0]) << 4
+ | qt_convertToGray4<SRC>(src[1]);
+ src += 2;
+ } while (--n > 0);
+ }
+ }
+
+ if (doTail)
+ *dest8 = qt_convertToGray4<SRC>(*src++) << 4 | (*dest8 & 0x0f);
+
+ dest8 += dstStride;
+ src += srcStride;
+ }
+}
+
+template <>
+void qt_rectconvert(qgray4 *dest, const quint32 *src,
+ int x, int y, int width, int height,
+ int dstStride, int srcStride)
+{
+ qt_rectconvert_gray4<quint32>(dest, src, x, y, width, height,
+ dstStride, srcStride);
+}
+
+template <>
+void qt_rectconvert(qgray4 *dest, const quint16 *src,
+ int x, int y, int width, int height,
+ int dstStride, int srcStride)
+{
+ qt_rectconvert_gray4<quint16>(dest, src, x, y, width, height,
+ dstStride, srcStride);
+}
+
+template <>
+void qt_rectconvert(qgray4 *dest, const qrgb444 *src,
+ int x, int y, int width, int height,
+ int dstStride, int srcStride)
+{
+ qt_rectconvert_gray4<qrgb444>(dest, src, x, y, width, height,
+ dstStride, srcStride);
+}
+
+template <>
+void qt_rectconvert(qgray4 *dest, const qargb4444 *src,
+ int x, int y, int width, int height,
+ int dstStride, int srcStride)
+{
+ qt_rectconvert_gray4<qargb4444>(dest, src, x, y, width, height,
+ dstStride, srcStride);
+}
+
+static void blit_4(QScreen *screen, const QImage &image,
+ const QPoint &topLeft, const QRegion &region)
+{
+ switch (image.format()) {
+ case QImage::Format_ARGB32_Premultiplied:
+ blit_template<qgray4, quint32>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_RGB16:
+ blit_template<qgray4, quint16>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_RGB444:
+ blit_template<qgray4, qrgb444>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_ARGB4444_Premultiplied:
+ blit_template<qgray4, qargb4444>(screen, image, topLeft, region);
+ return;
+ default:
+ qCritical("blit_4(): Image format %d not supported!", image.format());
+ }
+}
+#endif // QT_QWS_DEPTH_4
+
+#ifdef QT_QWS_DEPTH_1
+
+struct qmono { quint8 dummy; } Q_PACKED;
+
+template <typename SRC>
+Q_STATIC_TEMPLATE_FUNCTION inline quint8 qt_convertToMono(SRC color);
+
+template <>
+inline quint8 qt_convertToMono(quint32 color)
+{
+ return qGray(color) >> 7;
+}
+
+template <>
+inline quint8 qt_convertToMono(quint16 color)
+{
+ return (qGray(qt_colorConvert<quint32, quint16>(color, 0)) >> 7);
+}
+
+template <>
+inline quint8 qt_convertToMono(qargb4444 color)
+{
+ return (qGray(quint32(color)) >> 7);
+}
+
+template <>
+inline quint8 qt_convertToMono(qrgb444 color)
+{
+ return (qGray(quint32(color)) >> 7);
+}
+
+template <typename SRC>
+inline void qt_rectconvert_mono(qmono *dest, const SRC *src,
+ int x, int y, int width, int height,
+ int dstStride, int srcStride)
+{
+ const int pixelsPerByte = 8;
+ quint8 *dest8 = reinterpret_cast<quint8*>(dest)
+ + y * dstStride + x / pixelsPerByte;
+ const int alignWidth = qMin(width, (8 - (x & 7)) & 7);
+ const int doAlign = (alignWidth > 0 ? 1 : 0);
+ const int alignStart = pixelsPerByte - 1 - (x & 7);
+ const int alignStop = alignStart - (alignWidth - 1);
+ const quint8 alignMask = ((1 << alignWidth) - 1) << alignStop;
+ const int tailWidth = (width - alignWidth) & 7;
+ const int doTail = (tailWidth > 0 ? 1 : 0);
+ const quint8 tailMask = (1 << (pixelsPerByte - tailWidth)) - 1;
+ const int width8 = (width - alignWidth) / pixelsPerByte;
+
+ srcStride = srcStride / sizeof(SRC) - (width8 * 8 + alignWidth);
+ dstStride -= (width8 + doAlign);
+
+ for (int j = 0; j < height; ++j) {
+ if (doAlign) {
+ quint8 d = *dest8 & ~alignMask;
+ for (int i = alignStart; i >= alignStop; --i)
+ d |= qt_convertToMono<SRC>(*src++) << i;
+ *dest8++ = d;
+ }
+ for (int i = 0; i < width8; ++i) {
+ *dest8 = (qt_convertToMono<SRC>(src[0]) << 7)
+ | (qt_convertToMono<SRC>(src[1]) << 6)
+ | (qt_convertToMono<SRC>(src[2]) << 5)
+ | (qt_convertToMono<SRC>(src[3]) << 4)
+ | (qt_convertToMono<SRC>(src[4]) << 3)
+ | (qt_convertToMono<SRC>(src[5]) << 2)
+ | (qt_convertToMono<SRC>(src[6]) << 1)
+ | (qt_convertToMono<SRC>(src[7]));
+ src += 8;
+ ++dest8;
+ }
+ if (doTail) {
+ quint8 d = *dest8 & tailMask;
+ switch (tailWidth) {
+ case 7: d |= qt_convertToMono<SRC>(src[6]) << 1;
+ case 6: d |= qt_convertToMono<SRC>(src[5]) << 2;
+ case 5: d |= qt_convertToMono<SRC>(src[4]) << 3;
+ case 4: d |= qt_convertToMono<SRC>(src[3]) << 4;
+ case 3: d |= qt_convertToMono<SRC>(src[2]) << 5;
+ case 2: d |= qt_convertToMono<SRC>(src[1]) << 6;
+ case 1: d |= qt_convertToMono<SRC>(src[0]) << 7;
+ }
+ *dest8 = d;
+ }
+
+ dest8 += dstStride;
+ src += srcStride;
+ }
+}
+
+template <>
+void qt_rectconvert(qmono *dest, const quint32 *src,
+ int x, int y, int width, int height,
+ int dstStride, int srcStride)
+{
+ qt_rectconvert_mono<quint32>(dest, src, x, y, width, height,
+ dstStride, srcStride);
+}
+
+template <>
+void qt_rectconvert(qmono *dest, const quint16 *src,
+ int x, int y, int width, int height,
+ int dstStride, int srcStride)
+{
+ qt_rectconvert_mono<quint16>(dest, src, x, y, width, height,
+ dstStride, srcStride);
+}
+
+template <>
+void qt_rectconvert(qmono *dest, const qrgb444 *src,
+ int x, int y, int width, int height,
+ int dstStride, int srcStride)
+{
+ qt_rectconvert_mono<qrgb444>(dest, src, x, y, width, height,
+ dstStride, srcStride);
+}
+
+template <>
+void qt_rectconvert(qmono *dest, const qargb4444 *src,
+ int x, int y, int width, int height,
+ int dstStride, int srcStride)
+{
+ qt_rectconvert_mono<qargb4444>(dest, src, x, y, width, height,
+ dstStride, srcStride);
+}
+
+static void blit_1(QScreen *screen, const QImage &image,
+ const QPoint &topLeft, const QRegion &region)
+{
+ switch (image.format()) {
+ case QImage::Format_ARGB32_Premultiplied:
+ blit_template<qmono, quint32>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_RGB16:
+ blit_template<qmono, quint16>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_RGB444:
+ blit_template<qmono, qrgb444>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_ARGB4444_Premultiplied:
+ blit_template<qmono, qargb4444>(screen, image, topLeft, region);
+ return;
+ default:
+ qCritical("blit_1(): Image format %d not supported!", image.format());
+ }
+}
+#endif // QT_QWS_DEPTH_1
+
+#ifdef QT_QWS_DEPTH_GENERIC
+
+static void blit_rgb(QScreen *screen, const QImage &image,
+ const QPoint &topLeft, const QRegion &region)
+{
+ switch (image.format()) {
+ case QImage::Format_ARGB32_Premultiplied:
+ blit_template<qrgb, quint32>(screen, image, topLeft, region);
+ return;
+ case QImage::Format_RGB16:
+ blit_template<qrgb, quint16>(screen, image, topLeft, region);
+ return;
+ default:
+ qCritical("blit_rgb(): Image format %d not supported!", image.format());
+ }
+}
+
+void qt_set_generic_blit(QScreen *screen, int bpp,
+ int len_red, int len_green, int len_blue, int len_alpha,
+ int off_red, int off_green, int off_blue, int off_alpha)
+{
+ qrgb::bpp = bpp / 8;
+ qrgb::len_red = len_red;
+ qrgb::len_green = len_green;
+ qrgb::len_blue = len_blue;
+ qrgb::len_alpha = len_alpha;
+ qrgb::off_red = off_red;
+ qrgb::off_green = off_green;
+ qrgb::off_blue = off_blue;
+ qrgb::off_alpha = off_alpha;
+ screen->d_ptr->blit = blit_rgb;
+ if (bpp == 16)
+ screen->d_ptr->solidFill = solidFill_rgb_16bpp;
+ else if (bpp == 32)
+ screen->d_ptr->solidFill = solidFill_rgb_32bpp;
+}
+
+#endif // QT_QWS_DEPTH_GENERIC
+
+void qt_blit_setup(QScreen *screen, const QImage &image,
+ const QPoint &topLeft, const QRegion &region)
+{
+ switch (screen->depth()) {
+#ifdef QT_QWS_DEPTH_32
+ case 32:
+ if (screen->pixelType() == QScreen::NormalPixel)
+ screen->d_ptr->blit = blit_32;
+ else
+ screen->d_ptr->blit = blit_template<qabgr8888, quint32>;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_24
+ case 24:
+ if (screen->pixelType() == QScreen::NormalPixel)
+ screen->d_ptr->blit = blit_qrgb888;
+ else
+ screen->d_ptr->blit = blit_24;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_18
+ case 18:
+ screen->d_ptr->blit = blit_18;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_16
+ case 16:
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ if (screen->d_ptr->fb_is_littleEndian)
+ screen->d_ptr->blit = blit_16_bigToLittleEndian;
+ else
+#endif
+ if (screen->pixelType() == QScreen::NormalPixel)
+ screen->d_ptr->blit = blit_16;
+ else
+ screen->d_ptr->blit = blit_template<qbgr565, quint16>;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_15
+ case 15:
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ if (screen->d_ptr->fb_is_littleEndian)
+ screen->d_ptr->blit = blit_15_bigToLittleEndian;
+ else
+#endif // Q_BIG_ENDIAN
+ if (screen->pixelType() == QScreen::NormalPixel)
+ screen->d_ptr->blit = blit_15;
+ else
+ screen->d_ptr->blit = blit_template<qbgr555, qrgb555>;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_12
+ case 12:
+ screen->d_ptr->blit = blit_12;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_8
+ case 8:
+ screen->d_ptr->blit = blit_8;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_4
+ case 4:
+ screen->d_ptr->blit = blit_4;
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_1
+ case 1:
+ screen->d_ptr->blit = blit_1;
+ break;
+#endif
+ default:
+ qFatal("blit_setup(): Screen depth %d not supported!",
+ screen->depth());
+ screen->d_ptr->blit = 0;
+ break;
+ }
+ screen->d_ptr->blit(screen, image, topLeft, region);
+}
+
+QScreenPrivate::QScreenPrivate(QScreen *parent, QScreen::ClassId id)
+ : defaultGraphicsSystem(QWSGraphicsSystem(parent)),
+ pixelFormat(QImage::Format_Invalid),
+#ifdef QT_QWS_CLIENTBLIT
+ supportsBlitInClients(false),
+#endif
+ classId(id), q_ptr(parent)
+{
+ solidFill = qt_solidFill_setup;
+ blit = qt_blit_setup;
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ fb_is_littleEndian = false;
+#endif
+ pixmapFactory = 0;
+ graphicsSystem = &defaultGraphicsSystem;
+}
+
+QScreenPrivate::~QScreenPrivate()
+{
+}
+
+QImage::Format QScreenPrivate::preferredImageFormat() const
+{
+ if (pixelFormat > QImage::Format_Indexed8)
+ return pixelFormat;
+
+ if (q_ptr->depth() <= 16)
+ return QImage::Format_RGB16;
+ else
+ return QImage::Format_ARGB32_Premultiplied;
+}
+
+/*!
+ \class QScreen
+ \ingroup qws
+
+ \brief The QScreen class is a base class for screen drivers in
+ Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ \l{Qt for Embedded Linux} provides ready-made drivers for several screen
+ protocols, see the \l{Qt for Embedded Linux Display Management}{display
+ management} documentation for details. Custom screen drivers can
+ be implemented by subclassing the QScreen class and creating a
+ screen driver plugin (derived from QScreenDriverPlugin). The
+ default implementation of the QScreenDriverFactory class
+ will automatically detect the plugin, and load the driver into the
+ server application at run-time using Qt's \l {How to Create Qt
+ Plugins}{plugin system}.
+
+ When rendering, the default behavior is for each
+ client to render its widgets as well as its decorations into
+ memory, while the server copies the memory content to the device's
+ framebuffer using the screen driver. See the \l{Qt for Embedded Linux
+ Architecture} overview for details (note that it is possible for
+ the clients to manipulate and control the underlying hardware
+ directly as well).
+
+ Starting with Qt 4.2, it is also possible to add an
+ accelerated graphics driver to take advantage of available
+ hardware resources. See the \l{Adding an Accelerated Graphics
+ Driver to Qt for Embedded Linux} documentation for details.
+
+ \tableofcontents
+
+ \section1 Framebuffer Management
+
+ When a \l{Qt for Embedded Linux} application starts running, it
+ calls the screen driver's connect() function to map the
+ framebuffer and the accelerated drivers that the graphics card
+ control registers. The connect() function should then read out the
+ parameters of the framebuffer and use them as required to set this
+ class's protected variables.
+
+ The initDevice() function can be reimplemented to initialize the
+ graphics card. Note, however, that connect() is called \e before
+ the initDevice() function, so, for some hardware configurations,
+ some of the initialization that would normally be done in the
+ initDevice() function might have to be done in the connect()
+ function.
+
+ Likewise, just before a \l{Qt for Embedded Linux} application
+ exits, it calls the screen driver's disconnect() function. The
+ server application will in addition call the shutdownDevice()
+ function before it calls disconnect(). Note that the default
+ implementation of the shutdownDevice() function only hides the
+ mouse cursor.
+
+ QScreen also provides the save() and restore() functions, making
+ it possible to save and restore the state of the graphics
+ card. Note that the default implementations do nothing. Hardware
+ screen drivers should reimplement these functions to save (and
+ restore) its registers, enabling switching between virtual
+ consoles.
+
+ In addition, you can use the base() function to retrieve a pointer
+ to the beginning of the framebuffer, and the region() function to
+ retrieve the framebuffer's region. Use the onCard() function to
+ determine whether the framebuffer is within the graphics card's
+ memory, and the totalSize() function to determine the size of the
+ available graphics card memory (including the screen). Finally,
+ you can use the offset() function to retrieve the offset between
+ the framebuffer's coordinates and the application's coordinate
+ system.
+
+ \section1 Palette Management
+
+ QScreen provides several functions to retrieve information about
+ the color palette: The clut() function returns a pointer to the
+ color lookup table (i.e. its color palette). Use the numCols()
+ function to determine the number of entries in this table, and the
+ alloc() function to retrieve the palette index of the color that
+ is the closest match to a given RGB value.
+
+ To determine if the screen driver supports a given color depth,
+ use the supportsDepth() function that returns true of the
+ specified depth is supported.
+
+ \section1 Drawing on Screen
+
+ When a screen update is required, the \l{Qt for Embedded Linux} server runs
+ through all the top-level windows that intersect with the region
+ that is about to be updated, and ensures that the associated
+ clients have updated their memory buffer. Then the server calls
+ the exposeRegion() function that composes the window surfaces and
+ copies the content of memory to screen by calling the blit() and
+ solidFill() functions.
+
+ The blit() function copies a given region in a given image to a
+ specified point using device coordinates, while the solidFill()
+ function fills the given region of the screen with the specified
+ color. Note that normally there is no need to call either of these
+ functions explicitly.
+
+ In addition, QScreen provides the blank() function that can be
+ reimplemented to prevent any contents from being displayed on the
+ screen, and the setDirty() function that can be reimplemented to
+ indicate that a given rectangle of the screen has been
+ altered. Note that the default implementations of these functions
+ do nothing.
+
+ Reimplement the the mapFromDevice() and mapToDevice() functions to
+ map objects from the framebuffer coordinate system to the
+ coordinate space used by the application, and vice versa. Be aware
+ that the default implementations simply return the given objects
+ as they are.
+
+ \section1 Properties
+
+ \table
+ \header \o Property \o Functions
+ \row
+ \o Size
+ \o
+
+ The size of the screen can be retrieved using the screenSize()
+ function. The size is returned in bytes.
+
+ The framebuffer's logical width and height can be retrieved using
+ width() and height(), respectively. These functions return values
+ are given in pixels. Alternatively, the physicalWidth() and
+ physicalHeight() function returns the same metrics in
+ millimeters. QScreen also provides the deviceWidth() and
+ deviceHeight() functions returning the physical width and height
+ of the device in pixels. Note that the latter metrics can differ
+ from the ones used if the display is centered within the
+ framebuffer.
+
+ \row
+ \o Resolution
+ \o
+
+ Reimplement the setMode() function to be able to set the
+ framebuffer to a new resolution (width and height) and bit depth.
+
+ The current depth of the framebuffer can be always be retrieved
+ using the depth() function. Use the pixmapDepth() function to
+ obtain the preferred depth for pixmaps.
+
+ \row
+ \o Pixmap Alignment
+ \o
+
+ Use the pixmapOffsetAlignment() function to retrieve the value to
+ which the start address of pixmaps held in the graphics card's
+ memory, should be aligned.
+
+ Use the pixmapLinestepAlignment() to retrieve the value to which
+ the \e {individual scanlines} of pixmaps should be aligned.
+
+ \row
+ \o Image Display
+ \o
+
+ The isInterlaced() function tells whether the screen is displaying
+ images progressively, and the isTransformed() function whether it
+ is rotated. The transformOrientation() function can be
+ reimplemented to return the current rotation.
+
+ \row
+ \o Scanlines
+ \o
+
+ Use the linestep() function to retrieve the length of each
+ scanline of the framebuffer.
+
+ \row
+ \o Pixel Type
+ \o
+
+ The pixelType() function returns the screen's pixel storage format as
+ described by the PixelType enum.
+
+ \endtable
+
+ \section1 Subclassing and Initial Values
+
+ You need to set the following members when implementing a subclass of QScreen:
+
+ \table
+ \header \o Member \o Initial Value
+ \row \o \l{QScreen::}{data} \o A pointer to the framebuffer if possible;
+ 0 otherwise.
+ \row \o \l{QScreen::}{lstep} \o The number of bytes between each scanline
+ in the framebuffer.
+ \row \o \l{QScreen::}{w} \o The logical screen width in pixels.
+ \row \o \l{QScreen::}{h} \o The logical screen height in pixels.
+ \row \o \l{QScreen::}{dw} \o The real screen width in pixels.
+ \row \o \l{QScreen::}{dh} \o The real screen height in pixels.
+ \row \o \l{QScreen::}{d} \o The number of bits per pixel.
+ \row \o \l{QScreen::}{physWidth} \o The screen width in millimeters.
+ \row \o \l{QScreen::}{physHeight} \o The screen height in millimeters.
+ \endtable
+
+ The logical screen values are the same as the real screen values unless the
+ screen is transformed in some way; e.g., rotated.
+
+ See also the \l{Accelerated Graphics Driver Example} for an example that
+ shows how to initialize these values.
+
+ \sa QScreenDriverPlugin, QScreenDriverFactory, {Qt for Embedded Linux Display
+ Management}
+*/
+
+/*!
+ \enum QScreen::PixelType
+
+ This enum describes the pixel storage format of the screen,
+ i.e. the order of the red (R), green (G) and blue (B) components
+ of a pixel.
+
+ \value NormalPixel Red-green-blue (RGB)
+ \value BGRPixel Blue-green-red (BGR)
+
+ \sa pixelType()
+*/
+
+/*!
+ \enum QScreen::ClassId
+
+ This enum defines the class identifiers for the known screen subclasses.
+
+ \value LinuxFBClass QLinuxFBScreen
+ \value TransformedClass QTransformedScreen
+ \value VNCClass QVNCScreen
+ \value MultiClass QMultiScreen
+ \value VFbClass QVFbScreen
+ \value DirectFBClass QDirectFBScreen
+ \value SvgalibClass QSvgalibScreen
+ \value ProxyClass QProxyScreen
+ \value GLClass QGLScreen
+ \value CustomClass Unknown QScreen subclass
+
+ \sa classId()
+*/
+
+/*!
+ \variable QScreen::screenclut
+ \brief the color table
+
+ Initialize this variable in a subclass using a paletted screen mode,
+ and initialize its partner, QScreen::screencols.
+
+ \sa screencols
+*/
+
+/*!
+ \variable QScreen::screencols
+ \brief the number of entries in the color table
+
+ Initialize this variable in a subclass using a paletted screen mode,
+ and initialize its partner, QScreen::screenclut.
+
+ \sa screenclut
+*/
+
+/*!
+ \variable QScreen::data
+ \brief points to the first visible pixel in the frame buffer.
+
+ You must initialize this variable if you are using the default
+ implementation of non-buffered painting Qt::WA_PaintOnScreen,
+ QPixmap::grabWindow() or QDirectPainter::frameBuffer(). If you
+ initialize this variable, you must also initialize QScreen::size and
+ QScreen::mapsize.
+
+ \sa QScreen::size, QScreen::mapsize
+*/
+
+/*!
+ \variable QScreen::w
+ \brief the logical width of the screen.
+
+ This variable \e{must} be initialized by a subclass.
+*/
+
+/*!
+ \variable QScreen::lstep
+ \brief the number of bytes representing a line in the frame buffer.
+
+ i.e., \e{line step}. \c {data[lstep * 2]} is the address of the
+ first visible pixel in the third line of the frame buffer.
+
+ \sa data
+*/
+
+/*!
+ \variable QScreen::h
+ \brief the logical height of the screen.
+
+ This variable \e{must} be initialized by a subclass.
+*/
+
+/*!
+ \variable QScreen::d
+ \brief the pixel depth
+
+ This is the number of significant bits used to set a pixel
+ color. This variable \e{must} be initialized by a subclass.
+*/
+
+/*!
+ \variable QScreen::pixeltype
+ \brief set to BGRPixel
+
+ Set this variable to BGRPixel in a subclass, if the screen pixel
+ format is a BGR type and you have used setPixelFormat() to set the
+ pixel format to the corresponding RGB format. e.g., you have set the
+ pixel format to QImage::Format_RGB555, but your screen really uses
+ BGR, not RGB.
+*/
+
+/*!
+ \variable QScreen::grayscale
+ \brief the gray scale screen mode flag
+
+ Set this variable to true in a subclass, if you are using a
+ grayscale screen mode. e.g., in an 8-bit mode where you don't want
+ to use the palette, but you want to use the grayscales.
+*/
+
+/*!
+ \variable QScreen::dw
+ \brief the device width
+
+ This is the number of pixels in a row of the physical screen. It
+ \e{must} be initialized by a subclass. Normally, it should be set to
+ the logical width QScreen::w, but it might be different, e.g., if
+ you are doing rotations in software.
+
+ \sa QScreen::w
+*/
+
+/*!
+ \variable QScreen::dh
+ \brief the device height
+
+ This is the number of pixels in a column of the physical screen. It
+ \e{must} be initialized by a subclass. Normally, it should be set to
+ the logical height QScreen::h, but it might be different, e.g., if
+ you are doing rotations in software.
+
+ \sa QScreen::h
+*/
+
+/*!
+ \variable QScreen::size
+ \brief the number of bytes in the visible region of the frame buffer
+
+ This is the number of bytes in the visible part of the block pointed
+ to by the QScreen::data pointer. You must initialize this variable
+ if you initialize the QScreen::data pointer.
+
+ \sa QScreen::data, QScreen::mapsize
+*/
+
+/*!
+ \variable QScreen::mapsize
+ \brief the total number of bytes in the frame buffer
+
+ This is the total number of bytes in the block pointed to by the
+ QScreen::data pointer. You must initialize this variable if you
+ initialize the QScreen::data pointer.
+
+ \sa QScreen::data, QScreen::size
+*/
+
+/*!
+ \variable QScreen::physWidth
+ \brief the physical width of the screen in millimeters.
+
+ Currently, this variable is used when calculating the screen DPI,
+ which in turn is used when deciding the actual font size Qt is
+ using.
+*/
+
+/*!
+ \variable QScreen::physHeight
+ \brief the physical height of the screen in millimeters.
+
+ Currently, this variable is used when calculating the screen DPI,
+ which in turn is used when deciding the actual font size Qt is
+ using.
+*/
+
+/*!
+ \fn static QScreen* QScreen::instance()
+
+ Returns a pointer to the application's QScreen instance.
+
+ If this screen consists of several subscreens, operations to the
+ returned instance will affect all its subscreens. Use the
+ subscreens() function to retrieve access to a particular
+ subscreen.
+
+ \sa subScreens(), subScreenIndexAt()
+*/
+
+/*!
+ \fn QList<QScreen*> QScreen::subScreens() const
+ \since 4.2
+
+ Returns a list of this screen's subscreens. Use the
+ subScreenIndexAt() function to retrieve the index of a screen at a
+ given position.
+
+ Note that if \e this screen consists of several subscreens,
+ operations to \e this instance will affect all subscreens by
+ default.
+
+ \sa instance(), subScreenIndexAt()
+*/
+
+/*!
+ \fn int QScreen::physicalWidth() const
+ \since 4.2
+
+ Returns the physical width of the screen in millimeters.
+
+ \sa width(), deviceWidth(), physicalHeight()
+*/
+
+/*!
+ \fn int QScreen::physicalHeight() const
+ \since 4.2
+
+ Returns the physical height of the screen in millimeters.
+
+ \sa height(), deviceHeight(), physicalWidth()
+*/
+
+/*!
+ \fn virtual bool QScreen::initDevice() = 0
+
+ This function is called by the \l{Qt for Embedded Linux} server to
+ initialize the framebuffer. Note that a server application will call the
+ connect() function prior to this function.
+
+ Implement this function to make accelerated drivers set up the
+ graphics card. Return true to indicate success and false to indicate
+ failure.
+
+ \sa shutdownDevice(), connect()
+*/
+
+/*!
+ \fn virtual bool QScreen::connect(const QString &displaySpec) = 0
+
+ This function is called by every \l{Qt for Embedded Linux}
+ application on startup, and must be implemented to map in the
+ framebuffer and the accelerated drivers that the graphics card
+ control registers. Note that coonnect must be called \e before
+ the initDevice() function.
+
+ Ensure that true is returned if a connection to the screen device
+ is made. Otherwise, return false. Upon making the connection, the
+ function should read out the parameters of the framebuffer and use
+ them as required to set this class's protected variables.
+
+ The \a displaySpec argument is passed by the QWS_DISPLAY
+ environment variable or the -display command line parameter, and
+ has the following syntax:
+
+ \snippet doc/src/snippets/code/src_gui_embedded_qscreen_qws.cpp 0
+
+ For example, to use the mach64 driver on fb1 as display 2:
+
+ \snippet doc/src/snippets/code/src_gui_embedded_qscreen_qws.cpp 1
+
+ See \l{Qt for Embedded Linux Display Management} for more details.
+
+ \sa disconnect(), initDevice(), {Running Qt for Embedded Linux Applications}
+*/
+
+/*!
+ \fn QScreen::disconnect()
+
+ This function is called by every \l{Qt for Embedded Linux} application
+ before exiting, and must be implemented to unmap the
+ framebuffer. Note that a server application will call the
+ shutdownDevice() function prior to this function.
+
+ \sa connect(), shutdownDevice(), {Running Qt for Embedded Linux
+ Applications}
+*/
+
+/*!
+ \fn QScreen::setMode(int width, int height, int depth)
+
+ Implement this function to reset the framebuffer's resolution (\a
+ width and \a height) and bit \a depth.
+
+ After the resolution has been set, existing paint engines will be
+ invalid and the framebuffer should be completely redrawn. In a
+ multiple-process situation, all other applications must be
+ notified to reset their mode and update themselves accordingly.
+*/
+
+/*!
+ \fn QScreen::blank(bool on)
+
+ Prevents the screen driver form displaying any content on the
+ screen.
+
+ Note that the default implementation does nothing.
+
+ Reimplement this function to prevent the screen driver from
+ displaying any contents on the screen if \a on is true; otherwise
+ the contents is expected to be shown.
+
+ \sa blit()
+*/
+
+/*!
+ \fn int QScreen::pixmapOffsetAlignment()
+
+ Returns the value (in bits) to which the start address of pixmaps
+ held in the graphics card's memory, should be aligned.
+
+ Note that the default implementation returns 64; reimplement this
+ function to override the return value, e.g., when implementing an
+ accelerated driver (see the \l {Adding an Accelerated Graphics
+ Driver to Qt for Embedded Linux}{Adding an Accelerated Graphics Driver}
+ documentation for details).
+
+ \sa pixmapLinestepAlignment()
+*/
+
+/*!
+ \fn int QScreen::pixmapLinestepAlignment()
+
+ Returns the value (in bits) to which individual scanlines of
+ pixmaps held in the graphics card's memory, should be
+ aligned.
+
+ Note that the default implementation returns 64; reimplement this
+ function to override the return value, e.g., when implementing an
+ accelerated driver (see the \l {Adding an Accelerated Graphics
+ Driver to Qt for Embedded Linux}{Adding an Accelerated Graphics Driver}
+ documentation for details).
+
+ \sa pixmapOffsetAlignment()
+*/
+
+/*!
+ \fn QScreen::width() const
+
+ Returns the logical width of the framebuffer in pixels.
+
+ \sa deviceWidth(), physicalWidth(), height()
+*/
+
+/*!
+ \fn int QScreen::height() const
+
+ Returns the logical height of the framebuffer in pixels.
+
+ \sa deviceHeight(), physicalHeight(), width()
+*/
+
+/*!
+ \fn QScreen::depth() const
+
+ Returns the depth of the framebuffer, in bits per pixel.
+
+ Note that the returned depth is the number of bits each pixel
+ fills rather than the number of significant bits, so 24bpp and
+ 32bpp express the same range of colors (8 bits of red, green and
+ blue).
+
+ \sa clut(), pixmapDepth()
+*/
+
+/*!
+ \fn int QScreen::pixmapDepth() const
+
+ Returns the preferred depth for pixmaps, in bits per pixel.
+
+ \sa depth()
+*/
+
+/*!
+ \fn QScreen::linestep() const
+
+ Returns the length of each scanline of the framebuffer in bytes.
+
+ \sa isInterlaced()
+*/
+
+/*!
+ \fn QScreen::deviceWidth() const
+
+ Returns the physical width of the framebuffer device in pixels.
+
+ Note that the returned width can differ from the width which
+ \l{Qt for Embedded Linux} will actually use, that is if the display is
+ centered within the framebuffer.
+
+ \sa width(), physicalWidth(), deviceHeight()
+*/
+
+/*!
+ \fn QScreen::deviceHeight() const
+
+ Returns the full height of the framebuffer device in pixels.
+
+ Note that the returned height can differ from the height which
+ \l{Qt for Embedded Linux} will actually use, that is if the display is
+ centered within the framebuffer.
+
+ \sa height(), physicalHeight(), deviceWidth()
+*/
+
+/*!
+ \fn uchar *QScreen::base() const
+
+ Returns a pointer to the beginning of the framebuffer.
+
+ \sa onCard(), region(), totalSize()
+*/
+
+/*!
+ \fn uchar *QScreen::cache(int)
+
+ \internal
+
+ This function is used to store pixmaps in graphics memory for the
+ use of the accelerated drivers. See QLinuxFbScreen (where the
+ caching is implemented) for more information.
+*/
+
+/*!
+ \fn QScreen::uncache(uchar *)
+
+ \internal
+
+ This function is called on pixmap destruction to remove them from
+ graphics card memory.
+*/
+
+/*!
+ \fn QScreen::screenSize() const
+
+ Returns the size of the screen in bytes.
+
+ The screen size is always located at the beginning of framebuffer
+ memory, i.e. it can also be retrieved using the base() function.
+
+ \sa base(), region()
+*/
+
+/*!
+ \fn QScreen::totalSize() const
+
+ Returns the size of the available graphics card memory (including
+ the screen) in bytes.
+
+ \sa onCard()
+*/
+
+// Unaccelerated screen/driver setup. Can be overridden by accelerated
+// drivers
+
+/*!
+ \fn QScreen::QScreen(int displayId)
+
+ Constructs a new screen driver.
+
+ The \a displayId identifies the \l{Qt for Embedded Linux} server to connect
+ to.
+*/
+
+/*!
+ \fn QScreen::clut()
+
+ Returns a pointer to the screen's color lookup table (i.e. its
+ color palette).
+
+ Note that this function only apply in paletted modes like 8-bit,
+ i.e. in modes where only the palette indexes (and not the actual
+ color values) are stored in memory.
+
+ \sa alloc(), depth(), numCols()
+*/
+
+/*!
+ \fn int QScreen::numCols()
+
+ Returns the number of entries in the screen's color lookup table
+ (i.e. its color palette). A pointer to the color table can be
+ retrieved using the clut() function.
+
+ \sa clut(), alloc()
+*/
+
+/*!
+ \since 4.4
+
+ Constructs a new screen driver.
+
+ The \a display_id identifies the \l{Qt for Embedded Linux}
+ server to connect to. The \a classId specifies the class
+ identifier.
+*/
+QScreen::QScreen(int display_id, ClassId classId)
+ : screencols(0), data(0), entries(0), entryp(0), lowest(0),
+ w(0), lstep(0), h(0), d(1), pixeltype(NormalPixel), grayscale(false),
+ dw(0), dh(0), size(0), mapsize(0), displayId(display_id),
+ physWidth(0), physHeight(0), d_ptr(new QScreenPrivate(this, classId))
+{
+ clearCacheFunc = 0;
+}
+
+QScreen::QScreen(int display_id)
+ : screencols(0), data(0), entries(0), entryp(0), lowest(0),
+ w(0), lstep(0), h(0), d(1), pixeltype(NormalPixel), grayscale(false),
+ dw(0), dh(0), size(0), mapsize(0), displayId(display_id),
+ physWidth(0), physHeight(0), d_ptr(new QScreenPrivate(this))
+{
+ clearCacheFunc = 0;
+}
+
+/*!
+ Destroys this screen driver.
+*/
+
+QScreen::~QScreen()
+{
+ delete d_ptr;
+}
+
+/*!
+ This function is called by the \l{Qt for Embedded Linux} server before it
+ calls the disconnect() function when exiting.
+
+ Note that the default implementation only hides the mouse cursor;
+ reimplement this function to do the necessary graphics card
+ specific cleanup.
+
+ \sa initDevice(), disconnect()
+*/
+
+void QScreen::shutdownDevice()
+{
+#ifndef QT_NO_QWS_CURSOR
+ if (qt_screencursor)
+ qt_screencursor->hide();
+#endif
+}
+
+extern bool qws_accel; //in qapplication_qws.cpp
+
+/*!
+ \fn PixelType QScreen::pixelType() const
+
+ Returns the pixel storage format of the screen.
+*/
+
+/*!
+ Returns the pixel format of the screen, or \c QImage::Format_Invalid
+ if the pixel format is not a supported image format.
+
+*/
+QImage::Format QScreen::pixelFormat() const
+{
+ return d_ptr->pixelFormat;
+}
+
+/*!
+ Sets the screen's pixel format to \a format.
+ */
+void QScreen::setPixelFormat(QImage::Format format)
+{
+ d_ptr->pixelFormat = format;
+}
+
+
+/*!
+ \fn int QScreen::alloc(unsigned int red, unsigned int green, unsigned int blue)
+
+ Returns the index in the screen's palette which is the closest
+ match to the given RGB value (\a red, \a green, \a blue).
+
+ Note that this function only apply in paletted modes like 8-bit,
+ i.e. in modes where only the palette indexes (and not the actual
+ color values) are stored in memory.
+
+ \sa clut(), numCols()
+*/
+
+int QScreen::alloc(unsigned int r,unsigned int g,unsigned int b)
+{
+ int ret = 0;
+ if (d == 8) {
+ if (grayscale)
+ return qGray(r, g, b);
+
+ // First we look to see if we match a default color
+ const int pos = (r + 25) / 51 * 36 + (g + 25) / 51 * 6 + (b + 25) / 51;
+ if (pos < screencols && screenclut[pos] == qRgb(r, g, b)) {
+ return pos;
+ }
+
+ // search for nearest color
+ unsigned int mindiff = 0xffffffff;
+ unsigned int diff;
+ int dr,dg,db;
+
+ for (int loopc = 0; loopc < screencols; ++loopc) {
+ dr = qRed(screenclut[loopc]) - r;
+ dg = qGreen(screenclut[loopc]) - g;
+ db = qBlue(screenclut[loopc]) - b;
+ diff = dr*dr + dg*dg + db*db;
+
+ if (diff < mindiff) {
+ ret = loopc;
+ if (!diff)
+ break;
+ mindiff = diff;
+ }
+ }
+ } else if (d == 4) {
+ ret = qGray(r, g, b) >> 4;
+ } else if (d == 1) {
+ ret = qGray(r, g, b) >= 128;
+ } else {
+ qFatal("cannot alloc %dbpp color", d);
+ }
+
+ return ret;
+}
+
+/*!
+ Saves the current state of the graphics card.
+
+ For example, hardware screen drivers should reimplement the save()
+ and restore() functions to save and restore its registers,
+ enabling swintching between virtual consoles.
+
+ Note that the default implementation does nothing.
+
+ \sa restore()
+*/
+
+void QScreen::save()
+{
+}
+
+/*!
+ Restores the previously saved state of the graphics card.
+
+ For example, hardware screen drivers should reimplement the save()
+ and restore() functions to save and restore its registers,
+ enabling swintching between virtual consoles.
+
+ Note that the default implementation does nothing.
+
+ \sa save()
+*/
+
+void QScreen::restore()
+{
+}
+
+void QScreen::blank(bool)
+{
+}
+
+/*!
+ \internal
+*/
+
+void QScreen::set(unsigned int, unsigned int, unsigned int, unsigned int)
+{
+}
+
+/*!
+ \fn bool QScreen::supportsDepth(int depth) const
+
+ Returns true if the screen supports the specified color \a depth;
+ otherwise returns false.
+
+ \sa clut()
+*/
+
+bool QScreen::supportsDepth(int d) const
+{
+ if (false) {
+ //Just to simplify the ifdeffery
+#ifdef QT_QWS_DEPTH_1
+ } else if(d==1) {
+ return true;
+#endif
+#ifdef QT_QWS_DEPTH_4
+ } else if(d==4) {
+ return true;
+#endif
+#ifdef QT_QWS_DEPTH_8
+ } else if(d==8) {
+ return true;
+#endif
+#ifdef QT_QWS_DEPTH_16
+ } else if(d==16) {
+ return true;
+#endif
+#ifdef QT_QWS_DEPTH_15
+ } else if (d == 15) {
+ return true;
+#endif
+#ifdef QT_QWS_DEPTH_18
+ } else if(d==18 || d==19) {
+ return true;
+#endif
+#ifdef QT_QWS_DEPTH_24
+ } else if(d==24) {
+ return true;
+#endif
+#ifdef QT_QWS_DEPTH_32
+ } else if(d==32) {
+ return true;
+#endif
+ }
+ return false;
+}
+
+/*!
+ \fn bool QScreen::onCard(const unsigned char *buffer) const
+
+ Returns true if the specified \a buffer is within the graphics
+ card's memory; otherwise returns false (i.e. if it's in main RAM).
+
+ \sa base(), totalSize()
+*/
+
+bool QScreen::onCard(const unsigned char * p) const
+{
+ long t=(unsigned long)p;
+ long bmin=(unsigned long)data;
+ if (t < bmin)
+ return false;
+ if(t >= bmin+mapsize)
+ return false;
+ return true;
+}
+
+/*!
+ \fn bool QScreen::onCard(const unsigned char * buffer, ulong& offset) const
+ \overload
+
+ If the specified \a buffer is within the graphics card's memory,
+ this function stores the offset from the start of graphics card
+ memory (in bytes), in the location specified by the \a offset
+ parameter.
+*/
+
+bool QScreen::onCard(const unsigned char * p, ulong& offset) const
+{
+ long t=(unsigned long)p;
+ long bmin=(unsigned long)data;
+ if (t < bmin)
+ return false;
+ long o = t - bmin;
+ if (o >= mapsize)
+ return false;
+ offset = o;
+ return true;
+}
+
+/*
+#if !defined(QT_NO_QWS_REPEATER)
+ { "Repeater", qt_get_screen_repeater, 0 },
+#endif
+#if defined(QT_QWS_EE)
+ { "EE", qt_get_screen_ee, 0 },
+#endif
+
+*/
+
+/*
+Given a display_id (number of the \l{Qt for Embedded Linux} server to connect to)
+and a spec (e.g. Mach64:/dev/fb0) return a QScreen-descendant.
+The QScreenDriverFactory is queried for a suitable driver and, if found,
+asked to create a driver.
+People writing new graphics drivers should either hook their own
+QScreen-descendant into QScreenDriverFactory or use the QScreenDriverPlugin
+to make a dynamically loadable driver.
+*/
+
+Q_GUI_EXPORT QScreen* qt_get_screen(int display_id, const char *spec)
+{
+ QString displaySpec = QString::fromAscii(spec);
+ QString driver = displaySpec;
+ int colon = displaySpec.indexOf(QLatin1Char(':'));
+ if (colon >= 0)
+ driver.truncate(colon);
+ driver = driver.trimmed();
+
+ bool foundDriver = false;
+ QString driverName = driver;
+
+ QStringList driverList;
+ if (!driver.isEmpty())
+ driverList << driver;
+ else
+ driverList = QScreenDriverFactory::keys();
+
+ for (int i = 0; i < driverList.size(); ++i) {
+ const QString driverName = driverList.at(i);
+ qt_screen = QScreenDriverFactory::create(driverName, display_id);
+ if (qt_screen) {
+ foundDriver = true;
+ if (qt_screen->connect(displaySpec)) {
+ return qt_screen;
+ } else {
+ delete qt_screen;
+ qt_screen = 0;
+ }
+ }
+ }
+
+ if (driver.isNull())
+ qFatal("No suitable driver found");
+ else if (foundDriver)
+ qFatal("%s: driver cannot connect", driver.toLatin1().constData());
+ else
+ qFatal("%s: driver not found", driver.toLatin1().constData());
+
+ return 0;
+}
+
+#ifndef QT_NO_QWS_CURSOR
+static void blendCursor(QImage *dest, const QImage &cursor, const QPoint &offset)
+{
+ QRasterBuffer rb;
+ rb.prepare(dest);
+
+ QSpanData spanData;
+ spanData.init(&rb, 0);
+ spanData.type = QSpanData::Texture;
+ spanData.initTexture(&cursor, 256);
+ spanData.dx = -offset.x();
+ spanData.dy = -offset.y();
+ if (!spanData.blend)
+ return;
+
+ const QRect rect = QRect(offset, cursor.size())
+ & QRect(QPoint(0, 0), dest->size());
+ const int w = rect.width();
+ const int h = rect.height();
+
+ QVarLengthArray<QT_FT_Span, 32> spans(h);
+ for (int i = 0; i < h; ++i) {
+ spans[i].x = rect.x();
+ spans[i].len = w;
+ spans[i].y = rect.y() + i;
+ spans[i].coverage = 255;
+ }
+ spanData.blend(h, spans.constData(), &spanData);
+}
+#endif // QT_NO_QWS_CURSOR
+
+/*!
+ \fn void QScreen::exposeRegion(QRegion region, int windowIndex)
+
+ This function is called by the \l{Qt for Embedded Linux} server whenever a
+ screen update is required. \a region is the area on the screen
+ that must be updated, and \a windowIndex is the index into
+ QWSServer::clientWindows() of the window that required the
+ update. QWSWindow::state() gives more information about the cause.
+
+ The default implementation composes the
+ affected windows and paints the given \a region on screen by
+ calling the blit() and solidFill() functions
+
+ This function can be reimplemented to perform composition in
+ hardware, or to perform transition effects.
+ For simpler hardware acceleration, or to interface with
+ this is typically done by reimplementing the blit() and
+ solidFill() functions instead.
+
+ Note that there is no need to call this function explicitly.
+
+ \sa blit(), solidFill(), blank()
+*/
+void QScreen::exposeRegion(QRegion r, int windowIndex)
+{
+ r &= region();
+ if (r.isEmpty())
+ return;
+
+ int changing = windowIndex;
+ // when we have just lowered a window, we have to expose all the windows below where the
+ // window used to be.
+ if (changing && qwsServer->clientWindows().at(changing)->state() == QWSWindow::Lowering)
+ changing = 0;
+#ifdef QTOPIA_PERFTEST
+ static enum { PerfTestUnknown, PerfTestOn, PerfTestOff } perfTestState = PerfTestUnknown;
+ if(PerfTestUnknown == perfTestState) {
+ if(::getenv("QTOPIA_PERFTEST"))
+ perfTestState = PerfTestOn;
+ else
+ perfTestState = PerfTestOff;
+ }
+ if(PerfTestOn == perfTestState) {
+ QWSWindow *changed = qwsServer->clientWindows().at(changing);
+ if(!changed->client()->identity().isEmpty())
+ qDebug() << "Performance : expose_region :"
+ << changed->client()->identity()
+ << r.boundingRect() << ": "
+ << qPrintable( QTime::currentTime().toString( "h:mm:ss.zzz" ) );
+ }
+#endif
+
+ const QRect bounds = r.boundingRect();
+ QRegion blendRegion;
+ QImage *blendBuffer = 0;
+
+#ifndef QT_NO_QWS_CURSOR
+ if (qt_screencursor && !qt_screencursor->isAccelerated()) {
+ blendRegion = r & qt_screencursor->boundingRect();
+ }
+#endif
+ compose(0, r, blendRegion, &blendBuffer, changing);
+
+ if (blendBuffer) {
+ const QPoint offset = blendRegion.boundingRect().topLeft();
+#ifndef QT_NO_QWS_CURSOR
+ if (qt_screencursor && !qt_screencursor->isAccelerated()) {
+ const QRect cursorRect = qt_screencursor->boundingRect();
+ if (blendRegion.intersects(cursorRect)) {
+ blendCursor(blendBuffer, qt_screencursor->image(),
+ cursorRect.topLeft() - offset);
+ }
+ }
+#endif // QT_NO_QWS_CURSOR
+ blit(*blendBuffer, offset, blendRegion);
+ delete blendBuffer;
+ }
+
+ if (r.numRects() == 1) {
+ setDirty(r.boundingRect());
+ } else {
+ const QVector<QRect> rects = r.rects();
+ for (int i = 0; i < rects.size(); ++i)
+ setDirty(rects.at(i));
+ }
+}
+
+/*!
+ \fn void QScreen::blit(const QImage &image, const QPoint &topLeft, const QRegion &region)
+
+ Copies the given \a region in the given \a image to the point
+ specified by \a topLeft using device coordinates.
+
+ This function is called from the exposeRegion() function; it is
+ not intended to be called explicitly.
+
+ Reimplement this function to make use of \l{Adding an Accelerated
+ Graphics Driver to Qt for Embedded Linux}{accelerated hardware}. Note that
+ this function must be reimplemented if the framebuffer format is
+ not supported by \l{Qt for Embedded Linux} (See the
+ \l{Qt for Embedded Linux Display Management}{Display Management}
+ documentation for more details).
+
+ \sa exposeRegion(), solidFill(), blank()
+*/
+void QScreen::blit(const QImage &img, const QPoint &topLeft, const QRegion &reg)
+{
+ const QRect bound = (region() & QRect(topLeft, img.size())).boundingRect();
+ QWSDisplay::grab();
+ d_ptr->blit(this, img, topLeft - offset(),
+ (reg & bound).translated(-topLeft));
+ QWSDisplay::ungrab();
+}
+
+#ifdef QT_QWS_CLIENTBLIT
+/*!
+ Returns true if this screen driver supports calling QScreen::blit() and
+ QScreen::setDirty() directly from non-server applications, otherwise returns
+ false.
+
+ If available, this is used to optimize the performance of non-occluded, opaque
+ client windows by removing the server round trip when they are updated.
+
+ \sa setSupportsBlitInClients()
+ */
+bool QScreen::supportsBlitInClients() const
+{
+ return d_ptr->supportsBlitInClients;
+}
+
+/*!
+ If \a supported, the screen driver is marked as supporting blitting directly
+ from non-server applications.
+
+ \sa supportsBlitInClients()
+ */
+void QScreen::setSupportsBlitInClients(bool supported)
+{
+ d_ptr->supportsBlitInClients = supported;
+}
+#endif
+
+/*!
+ \internal
+*/
+
+void QScreen::blit(QWSWindow *win, const QRegion &clip)
+{
+ QWSWindowSurface *surface = win->windowSurface();
+ if (!surface)
+ return;
+
+ const QImage &img = surface->image();
+ if (img.isNull())
+ return;
+
+ const QRegion rgn = clip & win->paintedRegion();
+ if (rgn.isEmpty())
+ return;
+
+ surface->lock();
+ blit(img, win->requestedRegion().boundingRect().topLeft(), rgn);
+ surface->unlock();
+}
+
+struct fill_data {
+ quint32 color;
+ uchar *data;
+ int lineStep;
+ int x;
+ int y;
+ int w;
+ int h;
+};
+
+/*!
+ Fills the given \a region of the screen with the specified \a
+ color.
+
+ This function is called from the exposeRegion() function; it is
+ not intended to be called explicitly.
+
+ Reimplement this function to make use of \l{Adding an Accelerated
+ Graphics Driver to Qt for Embedded Linux}{accelerated hardware}. Note that
+ this function must be reimplemented if the framebuffer format is
+ not supported by \l{Qt for Embedded Linux} (See the
+ \l{Qt for Embedded Linux Display Management}{Display Management}
+ documentation for more details).
+
+ \sa exposeRegion(), blit(), blank()
+*/
+// the base class implementation works in device coordinates, so that transformed drivers can use it
+void QScreen::solidFill(const QColor &color, const QRegion &region)
+{
+ QWSDisplay::grab();
+ d_ptr->solidFill(this, color,
+ region.translated(-offset()) & QRect(0, 0, dw, dh));
+ QWSDisplay::ungrab();
+}
+
+/*!
+ \since 4.2
+
+ Creates and returns a new window surface matching the given \a
+ key.
+
+ The server application will call this function whenever it needs
+ to create a server side representation of a window, e.g. when
+ copying the content of memory to the screen using the screen
+ driver.
+
+ Note that this function must be reimplemented when adding an
+ accelerated graphics driver. See the
+ \l{Adding an Accelerated Graphics Driver to Qt for Embedded Linux}
+ {Adding an Accelerated Graphics Driver} documentation for details.
+
+ \sa {Qt for Embedded Linux Architecture}
+*/
+QWSWindowSurface* QScreen::createSurface(const QString &key) const
+{
+#ifndef QT_NO_PAINTONSCREEN
+ if (key == QLatin1String("OnScreen"))
+ return new QWSOnScreenSurface;
+ else
+#endif
+ if (key == QLatin1String("mem"))
+ return new QWSLocalMemSurface;
+#ifndef QT_NO_QWS_MULTIPROCESS
+ else if (key == QLatin1String("shm"))
+ return new QWSSharedMemSurface;
+#endif
+#ifndef QT_NO_PAINT_DEBUG
+ else if (key == QLatin1String("Yellow"))
+ return new QWSYellowSurface;
+#endif
+#ifndef QT_NO_DIRECTPAINTER
+ else if (key == QLatin1String("DirectPainter"))
+ return new QWSDirectPainterSurface;
+#endif
+
+ return 0;
+}
+
+#ifndef QT_NO_PAINTONSCREEN
+bool QScreen::isWidgetPaintOnScreen(const QWidget *w)
+{
+ static int doOnScreen = -1;
+ if (doOnScreen == -1) {
+ const QByteArray env = qgetenv("QT_ONSCREEN_PAINT");
+ if (env == "force")
+ doOnScreen = 2;
+ else
+ doOnScreen = (env.toInt() > 0 ? 1 : 0);
+ }
+
+ if (doOnScreen == 2) // force
+ return true;
+
+ if (doOnScreen == 0 && !w->testAttribute(Qt::WA_PaintOnScreen))
+ return false;
+
+ return w->d_func()->isOpaque;
+}
+#endif
+
+/*!
+ \overload
+
+ Creates and returns a new window surface for the given \a widget.
+*/
+QWSWindowSurface* QScreen::createSurface(QWidget *widget) const
+{
+#ifndef QT_NO_PAINTONSCREEN
+ if (isWidgetPaintOnScreen(widget) && base())
+ return new QWSOnScreenSurface(widget);
+ else
+#endif
+ if (QApplication::type() == QApplication::GuiServer)
+ return new QWSLocalMemSurface(widget);
+#ifndef QT_NO_QWS_MULTIPROCESS
+ else
+ return new QWSSharedMemSurface(widget);
+#endif
+
+ return 0;
+}
+
+void QScreen::compose(int level, const QRegion &exposed, QRegion &blend,
+ QImage **blendbuffer, int changing_level)
+{
+ QRect exposed_bounds = exposed.boundingRect();
+ QWSWindow *win = 0;
+ do {
+ win = qwsServer->clientWindows().value(level); // null is background
+ ++level;
+ } while (win && !win->paintedRegion().boundingRect().intersects(exposed_bounds));
+
+ QWSWindowSurface *surface = (win ? win->windowSurface() : 0);
+ bool above_changing = level <= changing_level; // 0 is topmost
+
+ QRegion exposedBelow = exposed;
+ bool opaque = true;
+
+ if (win) {
+ opaque = win->isOpaque() || !surface->isBuffered();
+ if (opaque) {
+ exposedBelow -= win->paintedRegion();
+ if (above_changing || !surface->isBuffered())
+ blend -= exposed & win->paintedRegion();
+ } else {
+ blend += exposed & win->paintedRegion();
+ }
+ }
+ if (win && !exposedBelow.isEmpty()) {
+ compose(level, exposedBelow, blend, blendbuffer, changing_level);
+ } else {
+ QSize blendSize = blend.boundingRect().size();
+ if (!blendSize.isNull()) {
+ *blendbuffer = new QImage(blendSize, d_ptr->preferredImageFormat());
+ }
+ }
+
+ const QRegion blitRegion = exposed - blend;
+ if (!win)
+ paintBackground(blitRegion);
+ else if (!above_changing && surface->isBuffered())
+ blit(win, blitRegion);
+
+ QRegion blendRegion = exposed & blend;
+
+ if (win)
+ blendRegion &= win->paintedRegion();
+ if (!blendRegion.isEmpty()) {
+
+ QPoint off = blend.boundingRect().topLeft();
+
+ QRasterBuffer rb;
+ rb.prepare(*blendbuffer);
+ QSpanData spanData;
+ spanData.init(&rb, 0);
+ if (!win) {
+ const QImage::Format format = (*blendbuffer)->format();
+ switch (format) {
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_ARGB6666_Premultiplied:
+ case QImage::Format_ARGB4444_Premultiplied:
+ spanData.rasterBuffer->compositionMode = QPainter::CompositionMode_Source;
+ break;
+ default:
+ break;
+ }
+ spanData.setup(qwsServer->backgroundBrush(), 256);
+ spanData.dx = off.x();
+ spanData.dy = off.y();
+ } else if (!surface->isBuffered()) {
+ return;
+ } else {
+ const QImage &img = surface->image();
+ QPoint winoff = off - win->requestedRegion().boundingRect().topLeft();
+ // convert win->opacity() from scale [0..255] to [0..256]
+ int const_alpha = win->opacity();
+ const_alpha += (const_alpha >> 7);
+ spanData.type = QSpanData::Texture;
+ spanData.initTexture(&img, const_alpha);
+ spanData.dx = winoff.x();
+ spanData.dy = winoff.y();
+ }
+ if (!spanData.blend)
+ return;
+
+ if (surface)
+ surface->lock();
+ const QVector<QRect> rects = blendRegion.rects();
+ const int nspans = 256;
+ QT_FT_Span spans[nspans];
+ for (int i = 0; i < rects.size(); ++i) {
+ int y = rects.at(i).y() - off.y();
+ int ye = y + rects.at(i).height();
+ int x = rects.at(i).x() - off.x();
+ int len = rects.at(i).width();
+ while (y < ye) {
+ int n = qMin(nspans, ye - y);
+ int i = 0;
+ while (i < n) {
+ spans[i].x = x;
+ spans[i].len = len;
+ spans[i].y = y + i;
+ spans[i].coverage = 255;
+ ++i;
+ }
+ spanData.blend(n, spans, &spanData);
+ y += n;
+ }
+ }
+ if (surface)
+ surface->unlock();
+ }
+}
+
+void QScreen::paintBackground(const QRegion &r)
+{
+ const QBrush &bg = qwsServer->backgroundBrush();
+ Qt::BrushStyle bs = bg.style();
+ if (bs == Qt::NoBrush || r.isEmpty())
+ return;
+
+ if (bs == Qt::SolidPattern) {
+ solidFill(bg.color(), r);
+ } else {
+ const QRect br = r.boundingRect();
+ QImage img(br.size(), d_ptr->preferredImageFormat());
+ QPoint off = br.topLeft();
+ QRasterBuffer rb;
+ rb.prepare(&img);
+ QSpanData spanData;
+ spanData.init(&rb, 0);
+ spanData.setup(bg, 256);
+ spanData.dx = off.x();
+ spanData.dy = off.y();
+ Q_ASSERT(spanData.blend);
+
+ const QVector<QRect> rects = r.rects();
+ const int nspans = 256;
+ QT_FT_Span spans[nspans];
+ for (int i = 0; i < rects.size(); ++i) {
+ int y = rects.at(i).y() - off.y();
+ int ye = y + rects.at(i).height();
+ int x = rects.at(i).x() - off.x();
+ int len = rects.at(i).width();
+ while (y < ye) {
+ int n = qMin(nspans, ye - y);
+ int i = 0;
+ while (i < n) {
+ spans[i].x = x;
+ spans[i].len = len;
+ spans[i].y = y + i;
+ spans[i].coverage = 255;
+ ++i;
+ }
+ spanData.blend(n, spans, &spanData);
+ y += n;
+ }
+ }
+ blit(img, br.topLeft(), r);
+ }
+}
+
+/*!
+ \fn virtual int QScreen::sharedRamSize(void *)
+
+ \internal
+*/
+
+/*!
+ \fn QScreen::setDirty(const QRect& rectangle)
+
+ Marks the given \a rectangle as dirty.
+
+ Note that the default implementation does nothing; reimplement
+ this function to indicate that the given \a rectangle has been
+ altered.
+*/
+
+void QScreen::setDirty(const QRect&)
+{
+}
+
+/*!
+ \fn QScreen::isTransformed() const
+
+ Returns true if the screen is transformed (for instance, rotated
+ 90 degrees); otherwise returns false.
+
+ \sa transformOrientation(), isInterlaced()
+*/
+
+bool QScreen::isTransformed() const
+{
+ return false;
+}
+
+/*!
+ \fn QScreen::isInterlaced() const
+
+ Returns true if the display is interlaced (i.e. is displaying
+ images progressively like a television screen); otherwise returns
+ false.
+
+ If the display is interlaced, the drawing is altered to look
+ better.
+
+ \sa isTransformed(), linestep()
+*/
+
+bool QScreen::isInterlaced() const
+{
+ return false;//qws_screen_is_interlaced;;
+}
+
+/*!
+ \fn QScreen::mapToDevice(const QSize &size) const
+
+ Maps the given \a size from the coordinate space used by the
+ application to the framebuffer coordinate system. Note that the
+ default implementation simply returns the given \a size as it is.
+
+ Reimplement this function to use the given device's coordinate
+ system when mapping.
+
+ \sa mapFromDevice()
+*/
+
+QSize QScreen::mapToDevice(const QSize &s) const
+{
+ return s;
+}
+
+/*!
+ \fn QScreen::mapFromDevice(const QSize &size) const
+
+ Maps the given \a size from the framebuffer coordinate system to
+ the coordinate space used by the application. Note that the
+ default implementation simply returns the given \a size as it is.
+
+ Reimplement this function to use the given device's coordinate
+ system when mapping.
+
+ \sa mapToDevice()
+*/
+
+QSize QScreen::mapFromDevice(const QSize &s) const
+{
+ return s;
+}
+
+/*!
+ \fn QScreen::mapToDevice(const QPoint &point, const QSize &screenSize) const
+ \overload
+
+ Maps the given \a point from the coordinate space used by the
+ application to the framebuffer coordinate system, passing the
+ device's \a screenSize as argument. Note that the default
+ implementation returns the given \a point as it is.
+*/
+
+QPoint QScreen::mapToDevice(const QPoint &p, const QSize &) const
+{
+ return p;
+}
+
+/*!
+ \fn QScreen::mapFromDevice(const QPoint &point, const QSize &screenSize) const
+ \overload
+
+ Maps the given \a point from the framebuffer coordinate system to
+ the coordinate space used by the application, passing the device's
+ \a screenSize as argument. Note that the default implementation
+ simply returns the given \a point as it is.
+*/
+
+QPoint QScreen::mapFromDevice(const QPoint &p, const QSize &) const
+{
+ return p;
+}
+
+/*!
+ \fn QScreen::mapToDevice(const QRect &rectangle, const QSize &screenSize) const
+ \overload
+
+ Maps the given \a rectangle from the coordinate space used by the
+ application to the framebuffer coordinate system, passing the
+ device's \a screenSize as argument. Note that the default
+ implementation returns the given \a rectangle as it is.
+*/
+
+QRect QScreen::mapToDevice(const QRect &r, const QSize &) const
+{
+ return r;
+}
+
+/*!
+ \fn QScreen::mapFromDevice(const QRect &rectangle, const QSize &screenSize) const
+ \overload
+
+ Maps the given \a rectangle from the framebuffer coordinate system to
+ the coordinate space used by the application, passing the device's
+ \a screenSize as argument. Note that the default implementation
+ simply returns the given \a rectangle as it is.
+*/
+
+QRect QScreen::mapFromDevice(const QRect &r, const QSize &) const
+{
+ return r;
+}
+
+/*!
+ \fn QScreen::mapToDevice(const QImage &image) const
+ \overload
+
+ Maps the given \a image from the coordinate space used by the
+ application to the framebuffer coordinate system. Note that the
+ default implementation returns the given \a image as it is.
+*/
+
+QImage QScreen::mapToDevice(const QImage &i) const
+{
+ return i;
+}
+
+/*!
+ \fn QScreen::mapFromDevice(const QImage &image) const
+ \overload
+
+ Maps the given \a image from the framebuffer coordinate system to
+ the coordinate space used by the application. Note that the
+ default implementation simply returns the given \a image as it is.
+*/
+
+QImage QScreen::mapFromDevice(const QImage &i) const
+{
+ return i;
+}
+
+/*!
+ \fn QScreen::mapToDevice(const QRegion &region, const QSize &screenSize) const
+ \overload
+
+ Maps the given \a region from the coordinate space used by the
+ application to the framebuffer coordinate system, passing the
+ device's \a screenSize as argument. Note that the default
+ implementation returns the given \a region as it is.
+*/
+
+QRegion QScreen::mapToDevice(const QRegion &r, const QSize &) const
+{
+ return r;
+}
+
+/*!
+ \fn QScreen::mapFromDevice(const QRegion &region, const QSize &screenSize) const
+ \overload
+
+ Maps the given \a region from the framebuffer coordinate system to
+ the coordinate space used by the application, passing the device's
+ \a screenSize as argument. Note that the default implementation
+ simply returns the given \a region as it is.
+*/
+
+QRegion QScreen::mapFromDevice(const QRegion &r, const QSize &) const
+{
+ return r;
+}
+
+/*!
+ \fn QScreen::transformOrientation() const
+
+ Returns the current rotation as an integer value.
+
+ Note that the default implementation returns 0; reimplement this
+ function to override this value.
+
+ \sa isTransformed()
+*/
+
+int QScreen::transformOrientation() const
+{
+ return 0;
+}
+
+int QScreen::pixmapDepth() const
+{
+ return depth();
+}
+
+/*!
+ \internal
+*/
+int QScreen::memoryNeeded(const QString&)
+{
+ return 0;
+}
+
+/*!
+ \internal
+*/
+void QScreen::haltUpdates()
+{
+}
+
+/*!
+ \internal
+*/
+void QScreen::resumeUpdates()
+{
+}
+
+/*!
+ \fn QRegion QScreen::region() const
+ \since 4.2
+
+ Returns the region covered by this screen driver.
+
+ \sa base(), screenSize()
+*/
+
+/*!
+ \internal
+*/
+void QScreen::setOffset(const QPoint &p)
+{
+ d_ptr->offset = p;
+}
+
+/*!
+ \since 4.2
+
+ Returns the logical offset of the screen, i.e., the offset between
+ (0,0) in screen coordinates and the application coordinate system.
+*/
+QPoint QScreen::offset() const
+{
+ return d_ptr->offset;
+}
+
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+void QScreen::setFrameBufferLittleEndian(bool littleEndian)
+{
+ d_ptr->fb_is_littleEndian = littleEndian;
+}
+
+bool QScreen::frameBufferLittleEndian() const
+{
+ return d_ptr->fb_is_littleEndian;
+}
+#endif
+
+/*!
+ \fn int QScreen::subScreenIndexAt(const QPoint &position) const
+ \since 4.2
+
+ Returns the index of the subscreen at the given \a position;
+ returns -1 if no screen is found.
+
+ The index identifies the subscreen in the list of pointers
+ returned by the subScreens() function.
+
+ \sa instance(), subScreens()
+*/
+int QScreen::subScreenIndexAt(const QPoint &p) const
+{
+ const QList<QScreen*> screens = subScreens();
+ const int n = screens.count();
+ for (int i = 0; i < n; ++i) {
+ if (screens.at(i)->region().contains(p))
+ return i;
+ }
+
+ return -1;
+}
+
+#if 0
+#ifdef QT_LOADABLE_MODULES
+
+// ### needs update after driver init changes
+
+static QScreen * qt_dodriver(char * driver,char * a,unsigned char * b)
+
+{
+ char buf[200];
+ strcpy(buf,"/etc/qws/drivers/");
+ qstrcpy(buf+17,driver);
+ qDebug("Attempting driver %s",driver);
+
+ void * handle;
+ handle=dlopen(buf,RTLD_LAZY);
+ if(handle==0) {
+ qFatal("Module load error");
+ }
+ QScreen *(*qt_get_screen_func)(char *,unsigned char *);
+ qt_get_screen_func=dlsym(handle,"qt_get_screen");
+ if(qt_get_screen_func==0) {
+ qFatal("Couldn't get symbol");
+ }
+ QScreen * ret=qt_get_screen_func(a,b);
+ return ret;
+}
+
+static QScreen * qt_do_entry(char * entry)
+{
+ unsigned char config[256];
+
+ FILE * f=fopen(entry,"r");
+ if(!f) {
+ return 0;
+ }
+
+ int r=fread(config,256,1,f);
+ if(r<1)
+ return 0;
+
+ fclose(f);
+
+ unsigned short vendorid=*((unsigned short int *)config);
+ unsigned short deviceid=*(((unsigned short int *)config)+1);
+ if(config[0xb]!=3)
+ return 0;
+
+ if(vendorid==0x1002) {
+ if(deviceid==0x4c4d) {
+ qDebug("Compaq Armada/IBM Thinkpad's Mach64 card");
+ return qt_dodriver("mach64.so",entry,config);
+ } else if(deviceid==0x4742) {
+ qDebug("Desktop Rage Pro Mach64 card");
+ return qt_dodriver("mach64.so",entry,config);
+ } else {
+ qDebug("Unrecognised ATI card id %x",deviceid);
+ return 0;
+ }
+ } else {
+ qDebug("Unrecognised vendor");
+ }
+ return 0;
+}
+
+extern bool qws_accel;
+
+/// ** NOT SUPPPORTED **
+
+QScreen * qt_probe_bus()
+{
+ if(!qws_accel) {
+ return qt_dodriver("unaccel.so",0,0);
+ }
+
+ DIR * dirptr=opendir("/proc/bus/pci");
+ if(!dirptr)
+ return qt_dodriver("unaccel.so",0,0);
+ DIR * dirptr2;
+ dirent * cards;
+
+ dirent * busses=readdir(dirptr);
+
+ while(busses) {
+ if(busses->d_name[0]!='.') {
+ char buf[100];
+ strcpy(buf,"/proc/bus/pci/");
+ qstrcpy(buf+14,busses->d_name);
+ int p=strlen(buf);
+ dirptr2=opendir(buf);
+ if(dirptr2) {
+ cards=readdir(dirptr2);
+ while(cards) {
+ if(cards->d_name[0]!='.') {
+ buf[p]='/';
+ qstrcpy(buf+p+1,cards->d_name);
+ QScreen * ret=qt_do_entry(buf);
+ if(ret)
+ return ret;
+ }
+ cards=readdir(dirptr2);
+ }
+ closedir(dirptr2);
+ }
+ }
+ busses=readdir(dirptr);
+ }
+ closedir(dirptr);
+
+ return qt_dodriver("unaccel.so",0,0);
+}
+
+#else
+
+char *qt_qws_hardcoded_slot = "/proc/bus/pci/01/00.0";
+
+const unsigned char* qt_probe_bus()
+{
+ const char * slot;
+ slot=::getenv("QWS_CARD_SLOT");
+ if(!slot)
+ slot=qt_qws_hardcoded_slot;
+ if (slot) {
+ static unsigned char config[256];
+ FILE * f=fopen(slot,"r");
+ if(!f) {
+ qDebug("Open failure for %s",slot);
+ slot=0;
+ } else {
+ int r=fread((char*)config,256,1,f);
+ fclose(f);
+ if(r<1) {
+ qDebug("Read failure");
+ return 0;
+ } else {
+ return config;
+ }
+ }
+ }
+ return 0;
+}
+
+#endif
+
+#endif // 0
+
+/*!
+ \internal
+ \since 4.4
+*/
+void QScreen::setPixmapDataFactory(QPixmapDataFactory *factory)
+{
+ static bool shownWarning = false;
+ if (!shownWarning) {
+ qWarning("QScreen::setPixmapDataFactory() is deprecated - use setGraphicsSystem() instead");
+ shownWarning = true;
+ }
+
+ d_ptr->pixmapFactory = factory;
+}
+
+/*!
+ \internal
+ \since 4.4
+*/
+QPixmapDataFactory* QScreen::pixmapDataFactory() const
+{
+ return d_ptr->pixmapFactory;
+}
+
+/*!
+ \internal
+ \since 4.5
+*/
+void QScreen::setGraphicsSystem(QGraphicsSystem* system)
+{
+ d_ptr->graphicsSystem = system;
+}
+
+/*!
+ \internal
+ \since 4.5
+*/
+QGraphicsSystem* QScreen::graphicsSystem() const
+{
+ return d_ptr->graphicsSystem;
+}
+
+/*!
+ \since 4.4
+
+ Returns the class identifier for the screen object.
+*/
+QScreen::ClassId QScreen::classId() const
+{
+ return static_cast<ClassId>(d_ptr->classId);
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qscreen_qws.h b/src/gui/embedded/qscreen_qws.h
new file mode 100644
index 0000000000..e7773178cd
--- /dev/null
+++ b/src/gui/embedded/qscreen_qws.h
@@ -0,0 +1,387 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCREEN_QWS_H
+#define QSCREEN_QWS_H
+
+#include <QtCore/qnamespace.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qlist.h>
+#include <QtGui/qrgb.h>
+#include <QtCore/qrect.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qregion.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QScreenCursor;
+class QBrush;
+class QWSWindow;
+class QWSWindowSurface;
+class QGraphicsSystem;
+class QPixmapData;
+
+#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(const int r, const int g, const int b)
+{
+ const int tr = r << qt_red_shift;
+ const int tg = g << qt_green_shift;
+ const int tb = b >> qt_neg_blue_shift;
+
+ return (tb & qt_blue_mask) | (tg & qt_green_mask) | (tr & qt_red_mask);
+}
+
+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);
+}
+
+inline void qt_conv16ToRgb(ushort c, int& r, int& g, int& b)
+{
+ const int tr=(c & qt_red_mask);
+ const int tg=(c & qt_green_mask);
+ const int tb=(c & qt_blue_mask);
+ r = tr >> qt_red_shift | tr >> qt_red_rounding_shift;
+ g = tg >> qt_green_shift | tg >> qt_green_rounding_shift;
+ b = tb << qt_neg_blue_shift | tb >> qt_blue_rounding_shift;
+}
+
+const int SourceSolid=0;
+const int SourcePixmap=1;
+
+#ifndef QT_NO_QWS_CURSOR
+
+class QScreenCursor;
+extern QScreenCursor *qt_screencursor;
+extern bool qt_sw_cursor;
+
+class Q_GUI_EXPORT QScreenCursor
+{
+public:
+ QScreenCursor();
+ virtual ~QScreenCursor();
+
+ virtual void set(const QImage &image, int hotx, int hoty);
+ virtual void move(int x, int y);
+ virtual void show();
+ virtual void hide();
+
+ bool supportsAlphaCursor() const { return supportsAlpha; }
+
+ static bool enabled() { return qt_sw_cursor; }
+
+ QRect boundingRect() const { return QRect(pos - hotspot, size); }
+ QImage image() const { return cursor; }
+ bool isVisible() const { return enable; }
+ bool isAccelerated() const { return hwaccel; }
+
+ static void initSoftwareCursor();
+ static QScreenCursor* instance() { return qt_screencursor; }
+
+protected:
+ QImage cursor;
+
+ QSize size;
+ QPoint pos;
+ QPoint hotspot;
+ uint enable : 1;
+ uint hwaccel : 1;
+ uint supportsAlpha : 1;
+
+private:
+ friend class QProxyScreenCursor;
+};
+
+#endif // QT_NO_QWS_CURSOR
+
+struct fb_cmap;
+
+// A (used) chunk of offscreen memory
+
+class QPoolEntry
+{
+public:
+ unsigned int start;
+ unsigned int end;
+ int clientId;
+};
+
+class QScreen;
+class QScreenPrivate;
+class QPixmapDataFactory;
+
+extern Q_GUI_EXPORT QScreen *qt_screen;
+typedef void(*ClearCacheFunc)(QScreen *obj, int);
+
+class Q_GUI_EXPORT QScreen {
+
+public:
+ enum ClassId { LinuxFBClass, TransformedClass, VNCClass, MultiClass,
+ VFbClass, DirectFBClass, SvgalibClass, ProxyClass,
+ GLClass, CustomClass = 1024 };
+
+ QScreen(int display_id, ClassId classId);
+ explicit QScreen(int display_id);
+ virtual ~QScreen();
+ static QScreen* instance() { return qt_screen; }
+ virtual bool initDevice() = 0;
+ virtual bool connect(const QString &displaySpec) = 0;
+ virtual void disconnect() = 0;
+ virtual void shutdownDevice();
+ virtual void setMode(int,int,int) = 0;
+ virtual bool supportsDepth(int) const;
+
+ virtual void save();
+ virtual void restore();
+ virtual void blank(bool on);
+
+ virtual int pixmapOffsetAlignment() { return 64; }
+ virtual int pixmapLinestepAlignment() { return 64; }
+ virtual int sharedRamSize(void *) { return 0; }
+
+ virtual bool onCard(const unsigned char *) const;
+ virtual bool onCard(const unsigned char *, ulong& out_offset) const;
+
+ enum PixelType { NormalPixel, BGRPixel };
+
+ // sets a single color in the colormap
+ virtual void set(unsigned int,unsigned int,unsigned int,unsigned int);
+ // allocates a color
+ virtual int alloc(unsigned int,unsigned int,unsigned int);
+
+ int width() const { return w; }
+ int height() const { return h; }
+ int depth() const { return d; }
+ virtual int pixmapDepth() const;
+ PixelType pixelType() const { return pixeltype; }
+ int linestep() const { return lstep; }
+ int deviceWidth() const { return dw; }
+ int deviceHeight() const { return dh; }
+ uchar * base() const { return data; }
+ // Ask for memory from card cache with alignment
+ virtual uchar * cache(int) { return 0; }
+ virtual void uncache(uchar *) {}
+
+ QImage::Format pixelFormat() const;
+
+ int screenSize() const { return size; }
+ int totalSize() const { return mapsize; }
+
+ QRgb * clut() { return screenclut; }
+ int numCols() { return screencols; }
+
+ virtual QSize mapToDevice(const QSize &) const;
+ virtual QSize mapFromDevice(const QSize &) const;
+ virtual QPoint mapToDevice(const QPoint &, const QSize &) const;
+ virtual QPoint mapFromDevice(const QPoint &, const QSize &) const;
+ virtual QRect mapToDevice(const QRect &, const QSize &) const;
+ virtual QRect mapFromDevice(const QRect &, const QSize &) const;
+ virtual QImage mapToDevice(const QImage &) const;
+ virtual QImage mapFromDevice(const QImage &) const;
+ virtual QRegion mapToDevice(const QRegion &, const QSize &) const;
+ virtual QRegion mapFromDevice(const QRegion &, const QSize &) const;
+ virtual int transformOrientation() const;
+ virtual bool isTransformed() const;
+ virtual bool isInterlaced() const;
+
+ virtual void setDirty(const QRect&);
+
+ virtual int memoryNeeded(const QString&);
+
+ virtual void haltUpdates();
+ virtual void resumeUpdates();
+
+ // composition manager methods
+ virtual void exposeRegion(QRegion r, int changing);
+
+ // these work directly on the screen
+ virtual void blit(const QImage &img, const QPoint &topLeft, const QRegion &region);
+ virtual void solidFill(const QColor &color, const QRegion &region);
+ void blit(QWSWindow *bs, const QRegion &clip);
+
+ virtual QWSWindowSurface* createSurface(QWidget *widget) const;
+ virtual QWSWindowSurface* createSurface(const QString &key) const;
+
+ virtual QList<QScreen*> subScreens() const { return QList<QScreen*>(); }
+ virtual QRegion region() const { return QRect(offset(), QSize(w, h)); }
+ int subScreenIndexAt(const QPoint &p) const;
+
+ void setOffset(const QPoint &p);
+ QPoint offset() const;
+
+ int physicalWidth() const { return physWidth; } // physical display size in mm
+ int physicalHeight() const { return physHeight; } // physical display size in mm
+
+ QPixmapDataFactory* pixmapDataFactory() const; // Deprecated, will be removed in 4.6
+ QGraphicsSystem* graphicsSystem() const;
+
+#ifdef QT_QWS_CLIENTBLIT
+ bool supportsBlitInClients() const;
+ void setSupportsBlitInClients(bool);
+#endif
+
+ ClassId classId() const;
+
+protected:
+ void setPixelFormat(QImage::Format format);
+ void setPixmapDataFactory(QPixmapDataFactory *factory); // Deprecated, will be removed in 4.6
+ void setGraphicsSystem(QGraphicsSystem* system);
+
+ QRgb screenclut[256];
+ int screencols;
+
+ uchar * data;
+
+ // Table of allocated lumps, kept in sorted highest-to-lowest order
+ // The table itself is allocated at the bottom of offscreen memory
+ // i.e. it's similar to having a stack (the table) and a heap
+ // (the allocated blocks). Freed space is implicitly described
+ // by the gaps between the allocated lumps (this saves entries and
+ // means we don't need to worry about coalescing freed lumps)
+
+ QPoolEntry * entries;
+ int * entryp;
+ unsigned int * lowest;
+
+ 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;
+
+ friend class QWSServer;
+ friend class QWSServerPrivate;
+ static ClearCacheFunc clearCacheFunc;
+
+private:
+ void compose(int level, const QRegion &exposed, QRegion &blend,
+ QImage **blendbuffer, int changing_level);
+ void paintBackground(const QRegion &);
+
+ friend class QWSOnScreenSurface;
+ static bool isWidgetPaintOnScreen(const QWidget *w);
+
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ void setFrameBufferLittleEndian(bool littleEndian);
+ bool frameBufferLittleEndian() const;
+ friend class QVNCScreen;
+ friend class QLinuxFbScreen;
+ friend class QVFbScreen;
+ friend class QProxyScreen;
+#endif
+ friend void qt_solidFill_setup(QScreen*, const QColor&, const QRegion&);
+ friend void qt_blit_setup(QScreen *screen, const QImage &image,
+ const QPoint &topLeft, const QRegion &region);
+#ifdef QT_QWS_DEPTH_GENERIC
+ friend void qt_set_generic_blit(QScreen *screen, int bpp,
+ int len_red, int len_green, int len_blue,
+ int len_alpha, int off_red, int off_green,
+ int off_blue, int off_alpha);
+#endif
+
+ QScreenPrivate *d_ptr;
+};
+
+// This lives in loadable modules
+
+#ifndef QT_LOADABLE_MODULES
+extern "C" QScreen * qt_get_screen(int display_id, const char* spec);
+#endif
+
+// This is in main lib, loads the right module, calls qt_get_screen
+// In non-loadable cases just aliases to qt_get_screen
+
+const unsigned char * qt_probe_bus();
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSCREEN_QWS_H
diff --git a/src/gui/embedded/qscreendriverfactory_qws.cpp b/src/gui/embedded/qscreendriverfactory_qws.cpp
new file mode 100644
index 0000000000..8b17fbae7f
--- /dev/null
+++ b/src/gui/embedded/qscreendriverfactory_qws.cpp
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscreendriverfactory_qws.h"
+
+#include "qscreen_qws.h"
+#include "qapplication.h"
+#include "qscreenlinuxfb_qws.h"
+#include "qscreentransformed_qws.h"
+#include "qscreenvfb_qws.h"
+#include "qscreenmulti_qws_p.h"
+#include <stdlib.h>
+#include "private/qfactoryloader_p.h"
+#include "qscreendriverplugin_qws.h"
+
+#ifndef QT_NO_QWS_VNC
+#include "qscreenvnc_qws.h"
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL)
+#ifndef QT_NO_LIBRARY
+
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QScreenDriverFactoryInterface_iid,
+ QLatin1String("/gfxdrivers"), Qt::CaseInsensitive))
+
+#endif //QT_NO_LIBRARY
+#endif //QT_MAKEDLL
+
+/*!
+ \class QScreenDriverFactory
+ \ingroup qws
+
+ \brief The QScreenDriverFactory class creates screen drivers in
+ Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ QScreenDriverFactory is used to detect and instantiate the
+ available screen drivers, allowing \l{Qt for Embedded Linux} to load the
+ preferred driver into the server application at runtime. The
+ create() function returns a QScreen object representing the screen
+ driver identified by a given key. The valid keys (i.e. the
+ supported drivers) can be retrieved using the keys() function.
+
+
+ \l{Qt for Embedded Linux} provides several built-in screen drivers. In
+ addition, custom screen drivers can be added using Qt's plugin
+ mechanism, i.e. by subclassing the QScreen class and creating a
+ screen driver plugin (QScreenDriverPlugin). See the
+ \l{Qt for Embedded Linux Display Management}{display management}
+ documentation for details.
+
+ \sa QScreen, QScreenDriverPlugin
+*/
+
+/*!
+ Creates the screen driver specified by the given \a key, using the
+ display specified by the given \a displayId.
+
+ Note that the keys are case-insensitive.
+
+ \sa keys()
+*/
+QScreen *QScreenDriverFactory::create(const QString& key, int displayId)
+{
+ QString driver = key.toLower();
+#ifndef QT_NO_QWS_QVFB
+ if (driver == QLatin1String("qvfb") || driver.isEmpty())
+ return new QVFbScreen(displayId);
+#endif
+#ifndef QT_NO_QWS_LINUXFB
+ if (driver == QLatin1String("linuxfb") || driver.isEmpty())
+ return new QLinuxFbScreen(displayId);
+#endif
+#ifndef QT_NO_QWS_TRANSFORMED
+ if (driver == QLatin1String("transformed"))
+ return new QTransformedScreen(displayId);
+#endif
+#ifndef QT_NO_QWS_VNC
+ if (driver == QLatin1String("vnc"))
+ return new QVNCScreen(displayId);
+#endif
+#ifndef QT_NO_QWS_MULTISCREEN
+ if (driver == QLatin1String("multi"))
+ return new QMultiScreen(displayId);
+#endif
+
+#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL)
+#ifndef QT_NO_LIBRARY
+
+ if (QScreenDriverFactoryInterface *factory = qobject_cast<QScreenDriverFactoryInterface*>(loader()->instance(key)))
+ return factory->create(driver, displayId);
+
+#endif
+#endif
+ return 0;
+}
+
+/*!
+ Returns the list of valid keys, i.e. the available screen drivers.
+
+ \sa create()
+*/
+QStringList QScreenDriverFactory::keys()
+{
+ QStringList list;
+
+#ifndef QT_NO_QWS_QVFB
+ list << QLatin1String("QVFb");
+#endif
+#ifndef QT_NO_QWS_LINUXFB
+ list << QLatin1String("LinuxFb");
+#endif
+#ifndef QT_NO_QWS_TRANSFORMED
+ list << QLatin1String("Transformed");
+#endif
+#ifndef QT_NO_QWS_VNC
+ list << QLatin1String("VNC");
+#endif
+#ifndef QT_NO_QWS_MULTISCREEN
+ list << QLatin1String("Multi");
+#endif
+
+#if !defined(Q_OS_WIN32) || defined(QT_MAKEDLL)
+#ifndef QT_NO_LIBRARY
+ QStringList plugins = loader()->keys();
+ for (int i = 0; i < plugins.size(); ++i) {
+# ifdef QT_NO_QWS_QVFB
+ // give QVFb top priority for autodetection
+ if (plugins.at(i) == QLatin1String("QVFb"))
+ list.prepend(plugins.at(i));
+ else
+# endif
+ 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/embedded/qscreendriverfactory_qws.h b/src/gui/embedded/qscreendriverfactory_qws.h
new file mode 100644
index 0000000000..eb9364cc21
--- /dev/null
+++ b/src/gui/embedded/qscreendriverfactory_qws.h
@@ -0,0 +1,67 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCREENDRIVERFACTORY_QWS_H
+#define QSCREENDRIVERFACTORY_QWS_H
+
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QString;
+class QScreen;
+
+class Q_GUI_EXPORT QScreenDriverFactory
+{
+public:
+ static QStringList keys();
+ static QScreen *create(const QString&, int);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSCREENDRIVERFACTORY_QWS_H
diff --git a/src/gui/embedded/qscreendriverplugin_qws.cpp b/src/gui/embedded/qscreendriverplugin_qws.cpp
new file mode 100644
index 0000000000..5429bde4dd
--- /dev/null
+++ b/src/gui/embedded/qscreendriverplugin_qws.cpp
@@ -0,0 +1,123 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscreendriverplugin_qws.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_LIBRARY
+
+/*!
+ \class QScreenDriverPlugin
+ \ingroup plugins
+ \ingroup qws
+
+ \brief The QScreenDriverPlugin class is an abstract base class for
+ screen driver plugins in Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ \l{Qt for Embedded Linux} provides ready-made drivers for several screen
+ protocols, see the \l{Qt for Embedded Linux Display Management}{display
+ management} documentation for details. Custom screen drivers can be
+ implemented by subclassing the QScreen class and creating a screen
+ driver plugin.
+
+ A screen driver plugin can be created by subclassing
+ QScreenDriverPlugin 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
+ QScreenDriverFactory 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 QScreen, QScreenDriverFactory
+*/
+
+/*!
+ \fn QStringList QScreenDriverPlugin::keys() const
+
+ Implement this function to return the list of valid keys, i.e. the
+ screen drivers supported by this plugin.
+
+ \l{Qt for Embedded Linux} provides ready-made drivers for several screen
+ protocols, see the \l{Qt for Embedded Linux Display Management}{display
+ management} documentation for details.
+
+ \sa create()
+*/
+
+/*!
+ Constructs a screen driver 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.
+*/
+QScreenDriverPlugin::QScreenDriverPlugin(QObject *parent)
+ : QObject(parent)
+{
+}
+
+/*!
+ Destroys this screen driver plugin.
+
+ Note that Qt destroys a plugin automatically when it is no longer
+ used, so there is no need for calling the destructor explicitly.
+*/
+QScreenDriverPlugin::~QScreenDriverPlugin()
+{
+}
+
+
+/*!
+ \fn QScreen* QScreenDriverPlugin::create(const QString &key, int displayId)
+
+ Implement this function to create a driver matching the type
+ specified by the given \a key and \a displayId parameters. Note
+ that keys are case-insensitive.
+
+ \sa keys()
+*/
+
+#endif // QT_NO_LIBRARY
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qscreendriverplugin_qws.h b/src/gui/embedded/qscreendriverplugin_qws.h
new file mode 100644
index 0000000000..f7dd0fce1d
--- /dev/null
+++ b/src/gui/embedded/qscreendriverplugin_qws.h
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCREENDRIVERPLUGIN_QWS_H
+#define QSCREENDRIVERPLUGIN_QWS_H
+
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_LIBRARY
+
+class QScreen;
+
+struct Q_GUI_EXPORT QScreenDriverFactoryInterface : public QFactoryInterface
+{
+ virtual QScreen* create(const QString& driver, int displayId) = 0;
+};
+
+#define QScreenDriverFactoryInterface_iid "com.trolltech.Qt.QScreenDriverFactoryInterface"
+Q_DECLARE_INTERFACE(QScreenDriverFactoryInterface, QScreenDriverFactoryInterface_iid)
+
+class Q_GUI_EXPORT QScreenDriverPlugin : public QObject, public QScreenDriverFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QScreenDriverFactoryInterface:QFactoryInterface)
+public:
+ explicit QScreenDriverPlugin(QObject *parent = 0);
+ ~QScreenDriverPlugin();
+
+ virtual QStringList keys() const = 0;
+ virtual QScreen *create(const QString& driver, int displayId) = 0;
+};
+
+#endif // QT_NO_LIBRARY
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSCREENDRIVERPLUGIN_QWS_H
diff --git a/src/gui/embedded/qscreenlinuxfb_qws.cpp b/src/gui/embedded/qscreenlinuxfb_qws.cpp
new file mode 100644
index 0000000000..48fe881600
--- /dev/null
+++ b/src/gui/embedded/qscreenlinuxfb_qws.cpp
@@ -0,0 +1,1324 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscreenlinuxfb_qws.h"
+
+#ifndef QT_NO_QWS_LINUXFB
+//#include "qmemorymanager_qws.h"
+#include "qwsdisplay_qws.h"
+#include "qpixmap.h"
+#include <private/qwssignalhandler_p.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>
+
+#include "qwindowsystem_qws.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
+
+extern int qws_client_id;
+
+//#define DEBUG_CACHE
+
+class QLinuxFbScreenPrivate : public QObject
+{
+public:
+ QLinuxFbScreenPrivate();
+ ~QLinuxFbScreenPrivate();
+
+ 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;
+};
+
+QLinuxFbScreenPrivate::QLinuxFbScreenPrivate()
+ : fd(-1), blank(true), doGraphicsMode(true),
+#ifdef QT_QWS_DEPTH_GENERIC
+ doGenericColors(false),
+#endif
+ ttyfd(-1), oldKdMode(KD_TEXT)
+{
+ QWSSignalHandler::instance()->addObject(this);
+}
+
+QLinuxFbScreenPrivate::~QLinuxFbScreenPrivate()
+{
+ closeTty();
+}
+
+void QLinuxFbScreenPrivate::openTty()
+{
+ const char *const devs[] = {"/dev/tty0", "/dev/tty", "/dev/console", 0};
+
+ if (ttyDevice.isEmpty()) {
+ for (const char * const *dev = devs; *dev; ++dev) {
+ ttyfd = ::open(*dev, O_RDWR);
+ if (ttyfd != -1)
+ break;
+ }
+ } else {
+ ttyfd = ::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";
+ ::write(ttyfd, termctl, sizeof(termctl));
+}
+
+void QLinuxFbScreenPrivate::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";
+ ::write(ttyfd, termctl, sizeof(termctl));
+
+ ::close(ttyfd);
+ ttyfd = -1;
+}
+
+/*!
+ \internal
+
+ \class QLinuxFbScreen
+ \ingroup qws
+
+ \brief The QLinuxFbScreen class implements a screen driver for the
+ Linux framebuffer.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+ Custom screen drivers can be added by subclassing the
+ QScreenDriverPlugin class, using the QScreenDriverFactory class to
+ dynamically load the driver into the application, but there should
+ only be one screen object per application.
+
+ The QLinuxFbScreen class provides the cache() function allocating
+ off-screen graphics memory, and the complementary uncache()
+ function releasing the allocated memory. The latter function will
+ first sync the graphics card to ensure the memory isn't still
+ being used by a command in the graphics card FIFO queue. The
+ deleteEntry() function deletes the given memory block without such
+ synchronization. Given the screen instance and client id, the
+ memory can also be released using the clearCache() function, but
+ this should only be necessary if a client exits abnormally.
+
+ In addition, when in paletted graphics modes, the set() function
+ provides the possibility of setting a specified color index to a
+ given RGB value.
+
+ The QLinuxFbScreen class also acts as a factory for the
+ unaccelerated screen cursor and the unaccelerated raster-based
+ implementation of QPaintEngine (\c QRasterPaintEngine);
+ accelerated drivers for Linux should derive from this class.
+
+ \sa QScreen, QScreenDriverPlugin, {Running Applications}
+*/
+
+/*!
+ \fn bool QLinuxFbScreen::useOffscreen()
+ \internal
+*/
+
+// Unaccelerated screen/driver setup. Can be overridden by accelerated
+// drivers
+
+/*!
+ \fn QLinuxFbScreen::QLinuxFbScreen(int displayId)
+
+ Constructs a QLinuxFbScreen object. The \a displayId argument
+ identifies the Qt for Embedded Linux server to connect to.
+*/
+
+QLinuxFbScreen::QLinuxFbScreen(int display_id)
+ : QScreen(display_id, LinuxFBClass), d_ptr(new QLinuxFbScreenPrivate)
+{
+ canaccel=false;
+ clearCacheFunc = &clearCache;
+#ifdef QT_QWS_CLIENTBLIT
+ setSupportsBlitInClients(true);
+#endif
+}
+
+/*!
+ Destroys this QLinuxFbScreen object.
+*/
+
+QLinuxFbScreen::~QLinuxFbScreen()
+{
+}
+
+/*!
+ \reimp
+
+ This is called by \l{Qt for Embedded Linux} clients to map in the framebuffer.
+ It should be reimplemented by accelerated drivers to map in
+ graphics card registers; those drivers should then call this
+ function in order to set up offscreen memory management. The
+ device is specified in \a displaySpec; e.g. "/dev/fb".
+
+ \sa disconnect()
+*/
+
+bool QLinuxFbScreen::connect(const QString &displaySpec)
+{
+ d_ptr->displaySpec = 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 Q_BYTE_ORDER == Q_BIG_ENDIAN
+#ifndef QT_QWS_FRAMEBUFFER_LITTLE_ENDIAN
+ if (args.contains(QLatin1String("littleendian")))
+#endif
+ QScreen::setFrameBufferLittleEndian(true);
+#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 = open(dev.toLatin1().constData(), O_RDWR);
+ if (d_ptr->fd == -1) {
+ if (QApplication::type() == QApplication::GuiServer) {
+ perror("QScreenLinuxFb::connect");
+ qCritical("Error opening framebuffer device %s", qPrintable(dev));
+ return false;
+ }
+ if (access(dev.toLatin1().constData(), R_OK) == 0)
+ d_ptr->fd = open(dev.toLatin1().constData(), O_RDONLY);
+ }
+
+ 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("QLinuxFbScreen::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("QLinuxFbScreen::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 > vinfo.xres)
+ xxoff = vinfo.xres - w;
+ if (yyoff < 0 || yyoff + h > 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("QScreenLinuxFb::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) {
+ if (QApplication::type() == QApplication::GuiServer) {
+ perror("QLinuxFbScreen::connect");
+ qWarning("Error: failed to map framebuffer device to memory.");
+ return false;
+ }
+ data = 0;
+ } else {
+ data += dataoffset;
+ }
+
+ canaccel = useOffscreen();
+ if(canaccel)
+ setupOffScreen();
+
+ // 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("QLinuxFbScreen::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;
+}
+
+/*!
+ \reimp
+
+ This unmaps the framebuffer.
+
+ \sa connect()
+*/
+
+void QLinuxFbScreen::disconnect()
+{
+ data -= dataoffset;
+ if (data)
+ munmap((char*)data,mapsize);
+ close(d_ptr->fd);
+}
+
+// #define DEBUG_VINFO
+
+void QLinuxFbScreen::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;
+ }
+ }
+}
+
+/*!
+ \reimp
+
+ This is called by the \l{Qt for Embedded Linux} server at startup time.
+ It turns off console blinking, sets up the color palette, enables write
+ combining on the framebuffer and initialises the off-screen memory
+ manager.
+*/
+
+bool QLinuxFbScreen::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=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));
+ }
+ }
+ }
+#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 (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;
+
+#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
+
+#ifndef QT_NO_QWS_CURSOR
+ QScreenCursor::initSoftwareCursor();
+#endif
+ blank(false);
+
+ return true;
+}
+
+/*
+ The offscreen memory manager's list of entries is stored at the bottom
+ of the offscreen memory area and consistes of a series of QPoolEntry's,
+ each of which keep track of a block of allocated memory. Unallocated memory
+ is implicitly indicated by the gap between blocks indicated by QPoolEntry's.
+ The memory manager looks through any unallocated memory before the end
+ of currently-allocated memory to see if a new block will fit in the gap;
+ if it doesn't it allocated it from the end of currently-allocated memory.
+ Memory is allocated from the top of the framebuffer downwards; if it hits
+ the list of entries then offscreen memory is full and further allocations
+ are made from main RAM (and hence unaccelerated). Allocated memory can
+ be seen as a sort of upside-down stack; lowest keeps track of the
+ bottom of the stack.
+*/
+
+void QLinuxFbScreen::delete_entry(int pos)
+{
+ if (pos > *entryp || pos < 0) {
+ qWarning("Attempt to delete odd pos! %d %d", pos, *entryp);
+ return;
+ }
+
+#ifdef DEBUG_CACHE
+ qDebug("Remove entry: %d", pos);
+#endif
+
+ QPoolEntry *qpe = &entries[pos];
+ if (qpe->start <= *lowest) {
+ // Lowest goes up again
+ *lowest = entries[pos-1].start;
+#ifdef DEBUG_CACHE
+ qDebug(" moved lowest to %d", *lowest);
+#endif
+ }
+
+ (*entryp)--;
+ if (pos == *entryp)
+ return;
+
+ int size = (*entryp)-pos;
+ memmove(&entries[pos], &entries[pos+1], size*sizeof(QPoolEntry));
+}
+
+void QLinuxFbScreen::insert_entry(int pos, int start, int end)
+{
+ if (pos > *entryp) {
+ qWarning("Attempt to insert odd pos! %d %d",pos,*entryp);
+ return;
+ }
+
+#ifdef DEBUG_CACHE
+ qDebug("Insert entry: %d, %d -> %d", pos, start, end);
+#endif
+
+ if (start < (int)*lowest) {
+ *lowest = start;
+#ifdef DEBUG_CACHE
+ qDebug(" moved lowest to %d", *lowest);
+#endif
+ }
+
+ if (pos == *entryp) {
+ entries[pos].start = start;
+ entries[pos].end = end;
+ entries[pos].clientId = qws_client_id;
+ (*entryp)++;
+ return;
+ }
+
+ int size=(*entryp)-pos;
+ memmove(&entries[pos+1],&entries[pos],size*sizeof(QPoolEntry));
+ entries[pos].start=start;
+ entries[pos].end=end;
+ entries[pos].clientId=qws_client_id;
+ (*entryp)++;
+}
+
+/*!
+ \fn uchar * QLinuxFbScreen::cache(int amount)
+
+ Requests the specified \a amount of offscreen graphics card memory
+ from the memory manager, and returns a pointer to the data within
+ the framebuffer (or 0 if there is no free memory).
+
+ Note that the display is locked while memory is allocated in order to
+ preserve the memory pool's integrity.
+
+ Use the QScreen::onCard() function to retrieve an offset (in
+ bytes) from the start of graphics card memory for the returned
+ pointer.
+
+ \sa uncache(), clearCache(), deleteEntry()
+*/
+
+uchar * QLinuxFbScreen::cache(int amount)
+{
+ if (!canaccel || entryp == 0)
+ return 0;
+
+ qt_fbdpy->grab();
+
+ int startp = cacheStart + (*entryp+1) * sizeof(QPoolEntry);
+ if (startp >= (int)*lowest) {
+ // We don't have room for another cache QPoolEntry.
+#ifdef DEBUG_CACHE
+ qDebug("No room for pool entry in VRAM");
+#endif
+ qt_fbdpy->ungrab();
+ return 0;
+ }
+
+ int align = pixmapOffsetAlignment();
+
+ if (*entryp > 1) {
+ // Try to find a gap in the allocated blocks.
+ for (int loopc = 0; loopc < *entryp-1; loopc++) {
+ int freestart = entries[loopc+1].end;
+ int freeend = entries[loopc].start;
+ if (freestart != freeend) {
+ while (freestart % align) {
+ freestart++;
+ }
+ int len=freeend-freestart;
+ if (len >= amount) {
+ insert_entry(loopc+1, freestart, freestart+amount);
+ qt_fbdpy->ungrab();
+ return data+freestart;
+ }
+ }
+ }
+ }
+
+ // No free blocks in already-taken memory; get some more
+ // if we can
+ int newlowest = (*lowest)-amount;
+ if (newlowest % align) {
+ newlowest -= align;
+ while (newlowest % align) {
+ newlowest++;
+ }
+ }
+ if (startp >= newlowest) {
+ qt_fbdpy->ungrab();
+#ifdef DEBUG_CACHE
+ qDebug("No VRAM available for %d bytes", amount);
+#endif
+ return 0;
+ }
+ insert_entry(*entryp, newlowest, *lowest);
+ qt_fbdpy->ungrab();
+
+ return data + newlowest;
+}
+
+/*!
+ \fn void QLinuxFbScreen::uncache(uchar * memoryBlock)
+
+ Deletes the specified \a memoryBlock allocated from the graphics
+ card memory.
+
+ Note that the display is locked while memory is unallocated in
+ order to preserve the memory pool's integrity.
+
+ This function will first sync the graphics card to ensure the
+ memory isn't still being used by a command in the graphics card
+ FIFO queue. It is possible to speed up a driver by overriding this
+ function to avoid syncing. For example, the driver might delay
+ deleting the memory until it detects that all commands dealing
+ with the memory are no longer in the queue. Note that it will then
+ be up to the driver to ensure that the specified \a memoryBlock no
+ longer is being used.
+
+ \sa cache(), deleteEntry(), clearCache()
+ */
+void QLinuxFbScreen::uncache(uchar * c)
+{
+ // need to sync graphics card
+
+ deleteEntry(c);
+}
+
+/*!
+ \fn void QLinuxFbScreen::deleteEntry(uchar * memoryBlock)
+
+ Deletes the specified \a memoryBlock allocated from the graphics
+ card memory.
+
+ \sa uncache(), cache(), clearCache()
+*/
+void QLinuxFbScreen::deleteEntry(uchar * c)
+{
+ qt_fbdpy->grab();
+ unsigned long pos=(unsigned long)c;
+ pos-=((unsigned long)data);
+ unsigned int hold=(*entryp);
+ for(unsigned int loopc=1;loopc<hold;loopc++) {
+ if (entries[loopc].start==pos) {
+ if (entries[loopc].clientId == qws_client_id)
+ delete_entry(loopc);
+ else
+ qWarning("Attempt to delete client id %d cache entry",
+ entries[loopc].clientId);
+ qt_fbdpy->ungrab();
+ return;
+ }
+ }
+ qt_fbdpy->ungrab();
+ qWarning("Attempt to delete unknown offset %ld",pos);
+}
+
+/*!
+ Removes all entries from the cache for the specified screen \a
+ instance and client identified by the given \a clientId.
+
+ Calling this function should only be necessary if a client exits
+ abnormally.
+
+ \sa cache(), uncache(), deleteEntry()
+*/
+void QLinuxFbScreen::clearCache(QScreen *instance, int clientId)
+{
+ QLinuxFbScreen *screen = (QLinuxFbScreen *)instance;
+ if (!screen->canaccel || !screen->entryp)
+ return;
+ qt_fbdpy->grab();
+ for (int loopc = 0; loopc < *(screen->entryp); loopc++) {
+ if (screen->entries[loopc].clientId == clientId) {
+ screen->delete_entry(loopc);
+ loopc--;
+ }
+ }
+ qt_fbdpy->ungrab();
+}
+
+
+void QLinuxFbScreen::setupOffScreen()
+{
+ // Figure out position of offscreen memory
+ // Set up pool entries pointer table and 64-bit align it
+ int psize = size;
+
+ // hw: this causes the limitation of cursors to 64x64
+ // the cursor should rather use the normal pixmap mechanism
+ psize += 4096; // cursor data
+ psize += 8; // for alignment
+ psize &= ~0x7; // align
+
+ unsigned long pos = (unsigned long)data;
+ pos += psize;
+ entryp = ((int *)pos);
+ lowest = ((unsigned int *)pos)+1;
+ pos += (sizeof(int))*4;
+ entries = (QPoolEntry *)pos;
+
+ // beginning of offscreen memory available for pixmaps.
+ cacheStart = psize + 4*sizeof(int) + sizeof(QPoolEntry);
+}
+
+/*!
+ \reimp
+
+ This is called by the \l{Qt for Embedded Linux} server when it shuts
+ down, and should be inherited if you need to do any card-specific cleanup.
+ The default version hides the screen cursor and reenables the blinking
+ cursor and screen blanking.
+*/
+
+void QLinuxFbScreen::shutdownDevice()
+{
+ // Causing crashes. Not needed.
+ //setMode(startupw,startuph,startupd);
+/*
+ if (startupd == 8) {
+ ioctl(fd,FBIOPUTCMAP,startcmap);
+ free(startcmap->red);
+ free(startcmap->green);
+ free(startcmap->blue);
+ free(startcmap->transp);
+ delete startcmap;
+ startcmap = 0;
+ }
+*/
+ d_ptr->closeTty();
+}
+
+/*!
+ \fn void QLinuxFbScreen::set(unsigned int index,unsigned int red,unsigned int green,unsigned int blue)
+
+ Sets the specified color \a index to the specified RGB value, (\a
+ red, \a green, \a blue), when in paletted graphics modes.
+*/
+
+void QLinuxFbScreen::set(unsigned int i,unsigned int r,unsigned int g,unsigned int b)
+{
+ if (d_ptr->fd != -1) {
+ fb_cmap cmap;
+ cmap.start=i;
+ cmap.len=1;
+ 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);
+ cmap.red[0]=r << 8;
+ cmap.green[0]=g << 8;
+ cmap.blue[0]=b << 8;
+ cmap.transp[0]=0;
+ ioctl(d_ptr->fd, FBIOPUTCMAP, &cmap);
+ free(cmap.red);
+ free(cmap.green);
+ free(cmap.blue);
+ free(cmap.transp);
+ }
+ screenclut[i] = qRgb(r, g, b);
+}
+
+/*!
+ \reimp
+
+ Sets the framebuffer to a new resolution and bit depth. The width is
+ in \a nw, the height is in \a nh, and the depth is in \a nd. After
+ doing this any currently-existing paint engines will be invalid and the
+ screen should be completely redrawn. In a multiple-process
+ Embedded Qt situation you must signal all other applications to
+ call setMode() to the same mode and redraw.
+*/
+
+void QLinuxFbScreen::setMode(int nw,int nh,int nd)
+{
+ if (d_ptr->fd == -1)
+ return;
+
+ fb_fix_screeninfo finfo;
+ fb_var_screeninfo vinfo;
+ //#######################
+ // Shut up Valgrind
+ memset(&vinfo, 0, sizeof(vinfo));
+ memset(&finfo, 0, sizeof(finfo));
+ //#######################
+
+ if (ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) {
+ perror("QLinuxFbScreen::setMode");
+ qFatal("Error reading variable information in mode change");
+ }
+
+ vinfo.xres=nw;
+ vinfo.yres=nh;
+ vinfo.bits_per_pixel=nd;
+
+ if (ioctl(d_ptr->fd, FBIOPUT_VSCREENINFO, &vinfo)) {
+ perror("QLinuxFbScreen::setMode");
+ qCritical("Error writing variable information in mode change");
+ }
+
+ if (ioctl(d_ptr->fd, FBIOGET_VSCREENINFO, &vinfo)) {
+ perror("QLinuxFbScreen::setMode");
+ qFatal("Error reading changed variable information in mode change");
+ }
+
+ if (ioctl(d_ptr->fd, FBIOGET_FSCREENINFO, &finfo)) {
+ perror("QLinuxFbScreen::setMode");
+ qFatal("Error reading fixed information");
+ }
+
+ disconnect();
+ connect(d_ptr->displaySpec);
+ exposeRegion(region(), 0);
+}
+
+// save the state of the graphics card
+// This is needed so that e.g. we can restore the palette when switching
+// between linux virtual consoles.
+
+/*!
+ \reimp
+
+ This doesn't do anything; accelerated drivers may wish to reimplement
+ it to save graphics cards registers. It's called by the
+ \l{Qt for Embedded Linux} server when the virtual console is switched.
+*/
+
+void QLinuxFbScreen::save()
+{
+ // nothing to do.
+}
+
+
+// restore the state of the graphics card.
+/*!
+ \reimp
+
+ This is called when the virtual console is switched back to
+ \l{Qt for Embedded Linux} and restores the palette.
+*/
+void QLinuxFbScreen::restore()
+{
+ if (d_ptr->fd == -1)
+ return;
+
+ if ((d == 8) || (d == 4)) {
+ fb_cmap cmap;
+ cmap.start=0;
+ cmap.len=screencols;
+ 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 (int loopc = 0; loopc < screencols; loopc++) {
+ cmap.red[loopc] = qRed(screenclut[loopc]) << 8;
+ cmap.green[loopc] = qGreen(screenclut[loopc]) << 8;
+ cmap.blue[loopc] = qBlue(screenclut[loopc]) << 8;
+ cmap.transp[loopc] = 0;
+ }
+ ioctl(d_ptr->fd, FBIOPUTCMAP, &cmap);
+ free(cmap.red);
+ free(cmap.green);
+ free(cmap.blue);
+ free(cmap.transp);
+ }
+}
+
+/*!
+ \fn int QLinuxFbScreen::sharedRamSize(void * end)
+ \internal
+*/
+
+// This works like the QScreenCursor code. end points to the end
+// of our shared structure, we return the amount of memory we reserved
+int QLinuxFbScreen::sharedRamSize(void * end)
+{
+ shared=(QLinuxFb_Shared *)end;
+ shared--;
+ return sizeof(QLinuxFb_Shared);
+}
+
+/*!
+ \reimp
+*/
+void QLinuxFbScreen::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;
+}
+
+void QLinuxFbScreen::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 = QScreen::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 = QScreen::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 = QScreen::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 = QScreen::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;
+ }
+
+ QScreen::setPixelFormat(format);
+}
+
+bool QLinuxFbScreen::useOffscreen()
+{
+ if ((mapsize - size) < 16*1024)
+ return false;
+
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QWS_LINUXFB
diff --git a/src/gui/embedded/qscreenlinuxfb_qws.h b/src/gui/embedded/qscreenlinuxfb_qws.h
new file mode 100644
index 0000000000..781b20585b
--- /dev/null
+++ b/src/gui/embedded/qscreenlinuxfb_qws.h
@@ -0,0 +1,129 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCREENLINUXFB_QWS_H
+#define QSCREENLINUXFB_QWS_H
+
+#include <QtGui/qscreen_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_LINUXFB
+
+class QLinuxFb_Shared
+{
+public:
+ volatile int lastop;
+ volatile int optype;
+ volatile int fifocount; // Accel drivers only
+ volatile int fifomax;
+ volatile int forecol; // Foreground colour caching
+ volatile unsigned int buffer_offset; // Destination
+ volatile int linestep;
+ volatile int cliptop; // Clip rectangle
+ volatile int clipleft;
+ volatile int clipright;
+ volatile int clipbottom;
+ volatile unsigned int rop;
+
+};
+
+struct fb_cmap;
+struct fb_var_screeninfo;
+struct fb_fix_screeninfo;
+class QLinuxFbScreenPrivate;
+
+class Q_GUI_EXPORT QLinuxFbScreen : public QScreen
+{
+public:
+ explicit QLinuxFbScreen(int display_id);
+ virtual ~QLinuxFbScreen();
+
+ virtual bool initDevice();
+ virtual bool connect(const QString &displaySpec);
+
+ virtual bool useOffscreen();
+
+ virtual void disconnect();
+ virtual void shutdownDevice();
+ virtual void setMode(int,int,int);
+ virtual void save();
+ virtual void restore();
+ virtual void blank(bool on);
+ virtual void set(unsigned int,unsigned int,unsigned int,unsigned int);
+ virtual uchar * cache(int);
+ virtual void uncache(uchar *);
+ virtual int sharedRamSize(void *);
+
+ QLinuxFb_Shared * shared;
+
+protected:
+
+ void deleteEntry(uchar *);
+
+ bool canaccel;
+ int dataoffset;
+ int cacheStart;
+
+ static void clearCache(QScreen *instance, int);
+
+private:
+
+ void delete_entry(int);
+ void insert_entry(int,int,int);
+ void setupOffScreen();
+ void createPalette(fb_cmap &cmap, fb_var_screeninfo &vinfo, fb_fix_screeninfo &finfo);
+ void setPixelFormat(struct fb_var_screeninfo);
+
+ QLinuxFbScreenPrivate *d_ptr;
+};
+
+#endif // QT_NO_QWS_LINUXFB
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSCREENLINUXFB_QWS_H
diff --git a/src/gui/embedded/qscreenmulti_qws.cpp b/src/gui/embedded/qscreenmulti_qws.cpp
new file mode 100644
index 0000000000..1914b4423f
--- /dev/null
+++ b/src/gui/embedded/qscreenmulti_qws.cpp
@@ -0,0 +1,482 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscreenmulti_qws_p.h"
+
+#ifndef QT_NO_QWS_MULTISCREEN
+
+#include <qlist.h>
+#include <qstringlist.h>
+#include <qwidget.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_QWS_CURSOR
+
+class QMultiScreenCursor : public QScreenCursor
+{
+public:
+ QMultiScreenCursor() : currentCursor(qt_screencursor) { enable = false; }
+ ~QMultiScreenCursor() { qt_screencursor = 0; }
+
+ void set(const QImage &image, int hotx, int hoty);
+ void move(int x, int y);
+ void show();
+ void hide();
+
+ void addCursor(QScreenCursor *cursor);
+
+private:
+ void setCurrentCursor(QScreenCursor *newCursor);
+
+ QScreenCursor *currentCursor;
+ QList<QScreenCursor*> cursors;
+};
+
+void QMultiScreenCursor::set(const QImage &image, int hotx, int hoty)
+{
+ QScreenCursor::set(image, hotx, hoty);
+ if (currentCursor)
+ currentCursor->set(image, hotx, hoty);
+}
+
+void QMultiScreenCursor::setCurrentCursor(QScreenCursor *newCursor)
+{
+ *((QScreenCursor*)this) = *newCursor;
+ currentCursor = newCursor;
+}
+
+// XXX: this is a mess!
+void QMultiScreenCursor::move(int x, int y)
+{
+ const int oldIndex = qt_screen->subScreenIndexAt(pos);
+ QScreenCursor::move(x, y); // updates pos
+ const int newIndex = qt_screen->subScreenIndexAt(pos);
+
+ if (!currentCursor && oldIndex != -1)
+ setCurrentCursor(cursors.at(oldIndex));
+ QScreenCursor *oldCursor = currentCursor;
+
+ if (oldIndex != -1) {
+ const QScreen *oldScreen = qt_screen->subScreens().at(oldIndex);
+ if (newIndex == -1 || oldScreen->region().contains(pos)) {
+ oldCursor->move(x, y);
+ return;
+ }
+ }
+
+ if (newIndex != -1) {
+ QScreenCursor *newCursor = cursors.at(newIndex);
+ newCursor->set(cursor, hotspot.x(), hotspot.y());
+
+ if (oldCursor) {
+ if (oldCursor->isVisible())
+ newCursor->show();
+ oldCursor->hide();
+ }
+
+ newCursor->move(x, y);
+
+ setCurrentCursor(newCursor);
+ }
+}
+
+void QMultiScreenCursor::show()
+{
+ if (currentCursor)
+ currentCursor->show();
+}
+
+void QMultiScreenCursor::hide()
+{
+ if (currentCursor)
+ currentCursor->hide();
+}
+
+void QMultiScreenCursor::addCursor(QScreenCursor *cursor)
+{
+ cursors.append(cursor);
+}
+
+#endif
+
+class QMultiScreenPrivate
+{
+public:
+ QMultiScreenPrivate()
+#ifndef QT_NO_QWS_CURSOR
+ : cursor(0)
+#endif
+ {}
+ ~QMultiScreenPrivate()
+ {
+#ifndef QT_NO_QWS_CURSOR
+ delete cursor;
+#endif
+ }
+
+ QList<QScreen*> screens;
+ QRegion region;
+#ifndef QT_NO_QWS_CURSOR
+ QMultiScreenCursor *cursor;
+#endif
+};
+
+QMultiScreen::QMultiScreen(int displayId)
+ : QScreen(displayId, MultiClass), d_ptr(new QMultiScreenPrivate)
+{
+}
+
+QMultiScreen::~QMultiScreen()
+{
+ delete d_ptr;
+}
+
+bool QMultiScreen::initDevice()
+{
+ bool ok = true;
+
+#ifndef QT_NO_QWS_CURSOR
+ d_ptr->cursor = new QMultiScreenCursor;
+#endif
+
+ const int n = d_ptr->screens.count();
+ for (int i = 0; i < n; ++i) {
+ QScreen *s = d_ptr->screens.at(i);
+ ok = s->initDevice() && ok;
+#ifndef QT_NO_QWS_CURSOR
+ d_ptr->cursor->addCursor(qt_screencursor); // XXX
+#endif
+ }
+
+#ifndef QT_NO_QWS_CURSOR
+ // XXX
+ qt_screencursor = d_ptr->cursor;
+#endif
+
+ return ok;
+}
+
+static int getDisplayId(const QString &spec)
+{
+ QRegExp regexp(QLatin1String(":(\\d+)\\b"));
+ if (regexp.lastIndexIn(spec) != -1) {
+ const QString capture = regexp.cap(1);
+ return capture.toInt();
+ }
+ return 0;
+}
+
+static QPoint filterDisplayOffset(QString &spec)
+{
+ QRegExp regexp(QLatin1String(":offset=(\\d+),(\\d+)\\b"));
+ if (regexp.indexIn(spec) == -1)
+ return QPoint();
+
+ const int x = regexp.cap(1).toInt();
+ const int y = regexp.cap(2).toInt();
+ spec.remove(regexp.pos(0), regexp.matchedLength());
+ return QPoint(x, y);
+}
+
+bool QMultiScreen::connect(const QString &displaySpec)
+{
+ QString dSpec = displaySpec;
+ if (dSpec.startsWith(QLatin1String("Multi:"), Qt::CaseInsensitive))
+ dSpec = dSpec.mid(QString(QLatin1String("Multi:")).size());
+
+ const QString displayIdSpec = QString(QLatin1String(" :%1")).arg(displayId);
+ if (dSpec.endsWith(displayIdSpec))
+ dSpec = dSpec.left(dSpec.size() - displayIdSpec.size());
+
+ QStringList specs = dSpec.split(QLatin1Char(' '), QString::SkipEmptyParts);
+ foreach (QString spec, specs) {
+ const int id = getDisplayId(spec);
+ const QPoint offset = filterDisplayOffset(spec);
+ QScreen *s = qt_get_screen(id, spec.toLatin1().constData());
+ s->setOffset(offset);
+ addSubScreen(s);
+ }
+
+ QScreen *firstScreen = d_ptr->screens.at(0);
+ Q_ASSERT(firstScreen);
+
+ // XXX
+ QScreen::d = firstScreen->depth();
+
+ QScreen::lstep = 0;
+ QScreen::data = 0;
+ QScreen::size = 0;
+
+ QScreen::w = d_ptr->region.boundingRect().width();
+ QScreen::h = d_ptr->region.boundingRect().height();
+
+ QScreen::dw = QScreen::w;
+ QScreen::dh = QScreen::h;
+
+ // XXX - Extend the physical size based on the first screen
+ // to encompass all screens, so that code that uses the multi
+ // screen to calculate dpi values will get the right numbers.
+ QScreen::physWidth = firstScreen->physicalWidth() * w / firstScreen->width();
+ QScreen::physHeight = firstScreen->physicalHeight() * h / firstScreen->height();
+
+ // XXXXX
+ qt_screen = this;
+
+ return true;
+}
+
+void QMultiScreen::disconnect()
+{
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i)
+ d_ptr->screens.at(i)->disconnect();
+}
+
+void QMultiScreen::shutdownDevice()
+{
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i)
+ d_ptr->screens.at(i)->shutdownDevice();
+}
+
+void QMultiScreen::setMode(int, int, int)
+{
+ return;
+}
+
+bool QMultiScreen::supportsDepth(int) const
+{
+ return false;
+}
+
+void QMultiScreen::save()
+{
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i)
+ d_ptr->screens.at(i)->save();
+}
+
+void QMultiScreen::restore()
+{
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i)
+ d_ptr->screens.at(i)->restore();
+}
+
+void QMultiScreen::blank(bool on)
+{
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i)
+ d_ptr->screens.at(i)->blank(on);
+}
+
+bool QMultiScreen::onCard(const unsigned char *ptr) const
+{
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i)
+ if (d_ptr->screens.at(i)->onCard(ptr))
+ return true;
+ return false;
+}
+
+bool QMultiScreen::onCard(const unsigned char *ptr, ulong &offset) const
+{
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i)
+ if (d_ptr->screens.at(i)->onCard(ptr, offset))
+ return true;
+ return false;
+}
+
+bool QMultiScreen::isInterlaced() const
+{
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i)
+ if (d_ptr->screens.at(i)->isInterlaced())
+ return true;
+
+ return false;
+}
+
+int QMultiScreen::memoryNeeded(const QString &string)
+{
+ int total = 0;
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i)
+ total += d_ptr->screens.at(i)->memoryNeeded(string);
+ return total;
+}
+
+int QMultiScreen::sharedRamSize(void *arg)
+{
+ int total = 0;
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i)
+ total += d_ptr->screens.at(i)->sharedRamSize(arg);
+ return total;
+}
+
+void QMultiScreen::haltUpdates()
+{
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i)
+ d_ptr->screens.at(i)->haltUpdates();
+}
+
+void QMultiScreen::resumeUpdates()
+{
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i)
+ d_ptr->screens.at(i)->resumeUpdates();
+}
+
+void QMultiScreen::exposeRegion(QRegion region, int changing)
+{
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i) {
+ QScreen *screen = d_ptr->screens.at(i);
+ const QRegion r = region & screen->region();
+ if (r.isEmpty())
+ continue;
+ screen->exposeRegion(r, changing);
+ }
+}
+
+void QMultiScreen::solidFill(const QColor &color, const QRegion &region)
+{
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i) {
+ QScreen *screen = d_ptr->screens.at(i);
+ const QRegion r = region & screen->region();
+ if (r.isEmpty())
+ continue;
+ screen->solidFill(color, r);
+ }
+}
+
+void QMultiScreen::blit(const QImage &img, const QPoint &topLeft,
+ const QRegion &region)
+{
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i) {
+ QScreen *screen = d_ptr->screens.at(i);
+ const QRegion r = region & screen->region();
+ if (r.isEmpty())
+ continue;
+ screen->blit(img, topLeft, r);
+ }
+}
+
+void QMultiScreen::blit(QWSWindow *bs, const QRegion &clip)
+{
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i) {
+ QScreen *screen = d_ptr->screens.at(i);
+ const QRegion r = clip & screen->region();
+ if (r.isEmpty())
+ continue;
+ screen->blit(bs, r);
+ }
+}
+
+void QMultiScreen::setDirty(const QRect &rect)
+{
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i) {
+ QScreen *screen = d_ptr->screens.at(i);
+ const QRegion r = screen->region() & rect;
+ if (r.isEmpty())
+ continue;
+ screen->setDirty(r.boundingRect());
+ }
+}
+
+
+QWSWindowSurface* QMultiScreen::createSurface(const QString &key) const
+{
+ QWSWindowSurface* surf = 0;
+ const int n = d_ptr->screens.size();
+ for (int i = 0; i < n; ++i) {
+ QScreen *screen = d_ptr->screens.at(i);
+ surf = screen->createSurface(key);
+ if (surf)
+ break;
+ }
+ return surf;
+}
+
+
+QWSWindowSurface* QMultiScreen::createSurface(QWidget *widget) const
+{
+ const QPoint midpoint = (widget->frameGeometry().topLeft()
+ + widget->frameGeometry().bottomRight()) / 2;
+ int index = subScreenIndexAt(midpoint);
+ if (index == -1)
+ index = 0; // XXX
+ return d_ptr->screens.at(index)->createSurface(widget);
+}
+
+QList<QScreen*> QMultiScreen::subScreens() const
+{
+ return d_ptr->screens;
+}
+
+QRegion QMultiScreen::region() const
+{
+ return d_ptr->region;
+}
+
+void QMultiScreen::addSubScreen(QScreen *screen)
+{
+ d_ptr->screens.append(screen);
+ d_ptr->region += screen->region();
+}
+
+void QMultiScreen::removeSubScreen(QScreen *screen)
+{
+ d_ptr->screens.removeAll(screen);
+ d_ptr->region -= screen->region();
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QWS_MULTISCREEN
diff --git a/src/gui/embedded/qscreenmulti_qws_p.h b/src/gui/embedded/qscreenmulti_qws_p.h
new file mode 100644
index 0000000000..e01b167726
--- /dev/null
+++ b/src/gui/embedded/qscreenmulti_qws_p.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMULTISCREEN_QWS_P_H
+#define QMULTISCREEN_QWS_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 <qscreen_qws.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_QWS_MULTISCREEN
+
+class QMultiScreenPrivate;
+
+class QMultiScreen : public QScreen
+{
+public:
+ QMultiScreen(int displayId);
+ ~QMultiScreen();
+ bool initDevice();
+ bool connect(const QString &displaySpec);
+ void disconnect();
+ void shutdownDevice();
+ void setMode(int,int,int);
+ bool supportsDepth(int) const;
+
+ void save();
+ void restore();
+ void blank(bool on);
+
+ bool onCard(const unsigned char *) const;
+ bool onCard(const unsigned char *, ulong& out_offset) const;
+
+ bool isInterlaced() const;
+
+ int memoryNeeded(const QString&);
+ int sharedRamSize(void *);
+
+ void haltUpdates();
+ void resumeUpdates();
+
+ void exposeRegion(QRegion r, int changing);
+
+ void blit(const QImage &img, const QPoint &topLeft, const QRegion &region);
+ void solidFill(const QColor &color, const QRegion &region);
+ void blit(QWSWindow *bs, const QRegion &clip);
+ void setDirty(const QRect&);
+
+ QWSWindowSurface* createSurface(QWidget *widget) const;
+ QWSWindowSurface* createSurface(const QString &key) const;
+
+ QList<QScreen*> subScreens() const;
+ QRegion region() const;
+
+private:
+ void addSubScreen(QScreen *screen);
+ void removeSubScreen(QScreen *screen);
+
+ QMultiScreenPrivate *d_ptr;
+};
+
+
+QT_END_NAMESPACE
+#endif // QT_NO_QWS_MULTISCREEN
+#endif // QMULTISCREEN_QWS_P_H
diff --git a/src/gui/embedded/qscreenproxy_qws.cpp b/src/gui/embedded/qscreenproxy_qws.cpp
new file mode 100644
index 0000000000..5b8f6f0794
--- /dev/null
+++ b/src/gui/embedded/qscreenproxy_qws.cpp
@@ -0,0 +1,631 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <qscreenproxy_qws.h>
+
+#ifndef QT_NO_QWS_PROXYSCREEN
+
+#include <qregexp.h>
+
+#ifndef QT_NO_QWS_CURSOR
+
+/*!
+ \class QProxyScreenCursor
+ \since 4.5
+ \ingroup qws
+ \brief The QProxyScreenCursor class provides a generic interface to
+ QScreenCursor implementations.
+*/
+
+/*!
+ Constructs a proxy screen cursor.
+*/
+QProxyScreenCursor::QProxyScreenCursor()
+ : QScreenCursor(), realCursor(0), d_ptr(0)
+{
+}
+
+/*!
+ Destroys the proxy screen cursor.
+*/
+QProxyScreenCursor::~QProxyScreenCursor()
+{
+}
+
+/*!
+ Sets the real screen cursor to be used for the proxy screen cursor to
+ the \a cursor specified.
+
+ \sa screenCursor()
+*/
+void QProxyScreenCursor::setScreenCursor(QScreenCursor *cursor)
+{
+ realCursor = cursor;
+ configure();
+}
+
+/*!
+ Returns the real screen cursor used by the proxy screen cursor.
+
+ \sa setScreenCursor()
+*/
+QScreenCursor* QProxyScreenCursor::screenCursor() const
+{
+ return realCursor;
+}
+
+/*!
+ \reimp
+*/
+void QProxyScreenCursor::set(const QImage &image, int hotx, int hoty)
+{
+ if (realCursor) {
+ hotspot = QPoint(hotx, hoty);
+ cursor = image;
+ size = image.size();
+ realCursor->set(image, hotx, hoty);
+ } else {
+ QScreenCursor::set(image, hotx, hoty);
+ }
+}
+
+/*!
+ \reimp
+*/
+void QProxyScreenCursor::move(int x, int y)
+{
+ if (realCursor) {
+ pos = QPoint(x, y);
+ realCursor->move(x, y);
+ } else {
+ QScreenCursor::move(x, y);
+ }
+}
+
+/*!
+ \reimp
+*/
+void QProxyScreenCursor::show()
+{
+ if (realCursor) {
+ realCursor->show();
+ enable = true;
+ } else {
+ QScreenCursor::show();
+ }
+}
+
+/*!
+ \reimp
+*/
+void QProxyScreenCursor::hide()
+{
+ if (realCursor) {
+ realCursor->hide();
+ enable = false;
+ } else {
+ QScreenCursor::hide();
+ }
+}
+
+/*!
+ \internal
+*/
+void QProxyScreenCursor::configure()
+{
+ if (!realCursor)
+ return;
+
+ cursor = realCursor->cursor;
+ size = realCursor->size;
+ pos = realCursor->pos;
+ hotspot = realCursor->hotspot;
+ enable = realCursor->enable;
+ hwaccel = realCursor->hwaccel;
+ supportsAlpha = realCursor->supportsAlpha;
+}
+
+#endif // QT_NO_QWS_CURSOR
+
+/*!
+ \class QProxyScreen
+ \ingroup qws
+ \brief The QProxyScreen class provides a generic interface to QScreen implementations.
+*/
+
+/*!
+ \fn QProxyScreen::QProxyScreen(int displayId, ClassId classId)
+
+ Constructs a proxy screen with the given \a displayId and \a classId.
+*/
+QProxyScreen::QProxyScreen(int displayId, QScreen::ClassId classId)
+ : QScreen(displayId, classId), realScreen(0), d_ptr(0)
+{
+}
+
+/*!
+ Destroys the proxy screen.
+*/
+QProxyScreen::~QProxyScreen()
+{
+}
+
+/*!
+ Sets the real \a screen to be used by the proxy screen.
+
+ \sa screen()
+*/
+void QProxyScreen::setScreen(QScreen *screen)
+{
+ realScreen = screen;
+ configure();
+}
+
+/*!
+ Returns the real screen used by the proxy screen.
+
+ \sa setScreen()
+*/
+QScreen* QProxyScreen::screen() const
+{
+ return realScreen;
+}
+
+
+/*!
+ \internal
+*/
+void QProxyScreen::configure()
+{
+ if (!realScreen)
+ return;
+
+ d = realScreen->depth();
+ w = realScreen->width();
+ h = realScreen->height();
+ dw = realScreen->deviceWidth();
+ dh = realScreen->deviceHeight();
+ lstep = realScreen->linestep();
+ data = realScreen->base();
+ lstep = realScreen->linestep();
+ size = realScreen->screenSize();
+ physWidth = realScreen->physicalWidth();
+ physHeight = realScreen->physicalHeight();
+ pixeltype = realScreen->pixelType();
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+ setFrameBufferLittleEndian(realScreen->frameBufferLittleEndian());
+#endif
+
+ setOffset(realScreen->offset());
+ setPixelFormat(realScreen->pixelFormat());
+
+#ifdef QT_QWS_CLIENTBLIT
+ setSupportsBlitInClients(realScreen->supportsBlitInClients());
+#endif
+}
+
+/*!
+ \internal
+ Returns the display ID that corresponds to the given \a spec.
+*/
+static int getDisplayId(const QString &spec)
+{
+ QRegExp regexp(QLatin1String(":(\\d+)\\b"));
+ if (regexp.lastIndexIn(spec) != -1) {
+ const QString capture = regexp.cap(1);
+ return capture.toInt();
+ }
+ return 0;
+}
+
+/*!
+ \reimp
+*/
+bool QProxyScreen::connect(const QString &displaySpec)
+{
+ const int id = getDisplayId(displaySpec);
+ realScreen = qt_get_screen(id, displaySpec.toLatin1().constData());
+ configure();
+
+ return true;
+}
+
+/*!
+ \reimp
+*/
+void QProxyScreen::exposeRegion(QRegion r, int changing)
+{
+ if (!realScreen) {
+ QScreen::exposeRegion(r, changing);
+ return;
+ }
+
+ realScreen->exposeRegion(r, changing);
+
+ const QVector<QRect> rects = r.rects();
+ for (int i = 0; i < rects.size(); ++i)
+ setDirty(rects.at(i));
+}
+
+/*!
+ \reimp
+*/
+void QProxyScreen::blit(const QImage &image, const QPoint &topLeft,
+ const QRegion &region)
+{
+ if (!realScreen) {
+ QScreen::blit(image, topLeft, region);
+ return;
+ }
+
+ realScreen->blit(image, topLeft, region);
+}
+
+/*!
+ \reimp
+*/
+void QProxyScreen::solidFill(const QColor &color, const QRegion &region)
+{
+ if (!realScreen) {
+ QScreen::solidFill(color, region);
+ return;
+ }
+ realScreen->solidFill(color, region);
+}
+
+/*!
+ \reimp
+*/
+QSize QProxyScreen::mapToDevice(const QSize &s) const
+{
+ if (!realScreen)
+ return QScreen::mapToDevice(s);
+
+ return realScreen->mapToDevice(s);
+}
+
+/*!
+ \reimp
+*/
+QSize QProxyScreen::mapFromDevice(const QSize &s) const
+{
+ if (!realScreen)
+ return QScreen::mapFromDevice(s);
+
+ return realScreen->mapFromDevice(s);
+}
+
+/*!
+ \reimp
+*/
+QPoint QProxyScreen::mapToDevice(const QPoint &p, const QSize &s) const
+{
+ if (!realScreen)
+ return QScreen::mapToDevice(p, s);
+
+ return realScreen->mapToDevice(p, s);
+}
+
+/*!
+ \reimp
+*/
+QPoint QProxyScreen::mapFromDevice(const QPoint &p, const QSize &s) const
+{
+ if (!realScreen)
+ return QScreen::mapFromDevice(p, s);
+
+ return realScreen->mapFromDevice(p, s);
+}
+
+/*!
+ \reimp
+*/
+QRect QProxyScreen::mapToDevice(const QRect &r, const QSize &s) const
+{
+ if (!realScreen)
+ return QScreen::mapToDevice(r, s);
+
+ return realScreen->mapToDevice(r, s);
+}
+
+/*!
+ \reimp
+*/
+QRect QProxyScreen::mapFromDevice(const QRect &r, const QSize &s) const
+{
+ if (!realScreen)
+ return QScreen::mapFromDevice(r, s);
+
+ return realScreen->mapFromDevice(r, s);
+}
+
+/*!
+ \reimp
+*/
+QRegion QProxyScreen::mapToDevice(const QRegion &r, const QSize &s) const
+{
+ if (!realScreen)
+ return QScreen::mapToDevice(r, s);
+
+ return realScreen->mapToDevice(r, s);
+}
+
+/*!
+ \reimp
+*/
+QRegion QProxyScreen::mapFromDevice(const QRegion &r, const QSize &s) const
+{
+ if (!realScreen)
+ return QScreen::mapFromDevice(r, s);
+
+ return realScreen->mapFromDevice(r, s);
+}
+
+/*!
+ \reimp
+*/
+void QProxyScreen::disconnect()
+{
+ if (realScreen) {
+ realScreen->disconnect();
+ delete realScreen;
+ realScreen = 0;
+ }
+}
+
+/*!
+*/
+bool QProxyScreen::initDevice()
+{
+ if (realScreen)
+ return realScreen->initDevice();
+
+ return false;
+}
+
+/*!
+ \reimp
+*/
+void QProxyScreen::shutdownDevice()
+{
+ if (realScreen)
+ realScreen->shutdownDevice();
+}
+
+/*!
+ \reimp
+*/
+void QProxyScreen::setMode(int w,int h, int d)
+{
+ if (realScreen) {
+ realScreen->setMode(w, h, d);
+ } else {
+ QScreen::dw = QScreen::w = w;
+ QScreen::dh = QScreen::h = h;
+ QScreen::d = d;
+ }
+ configure();
+ exposeRegion(region(), 0);
+}
+
+/*!
+ \reimp
+*/
+bool QProxyScreen::supportsDepth(int depth) const
+{
+ if (realScreen)
+ return realScreen->supportsDepth(depth);
+ return false;
+}
+
+/*!
+ \reimp
+*/
+void QProxyScreen::save()
+{
+ if (realScreen)
+ realScreen->save();
+ QScreen::save();
+}
+
+/*!
+ \reimp
+*/
+void QProxyScreen::restore()
+{
+ if (realScreen)
+ realScreen->restore();
+ QScreen::restore();
+}
+
+/*!
+ \reimp
+*/
+void QProxyScreen::blank(bool on)
+{
+ if (realScreen)
+ realScreen->blank(on);
+}
+
+/*!
+ \reimp
+*/
+bool QProxyScreen::onCard(const unsigned char *ptr) const
+{
+ if (realScreen)
+ return realScreen->onCard(ptr);
+ return false;
+}
+
+/*!
+ \reimp
+*/
+bool QProxyScreen::onCard(const unsigned char *ptr, ulong &offset) const
+{
+ if (realScreen)
+ return realScreen->onCard(ptr, offset);
+ return false;
+}
+
+/*!
+ \reimp
+*/
+bool QProxyScreen::isInterlaced() const
+{
+ if (realScreen)
+ return realScreen->isInterlaced();
+ return false;
+}
+
+/*!
+ \reimp
+*/
+bool QProxyScreen::isTransformed() const
+{
+ if (realScreen)
+ return realScreen->isTransformed();
+ return QScreen::isTransformed();
+}
+
+/*!
+ \reimp
+*/
+int QProxyScreen::transformOrientation() const
+{
+ if (realScreen)
+ return realScreen->transformOrientation();
+ return QScreen::transformOrientation();
+}
+
+/*!
+\reimp
+*/
+int QProxyScreen::memoryNeeded(const QString &str)
+{
+ if (realScreen)
+ return realScreen->memoryNeeded(str);
+ else
+ return QScreen::memoryNeeded(str);
+}
+
+/*!
+\reimp
+*/
+int QProxyScreen::sharedRamSize(void *ptr)
+{
+ if (realScreen)
+ return realScreen->sharedRamSize(ptr);
+ else
+ return QScreen::sharedRamSize(ptr);
+}
+
+/*!
+\reimp
+*/
+void QProxyScreen::haltUpdates()
+{
+ if (realScreen)
+ realScreen->haltUpdates();
+}
+
+/*!
+\reimp
+*/
+void QProxyScreen::resumeUpdates()
+{
+ if (realScreen)
+ realScreen->resumeUpdates();
+}
+
+/*!
+ \reimp
+*/
+void QProxyScreen::setDirty(const QRect &rect)
+{
+ if (realScreen)
+ realScreen->setDirty(rect);
+}
+
+/*!
+ \reimp
+*/
+QWSWindowSurface* QProxyScreen::createSurface(QWidget *widget) const
+{
+ if (realScreen)
+ return realScreen->createSurface(widget);
+
+ return QScreen::createSurface(widget);
+}
+
+/*!
+ \reimp
+*/
+QWSWindowSurface* QProxyScreen::createSurface(const QString &key) const
+{
+ if (realScreen)
+ return realScreen->createSurface(key);
+
+ return QScreen::createSurface(key);
+}
+
+/*!
+ \reimp
+*/
+QList<QScreen*> QProxyScreen::subScreens() const
+{
+ if (realScreen)
+ return realScreen->subScreens();
+
+ return QScreen::subScreens();
+}
+
+/*!
+ \reimp
+*/
+QRegion QProxyScreen::region() const
+{
+ if (realScreen)
+ return realScreen->region();
+ else
+ return QScreen::region();
+}
+
+#endif // QT_NO_QWS_PROXYSCREEN
diff --git a/src/gui/embedded/qscreenproxy_qws.h b/src/gui/embedded/qscreenproxy_qws.h
new file mode 100644
index 0000000000..6373c2af7b
--- /dev/null
+++ b/src/gui/embedded/qscreenproxy_qws.h
@@ -0,0 +1,153 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPROXYSCREEN_QWS_H
+#define QPROXYSCREEN_QWS_H
+
+#include <QtGui/qscreen_qws.h>
+
+#ifndef QT_NO_QWS_PROXYSCREEN
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QProxyScreenPrivate;
+
+#ifndef QT_NO_QWS_CURSOR
+
+class QProxyScreenCursorPrivate;
+
+class Q_GUI_EXPORT QProxyScreenCursor : public QScreenCursor
+{
+public:
+ QProxyScreenCursor();
+ ~QProxyScreenCursor();
+
+ void setScreenCursor(QScreenCursor *cursor);
+ QScreenCursor* screenCursor() const;
+
+ void set(const QImage &image, int hotx, int hoty);
+ void move(int x, int y);
+ void show();
+ void hide();
+
+private:
+ void configure();
+
+ QScreenCursor *realCursor;
+ QProxyScreenCursorPrivate *d_ptr;
+};
+
+#endif // QT_NO_QWS_CURSOR
+
+class Q_GUI_EXPORT QProxyScreen : public QScreen
+{
+public:
+ QProxyScreen(int display_id, ClassId = ProxyClass);
+ ~QProxyScreen();
+
+ void setScreen(QScreen *screen);
+ QScreen *screen() const;
+
+ QSize mapToDevice(const QSize &s) const;
+ QSize mapFromDevice(const QSize &s) const;
+
+ QPoint mapToDevice(const QPoint &, const QSize &) const;
+ QPoint mapFromDevice(const QPoint &, const QSize &) const;
+
+ QRect mapToDevice(const QRect &, const QSize &) const;
+ QRect mapFromDevice(const QRect &, const QSize &) const;
+
+ QRegion mapToDevice(const QRegion &, const QSize &) const;
+ QRegion mapFromDevice(const QRegion &, const QSize &) const;
+
+ bool connect(const QString &displaySpec);
+ bool initDevice();
+ void shutdownDevice();
+ void disconnect();
+
+ void setMode(int width, int height, int depth);
+ bool supportsDepth(int) const;
+
+ void save();
+ void restore();
+ void blank(bool on);
+
+ bool onCard(const unsigned char *) const;
+ bool onCard(const unsigned char *, ulong& out_offset) const;
+
+ bool isInterlaced() const;
+ bool isTransformed() const;
+ int transformOrientation() const;
+
+ int memoryNeeded(const QString&);
+ int sharedRamSize(void *);
+
+ void haltUpdates();
+ void resumeUpdates();
+
+ void exposeRegion(QRegion r, int changing);
+ void blit(const QImage &img, const QPoint &topLeft, const QRegion &region);
+ void solidFill(const QColor &color, const QRegion &region);
+ void setDirty(const QRect&);
+
+ QWSWindowSurface* createSurface(QWidget *widget) const;
+ QWSWindowSurface* createSurface(const QString &key) const;
+
+ QList<QScreen*> subScreens() const;
+ QRegion region() const;
+
+private:
+ void configure();
+
+ QScreen *realScreen;
+ QProxyScreenPrivate *d_ptr;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_QWS_PROXYSCREEN
+#endif // QPROXYSCREEN_QWS_H
diff --git a/src/gui/embedded/qscreentransformed_qws.cpp b/src/gui/embedded/qscreentransformed_qws.cpp
new file mode 100644
index 0000000000..f9887890fd
--- /dev/null
+++ b/src/gui/embedded/qscreentransformed_qws.cpp
@@ -0,0 +1,734 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qscreentransformed_qws.h"
+
+#ifndef QT_NO_QWS_TRANSFORMED
+#include <qscreendriverfactory_qws.h>
+#include <qvector.h>
+#include <private/qpainter_p.h>
+#include <private/qmemrotate_p.h>
+#include <qmatrix.h>
+
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <errno.h>
+
+#include <qwindowsystem_qws.h>
+#include <qwsdisplay_qws.h>
+
+QT_BEGIN_NAMESPACE
+
+//#define QT_REGION_DEBUG
+
+#ifdef QT_REGION_DEBUG
+#include <QDebug>
+#endif
+
+class QTransformedScreenPrivate
+{
+public:
+ QTransformedScreenPrivate(QTransformedScreen *parent);
+
+ void configure();
+
+ QTransformedScreen::Transformation transformation;
+#ifdef QT_QWS_DEPTH_GENERIC
+ bool doGenericColors;
+#endif
+ QTransformedScreen *q;
+};
+
+QTransformedScreenPrivate::QTransformedScreenPrivate(QTransformedScreen *parent)
+ : transformation(QTransformedScreen::None),
+#ifdef QT_QWS_DEPTH_GENERIC
+ doGenericColors(false),
+#endif
+ q(parent)
+{
+}
+
+extern "C"
+#ifndef QT_BUILD_GUI_LIB
+Q_DECL_EXPORT
+#endif
+void qws_setScreenTransformation(QScreen *that, int t)
+{
+ QTransformedScreen *tscreen = static_cast<QTransformedScreen*>(that);
+ tscreen->setTransformation((QTransformedScreen::Transformation)t);
+}
+
+// ---------------------------------------------------------------------------
+// Transformed Screen
+// ---------------------------------------------------------------------------
+
+/*!
+ \internal
+
+ \class QTransformedScreen
+ \ingroup qws
+
+ \brief The QTransformedScreen class implements a screen driver for
+ a transformed screen.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+ Custom screen drivers can be added by subclassing the
+ QScreenDriverPlugin class, using the QScreenDriverFactory class to
+ dynamically load the driver into the application, but there should
+ only be one screen object per application.
+
+ Use the QScreen::isTransformed() function to determine if a screen
+ is transformed. The QTransformedScreen class itself provides means
+ of rotating the screen with its setTransformation() function; the
+ transformation() function returns the currently set rotation in
+ terms of the \l Transformation enum (which describes the various
+ available rotation settings). Alternatively, QTransformedScreen
+ provides an implementation of the QScreen::transformOrientation()
+ function, returning the current rotation as an integer value.
+
+ \sa QScreen, QScreenDriverPlugin, {Running Applications}
+*/
+
+/*!
+ \enum QTransformedScreen::Transformation
+
+ This enum describes the various rotations a transformed screen can
+ have.
+
+ \value None No rotation
+ \value Rot90 90 degrees rotation
+ \value Rot180 180 degrees rotation
+ \value Rot270 270 degrees rotation
+*/
+
+/*!
+ \fn bool QTransformedScreen::isTransformed() const
+ \reimp
+*/
+
+/*!
+ Constructs a QTransformedScreen object. The \a displayId argument
+ identifies the Qt for Embedded Linux server to connect to.
+*/
+QTransformedScreen::QTransformedScreen(int displayId)
+ : QProxyScreen(displayId, QScreen::TransformedClass)
+{
+ d_ptr = new QTransformedScreenPrivate(this);
+ d_ptr->transformation = None;
+
+#ifdef QT_REGION_DEBUG
+ qDebug() << "QTransformedScreen::QTransformedScreen";
+#endif
+}
+
+void QTransformedScreenPrivate::configure()
+{
+ // ###: works because setTransformation recalculates unconditionally
+ q->setTransformation(transformation);
+}
+
+/*!
+ Destroys the QTransformedScreen object.
+*/
+QTransformedScreen::~QTransformedScreen()
+{
+ delete d_ptr;
+}
+
+static int getDisplayId(const QString &spec)
+{
+ QRegExp regexp(QLatin1String(":(\\d+)\\b"));
+ if (regexp.lastIndexIn(spec) != -1) {
+ const QString capture = regexp.cap(1);
+ return capture.toInt();
+ }
+ return 0;
+}
+
+static QTransformedScreen::Transformation filterTransformation(QString &spec)
+{
+ QRegExp regexp(QLatin1String("\\bRot(\\d+):?\\b"), Qt::CaseInsensitive);
+ if (regexp.indexIn(spec) == -1)
+ return QTransformedScreen::None;
+
+ const int degrees = regexp.cap(1).toInt();
+ spec.remove(regexp.pos(0), regexp.matchedLength());
+
+ return static_cast<QTransformedScreen::Transformation>(degrees / 90);
+}
+
+/*!
+ \reimp
+*/
+bool QTransformedScreen::connect(const QString &displaySpec)
+{
+ QString dspec = displaySpec.trimmed();
+ if (dspec.startsWith(QLatin1String("Transformed:"), Qt::CaseInsensitive))
+ dspec = dspec.mid(QString(QLatin1String("Transformed:")).size());
+ else if (!dspec.compare(QLatin1String("Transformed"), Qt::CaseInsensitive))
+ dspec = QString();
+
+ const QString displayIdSpec = QString(QLatin1String(" :%1")).arg(displayId);
+ if (dspec.endsWith(displayIdSpec))
+ dspec = dspec.left(dspec.size() - displayIdSpec.size());
+
+ d_ptr->transformation = filterTransformation(dspec);
+
+ QString driver = dspec;
+ int colon = driver.indexOf(QLatin1Char(':'));
+ if (colon >= 0)
+ driver.truncate(colon);
+
+ if (!QScreenDriverFactory::keys().contains(driver, Qt::CaseInsensitive))
+ if (!dspec.isEmpty())
+ dspec.prepend(QLatin1String(":"));
+
+ const int id = getDisplayId(dspec);
+ QScreen *s = qt_get_screen(id, dspec.toLatin1().constData());
+ setScreen(s);
+
+#ifdef QT_QWS_DEPTH_GENERIC
+ d_ptr->doGenericColors = dspec.contains(QLatin1String("genericcolors"));
+#endif
+
+ d_ptr->configure();
+
+ // XXX
+ qt_screen = this;
+
+ return true;
+}
+
+/*!
+ Returns the currently set rotation.
+
+ \sa setTransformation(), QScreen::transformOrientation()
+*/
+QTransformedScreen::Transformation QTransformedScreen::transformation() const
+{
+ return d_ptr->transformation;
+}
+
+/*!
+ \reimp
+*/
+int QTransformedScreen::transformOrientation() const
+{
+ return (int)d_ptr->transformation;
+}
+
+/*!
+ \reimp
+*/
+void QTransformedScreen::exposeRegion(QRegion region, int changing)
+{
+ if (!data || d_ptr->transformation == None) {
+ QProxyScreen::exposeRegion(region, changing);
+ return;
+ }
+ QScreen::exposeRegion(region, changing);
+}
+
+/*!
+ Rotates this screen object according to the specified \a transformation.
+
+ \sa transformation()
+*/
+void QTransformedScreen::setTransformation(Transformation transformation)
+{
+ d_ptr->transformation = transformation;
+ QSize size = mapFromDevice(QSize(dw, dh));
+ w = size.width();
+ h = size.height();
+
+ const QScreen *s = screen();
+ size = mapFromDevice(QSize(s->physicalWidth(), s->physicalHeight()));
+ physWidth = size.width();
+ physHeight = size.height();
+
+#ifdef QT_REGION_DEBUG
+ qDebug() << "QTransformedScreen::setTransformation" << transformation
+ << "size" << w << h << "dev size" << dw << dh;
+#endif
+
+}
+
+static inline QRect correctNormalized(const QRect &r) {
+ const int x1 = qMin(r.left(), r.right());
+ const int x2 = qMax(r.left(), r.right());
+ const int y1 = qMin(r.top(), r.bottom());
+ const int y2 = qMax(r.top(), r.bottom());
+
+ return QRect( QPoint(x1,y1), QPoint(x2,y2) );
+}
+
+template <class DST, class SRC>
+static inline void blit90(QScreen *screen, const QImage &image,
+ const QRect &rect, const QPoint &topLeft)
+{
+ const SRC *src = (const SRC*)(image.scanLine(rect.top())) + rect.left();
+ DST *dest = (DST*)(screen->base() + topLeft.y() * screen->linestep())
+ + topLeft.x();
+ qt_memrotate90(src, rect.width(), rect.height(), image.bytesPerLine(),
+ dest, screen->linestep());
+}
+
+template <class DST, class SRC>
+static inline void blit180(QScreen *screen, const QImage &image,
+ const QRect &rect, const QPoint &topLeft)
+{
+ const SRC *src = (const SRC*)(image.scanLine(rect.top())) + rect.left();
+ DST *dest = (DST*)(screen->base() + topLeft.y() * screen->linestep())
+ + topLeft.x();
+ qt_memrotate180(src, rect.width(), rect.height(), image.bytesPerLine(),
+ dest, screen->linestep());
+}
+
+template <class DST, class SRC>
+static inline void blit270(QScreen *screen, const QImage &image,
+ const QRect &rect, const QPoint &topLeft)
+{
+ const SRC *src = (const SRC *)(image.scanLine(rect.top())) + rect.left();
+ DST *dest = (DST*)(screen->base() + topLeft.y() * screen->linestep())
+ + topLeft.x();
+ qt_memrotate270(src, rect.width(), rect.height(), image.bytesPerLine(),
+ dest, screen->linestep());
+}
+
+typedef void (*BlitFunc)(QScreen *, const QImage &, const QRect &, const QPoint &);
+
+#define SET_BLIT_FUNC(dst, src, rotation, func) \
+do { \
+ switch (rotation) { \
+ case Rot90: \
+ func = blit90<dst, src>; \
+ break; \
+ case Rot180: \
+ func = blit180<dst, src>; \
+ break; \
+ case Rot270: \
+ func = blit270<dst, src>; \
+ break; \
+ default: \
+ break; \
+ } \
+} while (0)
+
+/*!
+ \reimp
+*/
+void QTransformedScreen::blit(const QImage &image, const QPoint &topLeft,
+ const QRegion &region)
+{
+ const Transformation trans = d_ptr->transformation;
+ if (trans == None) {
+ QProxyScreen::blit(image, topLeft, region);
+ return;
+ }
+
+ const QVector<QRect> rects = region.rects();
+ const QRect bound = QRect(0, 0, QScreen::w, QScreen::h)
+ & QRect(topLeft, image.size());
+
+ BlitFunc func = 0;
+#ifdef QT_QWS_DEPTH_GENERIC
+ if (d_ptr->doGenericColors && depth() == 16) {
+ if (image.depth() == 16)
+ SET_BLIT_FUNC(qrgb_generic16, quint16, trans, func);
+ else
+ SET_BLIT_FUNC(qrgb_generic16, quint32, trans, func);
+ } else
+#endif
+ switch (depth()) {
+#ifdef QT_QWS_DEPTH_32
+ case 32:
+#ifdef QT_QWS_DEPTH_16
+ if (image.depth() == 16)
+ SET_BLIT_FUNC(quint32, quint16, trans, func);
+ else
+#endif
+ SET_BLIT_FUNC(quint32, quint32, trans, func);
+ break;
+#endif
+#if defined(QT_QWS_DEPTH_24) || defined(QT_QWS_DEPTH18)
+ case 24:
+ case 18:
+ SET_BLIT_FUNC(quint24, quint24, trans, func);
+ break;
+#endif
+#if defined(QT_QWS_DEPTH_16) || defined(QT_QWS_DEPTH_15) || defined(QT_QWS_DEPTH_12)
+ case 16:
+ case 15:
+ case 12:
+ if (image.depth() == 16)
+ SET_BLIT_FUNC(quint16, quint16, trans, func);
+ else
+ SET_BLIT_FUNC(quint16, quint32, trans, func);
+ break;
+#endif
+#ifdef QT_QWS_DEPTH_8
+ case 8:
+ if (image.depth() == 16)
+ SET_BLIT_FUNC(quint8, quint16, trans, func);
+ else
+ SET_BLIT_FUNC(quint8, quint32, trans, func);
+ break;
+#endif
+ default:
+ return;
+ }
+ if (!func)
+ return;
+
+ QWSDisplay::grab();
+ for (int i = 0; i < rects.size(); ++i) {
+ const QRect r = rects.at(i) & bound;
+
+ QPoint dst;
+ switch (trans) {
+ case Rot90:
+ dst = mapToDevice(r.topRight(), QSize(w, h));
+ break;
+ case Rot180:
+ dst = mapToDevice(r.bottomRight(), QSize(w, h));
+ break;
+ case Rot270:
+ dst = mapToDevice(r.bottomLeft(), QSize(w, h));
+ break;
+ default:
+ break;
+ }
+ func(this, image, r.translated(-topLeft), dst);
+ }
+ QWSDisplay::ungrab();
+
+}
+
+/*!
+ \reimp
+*/
+void QTransformedScreen::solidFill(const QColor &color, const QRegion &region)
+{
+ const QRegion tr = mapToDevice(region, QSize(w,h));
+
+ Q_ASSERT(tr.boundingRect() == mapToDevice(region.boundingRect(), QSize(w,h)));
+
+#ifdef QT_REGION_DEBUG
+ qDebug() << "QTransformedScreen::solidFill region" << region << "transformed" << tr;
+#endif
+ QProxyScreen::solidFill(color, tr);
+}
+
+/*!
+ \reimp
+*/
+QSize QTransformedScreen::mapToDevice(const QSize &s) const
+{
+ switch (d_ptr->transformation) {
+ case None:
+ case Rot180:
+ break;
+ case Rot90:
+ case Rot270:
+ return QSize(s.height(), s.width());
+ break;
+ }
+ return s;
+}
+
+/*!
+ \reimp
+*/
+QSize QTransformedScreen::mapFromDevice(const QSize &s) const
+{
+ switch (d_ptr->transformation) {
+ case None:
+ case Rot180:
+ break;
+ case Rot90:
+ case Rot270:
+ return QSize(s.height(), s.width());
+ break;
+ }
+ return s;
+}
+
+/*!
+ \reimp
+*/
+QPoint QTransformedScreen::mapToDevice(const QPoint &p, const QSize &s) const
+{
+ QPoint rp(p);
+
+ switch (d_ptr->transformation) {
+ case None:
+ break;
+ case Rot90:
+ rp.setX(p.y());
+ rp.setY(s.width() - p.x() - 1);
+ break;
+ case Rot180:
+ rp.setX(s.width() - p.x() - 1);
+ rp.setY(s.height() - p.y() - 1);
+ break;
+ case Rot270:
+ rp.setX(s.height() - p.y() - 1);
+ rp.setY(p.x());
+ break;
+ }
+
+ return rp;
+}
+
+/*!
+ \reimp
+*/
+QPoint QTransformedScreen::mapFromDevice(const QPoint &p, const QSize &s) const
+{
+ QPoint rp(p);
+
+ switch (d_ptr->transformation) {
+ case None:
+ break;
+ case Rot90:
+ rp.setX(s.height() - p.y() - 1);
+ rp.setY(p.x());
+ break;
+ case Rot180:
+ rp.setX(s.width() - p.x() - 1);
+ rp.setY(s.height() - p.y() - 1);
+ break;
+ case Rot270:
+ rp.setX(p.y());
+ rp.setY(s.width() - p.x() - 1);
+ break;
+ }
+
+ return rp;
+}
+
+/*!
+ \reimp
+*/
+QRect QTransformedScreen::mapToDevice(const QRect &r, const QSize &s) const
+{
+ if (r.isNull())
+ return QRect();
+
+ QRect tr;
+ switch (d_ptr->transformation) {
+ case None:
+ tr = r;
+ break;
+ case Rot90:
+ tr.setCoords(r.y(), s.width() - r.x() - 1,
+ r.bottom(), s.width() - r.right() - 1);
+ break;
+ case Rot180:
+ tr.setCoords(s.width() - r.x() - 1, s.height() - r.y() - 1,
+ s.width() - r.right() - 1, s.height() - r.bottom() - 1);
+ break;
+ case Rot270:
+ tr.setCoords(s.height() - r.y() - 1, r.x(),
+ s.height() - r.bottom() - 1, r.right());
+ break;
+ }
+
+ return correctNormalized(tr);
+}
+
+/*!
+ \reimp
+*/
+QRect QTransformedScreen::mapFromDevice(const QRect &r, const QSize &s) const
+{
+ if (r.isNull())
+ return QRect();
+
+ QRect tr;
+ switch (d_ptr->transformation) {
+ case None:
+ tr = r;
+ break;
+ case Rot90:
+ tr.setCoords(s.height() - r.y() - 1, r.x(),
+ s.height() - r.bottom() - 1, r.right());
+ break;
+ case Rot180:
+ tr.setCoords(s.width() - r.x() - 1, s.height() - r.y() - 1,
+ s.width() - r.right() - 1, s.height() - r.bottom() - 1);
+ break;
+ case Rot270:
+ tr.setCoords(r.y(), s.width() - r.x() - 1,
+ r.bottom(), s.width() - r.right() - 1);
+ break;
+ }
+
+ return correctNormalized(tr);
+}
+
+/*!
+ \reimp
+*/
+QRegion QTransformedScreen::mapToDevice(const QRegion &rgn, const QSize &s) const
+{
+ if (d_ptr->transformation == None)
+ return QProxyScreen::mapToDevice(rgn, s);
+
+#ifdef QT_REGION_DEBUG
+ qDebug() << "mapToDevice size" << s << "rgn: " << rgn;
+#endif
+ QRect tr;
+ QRegion trgn;
+ QVector<QRect> a = rgn.rects();
+ const QRect *r = a.data();
+
+ int w = s.width();
+ int h = s.height();
+ int size = a.size();
+
+ switch (d_ptr->transformation) {
+ case None:
+ break;
+ case Rot90:
+ for (int i = 0; i < size; i++, r++) {
+ tr.setCoords(r->y(), w - r->x() - 1,
+ r->bottom(), w - r->right() - 1);
+ trgn |= correctNormalized(tr);
+ }
+ break;
+ case Rot180:
+ for (int i = 0; i < size; i++, r++) {
+ tr.setCoords(w - r->x() - 1, h - r->y() - 1,
+ w - r->right() - 1, h - r->bottom() - 1);
+ trgn |= correctNormalized(tr);
+ }
+ break;
+ case Rot270:
+ for (int i = 0; i < size; i++, r++) {
+ tr.setCoords(h - r->y() - 1, r->x(),
+ h - r->bottom() - 1, r->right());
+ trgn |= correctNormalized(tr);
+ }
+ break;
+ }
+#ifdef QT_REGION_DEBUG
+ qDebug() << "mapToDevice trgn: " << trgn;
+#endif
+ return trgn;
+}
+
+/*!
+ \reimp
+*/
+QRegion QTransformedScreen::mapFromDevice(const QRegion &rgn, const QSize &s) const
+{
+ if (d_ptr->transformation == None)
+ return QProxyScreen::mapFromDevice(rgn, s);
+
+#ifdef QT_REGION_DEBUG
+ qDebug() << "fromDevice: realRegion count: " << rgn.rects().size() << " isEmpty? " << rgn.isEmpty() << " bounds:" << rgn.boundingRect();
+#endif
+ QRect tr;
+ QRegion trgn;
+ QVector<QRect> a = rgn.rects();
+ const QRect *r = a.data();
+
+ int w = s.width();
+ int h = s.height();
+ int size = a.size();
+
+ switch (d_ptr->transformation) {
+ case None:
+ break;
+ case Rot90:
+ for (int i = 0; i < size; i++, r++) {
+ tr.setCoords(h - r->y() - 1, r->x(),
+ h - r->bottom() - 1, r->right());
+ trgn |= correctNormalized(tr);
+ }
+ break;
+ case Rot180:
+ for (int i = 0; i < size; i++, r++) {
+ tr.setCoords(w - r->x() - 1, h - r->y() - 1,
+ w - r->right() - 1, h - r->bottom() - 1);
+ trgn |= correctNormalized(tr);
+ }
+ break;
+ case Rot270:
+ for (int i = 0; i < size; i++, r++) {
+ tr.setCoords(r->y(), w - r->x() - 1,
+ r->bottom(), w - r->right() - 1);
+ trgn |= correctNormalized(tr);
+ }
+ break;
+ }
+#ifdef QT_REGION_DEBUG
+ qDebug() << "fromDevice: transRegion count: " << trgn.rects().size() << " isEmpty? " << trgn.isEmpty() << " bounds:" << trgn.boundingRect();
+#endif
+ return trgn;
+}
+
+/*!
+ \reimp
+*/
+void QTransformedScreen::setDirty(const QRect& rect)
+{
+ const QRect r = mapToDevice(rect, QSize(width(), height()));
+ QProxyScreen::setDirty(r);
+}
+
+/*!
+ \reimp
+*/
+QRegion QTransformedScreen::region() const
+{
+ QRegion deviceRegion = QProxyScreen::region();
+ return mapFromDevice(deviceRegion, QSize(deviceWidth(), deviceHeight()));
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QWS_TRANSFORMED
diff --git a/src/gui/embedded/qscreentransformed_qws.h b/src/gui/embedded/qscreentransformed_qws.h
new file mode 100644
index 0000000000..e2d5a33e7f
--- /dev/null
+++ b/src/gui/embedded/qscreentransformed_qws.h
@@ -0,0 +1,103 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCREENTRANSFORMED_QWS_H
+#define QSCREENTRANSFORMED_QWS_H
+
+#include <QtGui/qscreenproxy_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_TRANSFORMED
+
+class QTransformedScreenPrivate;
+
+class Q_AUTOTEST_EXPORT QTransformedScreen : public QProxyScreen
+{
+public:
+ explicit QTransformedScreen(int display_id);
+ ~QTransformedScreen();
+
+ enum Transformation { None, Rot90, Rot180, Rot270 };
+
+ void setTransformation(Transformation t);
+ Transformation transformation() const;
+ int transformOrientation() const;
+
+ QSize mapToDevice(const QSize &s) const;
+ QSize mapFromDevice(const QSize &s) const;
+
+ QPoint mapToDevice(const QPoint &, const QSize &) const;
+ QPoint mapFromDevice(const QPoint &, const QSize &) const;
+
+ QRect mapToDevice(const QRect &, const QSize &) const;
+ QRect mapFromDevice(const QRect &, const QSize &) const;
+
+ QRegion mapToDevice(const QRegion &, const QSize &) const;
+ QRegion mapFromDevice(const QRegion &, const QSize &) const;
+
+ bool connect(const QString &displaySpec);
+
+ bool isTransformed() const { return transformation() != None; }
+
+ void exposeRegion(QRegion region, int changing);
+ void blit(const QImage &img, const QPoint &topLeft, const QRegion &region);
+ void solidFill(const QColor &color, const QRegion &region);
+ void setDirty(const QRect&);
+
+ QRegion region() const;
+
+private:
+ friend class QTransformedScreenPrivate;
+ QTransformedScreenPrivate *d_ptr;
+};
+
+#endif // QT_NO_QWS_TRANSFORMED
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSCREENTRANSFORMED_QWS_H
diff --git a/src/gui/embedded/qscreenvfb_qws.cpp b/src/gui/embedded/qscreenvfb_qws.cpp
new file mode 100644
index 0000000000..abbe73bd91
--- /dev/null
+++ b/src/gui/embedded/qscreenvfb_qws.cpp
@@ -0,0 +1,444 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT_NO_QWS_QVFB
+
+#define QTOPIA_QVFB_BRIGHTNESS
+
+#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 <qvfbhdr.h>
+#include <qscreenvfb_qws.h>
+#include <qkbdvfb_qws.h>
+#include <qmousevfb_qws.h>
+#include <qwindowsystem_qws.h>
+#include <qsocketnotifier.h>
+#include <qapplication.h>
+#include <qscreen_qws.h>
+#include <qmousedriverfactory_qws.h>
+#include <qkbddriverfactory_qws.h>
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QVFbScreenPrivate
+{
+public:
+ QVFbScreenPrivate();
+ ~QVFbScreenPrivate();
+
+ bool success;
+ unsigned char *shmrgn;
+ int brightness;
+ bool blank;
+ QVFbHeader *hdr;
+ QWSMouseHandler *mouse;
+#ifndef QT_NO_QWS_KEYBOARD
+ QWSKeyboardHandler *keyboard;
+#endif
+};
+
+QVFbScreenPrivate::QVFbScreenPrivate()
+ : mouse(0)
+
+{
+#ifndef QT_NO_QWS_KEYBOARD
+ keyboard = 0;
+#endif
+ brightness = 255;
+ blank = false;
+}
+
+QVFbScreenPrivate::~QVFbScreenPrivate()
+{
+ delete mouse;
+#ifndef QT_NO_QWS_KEYBOARD
+ delete keyboard;
+#endif
+}
+
+/*!
+ \internal
+
+ \class QVFbScreen
+ \ingroup qws
+
+ \brief The QVFbScreen class implements a screen driver for the
+ virtual framebuffer.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+ Custom screen drivers can be added by subclassing the
+ QScreenDriverPlugin class, using the QScreenDriverFactory class to
+ dynamically load the driver into the application, but there should
+ only be one screen object per application.
+
+ The Qt for Embedded Linux platform provides a \l{The Virtual
+ Framebuffer}{virtual framebuffer} for development and debugging;
+ the virtual framebuffer allows Qt for Embedded Linux applications to be
+ developed on a desktop machine, without switching between consoles
+ and X11.
+
+ \sa QScreen, QScreenDriverPlugin, {Running Applications}
+*/
+
+/*!
+ \fn bool QVFbScreen::connect(const QString & displaySpec)
+ \reimp
+*/
+
+/*!
+ \fn void QVFbScreen::disconnect()
+ \reimp
+*/
+
+/*!
+ \fn bool QVFbScreen::initDevice()
+ \reimp
+*/
+
+/*!
+ \fn void QVFbScreen::restore()
+ \reimp
+*/
+
+/*!
+ \fn void QVFbScreen::save()
+ \reimp
+*/
+
+/*!
+ \fn void QVFbScreen::setDirty(const QRect & r)
+ \reimp
+*/
+
+/*!
+ \fn void QVFbScreen::setMode(int nw, int nh, int nd)
+ \reimp
+*/
+
+/*!
+ \fn void QVFbScreen::shutdownDevice()
+ \reimp
+*/
+
+/*!
+ \fn QVFbScreen::QVFbScreen(int displayId)
+
+ Constructs a QVNCScreen object. The \a displayId argument
+ identifies the Qt for Embedded Linux server to connect to.
+*/
+QVFbScreen::QVFbScreen(int display_id)
+ : QScreen(display_id, VFbClass), d_ptr(new QVFbScreenPrivate)
+{
+ d_ptr->shmrgn = 0;
+ d_ptr->hdr = 0;
+ data = 0;
+}
+
+/*!
+ Destroys this QVFbScreen object.
+*/
+QVFbScreen::~QVFbScreen()
+{
+ delete d_ptr;
+}
+
+static QVFbScreen *connected = 0;
+
+bool QVFbScreen::connect(const QString &displaySpec)
+{
+ QStringList displayArgs = displaySpec.split(QLatin1Char(':'));
+ if (displayArgs.contains(QLatin1String("Gray")))
+ grayscale = true;
+
+ key_t key = ftok(QByteArray(QT_VFB_MOUSE_PIPE).replace("%1", QByteArray::number(displayId)), 'b');
+
+ if (key == -1)
+ return false;
+
+#if Q_BYTE_ORDER == Q_BIG_ENDIAN
+#ifndef QT_QWS_FRAMEBUFFER_LITTLE_ENDIAN
+ if (displayArgs.contains(QLatin1String("littleendian")))
+#endif
+ QScreen::setFrameBufferLittleEndian(true);
+#endif
+
+ int shmId = shmget(key, 0, 0);
+ if (shmId != -1)
+ d_ptr->shmrgn = (unsigned char *)shmat(shmId, 0, 0);
+ else
+ return false;
+
+ if ((long)d_ptr->shmrgn == -1 || d_ptr->shmrgn == 0) {
+ qDebug("No shmrgn %ld", (long)d_ptr->shmrgn);
+ return false;
+ }
+
+ d_ptr->hdr = (QVFbHeader *)d_ptr->shmrgn;
+ data = d_ptr->shmrgn + d_ptr->hdr->dataoffset;
+
+ dw = w = d_ptr->hdr->width;
+ dh = h = d_ptr->hdr->height;
+ d = d_ptr->hdr->depth;
+
+ switch (d) {
+ case 1:
+ setPixelFormat(QImage::Format_Mono);
+ break;
+ case 8:
+ setPixelFormat(QImage::Format_Indexed8);
+ break;
+ case 12:
+ setPixelFormat(QImage::Format_RGB444);
+ break;
+ case 15:
+ setPixelFormat(QImage::Format_RGB555);
+ break;
+ case 16:
+ setPixelFormat(QImage::Format_RGB16);
+ break;
+ case 18:
+ setPixelFormat(QImage::Format_RGB666);
+ break;
+ case 24:
+ setPixelFormat(QImage::Format_RGB888);
+ break;
+ case 32:
+ setPixelFormat(QImage::Format_ARGB32_Premultiplied);
+ break;
+ }
+
+ lstep = d_ptr->hdr->linestep;
+
+ // Handle display physical size spec.
+ int dimIdxW = -1;
+ int dimIdxH = -1;
+ for (int i = 0; i < displayArgs.size(); ++i) {
+ if (displayArgs.at(i).startsWith(QLatin1String("mmWidth"))) {
+ dimIdxW = i;
+ break;
+ }
+ }
+ for (int i = 0; i < displayArgs.size(); ++i) {
+ if (displayArgs.at(i).startsWith(QLatin1String("mmHeight"))) {
+ dimIdxH = i;
+ break;
+ }
+ }
+ if (dimIdxW >= 0) {
+ bool ok;
+ int pos = 7;
+ if (displayArgs.at(dimIdxW).at(pos) == QLatin1Char('='))
+ ++pos;
+ int pw = displayArgs.at(dimIdxW).mid(pos).toInt(&ok);
+ if (ok) {
+ physWidth = pw;
+ if (dimIdxH < 0)
+ physHeight = dh*physWidth/dw;
+ }
+ }
+ if (dimIdxH >= 0) {
+ bool ok;
+ int pos = 8;
+ if (displayArgs.at(dimIdxH).at(pos) == QLatin1Char('='))
+ ++pos;
+ int ph = displayArgs.at(dimIdxH).mid(pos).toInt(&ok);
+ if (ok) {
+ physHeight = ph;
+ 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);
+ }
+
+ qDebug("Connected to VFB server %s: %d x %d x %d %dx%dmm (%dx%ddpi)", displaySpec.toLatin1().data(),
+ w, h, d, physWidth, physHeight, qRound(dw*25.4/physWidth), qRound(dh*25.4/physHeight) );
+
+ size = lstep * h;
+ mapsize = size;
+ screencols = d_ptr->hdr->numcols;
+ memcpy(screenclut, d_ptr->hdr->clut, sizeof(QRgb) * screencols);
+
+ connected = this;
+
+ return true;
+}
+
+void QVFbScreen::disconnect()
+{
+ connected = 0;
+ if ((long)d_ptr->shmrgn != -1 && d_ptr->shmrgn) {
+ if (qApp->type() == QApplication::GuiServer && d_ptr->hdr->dataoffset >= (int)sizeof(QVFbHeader)) {
+ d_ptr->hdr->serverVersion = 0;
+ }
+ shmdt((char*)d_ptr->shmrgn);
+ }
+}
+
+bool QVFbScreen::initDevice()
+{
+#ifndef QT_NO_QWS_MOUSE_QVFB
+ const QString mouseDev = QString(QLatin1String(QT_VFB_MOUSE_PIPE))
+ .arg(displayId);
+ d_ptr->mouse = new QVFbMouseHandler(QLatin1String("QVFbMouse"), mouseDev);
+ qwsServer->setDefaultMouse("None");
+ if (d_ptr->mouse)
+ d_ptr->mouse->setScreen(this);
+#endif
+
+#if !defined(QT_NO_QWS_KBD_QVFB) && !defined(QT_NO_QWS_KEYBOARD)
+ const QString keyboardDev = QString(QLatin1String(QT_VFB_KEYBOARD_PIPE))
+ .arg(displayId);
+ d_ptr->keyboard = new QVFbKeyboardHandler(keyboardDev);
+ qwsServer->setDefaultKeyboard("None");
+#endif
+
+ if (d_ptr->hdr->dataoffset >= (int)sizeof(QVFbHeader))
+ d_ptr->hdr->serverVersion = QT_VERSION;
+
+ if(d==8) {
+ screencols=256;
+ if (grayscale) {
+ // Build grayscale palette
+ for(int loopc=0;loopc<256;loopc++) {
+ screenclut[loopc]=qRgb(loopc,loopc,loopc);
+ }
+ } 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) {
+ screenclut[idx]=qRgb(ir, ig, ib);
+ idx++;
+ }
+ }
+ }
+ screencols=idx;
+ }
+ memcpy(d_ptr->hdr->clut, screenclut, sizeof(QRgb) * screencols);
+ d_ptr->hdr->numcols = screencols;
+ } else if (d == 4) {
+ int val = 0;
+ for (int idx = 0; idx < 16; idx++, val += 17) {
+ screenclut[idx] = qRgb(val, val, val);
+ }
+ screencols = 16;
+ memcpy(d_ptr->hdr->clut, screenclut, sizeof(QRgb) * screencols);
+ d_ptr->hdr->numcols = screencols;
+ } else if (d == 1) {
+ screencols = 2;
+ screenclut[1] = qRgb(0xff, 0xff, 0xff);
+ screenclut[0] = qRgb(0, 0, 0);
+ memcpy(d_ptr->hdr->clut, screenclut, sizeof(QRgb) * screencols);
+ d_ptr->hdr->numcols = screencols;
+ }
+
+#ifndef QT_NO_QWS_CURSOR
+ QScreenCursor::initSoftwareCursor();
+#endif
+ return true;
+}
+
+void QVFbScreen::shutdownDevice()
+{
+}
+
+void QVFbScreen::setMode(int ,int ,int)
+{
+}
+
+// save the state of the graphics card
+// This is needed so that e.g. we can restore the palette when switching
+// between linux virtual consoles.
+void QVFbScreen::save()
+{
+ // nothing to do.
+}
+
+// restore the state of the graphics card.
+void QVFbScreen::restore()
+{
+}
+void QVFbScreen::setDirty(const QRect& rect)
+{
+ const QRect r = rect.translated(-offset());
+ d_ptr->hdr->dirty = true;
+ d_ptr->hdr->update = d_ptr->hdr->update.united(r);
+}
+
+void QVFbScreen::setBrightness(int b)
+{
+ if (connected) {
+ connected->d_ptr->brightness = b;
+
+ QVFbHeader *hdr = connected->d_ptr->hdr;
+ if (hdr->viewerVersion < 0x040400) // brightness not supported
+ return;
+
+ const int br = connected->d_ptr->blank ? 0 : b;
+ if (hdr->brightness != br) {
+ hdr->brightness = br;
+ connected->setDirty(connected->region().boundingRect());
+ }
+ }
+}
+
+void QVFbScreen::blank(bool on)
+{
+ d_ptr->blank = on;
+ setBrightness(connected->d_ptr->brightness);
+}
+
+#endif // QT_NO_QWS_QVFB
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qscreenvfb_qws.h b/src/gui/embedded/qscreenvfb_qws.h
new file mode 100644
index 0000000000..1f8edf2d7a
--- /dev/null
+++ b/src/gui/embedded/qscreenvfb_qws.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSCREENVFB_QWS_H
+#define QSCREENVFB_QWS_H
+
+#include <QtGui/qscreen_qws.h>
+#include <QtGui/qvfbhdr.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_QVFB
+
+class QVFbScreenPrivate;
+
+class Q_GUI_EXPORT QVFbScreen : public QScreen
+{
+public:
+ explicit QVFbScreen(int display_id);
+ virtual ~QVFbScreen();
+ virtual bool initDevice();
+ virtual bool connect(const QString &displaySpec);
+ virtual void disconnect();
+ virtual void shutdownDevice();
+ virtual void save();
+ virtual void restore();
+ virtual void setMode(int nw,int nh,int nd);
+ virtual void setDirty(const QRect& r);
+ virtual void blank(bool);
+#ifdef QTOPIA_QVFB_BRIGHTNESS
+ static void setBrightness(int b);
+#endif
+
+private:
+ QVFbScreenPrivate *d_ptr;
+};
+
+#endif // QT_NO_QWS_QVFB
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QSCREENVFB_QWS_H
diff --git a/src/gui/embedded/qsoundqss_qws.cpp b/src/gui/embedded/qsoundqss_qws.cpp
new file mode 100644
index 0000000000..c72ea9121b
--- /dev/null
+++ b/src/gui/embedded/qsoundqss_qws.cpp
@@ -0,0 +1,1498 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qsoundqss_qws.h"
+
+#ifndef QT_NO_SOUND
+#include <qbytearray.h>
+#include <qlist.h>
+#include <qsocketnotifier.h>
+#include <qfile.h>
+#include <qfileinfo.h>
+#include <qstringlist.h>
+#include <qevent.h>
+#include <qalgorithms.h>
+#include <qtimer.h>
+#include <qpointer.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
+
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+extern int errno;
+
+#define QT_QWS_SOUND_16BIT 1 // or 0, or undefined for always 0
+#define QT_QWS_SOUND_STEREO 1 // or 0, or undefined for always 0
+
+// Zaurus SL5000D doesn't seem to return any error if setting to 44000 and it fails,
+// however 44100 works, 44100 is more common that 44000.
+static int sound_speed = 44100;
+#ifndef QT_NO_QWS_SOUNDSERVER
+extern int qws_display_id;
+#define SOUND_PIPE "/tmp/.qt_soundserver-%1"
+#endif
+
+static char *zeroMem = 0;
+
+struct QRiffChunk {
+ char id[4];
+ quint32 size;
+ char data[4/*size*/];
+};
+
+#if defined(QT_QWS_IPAQ)
+static const int sound_fragment_size = 12;
+#else
+static const int sound_fragment_size = 12;
+#endif
+static const int sound_buffer_size = 1 << sound_fragment_size;
+// nb. there will be an sound startup delay of
+// 2^sound_fragment_size / sound_speed seconds.
+// (eg. sound_fragment_size==12, sound_speed==44000 means 0.093s delay)
+
+#ifdef QT_QWS_SOUND_STEREO
+static int sound_stereo=QT_QWS_SOUND_STEREO;
+#else
+static const int sound_stereo=0;
+#endif
+#ifdef QT_QWS_SOUND_16BIT
+static bool sound_16bit=QT_QWS_SOUND_16BIT;
+#else
+static const bool sound_16bit=false;
+#endif
+
+#ifndef QT_NO_QWS_SOUNDSERVER
+class QWSSoundServerClient : public QObject {
+ Q_OBJECT
+
+public:
+ QWSSoundServerClient(QWS_SOCK_BASE *s, QObject* parent);
+ ~QWSSoundServerClient();
+
+public slots:
+ void sendSoundCompleted(int, int);
+ void sendDeviceReady(int, int);
+ void sendDeviceError(int, int, int);
+
+signals:
+ void play(int, int, const QString&);
+ void play(int, int, const QString&, int, int);
+ void playRaw(int, int, const QString&, int, int, int, int);
+
+ void pause(int, int);
+ void stop(int, int);
+ void resume(int, int);
+ void setVolume(int, int, int, int);
+ void setMute(int, int, bool);
+
+ void stopAll(int);
+
+ void playPriorityOnly(bool);
+
+ void setSilent( bool );
+
+private slots:
+ void tryReadCommand();
+
+private:
+ void sendClientMessage(QString msg);
+ int mCurrentID;
+ int left, right;
+ bool priExist;
+ static int lastId;
+ static int nextId() { return ++lastId; }
+ QPointer<QWS_SOCK_BASE> socket;
+};
+
+int QWSSoundServerClient::lastId = 0;
+
+QWSSoundServerClient::QWSSoundServerClient(QWS_SOCK_BASE *s, QObject* parent) :
+ QObject( parent )
+{
+ socket = s;
+ priExist = false;
+ mCurrentID = nextId();
+ connect(socket,SIGNAL(readyRead()),
+ this,SLOT(tryReadCommand()));
+ connect(socket, SIGNAL(disconnected()), this, SLOT(deleteLater()));
+}
+
+QWSSoundServerClient::~QWSSoundServerClient()
+{
+ if (priExist)
+ playPriorityOnly(false);
+ emit stopAll(mCurrentID);
+ if (socket)
+ socket->deleteLater();
+}
+
+static QString getStringTok(QString &in)
+{
+ int pos = in.indexOf(QLatin1Char(' '));
+ QString ret;
+ if (pos > 0) {
+ ret = in.left(pos);
+ in = in.mid(pos+1);
+ } else {
+ ret = in;
+ in = QString::null;
+ }
+ return ret;
+}
+
+static int getNumTok(QString &in)
+{
+ return getStringTok(in).toInt();
+}
+
+void QWSSoundServerClient::tryReadCommand()
+{
+ while ( socket->canReadLine() ) {
+ QString l = QString::fromAscii(socket->readLine());
+ l.truncate(l.length()-1); // chomp
+ QString functionName = getStringTok(l);
+ int soundid = getNumTok(l);
+ if (functionName == QLatin1String("PLAY")) {
+ emit play(mCurrentID, soundid, l);
+ } else if (functionName == QLatin1String("PLAYEXTEND")) {
+ int volume = getNumTok(l);
+ int flags = getNumTok(l);
+ emit play(mCurrentID, soundid, l, volume, flags);
+ } else if (functionName == QLatin1String("PLAYRAW")) {
+ int chs = getNumTok(l);
+ int freq = getNumTok(l);
+ int bitspersample = getNumTok(l);
+ int flags = getNumTok(l);
+ emit playRaw(mCurrentID, soundid, l, freq, chs, bitspersample, flags);
+ } else if (functionName == QLatin1String("PAUSE")) {
+ emit pause(mCurrentID, soundid);
+ } else if (functionName == QLatin1String("STOP")) {
+ emit stop(mCurrentID, soundid);
+ } else if (functionName == QLatin1String("RESUME")) {
+ emit resume(mCurrentID, soundid);
+ } else if (functionName == QLatin1String("SETVOLUME")) {
+ int left = getNumTok(l);
+ int right = getNumTok(l);
+ emit setVolume(mCurrentID, soundid, left, right);
+ } else if (functionName == QLatin1String("MUTE")) {
+ emit setMute(mCurrentID, soundid, true);
+ } else if (functionName == QLatin1String("UNMUTE")) {
+ emit setMute(mCurrentID, soundid, false);
+ } else if (functionName == QLatin1String("PRIORITYONLY")) {
+ bool sPri = soundid != 0;
+ if (sPri != priExist) {
+ priExist = sPri;
+ emit playPriorityOnly(sPri);
+ }
+ } else if(functionName == QLatin1String("SILENT")) {
+ emit setSilent( soundid != 0 );
+ }
+ }
+}
+
+void QWSSoundServerClient::sendClientMessage(QString msg)
+{
+#ifndef QT_NO_TEXTCODEC
+ QByteArray u = msg.toUtf8();
+#else
+ QByteArray u = msg.toLatin1();
+#endif
+ socket->write(u.data(), u.length());
+ socket->flush();
+}
+
+void QWSSoundServerClient::sendSoundCompleted(int gid, int sid)
+{
+ if (gid == mCurrentID)
+ sendClientMessage(QLatin1String("SOUNDCOMPLETED ")
+ + QString::number(sid) + QLatin1Char('\n'));
+}
+
+void QWSSoundServerClient::sendDeviceReady(int gid, int sid)
+{
+ if (gid == mCurrentID)
+ sendClientMessage(QLatin1String("DEVICEREADY ")
+ + QString::number(sid) + QLatin1Char('\n'));
+}
+
+void QWSSoundServerClient::sendDeviceError(int gid, int sid, int err)
+{
+ if (gid == mCurrentID)
+ sendClientMessage(QLatin1String("DEVICEERROR ")
+ + QString::number(sid) + QLatin1Char(' ')
+ + QString::number(err) + QLatin1Char('\n'));
+}
+#endif
+
+static const int maxVolume = 100;
+static const int runinLength = 2*sound_buffer_size;
+class QWSSoundServerProvider {
+public:
+ QWSSoundServerProvider(int w, int s)
+ : mWid(w), mSid(s), mMuted(false)
+ {
+ leftVolume = maxVolume>>1;
+ rightVolume = maxVolume>>1;
+ isPriority = false;
+ samples_due = 0;
+ max1 = max2 = out = 0;//= sound_buffer_size;
+ data = data1;
+ max = &max1;
+ sampleRunin = 0;
+ dev = -1;
+ }
+
+ virtual ~QWSSoundServerProvider() {
+ }
+
+ int groupId() const { return mWid; }
+ int soundId() const { return mSid; }
+
+ void startSampleRunin() {
+ // inteded to provide even audio return from mute/pause/dead samples.
+ //sampleRunin = runinLength; // or more?
+ }
+
+
+ void setVolume(int lv, int rv) {
+ leftVolume = qMin(maxVolume, qMax(0, lv));
+ rightVolume = qMin(maxVolume, qMax(0, rv));
+ }
+
+ void setMute(bool m) { mMuted = m; }
+ bool muted() { return mMuted; }
+
+ void setPriority(bool p) {
+ if (p != isPriority) {
+ isPriority = p; // currently meaningless.
+ }
+ }
+
+
+ static void setPlayPriorityOnly(bool p)
+ {
+ if (p)
+ priorityExists++;
+ else
+ priorityExists--;
+
+ if (priorityExists < 0)
+ qDebug("QSS: got more priority offs than ons");
+ }
+
+ // return -1 for file broken, give up.
+ // else return sampels ready for playing.
+ // argument is max samples server is looking for,
+ // in terms of current device status.
+ virtual int readySamples(int) = 0;
+
+ int getSample(int off, int bps) {
+ return (bps == 1) ? (data[out+off] - 128) * 128 : ((short*)data)[(out/2)+off];
+ }
+
+ int add(int* mixl, int* mixr, int count)
+ {
+ int bytesPerSample = chunkdata.wBitsPerSample >> 3;
+
+ if ( mMuted ) {
+ sampleRunin -= qMin(sampleRunin,count);
+ while (count && (dev != -1)) {
+ if (out >= *max) {
+ // switch buffers
+ out = 0;
+ if (data == data1 && max2 != 0) {
+ data = data2;
+ max = &max2;
+ max1 = 0;
+ } else if (data == data2 && max1 != 0) {
+ data = data1;
+ max = &max1;
+ max2 = 0;
+ } else {
+ qDebug("QSS Read Error: both buffers empty");
+ return 0;
+ }
+ }
+ samples_due += sound_speed;
+ while (count && samples_due >= chunkdata.samplesPerSec) {
+ samples_due -= chunkdata.samplesPerSec;
+ count--;
+ }
+ out += bytesPerSample * chunkdata.channels;
+ }
+ return count;
+ }
+
+ // This shouldn't be the case
+ if ( !mixl || !mixr )
+ return 0;
+
+ int lVolNum = leftVolume, lVolDen = maxVolume;
+ int rVolNum = rightVolume, rVolDen = maxVolume;
+ if (priorityExists > 0 && !isPriority) {
+ lVolNum = 0; // later, make this gradually fade in and out.
+ lVolDen = 5;
+ rVolNum = 0;
+ rVolDen = 5;
+ }
+
+ while (count && (dev != -1)) {
+ if (out >= *max) {
+ // switch buffers
+ out = 0;
+ if (data == data1 && max2 != 0) {
+ data = data2;
+ max = &max2;
+ max1 = 0;
+ } else if (data == data2 && max1 != 0) {
+ data = data1;
+ max = &max1;
+ max2 = 0;
+ } else {
+ qDebug("QSS Read Error: both buffers empty");
+ return 0;
+ }
+ }
+ samples_due += sound_speed;
+ if (count && samples_due >= chunkdata.samplesPerSec) {
+ int l = getSample(0,bytesPerSample)*lVolNum/lVolDen;
+ int r = (chunkdata.channels == 2) ? getSample(1,bytesPerSample)*rVolNum/rVolDen : l;
+ if (!sound_stereo && chunkdata.channels == 2)
+ l += r;
+ if (sampleRunin) {
+ while (sampleRunin && count && samples_due >= chunkdata.samplesPerSec) {
+ mixl++;
+ if (sound_stereo)
+ mixr++;
+ samples_due -= chunkdata.samplesPerSec;
+ sampleRunin--;
+ count--;
+ }
+ }
+ while (count && samples_due >= chunkdata.samplesPerSec) {
+ *mixl++ += l;
+ if (sound_stereo)
+ *mixr++ += r;
+ samples_due -= chunkdata.samplesPerSec;
+ count--;
+ }
+ }
+
+ // optimize out manipulation of sample if downsampling and we skip it
+ out += bytesPerSample * chunkdata.channels;
+ }
+
+ return count;
+ }
+
+ virtual bool finished() const = 0;
+
+ bool equal(int wid, int sid)
+ {
+ return (wid == mWid && sid == mSid);
+ }
+
+protected:
+
+ char * prepareBuffer( int &size)
+ {
+ // keep reading as long as there is 50 % or more room in off buffer.
+ if (data == data1 && (max2<<1 < sound_buffer_size)) {
+ size=sound_buffer_size - max2;
+ return (char *)data2;
+ } else if (data == data2 && (max1<<1 < sound_buffer_size)) {
+ size=sound_buffer_size - max1;
+ return (char *)data1;
+ } else {
+ size = 0;
+ return 0;
+ }
+ }
+
+ void updateBuffer(int read)
+ {
+ // always reads to off buffer.
+ if (read >= 0) {
+ if (data == data2) {
+ max1 = read;
+ } else {
+ max2 = read;
+ }
+ }
+ }
+
+ int devSamples()
+ {
+ int possible = (((max1+max2-out) / ((chunkdata.wBitsPerSample>>3)*chunkdata.channels))
+ *sound_speed)/chunkdata.samplesPerSec;
+
+ return possible;
+ }
+
+
+ struct {
+ qint16 formatTag;
+ qint16 channels;
+ qint32 samplesPerSec;
+ qint32 avgBytesPerSec;
+ qint16 blockAlign;
+ qint16 wBitsPerSample;
+ } chunkdata;
+ int dev;
+ int samples_due;
+private:
+ int mWid;
+ int mSid;
+ int leftVolume;
+ int rightVolume;
+ bool isPriority;
+ static int priorityExists;
+ int *max;
+ uchar *data;
+ uchar data1[sound_buffer_size+4]; // +4 to handle badly aligned input data
+ uchar data2[sound_buffer_size+4]; // +4 to handle badly aligned input data
+ int out, max1, max2;
+ int sampleRunin;
+ bool mMuted;
+};
+
+int QWSSoundServerProvider::priorityExists = 0;
+
+class QWSSoundServerBucket : public QWSSoundServerProvider {
+public:
+ QWSSoundServerBucket(int d, int wid, int sid)
+ : QWSSoundServerProvider(wid, sid)
+ {
+ dev = d;
+ wavedata_remaining = -1;
+ mFinishedRead = false;
+ mInsufficientSamples = false;
+ }
+ ~QWSSoundServerBucket()
+ {
+ //dev->close();
+ ::close(dev);
+ }
+ bool finished() const
+ {
+ //return !max;
+ return mInsufficientSamples && mFinishedRead ;
+ }
+ int readySamples(int)
+ {
+ int size;
+ char *dest = prepareBuffer(size);
+ // may want to change this to something like
+ // if (data == data1 && max2<<1 < sound_buffer_size
+ // ||
+ // data == data2 && max1<<1 < sound_buffer_size)
+ // so will keep filling off buffer while there is +50% space left
+ if (size > 0 && dest != 0) {
+ while ( wavedata_remaining < 0 ) {
+ //max = 0;
+ wavedata_remaining = -1;
+ // Keep reading chunks...
+ const int n = sizeof(chunk)-sizeof(chunk.data);
+ int nr = ::read(dev, (void*)&chunk,n);
+ if ( nr != n ) {
+ // XXX check error? or don't we care?
+ wavedata_remaining = 0;
+ mFinishedRead = true;
+ } else if ( qstrncmp(chunk.id,"data",4) == 0 ) {
+ wavedata_remaining = chunk.size;
+
+ //out = max = sound_buffer_size;
+
+ } else if ( qstrncmp(chunk.id,"RIFF",4) == 0 ) {
+ char d[4];
+ if ( read(dev, d, 4) != 4 ) {
+ // XXX check error? or don't we care?
+ //qDebug("couldn't read riff");
+ mInsufficientSamples = true;
+ mFinishedRead = true;
+ return 0;
+ } else if ( qstrncmp(d,"WAVE",4) != 0 ) {
+ // skip
+ if ( chunk.size > 1000000000 || lseek(dev,chunk.size-4, SEEK_CUR) == -1 ) {
+ //qDebug("oversized wav chunk");
+ mFinishedRead = true;
+ }
+ }
+ } else if ( qstrncmp(chunk.id,"fmt ",4) == 0 ) {
+ if ( ::read(dev,(char*)&chunkdata,sizeof(chunkdata)) != sizeof(chunkdata) ) {
+ // XXX check error? or don't we care?
+ //qDebug("couldn't ready chunkdata");
+ mFinishedRead = true;
+ }
+#define WAVE_FORMAT_PCM 1
+ else if ( chunkdata.formatTag != WAVE_FORMAT_PCM ) {
+ //qDebug("WAV file: UNSUPPORTED FORMAT %d",chunkdata.formatTag);
+ mFinishedRead = true;
+ }
+ } else {
+ // ignored chunk
+ if ( chunk.size > 1000000000 || lseek(dev, chunk.size, SEEK_CUR) == -1) {
+ //qDebug("chunk size too big");
+ mFinishedRead = true;
+ }
+ }
+ }
+ // this looks wrong.
+ if (wavedata_remaining <= 0) {
+ mFinishedRead = true;
+ }
+
+ }
+ // may want to change this to something like
+ // if (data == data1 && max2<<1 < sound_buffer_size
+ // ||
+ // data == data2 && max1<<1 < sound_buffer_size)
+ // so will keep filling off buffer while there is +50% space left
+
+ if (wavedata_remaining) {
+ if (size > 0 && dest != 0) {
+ int read = ::read(dev, dest, qMin(size, wavedata_remaining));
+ // XXX check error? or don't we care?
+ wavedata_remaining -= read;
+ updateBuffer(read);
+ if (read <= 0) // data unexpectidly ended
+ mFinishedRead = true;
+ }
+ }
+ int possible = devSamples();
+ if (possible == 0)
+ mInsufficientSamples = true;
+ return possible;
+ }
+
+protected:
+ QRiffChunk chunk;
+ int wavedata_remaining;
+ bool mFinishedRead;
+ bool mInsufficientSamples;
+};
+
+class QWSSoundServerStream : public QWSSoundServerProvider {
+public:
+ QWSSoundServerStream(int d,int c, int f, int b,
+ int wid, int sid)
+ : QWSSoundServerProvider(wid, sid)
+ {
+ chunkdata.channels = c;
+ chunkdata.samplesPerSec = f;
+ chunkdata.wBitsPerSample = b;
+ dev = d;
+ //fcntl( dev, F_SETFL, O_NONBLOCK );
+ lasttime = 0;
+ }
+
+ ~QWSSoundServerStream()
+ {
+ if (dev != -1) {
+ ::close(dev);
+ dev = -1;
+ }
+ }
+
+ bool finished() const
+ {
+ return (dev == -1);
+ }
+
+
+ int readySamples(int)
+ {
+ int size;
+ char *dest = prepareBuffer(size);
+ if (size > 0 && dest != 0 && dev != -1) {
+
+ int read = ::read(dev, dest, size);
+ if (read < 0) {
+ switch(errno) {
+ case EAGAIN:
+ case EINTR:
+ // means read may yet succeed on the next attempt
+ break;
+ default:
+ // unexpected error, fail.
+ ::close(dev);
+ dev = -1;
+ }
+ } else if (read == 0) {
+ // 0 means writer has closed dev and/or
+ // file is at end.
+ ::close(dev);
+ dev = -1;
+ } else {
+ updateBuffer(read);
+ }
+ }
+ int possible = devSamples();
+ if (possible == 0)
+ startSampleRunin();
+ return possible;
+ }
+
+protected:
+ time_t lasttime;
+};
+
+#ifndef QT_NO_QWS_SOUNDSERVER
+QWSSoundServerSocket::QWSSoundServerSocket(QObject *parent) :
+ QWSServerSocket(QString::fromLatin1(SOUND_PIPE).arg(qws_display_id), parent)
+{
+ connect(this, SIGNAL(newConnection()), this, SLOT(newConnection()));
+}
+
+
+#ifdef QT3_SUPPORT
+QWSSoundServerSocket::QWSSoundServerSocket(QObject *parent, const char *name) :
+ QWSServerSocket(QString::fromLatin1(SOUND_PIPE).arg(qws_display_id), parent)
+{
+ if (name)
+ setObjectName(QString::fromAscii(name));
+ connect(this, SIGNAL(newConnection()), this, SLOT(newConnection()));
+}
+#endif
+
+void QWSSoundServerSocket::newConnection()
+{
+ while (QWS_SOCK_BASE *sock = nextPendingConnection()) {
+ QWSSoundServerClient* client = new QWSSoundServerClient(sock,this);
+
+ connect(client, SIGNAL(play(int,int,QString)),
+ this, SIGNAL(playFile(int,int,QString)));
+ connect(client, SIGNAL(play(int,int,QString,int,int)),
+ this, SIGNAL(playFile(int,int,QString,int,int)));
+ connect(client, SIGNAL(playRaw(int,int,QString,int,int,int,int)),
+ this, SIGNAL(playRawFile(int,int,QString,int,int,int,int)));
+
+ connect(client, SIGNAL(pause(int,int)),
+ this, SIGNAL(pauseFile(int,int)));
+ connect(client, SIGNAL(stop(int,int)),
+ this, SIGNAL(stopFile(int,int)));
+ connect(client, SIGNAL(playPriorityOnly(bool)),
+ this, SIGNAL(playPriorityOnly(bool)));
+ connect(client, SIGNAL(stopAll(int)),
+ this, SIGNAL(stopAll(int)));
+ connect(client, SIGNAL(resume(int,int)),
+ this, SIGNAL(resumeFile(int,int)));
+
+ connect(client, SIGNAL(setSilent(bool)),
+ this, SIGNAL(setSilent(bool)));
+
+ connect(client, SIGNAL(setMute(int,int,bool)),
+ this, SIGNAL(setMute(int,int,bool)));
+ connect(client, SIGNAL(setVolume(int,int,int,int)),
+ this, SIGNAL(setVolume(int,int,int,int)));
+
+ connect(this, SIGNAL(soundFileCompleted(int,int)),
+ client, SLOT(sendSoundCompleted(int,int)));
+ connect(this, SIGNAL(deviceReady(int,int)),
+ client, SLOT(sendDeviceReady(int,int)));
+ connect(this, SIGNAL(deviceError(int,int,int)),
+ client, SLOT(sendDeviceError(int,int,int)));
+ }
+}
+
+#endif
+
+class QWSSoundServerPrivate : public QObject {
+ Q_OBJECT
+
+public:
+ QWSSoundServerPrivate(QObject* parent=0, const char* name=0) :
+ QObject(parent)
+ {
+ timerId = 0;
+ if (name)
+ setObjectName(QString::fromAscii(name));
+#ifndef QT_NO_QWS_SOUNDSERVER
+ server = new QWSSoundServerSocket(this);
+
+ connect(server, SIGNAL(playFile(int,int,QString)),
+ this, SLOT(playFile(int,int,QString)));
+ connect(server, SIGNAL(playFile(int,int,QString,int,int)),
+ this, SLOT(playFile(int,int,QString,int,int)));
+ connect(server, SIGNAL(playRawFile(int,int,QString,int,int,int,int)),
+ this, SLOT(playRawFile(int,int,QString,int,int,int,int)));
+
+ connect(server, SIGNAL(pauseFile(int,int)),
+ this, SLOT(pauseFile(int,int)));
+ connect(server, SIGNAL(stopFile(int,int)),
+ this, SLOT(stopFile(int,int)));
+ connect(server, SIGNAL(stopAll(int)),
+ this, SLOT(stopAll(int)));
+ connect(server, SIGNAL(playPriorityOnly(bool)),
+ this, SLOT(playPriorityOnly(bool)));
+ connect(server, SIGNAL(resumeFile(int,int)),
+ this, SLOT(resumeFile(int,int)));
+
+ connect( server, SIGNAL(setSilent(bool)),
+ this, SLOT(setSilent(bool)));
+
+ connect(server, SIGNAL(setMute(int,int,bool)),
+ this, SLOT(setMute(int,int,bool)));
+ connect(server, SIGNAL(setVolume(int,int,int,int)),
+ this, SLOT(setVolume(int,int,int,int)));
+
+ connect(this, SIGNAL(soundFileCompleted(int,int)),
+ server, SIGNAL(soundFileCompleted(int,int)));
+ connect(this, SIGNAL(deviceReady(int,int)),
+ server, SIGNAL(deviceReady(int,int)));
+ connect(this, SIGNAL(deviceError(int,int,int)),
+ server, SIGNAL(deviceError(int,int,int)));
+
+#endif
+ silent = false;
+ fd = -1;
+ unwritten = 0;
+ can_GETOSPACE = true;
+ }
+
+ ~QWSSoundServerPrivate()
+ {
+ qDeleteAll(active);
+ qDeleteAll(inactive);
+ }
+
+signals:
+ void soundFileCompleted(int, int);
+ void deviceReady(int, int);
+ void deviceError(int, int, int);
+
+public slots:
+ void playRawFile(int wid, int sid, const QString &filename, int freq, int channels, int bitspersample, int flags);
+ void playFile(int wid, int sid, const QString& filename);
+ void playFile(int wid, int sid, const QString& filename, int v, int flags);
+ void checkPresetVolumes(int wid, int sid, QWSSoundServerProvider *p);
+ void pauseFile(int wid, int sid);
+ void resumeFile(int wid, int sid);
+ void stopFile(int wid, int sid);
+ void stopAll(int wid);
+ void setVolume(int wid, int sid, int lv, int rv);
+ void setMute(int wid, int sid, bool m);
+ void playPriorityOnly(bool p);
+ void sendCompletedSignals();
+ void feedDevice(int fd);
+ void setSilent( bool enabled );
+
+protected:
+ void timerEvent(QTimerEvent* event);
+
+private:
+ int openFile(int wid, int sid, const QString& filename);
+ bool openDevice();
+ void closeDevice()
+ {
+ if (fd >= 0) {
+ ::close(fd);
+ fd = -1;
+ }
+ }
+
+ QList<QWSSoundServerProvider*> active;
+ QList<QWSSoundServerProvider*> inactive;
+ struct PresetVolume {
+ int wid;
+ int sid;
+ int left;
+ int right;
+ bool mute;
+ };
+ QList<PresetVolume> volumes;
+ struct CompletedInfo {
+ CompletedInfo( ) : groupId( 0 ), soundId( 0 ) { }
+ CompletedInfo( int _groupId, int _soundId ) : groupId( _groupId ), soundId( _soundId ) { }
+ int groupId;
+ int soundId;
+ };
+ QList<CompletedInfo> completed;
+
+ bool silent;
+
+ int fd;
+ int unwritten;
+ int timerId;
+ char* cursor;
+ short data[sound_buffer_size*2];
+ bool can_GETOSPACE;
+#ifndef QT_NO_QWS_SOUNDSERVER
+ QWSSoundServerSocket *server;
+#endif
+};
+
+void QWSSoundServerPrivate::setSilent( bool enabled )
+{
+ // Close output device
+ closeDevice();
+ if( !unwritten && !active.count() ) {
+ sendCompletedSignals();
+ }
+ // Stop processing audio
+ killTimer( timerId );
+ silent = enabled;
+ // If audio remaining, open output device and continue processing
+ if( unwritten || active.count() ) {
+ openDevice();
+ }
+}
+
+void QWSSoundServerPrivate::timerEvent(QTimerEvent* event)
+{
+ // qDebug("QSS timer event");
+ if( event->timerId() == timerId ) {
+ if (fd >= 0)
+ feedDevice(fd);
+ if (fd < 0) {
+ killTimer(timerId);
+ timerId = 0;
+ }
+ }
+}
+
+void QWSSoundServerPrivate::playRawFile(int wid, int sid, const QString &filename,
+ int freq, int channels, int bitspersample, int flags)
+{
+#ifdef QT_NO_QWS_SOUNDSERVER
+ Q_UNUSED(flags);
+#endif
+ int f = openFile(wid, sid, filename);
+ if ( f ) {
+ QWSSoundServerStream *b = new QWSSoundServerStream(f, channels, freq, bitspersample, wid, sid);
+ // check preset volumes.
+ checkPresetVolumes(wid, sid, b);
+#ifndef QT_NO_QWS_SOUNDSERVER
+ b->setPriority((flags & QWSSoundClient::Priority) == QWSSoundClient::Priority);
+#endif
+ active.append(b);
+ emit deviceReady(wid, sid);
+ }
+}
+
+void QWSSoundServerPrivate::playFile(int wid, int sid, const QString& filename)
+{
+ int f = openFile(wid, sid, filename);
+ if ( f ) {
+ QWSSoundServerProvider *b = new QWSSoundServerBucket(f, wid, sid);
+ checkPresetVolumes(wid, sid, b);
+ active.append( b );
+ emit deviceReady(wid, sid);
+ }
+}
+
+void QWSSoundServerPrivate::playFile(int wid, int sid, const QString& filename,
+ int v, int flags)
+{
+#ifdef QT_NO_QWS_SOUNDSERVER
+ Q_UNUSED(flags);
+#endif
+ int f = openFile(wid, sid, filename);
+ if ( f ) {
+ QWSSoundServerProvider *b = new QWSSoundServerBucket(f, wid, sid);
+ checkPresetVolumes(wid, sid, b);
+ b->setVolume(v, v);
+#ifndef QT_NO_QWS_SOUNDSERVER
+ b->setPriority((flags & QWSSoundClient::Priority) == QWSSoundClient::Priority);
+#endif
+ active.append(b);
+ emit deviceReady(wid, sid);
+ }
+}
+
+void QWSSoundServerPrivate::checkPresetVolumes(int wid, int sid, QWSSoundServerProvider *p)
+{
+ QList<PresetVolume>::Iterator it = volumes.begin();
+ while (it != volumes.end()) {
+ PresetVolume v = *it;
+ if (v.wid == wid && v.sid == sid) {
+ p->setVolume(v.left, v.right);
+ p->setMute(v.mute);
+ it = volumes.erase(it);
+ return;
+ } else {
+ ++it;
+ }
+ }
+}
+
+void QWSSoundServerPrivate::pauseFile(int wid, int sid)
+{
+ QWSSoundServerProvider *bucket;
+ for (int i = 0; i < active.size(); ++i ) {
+ bucket = active.at(i);
+ if (bucket->equal(wid, sid)) {
+ // found bucket....
+ active.removeAt(i);
+ inactive.append(bucket);
+ return;
+ }
+ }
+}
+
+void QWSSoundServerPrivate::resumeFile(int wid, int sid)
+{
+ QWSSoundServerProvider *bucket;
+ for (int i = 0; i < inactive.size(); ++i ) {
+ bucket = inactive.at(i);
+ if (bucket->equal(wid, sid)) {
+ // found bucket....
+ inactive.removeAt(i);
+ active.append(bucket);
+ return;
+ }
+ }
+}
+
+void QWSSoundServerPrivate::stopFile(int wid, int sid)
+{
+ QWSSoundServerProvider *bucket;
+ for (int i = 0; i < active.size(); ++i ) {
+ bucket = active.at(i);
+ if (bucket->equal(wid, sid)) {
+ active.removeAt(i);
+ delete bucket;
+ return;
+ }
+ }
+ for (int i = 0; i < inactive.size(); ++i ) {
+ bucket = inactive.at(i);
+ if (bucket->equal(wid, sid)) {
+ inactive.removeAt(i);
+ delete bucket;
+ return;
+ }
+ }
+}
+
+void QWSSoundServerPrivate::stopAll(int wid)
+{
+ QWSSoundServerProvider *bucket;
+ QList<QWSSoundServerProvider*>::Iterator it = active.begin();
+ while (it != active.end()) {
+ bucket = *it;
+ if (bucket->groupId() == wid) {
+ it = active.erase(it);
+ delete bucket;
+ } else {
+ ++it;
+ }
+ }
+ it = inactive.begin();
+ while (it != inactive.end()) {
+ bucket = *it;
+ if (bucket->groupId() == wid) {
+ it = inactive.erase(it);
+ delete bucket;
+ } else {
+ ++it;
+ }
+ }
+}
+
+void QWSSoundServerPrivate::setVolume(int wid, int sid, int lv, int rv)
+{
+ QWSSoundServerProvider *bucket;
+ for( int i = 0; i < active.size(); ++i ) {
+ bucket = active.at(i);
+ if (bucket->equal(wid, sid)) {
+ bucket->setVolume(lv,rv);
+ return;
+ }
+ }
+ // If gotten here, then it means wid/sid wasn't set up yet.
+ // first find and remove current preset volumes, then add this one.
+ QList<PresetVolume>::Iterator it = volumes.begin();
+ while (it != volumes.end()) {
+ PresetVolume v = *it;
+ if (v.wid == wid && v.sid == sid)
+ it = volumes.erase(it);
+ else
+ ++it;
+ }
+ // and then add this volume
+ PresetVolume nv;
+ nv.wid = wid;
+ nv.sid = sid;
+ nv.left = lv;
+ nv.right = rv;
+ nv.mute = false;
+ volumes.append(nv);
+}
+
+void QWSSoundServerPrivate::setMute(int wid, int sid, bool m)
+{
+ QWSSoundServerProvider *bucket;
+ for( int i = 0; i < active.size(); ++i ) {
+ bucket = active.at(i);
+ if (bucket->equal(wid, sid)) {
+ bucket->setMute(m);
+ return;
+ }
+ }
+ // if gotten here then setting is being applied before item
+ // is created.
+ QList<PresetVolume>::Iterator it = volumes.begin();
+ while (it != volumes.end()) {
+ PresetVolume v = *it;
+ if (v.wid == wid && v.sid == sid) {
+ (*it).mute = m;
+ return;
+ }
+ }
+ if (m) {
+ PresetVolume nv;
+ nv.wid = wid;
+ nv.sid = sid;
+ nv.left = maxVolume>>1;
+ nv.right = maxVolume>>1;
+ nv.mute = true;
+ volumes.append(nv);
+ }
+}
+
+void QWSSoundServerPrivate::playPriorityOnly(bool p)
+{
+ QWSSoundServerProvider::setPlayPriorityOnly(p);
+}
+
+void QWSSoundServerPrivate::sendCompletedSignals()
+{
+ while( !completed.isEmpty() ) {
+ emit soundFileCompleted( (*completed.begin()).groupId,
+ (*completed.begin()).soundId );
+ completed.erase( completed.begin() );
+ }
+}
+
+
+int QWSSoundServerPrivate::openFile(int wid, int sid, const QString& filename)
+{
+ stopFile(wid, sid); // close and re-open.
+ int f = ::open(QFile::encodeName(filename), O_RDONLY|O_NONBLOCK);
+ if (f == -1) {
+ // XXX check ferror, check reason.
+ qDebug("Failed opening \"%s\"",filename.toLatin1().data());
+#ifndef QT_NO_QWS_SOUNDSERVER
+ emit deviceError(wid, sid, (int)QWSSoundClient::ErrOpeningFile );
+#endif
+ } else if ( openDevice() ) {
+ return f;
+ }
+#ifndef QT_NO_QWS_SOUNDSERVER
+ emit deviceError(wid, sid, (int)QWSSoundClient::ErrOpeningAudioDevice );
+#endif
+ return 0;
+}
+
+bool QWSSoundServerPrivate::openDevice()
+{
+ if (fd < 0) {
+ if( silent ) {
+ fd = ::open( "/dev/null", O_WRONLY );
+ // Emulate write to audio device
+ int delay = 1000*(sound_buffer_size>>(sound_stereo+sound_16bit))/sound_speed/2;
+ timerId = startTimer(delay);
+
+ return true;
+ }
+ //
+ // Don't block open right away.
+ //
+ bool openOkay = false;
+ if ((fd = ::open("/dev/dsp", O_WRONLY|O_NONBLOCK)) != -1) {
+ int flags = fcntl(fd, F_GETFL);
+ flags &= ~O_NONBLOCK;
+ openOkay = (fcntl(fd, F_SETFL, flags) == 0);
+ }
+ if (!openOkay) {
+ qDebug("Failed opening audio device");
+ return false;
+ }
+
+ // Setup soundcard at 16 bit mono
+ int v;
+ //v=0x00010000+sound_fragment_size;
+ // um the media player did this instead.
+ v=0x10000 * 4 + sound_fragment_size;
+ if (ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &v))
+ qWarning("Could not set fragments to %08x",v);
+#ifdef QT_QWS_SOUND_16BIT
+ v=AFMT_S16_LE; if (ioctl(fd, SNDCTL_DSP_SETFMT, &v))
+ qWarning("Could not set format %d",v);
+ if (AFMT_S16_LE != v)
+ qDebug("Want format %d got %d", AFMT_S16_LE, v);
+#else
+ v=AFMT_U8; if (ioctl(fd, SNDCTL_DSP_SETFMT, &v))
+ qWarning("Could not set format %d",v);
+ if (AFMT_U8 != v)
+ qDebug("Want format %d got %d", AFMT_U8, v);
+#endif
+ v=sound_stereo; if (ioctl(fd, SNDCTL_DSP_STEREO, &v))
+ qWarning("Could not set stereo %d",v);
+ if (sound_stereo != v)
+ qDebug("Want stereo %d got %d", sound_stereo, v);
+#ifdef QT_QWS_SOUND_STEREO
+ sound_stereo=v;
+#endif
+ v=sound_speed; if (ioctl(fd, SNDCTL_DSP_SPEED, &sound_speed))
+ qWarning("Could not set speed %d",v);
+ if (v != sound_speed)
+ qDebug("Want speed %d got %d", v, sound_speed);
+
+ int delay = 1000*(sound_buffer_size>>(sound_stereo+sound_16bit))
+ /sound_speed/2;
+ // qDebug("QSS delay: %d", delay);
+ timerId = startTimer(delay);
+
+ //
+ // Check system volume
+ //
+ int mixerHandle = ::open( "/dev/mixer", O_RDWR|O_NONBLOCK );
+ if ( mixerHandle >= 0 ) {
+ int volume;
+ ioctl( mixerHandle, MIXER_READ(0), &volume );
+ close( mixerHandle );
+ if ( volume < 1<<(sound_stereo+sound_16bit) )
+ qDebug("Want sound at %d got %d",
+ 1<<(sound_stereo+sound_16bit), volume);
+ } else
+ qDebug( "get volume of audio device failed" );
+
+ }
+ return true;
+}
+
+void QWSSoundServerPrivate::feedDevice(int fd)
+{
+ if ( !unwritten && active.size() == 0 ) {
+ closeDevice();
+ sendCompletedSignals();
+ return;
+ } else {
+ sendCompletedSignals();
+ }
+
+ QWSSoundServerProvider* bucket;
+
+ // find out how much audio is possible
+ int available = sound_buffer_size;
+ QList<QWSSoundServerProvider*> running;
+ for (int i = 0; i < active.size(); ++i) {
+ bucket = active.at(i);
+ int ready = bucket->readySamples(available);
+ if (ready > 0) {
+ available = qMin(available, ready);
+ running.append(bucket);
+ }
+ }
+
+ audio_buf_info info;
+ if (can_GETOSPACE && ioctl(fd,SNDCTL_DSP_GETOSPACE,&info)) {
+ can_GETOSPACE = false;
+ fcntl(fd, F_SETFL, O_NONBLOCK);
+ }
+ if (!can_GETOSPACE)
+ info.fragments = 4; // #### configurable?
+ if (info.fragments > 0) {
+ if (!unwritten) {
+ int left[sound_buffer_size];
+ memset(left,0,available*sizeof(int));
+ int right[sound_buffer_size];
+ if ( sound_stereo )
+ memset(right,0,available*sizeof(int));
+
+ if (running.size() > 0) {
+ // should do volume mod here in regards to each bucket to avoid flattened/bad peaks.
+ for (int i = 0; i < running.size(); ++i ) {
+ bucket = running.at(i);
+ int unused = bucket->add(left,right,available);
+ if (unused > 0) {
+ // this error is quite serious, as
+ // it will really screw up mixing.
+ qDebug("provider lied about samples ready");
+ }
+ }
+ if ( sound_16bit ) {
+ short *d = (short*)data;
+ for (int i=0; i<available; i++) {
+ *d++ = (short)qMax(qMin(left[i],32767),-32768);
+ if ( sound_stereo )
+ *d++ = (short)qMax(qMin(right[i],32767),-32768);
+ }
+ } else {
+ signed char *d = (signed char *)data;
+ for (int i=0; i<available; i++) {
+ *d++ = (signed char)qMax(qMin(left[i]/256,127),-128)+128;
+ if ( sound_stereo )
+ *d++ = (signed char)qMax(qMin(right[i]/256,127),-128)+128;
+ }
+ }
+ unwritten = available*(sound_16bit+1)*(sound_stereo+1);
+ cursor = (char*)data;
+ }
+ }
+ // sound open, but nothing written. Should clear the buffer.
+
+ int w;
+ if (unwritten) {
+ w = ::write(fd,cursor,unwritten);
+
+ if (w < 0) {
+ if (can_GETOSPACE)
+ return;
+ w = 0;
+ }
+
+ cursor += w;
+ unwritten -= w;
+ } else {
+ // write some zeros to clear the buffer?
+ if (!zeroMem)
+ zeroMem = (char *)calloc(sound_buffer_size, sizeof(char));
+ w = ::write(fd, zeroMem, sound_buffer_size);
+ if (w < 0)
+ w = 0;
+ }
+ }
+
+ QList<QWSSoundServerProvider*>::Iterator it = active.begin();
+ while (it != active.end()) {
+ bucket = *it;
+ if (bucket->finished()) {
+ completed.append(CompletedInfo(bucket->groupId(), bucket->soundId()));
+ it = active.erase(it);
+ delete bucket;
+ } else {
+ ++it;
+ }
+ }
+}
+
+
+QWSSoundServer::QWSSoundServer(QObject* parent) :
+ QObject(parent)
+{
+ d = new QWSSoundServerPrivate(this);
+
+ connect( d, SIGNAL(soundFileCompleted(int,int)),
+ this, SLOT(translateSoundCompleted(int,int)) );
+}
+
+void QWSSoundServer::playFile( int sid, const QString& filename )
+{
+ //wid == 0, as it is the server initiating rather than a client
+ // if wid was passable, would accidently collide with server
+ // sockect's wids.
+ d->playFile(0, sid, filename);
+}
+
+void QWSSoundServer::pauseFile( int sid )
+{
+ d->pauseFile(0, sid);
+}
+
+void QWSSoundServer::stopFile( int sid )
+{
+ d->stopFile(0, sid);
+}
+
+void QWSSoundServer::resumeFile( int sid )
+{
+ d->resumeFile(0, sid);
+}
+
+QWSSoundServer::~QWSSoundServer()
+{
+ d->stopAll(0);
+}
+
+void QWSSoundServer::translateSoundCompleted( int, int sid )
+{
+ emit soundCompleted( sid );
+}
+
+#ifndef QT_NO_QWS_SOUNDSERVER
+QWSSoundClient::QWSSoundClient(QObject* parent) :
+ QWSSocket(parent)
+{
+ connectToLocalFile(QString::fromLatin1(SOUND_PIPE).arg(qws_display_id));
+ QObject::connect(this,SIGNAL(readyRead()),
+ this,SLOT(tryReadCommand()));
+ if( state() == QWS_SOCK_BASE::ConnectedState ) QTimer::singleShot(1, this, SIGNAL(connected()));
+ else QTimer::singleShot(1, this, SLOT(emitConnectionRefused()));
+}
+
+QWSSoundClient::~QWSSoundClient( )
+{
+ flush();
+}
+
+void QWSSoundClient::reconnect()
+{
+ connectToLocalFile(QString::fromLatin1(SOUND_PIPE).arg(qws_display_id));
+ if( state() == QWS_SOCK_BASE::ConnectedState ) emit connected();
+ else emit error( QTcpSocket::ConnectionRefusedError );
+}
+
+void QWSSoundClient::sendServerMessage(QString msg)
+{
+#ifndef QT_NO_TEXTCODEC
+ QByteArray u = msg.toUtf8();
+#else
+ QByteArray u = msg.toLatin1();
+#endif
+ write(u.data(), u.length());
+ flush();
+}
+
+void QWSSoundClient::play( int id, const QString& filename )
+{
+ QFileInfo fi(filename);
+ sendServerMessage(QLatin1String("PLAY ")
+ + QString::number(id) + QLatin1Char(' ')
+ + fi.absoluteFilePath() + QLatin1Char('\n'));
+}
+
+void QWSSoundClient::play( int id, const QString& filename, int volume, int flags)
+{
+ QFileInfo fi(filename);
+ sendServerMessage(QLatin1String("PLAYEXTEND ")
+ + QString::number(id) + QLatin1Char(' ')
+ + QString::number(volume) + QLatin1Char(' ')
+ + QString::number(flags) + QLatin1Char(' ')
+ + fi.absoluteFilePath() + QLatin1Char('\n'));
+}
+
+void QWSSoundClient::pause( int id )
+{
+ sendServerMessage(QLatin1String("PAUSE ")
+ + QString::number(id) + QLatin1Char('\n'));
+}
+
+void QWSSoundClient::stop( int id )
+{
+ sendServerMessage(QLatin1String("STOP ")
+ + QString::number(id) + QLatin1Char('\n'));
+}
+
+void QWSSoundClient::resume( int id )
+{
+ sendServerMessage(QLatin1String("RESUME ")
+ + QString::number(id) + QLatin1Char('\n'));
+}
+
+void QWSSoundClient::playRaw( int id, const QString& filename,
+ int freq, int chs, int bitspersample, int flags)
+{
+ QFileInfo fi(filename);
+ sendServerMessage(QLatin1String("PLAYRAW ")
+ + QString::number(id) + QLatin1Char(' ')
+ + QString::number(chs) + QLatin1Char(' ')
+ + QString::number(freq) + QLatin1Char(' ')
+ + QString::number(bitspersample) + QLatin1Char(' ')
+ + QString::number(flags) + QLatin1Char(' ')
+ + fi.absoluteFilePath() + QLatin1Char('\n'));
+}
+
+void QWSSoundClient::setMute( int id, bool m )
+{
+ sendServerMessage(QLatin1String(m ? "MUTE " : "UNMUTE ")
+ + QString::number(id) + QLatin1Char('\n'));
+}
+
+void QWSSoundClient::setVolume( int id, int leftVol, int rightVol )
+{
+ sendServerMessage(QLatin1String("SETVOLUME ")
+ + QString::number(id) + QLatin1Char(' ')
+ + QString::number(leftVol) + QLatin1Char(' ')
+ + QString::number(rightVol) + QLatin1Char('\n'));
+}
+
+void QWSSoundClient::playPriorityOnly( bool pri )
+{
+ sendServerMessage(QLatin1String("PRIORITYONLY ")
+ + QString::number(pri ? 1 : 0) + QLatin1Char('\n'));
+}
+
+void QWSSoundClient::setSilent( bool enable )
+{
+ sendServerMessage(QLatin1String("SILENT ")
+ + QString::number( enable ? 1 : 0 ) + QLatin1Char('\n'));
+}
+
+void QWSSoundClient::tryReadCommand()
+{
+ while ( canReadLine() ) {
+ QString l = QString::fromAscii(readLine());
+ l.truncate(l.length()-1); // chomp
+ QStringList token = l.split(QLatin1Char(' '));
+ if (token[0] == QLatin1String("SOUNDCOMPLETED")) {
+ emit soundCompleted(token[1].toInt());
+ } else if (token[0] == QLatin1String("DEVICEREADY")) {
+ emit deviceReady(token[1].toInt());
+ } else if (token[0] == QLatin1String("DEVICEERROR")) {
+ emit deviceError(token[1].toInt(),(DeviceErrors)token[2].toInt());
+ }
+ }
+}
+
+void QWSSoundClient::emitConnectionRefused()
+{
+ emit error( QTcpSocket::ConnectionRefusedError );
+}
+#endif
+
+QT_END_NAMESPACE
+
+#include "qsoundqss_qws.moc"
+
+#endif // QT_NO_SOUND
diff --git a/src/gui/embedded/qsoundqss_qws.h b/src/gui/embedded/qsoundqss_qws.h
new file mode 100644
index 0000000000..072a694f50
--- /dev/null
+++ b/src/gui/embedded/qsoundqss_qws.h
@@ -0,0 +1,177 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QSOUNDQSS_QWS_H
+#define QSOUNDQSS_QWS_H
+
+#include <QtCore/qglobal.h>
+
+#ifndef QT_NO_SOUND
+
+#include <QtNetwork/qtcpserver.h>
+#include <QtNetwork/qtcpsocket.h>
+#include <QtGui/qwssocket_qws.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#if defined(QT_NO_NETWORK) || defined(QT_NO_DNS)
+#define QT_NO_QWS_SOUNDSERVER
+#endif
+
+#ifndef Q_OS_MAC
+
+class QWSSoundServerPrivate;
+
+class Q_GUI_EXPORT QWSSoundServer : public QObject {
+ Q_OBJECT
+public:
+ explicit QWSSoundServer(QObject *parent=0);
+ ~QWSSoundServer();
+ void playFile( int id, const QString& filename );
+ void stopFile( int id );
+ void pauseFile( int id );
+ void resumeFile( int id );
+
+Q_SIGNALS:
+ void soundCompleted( int );
+
+private Q_SLOTS:
+ void translateSoundCompleted( int, int );
+
+private:
+ QWSSoundServerPrivate* d;
+};
+
+#ifndef QT_NO_QWS_SOUNDSERVER
+class Q_GUI_EXPORT QWSSoundClient : public QWSSocket {
+ Q_OBJECT
+public:
+
+ enum SoundFlags {
+ Priority = 0x01,
+ Streaming = 0x02 // currently ignored, but but could set up so both Raw and non raw can be done streaming or not.
+ };
+ enum DeviceErrors {
+ ErrOpeningAudioDevice = 0x01,
+ ErrOpeningFile = 0x02,
+ ErrReadingFile = 0x04
+ };
+ explicit QWSSoundClient(QObject* parent=0);
+ ~QWSSoundClient( );
+ void reconnect();
+ void play( int id, const QString& filename );
+ void play( int id, const QString& filename, int volume, int flags = 0 );
+ void playRaw( int id, const QString&, int, int, int, int flags = 0 );
+
+ void pause( int id );
+ void stop( int id );
+ void resume( int id );
+ void setVolume( int id, int left, int right );
+ void setMute( int id, bool m );
+
+ // to be used by server only, to protect phone conversation/rings.
+ void playPriorityOnly(bool);
+
+ // If silent, tell sound server to release audio device
+ // Otherwise, allow sound server to regain audio device
+ void setSilent(bool);
+
+Q_SIGNALS:
+ void soundCompleted(int);
+ void deviceReady(int id);
+ void deviceError(int id, QWSSoundClient::DeviceErrors);
+
+private Q_SLOTS:
+ void tryReadCommand();
+ void emitConnectionRefused();
+
+private:
+ void sendServerMessage(QString msg);
+};
+
+class QWSSoundServerSocket : public QWSServerSocket {
+ Q_OBJECT
+
+public:
+ explicit QWSSoundServerSocket(QObject *parent=0);
+public Q_SLOTS:
+ void newConnection();
+
+#ifdef QT3_SUPPORT
+public:
+ QT3_SUPPORT_CONSTRUCTOR QWSSoundServerSocket(QObject *parent, const char *name);
+#endif
+
+Q_SIGNALS:
+ void playFile(int, int, const QString&);
+ void playFile(int, int, const QString&, int, int);
+ void playRawFile(int, int, const QString&, int, int, int, int);
+ void pauseFile(int, int);
+ void stopFile(int, int);
+ void resumeFile(int, int);
+ void setVolume(int, int, int, int);
+ void setMute(int, int, bool);
+
+ void stopAll(int);
+
+ void playPriorityOnly(bool);
+
+ void setSilent(bool);
+
+ void soundFileCompleted(int, int);
+ void deviceReady(int, int);
+ void deviceError(int, int, int);
+};
+#endif
+
+#endif // Q_OS_MAC
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_SOUND
+
+#endif // QSOUNDQSS_QWS_H
diff --git a/src/gui/embedded/qtransportauth_qws.cpp b/src/gui/embedded/qtransportauth_qws.cpp
new file mode 100644
index 0000000000..97ba5b8a54
--- /dev/null
+++ b/src/gui/embedded/qtransportauth_qws.cpp
@@ -0,0 +1,1562 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qtransportauth_qws.h"
+#include "qtransportauth_qws_p.h"
+
+#ifndef QT_NO_SXE
+
+#include "../../3rdparty/md5/md5.h"
+#include "../../3rdparty/md5/md5.cpp"
+#include "qwsutils_qws.h"
+#include "qwssocket_qws.h"
+#include "qwscommand_qws_p.h"
+#include "qwindowsystem_qws.h"
+#include "qbuffer.h"
+#include "qthread.h"
+#include "qabstractsocket.h"
+#include "qlibraryinfo.h"
+#include "qfile.h"
+#include "qdebug.h"
+
+#include <syslog.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <time.h>
+
+#include <QtCore/qcache.h>
+
+#define BUF_SIZE 512
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ memset for security purposes, guaranteed not to be optimized away
+ http://www.faqs.org/docs/Linux-HOWTO/Secure-Programs-HOWTO.html
+*/
+Q_GUI_EXPORT void *guaranteed_memset(void *v,int c,size_t n)
+{
+ volatile char *p = (char *)v; while (n--) *p++=c; return v;
+}
+
+/*!
+ \class QTransportAuth
+ \internal
+
+ \brief Authenticate a message transport.
+
+ For performance reasons, message authentication is tied to an individual
+ message transport instance. For example in connection oriented transports
+ the authentication cookie can be cached against the connection avoiding
+ the overhead of authentication on every message.
+
+ For each process there is one instance of the QTransportAuth object.
+ For server processes it can determine the \link secure-exe-environ.html SXE
+ Program Identity \endlink and provide access to policy data to determine if
+ the message should be forwarded for action. If not actioned, the message
+ may be treated as being from a flawed or malicious process.
+
+ Retrieve the instance with the getInstance() method. The constructor is
+ disabled and instances of QTransportAuth should never be constructed by
+ calling classes.
+
+ To make the Authentication easier to use a proxied QIODevice is provided
+ which uses an internal QBuffer.
+
+ In the server code first get a pointer to a QTransportAuth::Data object
+ using the connectTransport() method:
+
+ \snippet doc/src/snippets/code/src_gui_embedded_qtransportauth_qws.cpp 0
+
+ Here it is asserted that the transport is trusted. See the assumptions
+ listed in the \link secure-exe-environ.html SXE documentation \endlink
+
+ Then proxy in the authentication device:
+
+ \snippet doc/src/snippets/code/src_gui_embedded_qtransportauth_qws.cpp 1
+
+ In the client code it is similar. Use the connectTransport() method
+ just the same then proxy in the authentication device instead of the
+ socket in write calls:
+
+ \snippet doc/src/snippets/code/src_gui_embedded_qtransportauth_qws.cpp 2
+*/
+
+static int hmac_md5(
+ unsigned char* text, /* pointer to data stream */
+ int text_length, /* length of data stream */
+ const unsigned char* key, /* pointer to authentication key */
+ int key_length, /* length of authentication key */
+ unsigned char * digest /* caller digest to be filled in */
+ );
+
+
+
+#define KEY_CACHE_SIZE 30
+
+const char * const errorStrings[] = {
+ "pending identity verification",
+ "message too small to carry auth data",
+ "cache miss on connection oriented transport",
+ "no magic bytes on message",
+ "key not found for prog id",
+ "authorization key match failed",
+ "key out of date"
+};
+
+const char *QTransportAuth::errorString( const Data &d )
+{
+ if (( d.status & ErrMask ) == Success )
+ return "success";
+ int e = d.status & ErrMask;
+ if ( e > OutOfDate )
+ return "unknown";
+ return errorStrings[e];
+}
+
+SxeRegistryLocker::SxeRegistryLocker( QObject *reg )
+ : m_success( false )
+ , m_reg( 0 )
+{
+ if ( reg )
+ if ( !QMetaObject::invokeMethod( reg, "lockManifest", Q_RETURN_ARG(bool, m_success) ))
+ m_success = false;
+ m_reg = reg;
+}
+
+SxeRegistryLocker::~SxeRegistryLocker()
+{
+ if ( m_success )
+ QMetaObject::invokeMethod( m_reg, "unlockManifest" );
+}
+
+
+QTransportAuthPrivate::QTransportAuthPrivate()
+ : keyInitialised(false)
+ , m_packageRegistry( 0 )
+{
+}
+
+QTransportAuthPrivate::~QTransportAuthPrivate()
+{
+}
+
+/*!
+ \internal
+ Construct a new QTransportAuth
+*/
+QTransportAuth::QTransportAuth() : QObject(*new QTransportAuthPrivate)
+{
+ // qDebug( "creating transport auth" );
+}
+
+/*!
+ \internal
+ Destructor
+*/
+QTransportAuth::~QTransportAuth()
+{
+ // qDebug( "deleting transport auth" );
+}
+
+/*!
+ Set the process key for this currently running Qt Extended process to
+ the \a authdata. \a authdata should be sizeof(struct AuthCookie)
+ in length and contain the key and program id. Use this method
+ when setting or changing the SXE identity of the current program.
+*/
+void QTransportAuth::setProcessKey( const char *authdata )
+{
+ Q_D(QTransportAuth);
+ ::memcpy(&d->authKey, authdata, sizeof(struct AuthCookie));
+ QFile proc_key( QLatin1String("/proc/self/lids_key") );
+ // where proc key exists use that instead
+ if ( proc_key.open( QIODevice::ReadOnly ))
+ {
+ qint64 kb = proc_key.read( (char*)&d->authKey.key, QSXE_KEY_LEN );
+#ifdef QTRANSPORTAUTH_DEBUG
+ qDebug( "Using %li bytes of /proc/%i/lids_key\n", (long int)kb, getpid() );
+#else
+ Q_UNUSED( kb );
+#endif
+ }
+ d->keyInitialised = true;
+}
+
+
+/*!
+ Apply \a key as the process key for the currently running application.
+
+ \a prog is current ignored
+
+ Deprecated function
+*/
+void QTransportAuth::setProcessKey( const char *key, const char *prog )
+{
+ Q_UNUSED(prog);
+ setProcessKey( key );
+#ifdef QTRANSPORTAUTH_DEBUG
+ char displaybuf[QSXE_KEY_LEN*2+1];
+ hexstring( displaybuf, (const unsigned char *)key, QSXE_KEY_LEN );
+ qDebug() << "key" << displaybuf << "set";
+#endif
+}
+
+/*!
+ Register \a pr as a policy handler object. The object pointed to
+ by \a pr should have a slot as follows
+ \snippet doc/src/snippets/code/src_gui_embedded_qtransportauth_qws.cpp 3
+ All requests received by this server will then generate a call to
+ this slot, and may be processed for policy compliance.
+*/
+void QTransportAuth::registerPolicyReceiver( QObject *pr )
+{
+ // not every policy receiver needs setup - no error if this fails
+ QMetaObject::invokeMethod( pr, "setupPolicyCheck" );
+
+ connect( this, SIGNAL(policyCheck(QTransportAuth::Data&,QString)),
+ pr, SLOT(policyCheck(QTransportAuth::Data&,QString)), Qt::DirectConnection );
+}
+
+/*!
+ Unregister the \a pr from being a policy handler. No more policyCheck signals
+ are received by this object.
+*/
+void QTransportAuth::unregisterPolicyReceiver( QObject *pr )
+{
+ disconnect( pr );
+ // not every policy receiver needs tear down - no error if this fails
+ QMetaObject::invokeMethod( pr, "teardownPolicyCheck" );
+}
+
+/*!
+ Record a new transport connection with \a properties and \a descriptor.
+
+ The calling code is responsible for destroying the returned data when the
+ tranport connection is closed.
+*/
+QTransportAuth::Data *QTransportAuth::connectTransport( unsigned char properties, int descriptor )
+{
+ Data *data = new Data(properties, descriptor);
+ data->status = Pending;
+ return data;
+}
+
+/*!
+ Is the transport trusted. This is true iff data written into the
+ transport medium cannot be intercepted or modified by another process.
+ This is for example true for Unix Domain Sockets, but not for shared
+ memory or UDP sockets.
+
+ There is of course an underlying assumption that the kernel implementing
+ the transport is sound, ie it cannot be compromised by writing to
+ /dev/kmem or loading untrusted modules
+*/
+inline bool QTransportAuth::Data::trusted() const
+{
+ return (bool)(properties & Trusted);
+}
+
+/*!
+ Assert that the transport is trusted.
+
+ For example with respect to shared memory, if it is ensured that no untrusted
+ root processes are running, and that unix permissions have been set such that
+ any untrusted non-root processes do not have access rights, then a shared
+ memory transport could be asserted to be trusted.
+
+ \sa trusted()
+*/
+inline void QTransportAuth::Data::setTrusted( bool t )
+{
+ properties = t ? properties | Trusted : properties & ~Trusted;
+}
+
+/*!
+ Is the transport connection oriented. This is true iff once a connection
+ has been accepted, and state established, then further messages over the
+ transport are guaranteed to have come from the original connecting entity.
+ This is for example true for Unix Domain Sockets, but not
+ for shared memory or UDP sockets.
+
+ By extension if the transport is not trusted() then it should not be
+ assumed to be connection oriented, since spoofed connection information
+ could be created. For example if we assume the TCP/IP transport is
+ trusted, it can be treated as connection oriented; but this is only the
+ case if intervening routers are trusted.
+
+ Connection oriented transports have authorization cached against the
+ connection, and thus authorization is only done at connect time.
+*/
+inline bool QTransportAuth::Data::connection() const
+{
+ return (bool)(properties & Connection);
+}
+
+/*!
+ Assert that the transport is connection oriented.
+
+ \sa connection()
+*/
+inline void QTransportAuth::Data::setConnection( bool t )
+{
+ properties = t ? properties | Connection : properties & ~Connection;
+}
+
+/*!
+ Return a pointer to the instance of this process's QTransportAuth object
+*/
+QTransportAuth *QTransportAuth::getInstance()
+{
+ static QTransportAuth theInstance;
+
+ return &theInstance;
+}
+
+/*!
+ Set the full path to the key file
+
+ Since this is normally relative to Qtopia::qpeDir() this needs to be
+ set within the Qt Extended framework.
+
+ The keyfile should be protected by file permissions or by MAC rules
+ such that it can only be read/written by the "qpe" server process
+*/
+void QTransportAuth::setKeyFilePath( const QString &path )
+{
+ Q_D(QTransportAuth);
+ d->m_keyFilePath = path;
+}
+
+QString QTransportAuth::keyFilePath() const
+{
+ Q_D(const QTransportAuth);
+ return d->m_keyFilePath;
+}
+
+void QTransportAuth::setLogFilePath( const QString &path )
+{
+ Q_D(QTransportAuth);
+ d->m_logFilePath = path;
+}
+
+QString QTransportAuth::logFilePath() const
+{
+ Q_D(const QTransportAuth);
+ return d->m_logFilePath;
+}
+
+void QTransportAuth::setPackageRegistry( QObject *registry )
+{
+ Q_D(QTransportAuth);
+ d->m_packageRegistry = registry;
+}
+
+bool QTransportAuth::isDiscoveryMode() const
+{
+#if defined(SXE_DISCOVERY)
+ static bool checked = false;
+ static bool yesItIs = false;
+
+ if ( checked ) return yesItIs;
+
+ yesItIs = ( getenv( "SXE_DISCOVERY_MODE" ) != 0 );
+ if ( yesItIs )
+ {
+ qWarning("SXE Discovery mode on, ALLOWING ALL requests and logging to %s",
+ qPrintable(logFilePath()));
+ QFile::remove( logFilePath() );
+ }
+ checked = true;
+ return yesItIs;
+#else
+ return false;
+#endif
+}
+
+/*!
+ \internal
+ Return the authorizer device mapped to this client. Note that this
+ could probably all be void* instead of QWSClient* for generality.
+ Until the need for that rears its head its QWSClient* to save the casts.
+
+ #### OK the need has arrived, but the public API is frozen.
+*/
+QIODevice *QTransportAuth::passThroughByClient( QWSClient *client ) const
+{
+ Q_D(const QTransportAuth);
+
+ if ( client == 0 ) return 0;
+ if ( d->buffersByClient.contains( client ))
+ {
+ return d->buffersByClient[client];
+ }
+ // qWarning( "buffer not found for client %p", client );
+ return 0;
+}
+
+/*!
+ \internal
+ Return a QIODevice pointer (to an internal QBuffer) which can be used
+ to receive data after authorisation on transport \a d.
+
+ The return QIODevice will act as a pass-through.
+
+ The data will be consumed from \a iod and forwarded on to the returned
+ QIODevice which can be connected to readyRead() signal handlers in
+ place of the original QIODevice \a iod.
+
+ This will be called in the server process to handle incoming
+ authenticated requests.
+
+ The returned QIODevice will take ownership of \a data which will be deleted
+ when the QIODevice is delected.
+
+ \sa setTargetDevice()
+*/
+QAuthDevice *QTransportAuth::recvBuf( QTransportAuth::Data *data, QIODevice *iod )
+{
+ return new QAuthDevice( iod, data, QAuthDevice::Receive );
+}
+
+/*!
+ Return a QIODevice pointer (to an internal QBuffer) which can be used
+ to write data onto, for authorisation on transport \a d.
+
+ The return QIODevice will act as a pass-through.
+
+ The data written to the return QIODevice will be forwarded on to the
+ returned QIODevice. In the case of a QTcpSocket, this will cause it
+ to send out the data with the authentication information on it.
+
+ This will be called in the client process to generate outgoing
+ authenticated requests.
+
+ The returned QIODevice will take ownership of \a data which will be deleted
+ when the QIODevice is delected.
+
+ \sa setTargetDevice()
+*/
+QAuthDevice *QTransportAuth::authBuf( QTransportAuth::Data *data, QIODevice *iod )
+{
+ return new QAuthDevice( iod, data, QAuthDevice::Send );
+}
+
+const unsigned char *QTransportAuth::getClientKey( unsigned char progId )
+{
+ Q_D(QTransportAuth);
+ return d->getClientKey( progId );
+}
+
+void QTransportAuth::invalidateClientKeyCache()
+{
+ Q_D(QTransportAuth);
+ d->invalidateClientKeyCache();
+}
+
+QMutex *QTransportAuth::getKeyFileMutex()
+{
+ Q_D(QTransportAuth);
+ return &d->keyfileMutex;
+}
+
+/*
+ \internal
+ Respond to the destroyed(QObject*) signal of the QAuthDevice's
+ client object and remove it from the buffersByClient lookup hash.
+*/
+void QTransportAuth::bufferDestroyed( QObject *cli )
+{
+ Q_D(QTransportAuth);
+ if ( cli == NULL ) return;
+
+ if ( d->buffersByClient.contains( cli ))
+ {
+ d->buffersByClient.remove( cli );
+ // qDebug( "@@@@@@@ client %p removed @@@@@@@@@", cli );
+ }
+ // qDebug( " client count %d", d->buffersByClient.count() );
+}
+
+bool QTransportAuth::authorizeRequest( QTransportAuth::Data &d, const QString &request )
+{
+ bool isAuthorized = true;
+
+ if ( !request.isEmpty() && request != QLatin1String("Unknown") )
+ {
+ d.status &= QTransportAuth::ErrMask; // clear the status
+ emit policyCheck( d, request );
+ isAuthorized = (( d.status & QTransportAuth::StatusMask ) == QTransportAuth::Allow );
+ }
+#if defined(SXE_DISCOVERY)
+ if (isDiscoveryMode()) {
+#ifndef QT_NO_TEXTSTREAM
+ if (!logFilePath().isEmpty()) {
+ QFile log( logFilePath() );
+ if (!log.open(QIODevice::WriteOnly | QIODevice::Append)) {
+ qWarning("Could not write to log in discovery mode: %s",
+ qPrintable(logFilePath()));
+ } else {
+ QTextStream ts( &log );
+ ts << d.progId << '\t' << ( isAuthorized ? "Allow" : "Deny" ) << '\t' << request << endl;
+ }
+ }
+#endif
+ isAuthorized = true;
+ }
+#endif
+ if ( !isAuthorized )
+ {
+ qWarning( "%s - denied: for Program Id %u [PID %d]"
+ , qPrintable(request), d.progId, d.processId );
+
+ char linkTarget[BUF_SIZE]="";
+ char exeLink[BUF_SIZE]="";
+ char cmdlinePath[BUF_SIZE]="";
+ char cmdline[BUF_SIZE]="";
+
+ //get executable from /proc/pid/exe
+ snprintf( exeLink, BUF_SIZE, "/proc/%d/exe", d.processId );
+ if ( -1 == ::readlink( exeLink, linkTarget, BUF_SIZE - 1 ) )
+ {
+ qWarning( "SXE:- Error encountered in retrieving executable link target from /proc/%u/exe : %s",
+ d.processId, strerror(errno) );
+ snprintf( linkTarget, BUF_SIZE, "%s", linkTarget );
+ }
+
+ //get cmdline from proc/pid/cmdline
+ snprintf( cmdlinePath, BUF_SIZE, "/proc/%d/cmdline", d.processId );
+ int cmdlineFd = open( cmdlinePath, O_RDONLY );
+ if ( cmdlineFd == -1 )
+ {
+ qWarning( "SXE:- Error encountered in opening /proc/%u/cmdline: %s",
+ d.processId, strerror(errno) );
+ snprintf( cmdline, BUF_SIZE, "%s", "Unknown" );
+ }
+ else
+ {
+ if ( -1 == ::read(cmdlineFd, cmdline, BUF_SIZE - 1 ) )
+ {
+ qWarning( "SXE:- Error encountered in reading /proc/%u/cmdline : %s",
+ d.processId, strerror(errno) );
+ snprintf( cmdline, BUF_SIZE, "%s", "Unknown" );
+ }
+ close( cmdlineFd );
+ }
+
+ syslog( LOG_ERR | LOG_LOCAL6, "%s // PID:%u // ProgId:%u // Exe:%s // Request:%s // Cmdline:%s",
+ "<SXE Breach>", d.processId, d.progId, linkTarget, qPrintable(request), cmdline);
+ }
+
+ return isAuthorized;
+}
+
+inline bool __fileOpen( QFile *f )
+{
+#ifdef QTRANSPORTAUTH_DEBUG
+ if ( f->open( QIODevice::ReadOnly ))
+ {
+ qDebug( "Opened file: %s\n", qPrintable( f->fileName() ));
+ return true;
+ }
+ else
+ {
+ qWarning( "Could not open file: %s\n", qPrintable( f->fileName() ));
+ return false;
+ }
+#else
+ return ( f->open( QIODevice::ReadOnly ));
+#endif
+}
+
+/*!
+ \internal
+ Find client keys for the \a progId. If it is cached should be very
+ fast, otherwise requires a read of the secret key file
+
+ In the success case a pointer to the keys is returned. The pointer is
+ to storage allocated for the internal cache and must be used asap.
+
+ The list returned is a sequence of one or more keys which match the
+ progId. There is no separator, each 16 byte sequence represents a key.
+ The sequence is followed by two iterations of the SXE magic
+ bytes,eg 0xBA, 0xD4, 0xD4, 0xBA, 0xBA, 0xD4, 0xD4, 0xBA
+
+ NULL is returned in the following cases:
+ \list
+ \o the keyfiles could not be accessed - error condition
+ \o there was no key for the supplied program id - key auth failed
+ \endlist
+
+ Note that for the keyfiles, there is multi-thread and multi-process
+ concurrency issues: they can be read by the qpe process when
+ QTransportAuth calls getClientKey to verify a request, and they can be
+ read or written by the packagemanager when updating package data.
+
+ To protect against this, the keyfileMutex & SxeRegistryLocker is used.
+
+ The sxe_installer tool can also update inode and device numbers in
+ the manifest file, but this only occurs outside of normal operation,
+ so qpe and packagemanager are never running when this occurs.
+*/
+const unsigned char *QTransportAuthPrivate::getClientKey(unsigned char progId)
+{
+ int manifestMatchCount = 0;
+ struct IdBlock mr;
+ int total_size = 0;
+ char *result = 0;
+ char *result_ptr;
+ int keysFound = 0;
+ bool foundKey;
+ int keysRead = 0;
+ struct usr_key_entry keys_list[128];
+
+ if ( keyCache.contains( progId ))
+ return (const unsigned char *)keyCache[progId];
+
+ SxeRegistryLocker rlock( m_packageRegistry );
+
+ // ### Qt 4.3: this is hacky - see documentation for setKeyFilePath
+ QString manifestPath = m_keyFilePath + QLatin1String("/manifest");
+ QString actualKeyPath = QLatin1String("/proc/lids/keys");
+ bool noFailOnKeyMissing = true;
+ if ( !QFile::exists( actualKeyPath )) {
+ actualKeyPath = m_keyFilePath + QLatin1String( "/" QSXE_KEYFILE );
+ }
+ QFile kf( actualKeyPath );
+ QFile mn( manifestPath );
+ if ( !__fileOpen( &mn ))
+ goto key_not_found;
+ // first find how much storage is needed
+ while ( mn.read( (char*)&mr, sizeof(struct IdBlock)) > 0 )
+ if ( mr.progId == progId )
+ manifestMatchCount++;
+ if ( manifestMatchCount == 0 )
+ goto key_not_found;
+ if ( !__fileOpen( &kf ))
+ {
+ noFailOnKeyMissing = false;
+ goto key_not_found;
+ }
+ total_size = 2 * QSXE_MAGIC_BYTES + manifestMatchCount * QSXE_KEY_LEN;
+ result = (char*)malloc( total_size );
+ Q_CHECK_PTR( result );
+ mn.seek( 0 );
+ result_ptr = result;
+ /* reading whole key array in is much more efficient, 99% case is this loop only
+ executes once, should not have more than 128 keyed items */
+ while (( keysRead = kf.read( (char*)keys_list, sizeof(struct usr_key_entry)*128 )) > 0 )
+ {
+ /* qDebug("PID %d: getClientKey() - read %d bytes = %d keys from %s", getpid(), keysRead,
+ keysRead/sizeof(struct usr_key_entry), qPrintable(actualKeyPath)); */
+ keysRead /= sizeof(struct usr_key_entry);
+ while ( mn.read( (char*)&mr, sizeof(struct IdBlock)) > 0 )
+ {
+ if ( mr.progId == progId )
+ {
+ foundKey = false;
+ for ( int i = 0; i < keysRead; ++i )
+ {
+ /* if ( i == 0 )
+ qDebug() << " pid" << getpid() << "looking for device" << (dev_t)mr.device << "inode" << (ino_t)mr.inode;
+ qDebug() << " pid" << getpid() << "trying device" << keys_list[i].dev << "inode" << keys_list[i].ino; */
+ if ( keys_list[i].ino == (ino_t)mr.inode && keys_list[i].dev == (dev_t)mr.device )
+ {
+ memcpy( result_ptr, keys_list[i].key, QSXE_KEY_LEN );
+ result_ptr += QSXE_KEY_LEN;
+ foundKey = true;
+ break;
+ }
+ }
+ if ( foundKey )
+ {
+ keysFound++;
+ if ( keysFound == manifestMatchCount )
+ break;
+ }
+ }
+ }
+ }
+ if ( result_ptr == result ) // nothing found!
+ goto key_not_found;
+ // 2 x magic bytes sentinel at end of sequence
+ for ( int i = 0; i < 2; ++i )
+ for ( int j = 0; j < QSXE_MAGIC_BYTES; ++j )
+ *result_ptr++ = magic[j];
+ keyCache.insert( progId, result, total_size / 10 );
+ /* qDebug( "PID %d : Found %d client keys for prog %u", getpid(), keysFound, progId ); */
+ goto success_out;
+
+key_not_found:
+ if ( noFailOnKeyMissing ) // return an "empty" set of keys in this case
+ {
+ if ( result == 0 )
+ {
+ result = (char*)malloc( 2 * QSXE_MAGIC_BYTES );
+ Q_CHECK_PTR( result );
+ }
+ result_ptr = result;
+ for ( int i = 0; i < 2; ++i )
+ for ( int j = 0; j < QSXE_MAGIC_BYTES; ++j )
+ *result_ptr++ = magic[j];
+ return (unsigned char *)result;
+ }
+ qWarning( "PID %d : Not found client key for prog %u", getpid(), progId );
+ if ( result )
+ {
+ free( result );
+ result = 0;
+ }
+success_out:
+ if ( mn.isOpen() )
+ mn.close();
+ if ( kf.isOpen() )
+ kf.close();
+ return (unsigned char *)result;
+}
+
+void QTransportAuthPrivate::invalidateClientKeyCache()
+{
+ keyfileMutex.lock();
+ keyCache.clear();
+ keyfileMutex.unlock();
+}
+
+////////////////////////////////////////////////////////////////////////
+////
+//// RequestAnalyzer definition
+////
+
+
+RequestAnalyzer::RequestAnalyzer()
+ : moreData( false )
+ , dataSize( 0 )
+{
+}
+
+RequestAnalyzer::~RequestAnalyzer()
+{
+}
+
+/*!
+ Analzye the data in the\a msgQueue according to some protocol
+ and produce a request string for policy analysis.
+
+ If enough data is in the queue for analysis of a complete message,
+ return a non-null string, and set a flag so requireMoreData() will
+ return false; otherwise return a null string and requireMoreData()
+ return true.
+
+ The amount of bytes analyzed is then available via bytesAnalyzed().
+
+ A null string is also returned in the case where the message was
+ corrupt and could not be analyzed. In this case requireMoreData()
+ returns false.
+
+Note: this method will modify the msgQueue and pull off the data
+ deemed to be corrupt, in the case of corrupt data.
+
+ In all other cases the msgQueue is left alone. The calling code
+ should then pull off the analyzed data. Use bytesAnalzyed() to
+ find how much data to pull off the queue.
+*/
+QString RequestAnalyzer::analyze( QByteArray *msgQueue )
+{
+#ifdef Q_WS_QWS
+ dataSize = 0;
+ moreData = false;
+ QBuffer cmdBuf( msgQueue );
+ cmdBuf.open( QIODevice::ReadOnly | QIODevice::Unbuffered );
+ QWSCommand::Type command_type = (QWSCommand::Type)(qws_read_uint( &cmdBuf ));
+ QWSCommand *command = QWSCommand::factory(command_type);
+ // if NULL, factory will have already printed warning for bogus
+ // command_type just purge the bad stuff and attempt to recover
+ if ( command == NULL )
+ {
+ *msgQueue = msgQueue->mid( sizeof(int) );
+ return QString();
+ }
+ QString request = QLatin1String(qws_getCommandTypeString(command_type));
+#ifndef QT_NO_COP
+ if ( !command->read( &cmdBuf ))
+ {
+ // not all command arrived yet - come back later
+ delete command;
+ moreData = true;
+ return QString();
+ }
+ if ( command_type == QWSCommand::QCopSend )
+ {
+ QWSQCopSendCommand *sendCommand = static_cast<QWSQCopSendCommand*>(command);
+ request += QString( QLatin1String("/QCop/%1/%2") ).arg( sendCommand->channel ).arg( sendCommand->message );
+ }
+ if ( command_type == QWSCommand::QCopRegisterChannel )
+ {
+ QWSQCopRegisterChannelCommand *registerCommand = static_cast<QWSQCopRegisterChannelCommand*>(command);
+ request += QString( QLatin1String("/QCop/RegisterChannel/%1") ).arg( registerCommand->channel );
+ }
+#endif
+ dataSize = QWS_PROTOCOL_ITEM_SIZE( *command );
+ delete command;
+ return request;
+#else
+ Q_UNUSED(msgQueue);
+ return QString();
+#endif
+}
+
+////////////////////////////////////////////////////////////////////////
+////
+//// AuthDevice definition
+////
+
+/*!
+ Constructs a new auth device for the transport \a data and I/O device \a parent.
+
+ Incoming or outgoing data will be authenticated according to the auth direction \a dir.
+
+ The auth device will take ownership of the transport \a data and delete it when the device
+ is destroyed.
+*/
+QAuthDevice::QAuthDevice( QIODevice *parent, QTransportAuth::Data *data, AuthDirection dir )
+ : QIODevice( parent )
+ , d( data )
+ , way( dir )
+ , m_target( parent )
+ , m_client( 0 )
+ , m_bytesAvailable( 0 )
+ , m_skipWritten( 0 )
+ , analyzer( 0 )
+{
+ if ( dir == Receive ) // server side
+ {
+ connect( m_target, SIGNAL(readyRead()),
+ this, SLOT(recvReadyRead()));
+ } else {
+ connect( m_target, SIGNAL(readyRead()),
+ this, SIGNAL(readyRead()));
+ }
+ connect( m_target, SIGNAL(bytesWritten(qint64)),
+ this, SLOT(targetBytesWritten(qint64)) );
+ open( QIODevice::ReadWrite | QIODevice::Unbuffered );
+}
+
+QAuthDevice::~QAuthDevice()
+{
+ if ( analyzer )
+ delete analyzer;
+ delete d;
+}
+
+/*!
+ \internal
+ Store a pointer to the related device or instance which this
+ authorizer is proxying for
+*/
+void QAuthDevice::setClient( QObject *cli )
+{
+ m_client = cli;
+ QTransportAuth::getInstance()->d_func()->buffersByClient[cli] = this;
+ QObject::connect( cli, SIGNAL(destroyed(QObject*)),
+ QTransportAuth::getInstance(), SLOT(bufferDestroyed(QObject*)) );
+ // qDebug( "@@@@@@@@@@@@ client set %p @@@@@@@@@", cli );
+ // qDebug( " client count %d", QTransportAuth::getInstance()->d_func()->buffersByClient.count() );
+}
+
+QObject *QAuthDevice::client() const
+{
+ return m_client;
+}
+
+/*
+ \fn void QAuthDevice::authViolation(QTransportAuth::Data &)
+
+ This signal is emitted if an authorization failure is generated, as
+ described in checkAuth();
+
+ \sa checkAuth()
+*/
+
+
+/*
+ \fn void QAuthDevice::policyCheck(QTransportAuth::Data &transport, const QString &request )
+
+ This signal is emitted when a transport successfully delivers a request
+ and gives the opportunity to either deny or accept the request.
+
+ This signal must be connected in the same thread, ie it cannot be queued.
+
+ As soon as all handlers connected to this signal are processed the Allow or
+ Deny state on the \a transport is checked, and the request is allowed or denied
+ accordingly.
+
+ \sa checkAuth()
+*/
+
+/*!
+ \internal
+ Reimplement QIODevice writeData method.
+
+ For client end, when the device is written to the incoming data is
+ processed and an authentication header calculated. This is pushed
+ into the target device, followed by the actual incoming data (the
+ payload).
+
+ For server end, it is a fatal error to write to the device.
+*/
+qint64 QAuthDevice::writeData(const char *data, qint64 len)
+{
+ if ( way == Receive ) // server
+ return m_target->write( data, len );
+ // client
+#ifdef QTRANSPORTAUTH_DEBUG
+ char displaybuf[1024];
+#endif
+ char header[QSXE_HEADER_LEN];
+ ::memset( header, 0, QSXE_HEADER_LEN );
+ qint64 bytes = 0;
+ if ( QTransportAuth::getInstance()->authToMessage( *d, header, data, len ))
+ {
+ m_target->write( header, QSXE_HEADER_LEN );
+#ifdef QTRANSPORTAUTH_DEBUG
+ hexstring( displaybuf, (const unsigned char *)header, QSXE_HEADER_LEN );
+ qDebug( "%d QAuthDevice::writeData - CLIENT: Header written: %s", getpid(), displaybuf );
+#endif
+ m_skipWritten += QSXE_HEADER_LEN;
+ }
+ m_target->write( data, len );
+ bytes += len;
+#ifdef QTRANSPORTAUTH_DEBUG
+ int bytesToDisplay = bytes;
+ const unsigned char *dataptr = (const unsigned char *)data;
+ while ( bytesToDisplay > 0 )
+ {
+ int amt = bytes < 500 ? bytes : 500;
+ hexstring( displaybuf, dataptr, amt );
+ qDebug( "%d QAuthDevice::writeData - CLIENT: %s", getpid(), bytes > 0 ? displaybuf : "(null)" );
+ dataptr += 500;
+ bytesToDisplay -= 500;
+ }
+#endif
+ if ( m_target->inherits( "QAbstractSocket" ))
+ static_cast<QAbstractSocket*>(m_target)->flush();
+ return bytes;
+}
+
+/*!
+ Reimplement from QIODevice
+
+ Read data out of the internal message queue, reduce the queue by the amount
+ read. Note that the amount available is only ever the size of a command
+ (although a command can be very big) since we need to check at command
+ boundaries for new authentication headers.
+*/
+qint64 QAuthDevice::readData( char *data, qint64 maxSize )
+{
+ if ( way == Send ) // client
+ return m_target->read( data, maxSize );
+ if ( msgQueue.size() == 0 )
+ return 0;
+#ifdef QTRANSPORTAUTH_DEBUG
+ char displaybuf[1024];
+ hexstring( displaybuf, reinterpret_cast<const unsigned char *>(msgQueue.constData()),
+ msgQueue.size() > 500 ? 500 : msgQueue.size() );
+ qDebug() << getpid() << "QAuthDevice::readData() buffered/requested/avail"
+ << msgQueue.size() << maxSize << m_bytesAvailable << displaybuf;
+#endif
+ Q_ASSERT( m_bytesAvailable <= msgQueue.size() );
+ qint64 bytes = ( maxSize > m_bytesAvailable ) ? m_bytesAvailable : maxSize;
+ ::memcpy( data, msgQueue.constData(), bytes );
+ msgQueue = msgQueue.mid( bytes );
+ m_bytesAvailable -= bytes;
+ return bytes;
+}
+
+/*!
+ \internal
+ Receive readyRead signal from the target recv device. In response
+ authorize the data, and write results out to the recvBuf() device
+ for processing by the application. Trigger the readyRead signal.
+
+ Authorizing involves first checking the transport is valid, ie the
+ handshake has either already been done and is cached on a trusted
+ transport, or was valid with this message; then second passing the
+ string representation of the service request up to any policyReceivers
+
+ If either of these fail, the message is denied. In discovery mode
+ denied messages are allowed, but the message is logged.
+*/
+void QAuthDevice::recvReadyRead()
+{
+ qint64 bytes = m_target->bytesAvailable();
+ if ( bytes <= 0 ) return;
+ open( QIODevice::ReadWrite | QIODevice::Unbuffered );
+ QUnixSocket *usock = static_cast<QUnixSocket*>(m_target);
+ QUnixSocketMessage msg = usock->read();
+ msgQueue.append( msg.bytes() );
+ d->processId = msg.processId();
+ // if "fragmented" packet 1/2 way through start of a command, ie
+ // in the QWS msg type, cant do anything, come back later when
+ // there's more of the packet
+ if ( msgQueue.size() < (int)sizeof(int) )
+ {
+ // qDebug() << "returning: msg size too small" << msgQueue.size();
+ return;
+ }
+#ifdef QTRANSPORTAUTH_DEBUG
+ char displaybuf[1024];
+ hexstring( displaybuf, reinterpret_cast<const unsigned char *>(msgQueue.constData()),
+ msgQueue.size() > 500 ? 500 : msgQueue.size() );
+ qDebug( "%d ***** SERVER read %lli bytes - msg %s", getpid(), bytes, displaybuf );
+#endif
+
+ bool bufHasMessages = msgQueue.size() >= (int)sizeof(int);
+ while ( bufHasMessages )
+ {
+ unsigned char saveStatus = d->status;
+ if (( d->status & QTransportAuth::ErrMask ) == QTransportAuth::NoSuchKey )
+ {
+ QTransportAuth::getInstance()->authorizeRequest( *d, QLatin1String("NoSuchKey") );
+ break;
+ }
+ if ( !QTransportAuth::getInstance()->authFromMessage( *d, msgQueue, msgQueue.size() ))
+ {
+ // not all arrived yet? come back later
+ if (( d->status & QTransportAuth::ErrMask ) == QTransportAuth::TooSmall )
+ {
+ d->status = saveStatus;
+ return;
+ }
+ }
+ if (( d->status & QTransportAuth::ErrMask ) == QTransportAuth::NoMagic )
+ {
+ // no msg auth header, don't change the success status for connections
+ if ( d->connection() )
+ d->status = saveStatus;
+ }
+ else
+ {
+ // msg auth header detected and auth determined, remove hdr
+ msgQueue = msgQueue.mid( QSXE_HEADER_LEN );
+ }
+ if ( !authorizeMessage() )
+ break;
+ bufHasMessages = msgQueue.size() >= (int)sizeof(int);
+ }
+}
+
+/**
+ \internal
+ Handle bytesWritten signals from the underlying target device.
+ We adjust the target's value for bytes that are part of auth packets.
+*/
+void QAuthDevice::targetBytesWritten( qint64 bytes )
+{
+ if ( m_skipWritten >= bytes ) {
+ m_skipWritten -= bytes;
+ bytes = 0;
+ } else if ( m_skipWritten > 0 ) {
+ bytes -= m_skipWritten;
+ m_skipWritten = 0;
+ }
+ if ( bytes > 0 ) {
+ emit bytesWritten( bytes );
+ }
+}
+
+/**
+ \internal
+ Pre-process the message to determine what QWS command it is. This
+ information is used as the "request" for the purposes of authorization.
+
+ The request and other data on the connection (id, PID, etc.) are forwarded
+ to all policy listeners by emitting a signal.
+
+ The signal must be processed synchronously because on return the allow/deny
+ status is used immediately to either drop or continue processing the message.
+*/
+bool QAuthDevice::authorizeMessage()
+{
+ if ( analyzer == NULL )
+ analyzer = new RequestAnalyzer();
+ QString request = (*analyzer)( &msgQueue );
+ if ( analyzer->requireMoreData() )
+ return false;
+ bool isAuthorized = true;
+
+ if ( !request.isEmpty() && request != QLatin1String("Unknown") )
+ {
+ isAuthorized = QTransportAuth::getInstance()->authorizeRequest( *d, request );
+ }
+
+ bool moreToProcess = ( msgQueue.size() - analyzer->bytesAnalyzed() ) > (int)sizeof(int);
+ if ( isAuthorized )
+ {
+#ifdef QTRANSPORTAUTH_DEBUG
+ qDebug() << getpid() << "SERVER authorized: releasing" << analyzer->bytesAnalyzed() << "byte command" << request;
+#endif
+ m_bytesAvailable = analyzer->bytesAnalyzed();
+ emit QIODevice::readyRead();
+ return moreToProcess;
+ }
+ else
+ {
+ msgQueue = msgQueue.mid( analyzer->bytesAnalyzed() );
+ }
+
+ return true;
+}
+
+void QAuthDevice::setRequestAnalyzer( RequestAnalyzer *ra )
+{
+ Q_ASSERT( ra );
+ if ( analyzer )
+ delete analyzer;
+ analyzer = ra;
+}
+
+/*!
+ \internal
+ Add authentication header to the beginning of a message
+
+ Note that the per-process auth cookie is used. This key should be rewritten in
+ the binary image of the executable at install time to make it unique.
+
+ For this to be secure some mechanism (eg MAC kernel or other
+ permissions) must prevent other processes from reading the key.
+
+ The buffer must have AUTH_SPACE(0) bytes spare at the beginning for the
+ authentication header to be added.
+
+ Returns true if header successfully added. Will fail if the
+ per-process key has not yet been set with setProcessKey()
+*/
+bool QTransportAuth::authToMessage( QTransportAuth::Data &d, char *hdr, const char *msg, int msgLen )
+{
+ // qDebug( "authToMessage(): prog id %u", d.progId );
+ // only authorize connection oriented transports once, unless key has changed
+ if ( d.connection() && ((d.status & QTransportAuth::ErrMask) != QTransportAuth::Pending) &&
+ d_func()->authKey.progId == d.progId )
+ return false;
+ d.progId = d_func()->authKey.progId;
+ // If Unix socket credentials are being used the key wont be set
+ if ( !d_func()->keyInitialised )
+ return false;
+ unsigned char digest[QSXE_KEY_LEN];
+ char *msgPtr = hdr;
+ // magic always goes on the beginning
+ for ( int m = 0; m < QSXE_MAGIC_BYTES; ++m )
+ *msgPtr++ = magic[m];
+ hdr[ QSXE_LEN_IDX ] = (unsigned char)msgLen;
+ if ( !d.trusted())
+ {
+ // Use HMAC
+ int rc = hmac_md5( (unsigned char *)msg, msgLen, d_func()->authKey.key, QSXE_KEY_LEN, digest );
+ if ( rc == -1 )
+ return false;
+ memcpy( hdr + QSXE_KEY_IDX, digest, QSXE_KEY_LEN );
+ }
+ else
+ {
+ memcpy( hdr + QSXE_KEY_IDX, d_func()->authKey.key, QSXE_KEY_LEN );
+ }
+
+ hdr[ QSXE_PROG_IDX ] = d_func()->authKey.progId;
+
+#ifdef QTRANSPORTAUTH_DEBUG
+ char keydisplay[QSXE_KEY_LEN*2+1];
+ hexstring( keydisplay, d_func()->authKey.key, QSXE_KEY_LEN );
+
+ qDebug( "%d CLIENT Auth to message %s against prog id %u and key %s\n",
+ getpid(), msg, d_func()->authKey.progId, keydisplay );
+#endif
+
+ // TODO implement sequence to prevent replay attack, not required
+ // for trusted transports
+ hdr[ QSXE_SEQ_IDX ] = 1; // dummy sequence
+
+ d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::Success;
+ return true;
+}
+
+
+/*!
+ Check authorization on the \a msg, which must be of size \a msgLen,
+ for the transport \a d.
+
+ If able to determine authorization, return the program identity of
+ the message source in the reference \a progId, and return true.
+
+ Otherwise return false.
+
+ If data is being received on a socket, it may be that more data is yet
+ needed before authentication can proceed.
+
+ Also the message may not be an authenticated at all.
+
+ In these cases the method returns false to indicate authorization could
+ not be determined:
+ \list
+ \i The message is too small to carry the authentication data
+ (status TooSmall is set on the \a d transport )
+ \i The 4 magic bytes are missing from the message start
+ (status NoMagic is set on the \a d transport )
+ \i The message is too small to carry the auth + claimed payload
+ (status TooSmall is set on the \a d transport )
+ \endlist
+
+ If however the authentication header (preceded by the magic bytes) and
+ any authenticated payload is received the method will determine the
+ authentication status, and return true.
+
+ In the following cases as well as returning true it will also emit
+ an authViolation():
+ \list
+ \i If the program id claimed by the message is not found in the key file
+ (status NoSuchKey is set on the \a d transport )
+ \i The authentication token failed against the claimed program id:
+ \list
+ \i in the case of trusted transports, the secret did not match
+ \i in the case of untrusted transports the HMAC code did not match
+ \endlist
+ (status FailMatch is set on the \a d transport )
+ \endlist
+
+ In these cases the authViolation( QTransportAuth::Data d ) signal is emitted
+ and the error string can be obtained from the status like this:
+ \snippet doc/src/snippets/code/src_gui_embedded_qtransportauth_qws.cpp 4
+*/
+bool QTransportAuth::authFromMessage( QTransportAuth::Data &d, const char *msg, int msgLen )
+{
+ if ( msgLen < QSXE_MAGIC_BYTES )
+ {
+ d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::TooSmall;
+ return false;
+ }
+ // if no magic bytes, exit straight away
+ int m;
+ const unsigned char *mptr = reinterpret_cast<const unsigned char *>(msg);
+ for ( m = 0; m < QSXE_MAGIC_BYTES; ++m )
+ {
+ if ( *mptr++ != magic[m] )
+ {
+ d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::NoMagic;
+ return false;
+ }
+ }
+
+ if ( msgLen < AUTH_SPACE(1) )
+ {
+ d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::TooSmall;
+ return false;
+ }
+
+ // At this point we know the header is at least long enough to contain valid auth
+ // data, however the data may be spoofed. If it is not verified then the status will
+ // be set to uncertified so the spoofed data will not be relied on. However we want to
+ // know the program id which is being reported (even if it might be spoofed) for
+ // policy debugging purposes. So set it here, rather than after verification.
+ d.progId = msg[QSXE_PROG_IDX];
+
+#ifdef QTRANSPORTAUTH_DEBUG
+ char authhdr[QSXE_HEADER_LEN*2+1];
+ hexstring( authhdr, reinterpret_cast<const unsigned char *>(msg), QSXE_HEADER_LEN );
+ qDebug( "%d SERVER authFromMessage(): message header is %s",
+ getpid(), authhdr );
+#endif
+
+ unsigned char authLen = (unsigned char)(msg[ QSXE_LEN_IDX ]);
+
+ if ( msgLen < AUTH_SPACE(authLen) )
+ {
+ d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::TooSmall;
+ return false;
+ }
+
+ bool isCached = d_func()->keyCache.contains( d.progId );
+ const unsigned char *clientKey = d_func()->getClientKey( d.progId );
+ if ( clientKey == NULL )
+ {
+ d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::NoSuchKey;
+ return false;
+ }
+
+#ifdef QTRANSPORTAUTH_DEBUG
+ char keydisplay[QSXE_KEY_LEN*2+1];
+ hexstring( keydisplay, clientKey, QSXE_KEY_LEN );
+ qDebug( "\t\tauthFromMessage(): message %s against prog id %u and key %s\n",
+ AUTH_DATA(msg), ((unsigned int)d.progId), keydisplay );
+#endif
+
+ const unsigned char *auth_tok;
+ unsigned char digest[QSXE_KEY_LEN];
+ bool multi_tok = false;
+
+ bool need_to_recheck=false;
+ do
+ {
+ if ( !d.trusted())
+ {
+ hmac_md5( AUTH_DATA(msg), authLen, clientKey, QSXE_KEY_LEN, digest );
+ auth_tok = digest;
+ }
+ else
+ {
+ auth_tok = clientKey;
+ multi_tok = true; // 1 or more keys are in the clientKey
+ }
+ while( true )
+ {
+ if ( memcmp( auth_tok, magic, QSXE_MAGIC_BYTES ) == 0
+ && memcmp( auth_tok + QSXE_MAGIC_BYTES, magic, QSXE_MAGIC_BYTES ) == 0 )
+ break;
+ if ( memcmp( msg + QSXE_KEY_IDX, auth_tok, QSXE_KEY_LEN ) == 0 )
+ {
+ d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::Success;
+ return true;
+ }
+ if ( !multi_tok )
+ break;
+ auth_tok += QSXE_KEY_LEN;
+ }
+ //the keys cached on d.progId may not contain the binary key because the cache entry was made
+ //before the binary had first started, must search for client key again.
+ if ( isCached )
+ {
+ d_func()->keyCache.remove(d.progId);
+ isCached = false;
+
+#ifdef QTRANSPORTAUTH_DEBUG
+ qDebug() << "QTransportAuth::authFromMessage(): key not found in set of keys cached"
+ << "against prog Id =" << d.progId << ". Re-obtaining client key. ";
+#endif
+ clientKey = d_func()->getClientKey( d.progId );
+ if ( clientKey == NULL )
+ {
+ d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::NoSuchKey;
+ return false;
+ }
+ need_to_recheck = true;
+ }
+ else
+ {
+ need_to_recheck = false;
+ }
+ } while( need_to_recheck );
+
+ d.status = ( d.status & QTransportAuth::StatusMask ) | QTransportAuth::FailMatch;
+ qWarning() << "QTransportAuth::authFromMessage():failed authentication";
+ FAREnforcer::getInstance()->logAuthAttempt( QDateTime::currentDateTime() );
+ emit authViolation( d );
+ return false;
+}
+
+
+#ifdef QTRANSPORTAUTH_DEBUG
+/*!
+ sprintf into hex - dest \a buf, src \a key, \a key_len is length of key.
+
+ The target buf should be [ key_len * 2 + 1 ] in size
+*/
+void hexstring( char *buf, const unsigned char* key, size_t key_len )
+{
+ unsigned int i, p;
+ for ( i = 0, p = 0; i < key_len; i++, p+=2 )
+ {
+ unsigned char lo_nibble = key[i] & 0x0f;
+ unsigned char hi_nibble = key[i] >> 4;
+ buf[p] = (int)hi_nibble > 9 ? hi_nibble-10 + 'A' : hi_nibble + '0';
+ buf[p+1] = (int)lo_nibble > 9 ? lo_nibble-10 + 'A' : lo_nibble + '0';
+ }
+ buf[p] = '\0';
+}
+#endif
+
+/*
+ HMAC MD5 as listed in RFC 2104
+
+ This code is taken from:
+
+ http://www.faqs.org/rfcs/rfc2104.html
+
+ with the allowance for keys other than length 16 removed, but otherwise
+ a straight cut-and-paste.
+
+ The HMAC_MD5 transform looks like:
+
+ \snippet doc/src/snippets/code/src.gui.embedded.qtransportauth_qws.cpp 5
+
+ \list
+ \i where K is an n byte key
+ \i ipad is the byte 0x36 repeated 64 times
+ \i opad is the byte 0x5c repeated 64 times
+ \i and text is the data being protected
+ \endlist
+
+ Hardware is available with accelerated implementations of HMAC-MD5 and
+ HMAC-SHA1. Where this hardware is available, this routine should be
+ replaced with a call into the accelerated version.
+*/
+
+static int hmac_md5(
+ unsigned char* text, /* pointer to data stream */
+ int text_length, /* length of data stream */
+ const unsigned char* key, /* pointer to authentication key */
+ int key_length, /* length of authentication key */
+ unsigned char * digest /* caller digest to be filled in */
+ )
+{
+ MD5Context context;
+ unsigned char k_ipad[65]; /* inner padding - * key XORd with ipad */
+ unsigned char k_opad[65]; /* outer padding - * key XORd with opad */
+ int i;
+
+ /* in this implementation key_length == 16 */
+ if ( key_length != 16 )
+ {
+ fprintf( stderr, "Key length was %d - must be 16 bytes", key_length );
+ return 0;
+ }
+
+ /* start out by storing key in pads */
+ memset( k_ipad, 0, sizeof k_ipad );
+ memset( k_opad, 0, sizeof k_opad );
+ memcpy( k_ipad, key, key_length );
+ memcpy( k_opad, key, key_length );
+
+ /* XOR key with ipad and opad values */
+ for (i=0; i<64; i++) {
+ k_ipad[i] ^= 0x36;
+ k_opad[i] ^= 0x5c;
+ }
+
+ /* perform inner MD5 */
+ MD5Init(&context); /* init context for 1st pass */
+ MD5Update(&context, k_ipad, 64); /* start with inner pad */
+ MD5Update(&context, text, text_length); /* then text of datagram */
+ MD5Final(&context, digest); /* finish up 1st pass */
+
+ /* perform outer MD5 */
+ MD5Init(&context); /* init context for 2nd pass */
+ MD5Update(&context, k_opad, 64); /* start with outer pad */
+ MD5Update(&context, digest, 16); /* then results of 1st * hash */
+ MD5Final(&context, digest); /* finish up 2nd pass */
+ return 1;
+}
+
+
+const int FAREnforcer::minutelyRate = 4; //allowed number of false authentication attempts per minute
+const QString FAREnforcer::FARMessage = QLatin1String("FAR_Exceeded");
+const QString FAREnforcer::SxeTag = QLatin1String("<SXE Breach>");
+const int FAREnforcer::minute = 60;
+
+FAREnforcer::FAREnforcer():authAttempts()
+{
+ QDateTime nullDateTime = QDateTime();
+ for (int i = 0; i < minutelyRate; i++ )
+ authAttempts << nullDateTime;
+}
+
+
+FAREnforcer *FAREnforcer::getInstance()
+{
+ static FAREnforcer theInstance;
+ return &theInstance;
+}
+
+void FAREnforcer::logAuthAttempt( QDateTime time )
+{
+ QDateTime dt = authAttempts.takeFirst();
+
+ authAttempts.append( time );
+ if ( dt.secsTo( authAttempts.last() ) <= minute )
+ {
+#if defined(SXE_DISCOVERY)
+ if ( QTransportAuth::getInstance()->isDiscoveryMode() ) {
+ static QBasicAtomicInt reported = Q_BASIC_ATOMIC_INITIALIZER(0);
+ if ( reported.testAndSetRelaxed(0,1) ) {
+#ifndef QT_NO_TEXTSTREAM
+ QString logFilePath = QTransportAuth::getInstance()->logFilePath();
+ if ( !logFilePath.isEmpty() ) {
+ QFile log( logFilePath );
+ if ( !log.open(QIODevice::WriteOnly | QIODevice::Append) ) {
+ qWarning("Could not write to log in discovery mode: %s",
+ qPrintable(logFilePath) );
+ } else {
+ QTextStream ts( &log );
+ ts << "\t\tWarning: False Authentication Rate of " << minutelyRate << "\n"
+ << "\t\tserver connections/authentications per minute has been exceeded,\n"
+ << "\t\tno further warnings will be issued\n";
+ }
+ }
+ }
+#endif
+ reset();
+ return;
+ }
+#endif
+ syslog( LOG_ERR | LOG_LOCAL6, "%s %s",
+ qPrintable( FAREnforcer::SxeTag ),
+ qPrintable( FAREnforcer::FARMessage ) );
+ reset();
+ }
+}
+
+void FAREnforcer::reset()
+{
+ QDateTime nullDateTime = QDateTime();
+ for (int i = 0; i < minutelyRate; i++ )
+ authAttempts[i] = nullDateTime;
+}
+
+QT_END_NAMESPACE
+
+#include "moc_qtransportauth_qws_p.cpp"
+
+#endif // QT_NO_SXE
diff --git a/src/gui/embedded/qtransportauth_qws.h b/src/gui/embedded/qtransportauth_qws.h
new file mode 100644
index 0000000000..2d2dd529fc
--- /dev/null
+++ b/src/gui/embedded/qtransportauth_qws.h
@@ -0,0 +1,281 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTRANSPORTAUTH_QWS_H
+#define QTRANSPORTAUTH_QWS_H
+
+#include <QtCore/qglobal.h>
+
+#if !defined(QT_NO_SXE) || defined(SXE_INSTALLER)
+
+#include <QtCore/qobject.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qbuffer.h>
+#include <QtCore/qpointer.h>
+
+#include <sys/types.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QAuthDevice;
+class QWSClient;
+class QIODevice;
+class QTransportAuthPrivate;
+class QMutex;
+
+class Q_GUI_EXPORT QTransportAuth : public QObject
+{
+ Q_OBJECT
+public:
+ static QTransportAuth *getInstance();
+
+ enum Result {
+ // Error codes
+ Pending = 0x00,
+ TooSmall = 0x01,
+ CacheMiss = 0x02,
+ NoMagic = 0x03,
+ NoSuchKey = 0x04,
+ FailMatch = 0x05,
+ OutOfDate = 0x06,
+ // reserved for expansion
+ Success = 0x1e,
+ ErrMask = 0x1f,
+
+ // Verification codes
+ Allow = 0x20,
+ Deny = 0x40,
+ Ask = 0x60,
+ // reserved
+ StatusMask = 0xe0
+ };
+
+ enum Properties {
+ Trusted = 0x01,
+ Connection = 0x02,
+ UnixStreamSock = 0x04,
+ SharedMemory = 0x08,
+ MessageQueue = 0x10,
+ UDP = 0x20,
+ TCP = 0x40,
+ UserDefined = 0x80,
+ TransportType = 0xfc
+ };
+
+ struct Data
+ {
+ Data() { processId = -1; }
+ Data( unsigned char p, int d )
+ : properties( p )
+ , descriptor( d )
+ , processId( -1 )
+ {
+ if (( properties & TransportType ) == TCP ||
+ ( properties & TransportType ) == UnixStreamSock )
+ properties |= Connection;
+ }
+
+ unsigned char properties;
+ unsigned char progId;
+ unsigned char status;
+ unsigned int descriptor; // socket fd or shmget key
+ pid_t processId;
+
+ bool trusted() const;
+ void setTrusted( bool );
+ bool connection() const;
+ void setConnection( bool );
+ };
+
+ static const char *errorString( const QTransportAuth::Data & );
+
+ QTransportAuth::Data *connectTransport( unsigned char, int );
+
+ QAuthDevice *authBuf( QTransportAuth::Data *, QIODevice * );
+ QAuthDevice *recvBuf( QTransportAuth::Data *, QIODevice * );
+ QIODevice *passThroughByClient( QWSClient * ) const;
+
+ void setKeyFilePath( const QString & );
+ QString keyFilePath() const;
+ const unsigned char *getClientKey( unsigned char progId );
+ void invalidateClientKeyCache();
+ QMutex *getKeyFileMutex();
+ void setLogFilePath( const QString & );
+ QString logFilePath() const;
+ void setPackageRegistry( QObject *registry );
+ bool isDiscoveryMode() const;
+ void setProcessKey( const char * );
+ void setProcessKey( const char *, const char * );
+ void registerPolicyReceiver( QObject * );
+ void unregisterPolicyReceiver( QObject * );
+
+ bool authToMessage( QTransportAuth::Data &d, char *hdr, const char *msg, int msgLen );
+ bool authFromMessage( QTransportAuth::Data &d, const char *msg, int msgLen );
+
+ bool authorizeRequest( QTransportAuth::Data &d, const QString &request );
+
+Q_SIGNALS:
+ void policyCheck( QTransportAuth::Data &, const QString & );
+ void authViolation( QTransportAuth::Data & );
+private Q_SLOTS:
+ void bufferDestroyed( QObject * );
+
+private:
+ // users should never construct their own
+ QTransportAuth();
+ ~QTransportAuth();
+
+ friend class QAuthDevice;
+ Q_DECLARE_PRIVATE(QTransportAuth)
+};
+
+class Q_GUI_EXPORT RequestAnalyzer
+{
+public:
+ RequestAnalyzer();
+ virtual ~RequestAnalyzer();
+ QString operator()( QByteArray *data ) { return analyze( data ); }
+ bool requireMoreData() const { return moreData; }
+ qint64 bytesAnalyzed() const { return dataSize; }
+protected:
+ virtual QString analyze( QByteArray * );
+ bool moreData;
+ qint64 dataSize;
+};
+
+/*!
+ \internal
+ \class QAuthDevice
+
+ \brief Pass-through QIODevice sub-class for authentication.
+
+ Use this class to forward on or receive forwarded data over a real
+ device for authentication.
+*/
+class Q_GUI_EXPORT QAuthDevice : public QIODevice
+{
+ Q_OBJECT
+public:
+ enum AuthDirection {
+ Receive,
+ Send
+ };
+ QAuthDevice( QIODevice *, QTransportAuth::Data *, AuthDirection );
+ ~QAuthDevice();
+ void setTarget( QIODevice *t ) { m_target = t; }
+ QIODevice *target() const { return m_target; }
+ void setClient( QObject* );
+ QObject *client() const;
+ void setRequestAnalyzer( RequestAnalyzer * );
+ bool isSequential() const;
+ bool atEnd() const;
+ qint64 bytesAvailable() const;
+ qint64 bytesToWrite() const;
+ bool seek( qint64 );
+ QByteArray & buffer();
+
+protected:
+ qint64 readData( char *, qint64 );
+ qint64 writeData(const char *, qint64 );
+private Q_SLOTS:
+ void recvReadyRead();
+ void targetBytesWritten( qint64 );
+private:
+ bool authorizeMessage();
+
+ QTransportAuth::Data *d;
+ AuthDirection way;
+ QIODevice *m_target;
+ QObject *m_client;
+ QByteArray msgQueue;
+ qint64 m_bytesAvailable;
+ qint64 m_skipWritten;
+
+ RequestAnalyzer *analyzer;
+};
+
+inline bool QAuthDevice::isSequential() const
+{
+ return true;
+}
+
+inline bool QAuthDevice::seek( qint64 )
+{
+ return false;
+}
+
+inline bool QAuthDevice::atEnd() const
+{
+ return msgQueue.isEmpty();
+}
+
+inline qint64 QAuthDevice::bytesAvailable() const
+{
+ if ( way == Receive )
+ return m_bytesAvailable;
+ else
+ return ( m_target ? m_target->bytesAvailable() : 0 );
+}
+
+inline qint64 QAuthDevice::bytesToWrite() const
+{
+ return msgQueue.size();
+}
+
+inline QByteArray &QAuthDevice::buffer()
+{
+ return msgQueue;
+}
+
+
+
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_SXE
+#endif // QTRANSPORTAUTH_QWS_H
diff --git a/src/gui/embedded/qtransportauth_qws_p.h b/src/gui/embedded/qtransportauth_qws_p.h
new file mode 100644
index 0000000000..33e2edc532
--- /dev/null
+++ b/src/gui/embedded/qtransportauth_qws_p.h
@@ -0,0 +1,189 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTRANSPORTAUTH_QWS_P_H
+#define QTRANSPORTAUTH_QWS_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/qglobal.h>
+
+#ifndef QT_NO_SXE
+
+#include "qtransportauth_qws.h"
+#include "qtransportauthdefs_qws.h"
+#include "qbuffer.h"
+
+#include <qmutex.h>
+#include <qdatetime.h>
+#include "private/qobject_p.h"
+
+#include <QtCore/qcache.h>
+
+QT_BEGIN_NAMESPACE
+
+// Uncomment to generate debug output
+// #define QTRANSPORTAUTH_DEBUG 1
+
+#ifdef QTRANSPORTAUTH_DEBUG
+void hexstring( char *buf, const unsigned char* key, size_t sz );
+#endif
+
+// proj id for ftok usage in sxe
+#define SXE_PROJ 10022
+
+/*!
+ \internal
+ memset for security purposes, guaranteed not to be optimized away
+ http://www.faqs.org/docs/Linux-HOWTO/Secure-Programs-HOWTO.html
+*/
+void *guaranteed_memset(void *v,int c,size_t n);
+
+class QUnixSocketMessage;
+
+/*!
+ \internal
+ \class AuthCookie
+ Struct to carry process authentication key and id
+*/
+#define QSXE_HEADER_LEN 24
+
+/*!
+ \macro AUTH_ID
+ Macro to manage authentication header. Format of header is:
+ \table
+ \header \i BYTES \i CONTENT
+ \row \i 0-3 \i magic numbers
+ \row \i 4 \i length of authenticated data (max 255 bytes)
+ \row i\ 5 \i reserved
+ \row \i 6-21 \i MAC digest, or shared secret in case of simple auth
+ \row \i 22 \i program id
+ \row \i 23 \i sequence number
+ \endtable
+ Total length of the header is 24 bytes
+
+ However this may change. Instead of coding these numbers use the AUTH_ID,
+ AUTH_KEY, AUTH_DATA and AUTH_SPACE macros.
+*/
+
+#define AUTH_ID(k) ((unsigned char)(k[QSXE_KEY_LEN]))
+#define AUTH_KEY(k) ((unsigned char *)(k))
+
+#define AUTH_DATA(x) (unsigned char *)((x) + QSXE_HEADER_LEN)
+#define AUTH_SPACE(x) ((x) + QSXE_HEADER_LEN)
+#define QSXE_LEN_IDX 4
+#define QSXE_KEY_IDX 6
+#define QSXE_PROG_IDX 22
+#define QSXE_SEQ_IDX 23
+
+class SxeRegistryLocker : public QObject
+{
+ Q_OBJECT
+public:
+ SxeRegistryLocker( QObject * );
+ ~SxeRegistryLocker();
+ bool success() const { return m_success; }
+private:
+ bool m_success;
+ QObject *m_reg;
+};
+
+class QTransportAuthPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QTransportAuth)
+public:
+ QTransportAuthPrivate();
+ ~QTransportAuthPrivate();
+
+ const unsigned char *getClientKey( unsigned char progId );
+ void invalidateClientKeyCache();
+
+ bool keyInitialised;
+ QString m_logFilePath;
+ QString m_keyFilePath;
+ QObject *m_packageRegistry;
+ AuthCookie authKey;
+ QCache<unsigned char, char> keyCache;
+ QHash< QObject*, QIODevice*> buffersByClient;
+ QMutex keyfileMutex;
+};
+
+/*!
+ \internal
+ Enforces the False Authentication Rate. If more than 4 authentications
+ are received per minute the sxemonitor is notified that the FAR has been exceeded
+*/
+class FAREnforcer
+{
+ public:
+ static FAREnforcer *getInstance();
+ void logAuthAttempt( QDateTime time = QDateTime::currentDateTime() );
+ void reset();
+
+#ifndef TEST_FAR_ENFORCER
+ private:
+#endif
+ FAREnforcer();
+ FAREnforcer( const FAREnforcer & );
+ FAREnforcer &operator=(FAREnforcer const & );
+
+ static const QString FARMessage;
+ static const int minutelyRate;
+ static const QString SxeTag;
+ static const int minute;
+
+ QList<QDateTime> authAttempts;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_SXE
+#endif // QTRANSPORTAUTH_QWS_P_H
+
diff --git a/src/gui/embedded/qtransportauthdefs_qws.h b/src/gui/embedded/qtransportauthdefs_qws.h
new file mode 100644
index 0000000000..85218b6647
--- /dev/null
+++ b/src/gui/embedded/qtransportauthdefs_qws.h
@@ -0,0 +1,174 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QTRANSPORTAUTHDEFS_QWS_H
+#define QTRANSPORTAUTHDEFS_QWS_H
+
+#include <sys/types.h>
+#include <string.h>
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#define QSXE_KEY_LEN 16
+#define QSXE_MAGIC_BYTES 4
+
+// Number of bytes of each message to authenticate. Just need to ensure
+// that the command at the beginning hasn't been tampered with. This value
+// does not matter for trusted transports.
+#define AMOUNT_TO_AUTHENTICATE 200
+
+#define AUTH_ID(k) ((unsigned char)(k[QSXE_KEY_LEN]))
+#define AUTH_KEY(k) ((unsigned char *)(k))
+
+// must be a largish -ve number under any endianess when cast as an int
+const unsigned char magic[QSXE_MAGIC_BYTES] = { 0xBA, 0xD4, 0xD4, 0xBA };
+const int magicInt = 0xBAD4D4BA;
+
+#define QSXE_KEYFILE "keyfile"
+
+/*
+ Header in above format, less the magic bytes.
+ Useful for reading off the socket
+*/
+struct AuthHeader
+{
+ unsigned char len;
+ unsigned char pad;
+ unsigned char digest[QSXE_KEY_LEN];
+ unsigned char id;
+ unsigned char seq;
+};
+
+/*
+ Header in a form suitable for authentication routines
+*/
+struct AuthMessage
+{
+ AuthMessage()
+ {
+ ::memset( authData, 0, sizeof(authData) );
+ ::memcpy( pad_magic, magic, QSXE_MAGIC_BYTES );
+ }
+ unsigned char pad_magic[QSXE_MAGIC_BYTES];
+ union {
+ AuthHeader hdr;
+ char authData[sizeof(AuthHeader)];
+ };
+ char payLoad[AMOUNT_TO_AUTHENTICATE];
+};
+
+/**
+ Auth data as stored in _key
+*/
+struct AuthCookie
+{
+ unsigned char key[QSXE_KEY_LEN];
+ unsigned char pad;
+ unsigned char progId;
+};
+
+/*
+ Auth data as written to the key file - SUPERSEDED by usr_key_entry
+
+ This is still used internally for some functions, ie the socket
+ related calls.
+*/
+struct AuthRecord
+{
+ union {
+ AuthCookie auth;
+ char data[sizeof(struct AuthCookie)];
+ };
+ time_t change_time;
+};
+
+/*!
+ \class usr_key_entry
+ This comes from the SXE kernel patch file include/linux/lidsif.h
+
+ This is the (new) data record for the key file (version 2).
+
+ The key file is (now) either /proc/lids/keys (and the per-process
+ keys in /proc/<pid>/lids_key) OR for desktop/development ONLY (not
+ for production) it is $QPEDIR/etc/keyfile
+
+ The key file maps keys to files.
+
+ File are identified by inode and device numbers, not paths.
+
+ (See the "installs" file for path to inode/device mapping)
+*/
+struct usr_key_entry
+{
+ char key[QSXE_KEY_LEN];
+ ino_t ino;
+ dev_t dev;
+};
+
+
+/*!
+ \class IdBlock
+ \brief Data record for the manifest file.
+ The manifest file maps program id's to files
+*/
+struct IdBlock
+{
+ quint64 inode;
+ quint64 device;
+ unsigned char pad;
+ unsigned char progId;
+ unsigned short installId;
+ unsigned int keyOffset;
+ qint64 install_time;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QTRANSPORTAUTHDEFS_QWS_H
+
diff --git a/src/gui/embedded/qunixsocket.cpp b/src/gui/embedded/qunixsocket.cpp
new file mode 100644
index 0000000000..16f2caecb8
--- /dev/null
+++ b/src/gui/embedded/qunixsocket.cpp
@@ -0,0 +1,1794 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qunixsocket_p.h"
+
+// #define QUNIXSOCKET_DEBUG 1
+
+#include <QtCore/qsocketnotifier.h>
+#include <QtCore/qqueue.h>
+#include <QtCore/qdatetime.h>
+
+#ifdef QUNIXSOCKET_DEBUG
+#include <QtCore/qdebug.h>
+#endif
+
+extern "C" {
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+};
+
+#define UNIX_PATH_MAX 108 // From unix(7)
+
+#ifdef QT_LINUXBASE
+// LSB doesn't declare ucred
+struct ucred
+{
+ pid_t pid; /* PID of sending process. */
+ uid_t uid; /* UID of sending process. */
+ gid_t gid; /* GID of sending process. */
+};
+
+// LSB doesn't define the ones below
+#ifndef SO_PASSCRED
+# define SO_PASSCRED 16
+#endif
+#ifndef SCM_CREDENTIALS
+# define SCM_CREDENTIALS 0x02
+#endif
+#ifndef MSG_DONTWAIT
+# define MSG_DONTWAIT 0x40
+#endif
+#ifndef MSG_NOSIGNAL
+# define MSG_NOSIGNAL 0x4000
+#endif
+
+#endif // QT_LINUXBASE
+
+QT_BEGIN_NAMESPACE
+
+///////////////////////////////////////////////////////////////////////////////
+// class QUnixSocketRights
+///////////////////////////////////////////////////////////////////////////////
+/*!
+ \class QUnixSocketRights
+ \internal
+
+ \brief The QUnixSocketRights class encapsulates QUnixSocket rights data.
+ \omit
+ \ingroup Platform::DeviceSpecific
+ \ingroup Platform::OS
+ \ingroup Platform::Communications
+ \endomit
+ \ingroup qws
+
+ \l QUnixSocket allows you to transfer Unix file descriptors between processes.
+ A file descriptor is referred to as "rights data" as it allows one process to
+ transfer its right to access a resource to another.
+
+ The Unix system verifies resource permissions only when the resource is first
+ opened. For example, consider a file on disk readable only by the user "qt".
+ A process running as user "qt" will be able to open this file for reading.
+ If, while the process was still reading from the file, the ownership was
+ changed from user "qt" to user "root", the process would be allowed to
+ continue reading from the file, even though attempting to reopen the file
+ would be denied. Permissions are associated with special descriptors called
+ file descriptors which are returned to a process after it initially opens a
+ resource.
+
+ File descriptors can be duplicated within a process through the dup(2) system
+ call. File descriptors can be passed between processes using the
+ \l QUnixSocket class in the same way. Even though the receiving process never
+ opened the resource directly, it has the same permissions to access it as the
+ process that did.
+
+ \sa QUnixSocket
+ */
+struct QUnixSocketRightsPrivate : public QSharedData
+{
+ virtual ~QUnixSocketRightsPrivate() {
+#ifdef QUNIXSOCKET_DEBUG
+ int closerv =
+#endif
+ ::close(fd);
+#ifdef QUNIXSOCKET_DEBUG
+ if(0 != closerv) {
+ qDebug() << "QUnixSocketRightsPrivate: Unable to close managed"
+ " file descriptor (" << ::strerror(errno) << ")";
+ }
+#endif
+ }
+
+ int fd;
+};
+
+/*!
+ Create a new QUnixSocketRights instance containing the file descriptor \a fd.
+ \a fd will be dup(2)'d internally, so the application is free to close \a fd
+ following this call.
+
+ If the dup(2) fails, or you pass an invalid \a fd, an
+ \l {QUnixSocketRights::isValid()}{invalid } object will be
+ constructed.
+
+ QUnixSocketRights instances are immutable and the internal file descriptor
+ will be shared between any copies made of this object. The system will
+ close(2) the file descriptor once it is no longer needed.
+ */
+QUnixSocketRights::QUnixSocketRights(int fd)
+{
+ d = new QUnixSocketRightsPrivate();
+ if(-1 == fd) {
+ d->fd = -1;
+ } else {
+ d->fd = ::dup(fd);
+#ifdef QUNIXSOCKET_DEBUG
+ if(-1 == d->fd) {
+ qDebug() << "QUnixSocketRights: Unable to duplicate fd "
+ << fd << " (" << ::strerror(errno) << ")";
+ }
+#endif
+ }
+}
+
+/*!
+ \internal
+
+ Construct a QUnixSocketRights instance on \a fd without dup(2)'ing the file
+ descriptor.
+ */
+QUnixSocketRights::QUnixSocketRights(int fd,int)
+{
+ Q_ASSERT(-1 != fd);
+ d = new QUnixSocketRightsPrivate();
+ d->fd = fd;
+}
+
+/*!
+ Destroys the QUnixSocketRights instance.
+ */
+QUnixSocketRights::~QUnixSocketRights()
+{
+}
+
+/*!
+ Create a copy of \a other.
+ */
+QUnixSocketRights &
+QUnixSocketRights::operator=(const QUnixSocketRights & other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Create a copy of \a other.
+ */
+QUnixSocketRights::QUnixSocketRights(const QUnixSocketRights & other)
+: d(other.d)
+{
+}
+
+/*!
+ Returns true if this QUnixSocketRights instance is managing a valid file
+ descriptor. This method is equivalent to (-1 != peekFd()).
+
+ \sa QUnixSocketRights::peekFd()
+ */
+bool QUnixSocketRights::isValid() const
+{
+ return d->fd != -1;
+}
+
+/*!
+ Return a duplicate of the file descriptor contained in this object. If this
+ is an \l {QUnixSocketRights::isValid()}{invalid } object, or the
+ dup(2) call fails, an invalid file descriptor (-1) will be returned.
+
+ \sa QUnixSocketRights::peekFd()
+ */
+int QUnixSocketRights::dupFd() const
+{
+ if(-1 == d->fd) return -1;
+
+ int rv = ::dup(d->fd);
+
+#ifdef QUNIXSOCKET_DEBUG
+ if(-1 == rv)
+ qDebug() << "QUnixSocketRights: Unable to duplicate managed file "
+ "descriptor (" << ::strerror(errno) << ")";
+#endif
+
+ return rv;
+}
+
+/*!
+ Returns the file descriptor contained in this object. If this
+ is an \l {QUnixSocketRights::isValid()}{invalid } object an invalid
+ file descriptor (-1) will be returned.
+
+ The lifetime of this file descriptor is tied to the lifetime of the
+ QUnixSocketRights instance. The file descriptor returned by this method
+ \e may be close(2)'d when the QUnixSocketRights instance is destroyed. If
+ you want to continue to use the file descriptor use
+ \l QUnixSocketRights::dupFd() instead.
+
+ \sa QUnixSocketRights::dupFd()
+ */
+int QUnixSocketRights::peekFd() const
+{
+ return d->fd;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// class QUnixSocketMessage
+///////////////////////////////////////////////////////////////////////////////
+struct QUnixSocketMessagePrivate : public QSharedData
+{
+ QUnixSocketMessagePrivate()
+ : state(Default), vec(0), iovecLen(0), dataSize(0) {}
+ QUnixSocketMessagePrivate(const QByteArray & b)
+ : bytes(b), state(Default), vec(0), iovecLen(0), dataSize(0) {}
+ QUnixSocketMessagePrivate(const QByteArray & b,
+ const QList<QUnixSocketRights> & r)
+ : bytes(b), rights(r), state(Default), vec(0), iovecLen(0), dataSize(0) {}
+
+ int size() const { return vec ? dataSize : bytes.size(); }
+ void removeBytes( unsigned int );
+
+ QByteArray bytes;
+ QList<QUnixSocketRights> rights;
+
+ enum AncillaryDataState {
+ Default = 0x00,
+ Truncated = 0x01,
+ Credential = 0x02
+ };
+ AncillaryDataState state;
+
+ pid_t pid;
+ gid_t gid;
+ uid_t uid;
+
+ ::iovec *vec;
+ int iovecLen; // number of vectors in array
+ int dataSize; // total size of vectors = payload
+};
+
+/*!
+ \internal
+ Remove \a bytesToDequeue bytes from the front of this message
+*/
+void QUnixSocketMessagePrivate::removeBytes( unsigned int bytesToDequeue )
+{
+ if ( vec )
+ {
+ ::iovec *vecPtr = vec;
+ if ( bytesToDequeue > (unsigned int)dataSize ) bytesToDequeue = dataSize;
+ while ( bytesToDequeue > 0 && iovecLen > 0 )
+ {
+ if ( vecPtr->iov_len > bytesToDequeue )
+ {
+ // dequeue the bytes by taking them off the front of the
+ // current vector. since we don't own the iovec, its okay
+ // to "leak" this away by pointing past it
+ char **base = reinterpret_cast<char**>(&(vecPtr->iov_base));
+ *base += bytesToDequeue;
+ vecPtr->iov_len -= bytesToDequeue;
+ bytesToDequeue = 0;
+ }
+ else
+ {
+ // dequeue bytes by skipping a whole vector. again, its ok
+ // to lose the pointers to this data
+ bytesToDequeue -= vecPtr->iov_len;
+ iovecLen--;
+ vecPtr++;
+ }
+ }
+ dataSize -= bytesToDequeue;
+ if ( iovecLen == 0 ) vec = 0;
+ }
+ else
+ {
+ bytes.remove(0, bytesToDequeue );
+ }
+}
+
+
+/*!
+ \class QUnixSocketMessage
+ \internal
+
+ \brief The QUnixSocketMessage class encapsulates a message sent or received
+ through the QUnixSocket class.
+ \omit
+ \ingroup Platform::DeviceSpecific
+ \ingroup Platform::OS
+ \ingroup Platform::Communications
+ \endomit
+ \ingroup qws
+
+ In addition to transmitting regular byte stream data, messages sent over Unix
+ domain sockets may have special ancillary properties. QUnixSocketMessage
+ instances allow programmers to retrieve and control these properties.
+
+ Every QUnixSocketMessage sent has an associated set of credentials. A
+ message's credentials consist of the process id, the user id and the group id
+ of the sending process. Normally these credentials are set automatically for
+ you by the QUnixSocketMessage class and can be queried by the receiving
+ process using the \l QUnixSocketMessage::processId(),
+ \l QUnixSocketMessage::userId() and \l QUnixSocketMessage::groupId() methods
+ respectively.
+
+ Advanced applications may wish to change the credentials that their message
+ is sent with, and may do so though the \l QUnixSocketMessage::setProcessId(),
+ \l QUnixSocketMessage::setUserId() and \l QUnixSocketMessage::setGroupId()
+ methods. The validity of these credentials is verified by the system kernel.
+ Only the root user can send messages with credentials that are not his own.
+ Sending of the message will fail for any non-root user who attempts to
+ fabricate credentials. Note that this failure is enforced by the system
+ kernel - receivers can trust the accuracy of credential data!
+
+ Unix domain socket messages may also be used to transmit Unix file descriptors
+ between processes. In this context, file descriptors are known as rights data
+ and are encapsulated by the \l QUnixSocketRights class. Senders can set the
+ file descriptors to transmit using the \l QUnixSocketMessage::setRights() and
+ receivers can retrieve this data through a call to
+ \l QUnixSocketMessage::rights(). \l QUnixSocket and \l QUnixSocketRights
+ discuss the specific copy and ordering semantic associated with rights data.
+
+ QUnixSocketMessage messages are sent by the \l QUnixSocket::write() method.
+ Like any normal network message, attempting to transmit an empty
+ QUnixSocketMessage will succeed, but result in a no-op. Limitations in the
+ Unix domain protocol semantic will cause a transmission of a
+ QUnixSocketMessage with rights data, but no byte data portion, to fail.
+
+ \sa QUnixSocket QUnixSocketRights
+ */
+
+/*!
+ Construct an empty QUnixSocketMessage. This instance will have not data and
+ no rights information. The message's credentials will be set to the
+ application's default credentials.
+ */
+QUnixSocketMessage::QUnixSocketMessage()
+: d(new QUnixSocketMessagePrivate())
+{
+}
+
+/*!
+ Construct a QUnixSocketMessage with an initial data payload of \a bytes. The
+ message's credentials will be set to the application's default credentials.
+ */
+QUnixSocketMessage::QUnixSocketMessage(const QByteArray & bytes)
+: d(new QUnixSocketMessagePrivate(bytes))
+{
+}
+
+/*!
+ Construct a QUnixSocketMessage with an initial data payload of \a bytes and
+ an initial rights payload of \a rights. The message's credentials will be set
+ to the application's default credentials.
+
+ A message with rights data but an empty data payload cannot be transmitted
+ by the system.
+ */
+QUnixSocketMessage::QUnixSocketMessage(const QByteArray & bytes,
+ const QList<QUnixSocketRights> & rights)
+: d(new QUnixSocketMessagePrivate(bytes, rights))
+{
+}
+
+/*!
+ Create a copy of \a other.
+ */
+QUnixSocketMessage::QUnixSocketMessage(const QUnixSocketMessage & other)
+: d(other.d)
+{
+}
+
+/*!
+ \fn QUnixSocketMessage::QUnixSocketMessage(const iovec* data, int vecLen)
+
+ Construct a QUnixSocketMessage with an initial data payload of \a
+ data which points to an array of \a vecLen iovec structures. The
+ message's credentials will be set to the application's default
+ credentials.
+
+ This method can be used to avoid the overhead of copying buffers of data
+ and will directly send the data pointed to by \a data on the socket. It also
+ avoids the syscall overhead of making a number of small socket write calls,
+ if a number of data items can be delivered with one write.
+
+ Caller must ensure the iovec * \a data remains valid until the message
+ is flushed. Caller retains ownership of the iovec structs.
+ */
+QUnixSocketMessage::QUnixSocketMessage(const ::iovec* data, int vecLen )
+: d(new QUnixSocketMessagePrivate())
+{
+ for ( int v = 0; v < vecLen; v++ )
+ d->dataSize += data[v].iov_len;
+ d->vec = const_cast<iovec*>(data);
+ d->iovecLen = vecLen;
+}
+
+/*!
+ Assign the contents of \a other to this object.
+ */
+QUnixSocketMessage & QUnixSocketMessage::operator=(const QUnixSocketMessage & other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Destroy this instance.
+ */
+QUnixSocketMessage::~QUnixSocketMessage()
+{
+}
+
+/*!
+ Set the data portion of the message to \a bytes.
+
+ \sa QUnixSocketMessage::bytes()
+ */
+void QUnixSocketMessage::setBytes(const QByteArray & bytes)
+{
+ d.detach();
+ d->bytes = bytes;
+}
+
+/*!
+ Set the rights portion of the message to \a rights.
+
+ A message with rights data but an empty byte data payload cannot be
+ transmitted by the system.
+
+ \sa QUnixSocketMessage::rights()
+ */
+void QUnixSocketMessage::setRights(const QList<QUnixSocketRights> & rights)
+{
+ d.detach();
+ d->rights = rights;
+}
+
+/*!
+ Return the rights portion of the message.
+
+ \sa QUnixSocketMessage::setRights()
+ */
+const QList<QUnixSocketRights> & QUnixSocketMessage::rights() const
+{
+ return d->rights;
+}
+
+/*!
+ Returns true if the rights portion of the message was truncated on reception
+ due to insufficient buffer size. The rights buffer size can be adjusted
+ through calls to the \l QUnixSocket::setRightsBufferSize() method.
+ \l QUnixSocket contains a discussion of the buffering and truncation
+ characteristics of the Unix domain protocol.
+
+ \sa QUnixSocket QUnixSocket::setRightsBufferSize()
+ */
+bool QUnixSocketMessage::rightsWereTruncated() const
+{
+ return d->state & QUnixSocketMessagePrivate::Truncated;
+}
+
+/*!
+ Return the data portion of the message.
+
+ \sa QUnixSocketMessage::setBytes()
+ */
+const QByteArray & QUnixSocketMessage::bytes() const
+{
+ return d->bytes;
+}
+
+/*!
+ Returns the process id credential associated with this message.
+
+ \sa QUnixSocketMessage::setProcessId()
+ */
+pid_t QUnixSocketMessage::processId() const
+{
+ if(QUnixSocketMessagePrivate::Credential & d->state)
+ return d->pid;
+ else
+ return ::getpid();
+}
+
+/*!
+ Returns the user id credential associated with this message.
+
+ \sa QUnixSocketMessage::setUserId()
+ */
+uid_t QUnixSocketMessage::userId() const
+{
+ if(QUnixSocketMessagePrivate::Credential & d->state)
+ return d->uid;
+ else
+ return ::geteuid();
+}
+
+/*!
+ Returns the group id credential associated with this message.
+
+ \sa QUnixSocketMessage::setGroupId()
+ */
+gid_t QUnixSocketMessage::groupId() const
+{
+ if(QUnixSocketMessagePrivate::Credential & d->state)
+ return d->gid;
+ else
+ return ::getegid();
+}
+
+/*!
+ Set the process id credential associated with this message to \a pid. Unless
+ you are the root user, setting a fraudulant credential will cause this message
+ to fail.
+
+ \sa QUnixSocketMessage::processId()
+ */
+void QUnixSocketMessage::setProcessId(pid_t pid)
+{
+ if(!(d->state & QUnixSocketMessagePrivate::Credential)) {
+ d->state = (QUnixSocketMessagePrivate::AncillaryDataState)( d->state | QUnixSocketMessagePrivate::Credential );
+ d->uid = ::geteuid();
+ d->gid = ::getegid();
+ }
+ d->pid = pid;
+}
+
+/*!
+ Set the user id credential associated with this message to \a uid. Unless
+ you are the root user, setting a fraudulant credential will cause this message
+ to fail.
+
+ \sa QUnixSocketMessage::userId()
+ */
+void QUnixSocketMessage::setUserId(uid_t uid)
+{
+ if(!(d->state & QUnixSocketMessagePrivate::Credential)) {
+ d->state = (QUnixSocketMessagePrivate::AncillaryDataState)( d->state | QUnixSocketMessagePrivate::Credential );
+ d->pid = ::getpid();
+ d->gid = ::getegid();
+ }
+ d->uid = uid;
+}
+
+/*!
+ Set the group id credential associated with this message to \a gid. Unless
+ you are the root user, setting a fraudulant credential will cause this message
+ to fail.
+
+ \sa QUnixSocketMessage::groupId()
+ */
+void QUnixSocketMessage::setGroupId(gid_t gid)
+{
+ if(!(d->state & QUnixSocketMessagePrivate::Credential)) {
+ d->state = (QUnixSocketMessagePrivate::AncillaryDataState)( d->state | QUnixSocketMessagePrivate::Credential );
+ d->pid = ::getpid();
+ d->uid = ::geteuid();
+ }
+ d->gid = gid;
+}
+
+/*!
+ Return true if this message is valid. A message with rights data but an empty
+ byte data payload cannot be transmitted by the system and is marked as
+ invalid.
+ */
+bool QUnixSocketMessage::isValid() const
+{
+ return d->rights.isEmpty() || !d->bytes.isEmpty();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// class QUnixSocket
+///////////////////////////////////////////////////////////////////////////////
+#define QUNIXSOCKET_DEFAULT_READBUFFER 1024
+#define QUNIXSOCKET_DEFAULT_ANCILLARYBUFFER 0
+
+/*!
+ \class QUnixSocket
+ \internal
+
+ \brief The QUnixSocket class provides a Unix domain socket.
+
+ \omit
+ \ingroup Platform::DeviceSpecific
+ \ingroup Platform::OS
+ \ingroup Platform::Communications
+ \endomit
+ \ingroup qws
+
+ Unix domain sockets provide an efficient mechanism for communications between
+ Unix processes on the same machine. Unix domain sockets support a reliable,
+ stream-oriented, connection-oriented transport protocol, much like TCP
+ sockets. Unlike IP based sockets, the connection endpoint of a Unix domain
+ socket is a file on disk of type socket.
+
+ In addition to transporting raw data bytes, Unix domain sockets are able to
+ transmit special ancillary data. The two types of ancillary data supported
+ by the QUnixSocket class are:
+
+ \list
+ \o Credential Data - Allows a receiver
+ to reliably identify the process sending each message.
+ \o \l {QUnixSocketRights}{Rights Data } - Allows Unix file descriptors
+ to be transmitted between processes.
+ \endlist
+
+ Because of the need to support ancillary data, QUnixSocket is not a QIODevice,
+ like QTcpSocket and QUdpSocket. Instead, QUnixSocket contains a number of
+ read and write methods that clients must invoke directly. Rather than
+ returning raw data bytes, \l QUnixSocket::read() returns \l QUnixSocketMessage
+ instances that encapsulate the message's byte data and any other ancillary
+ data.
+
+ Ancillary data is transmitted "out of band". Every \l QUnixSocketMessage
+ received will have credential data associated with it that the client can
+ access through calls to \l QUnixSocketMessage::processId(),
+ \l QUnixSocketMessage::groupId() and \l QUnixSocketMessage::userId().
+ Likewise, message creators can set the credential data to send through calls
+ to \l QUnixSocketMessage::setProcessId(), \l QUnixSocketMessage::setGroupId()
+ and \l QUnixSocketMessage::setUserId() respectively. The authenticity of the
+ credential values is verified by the system kernel and cannot be fabricated
+ by unprivileged processes. Only processes running as the root user can
+ specify credential data that does not match the sending process.
+
+ Unix file descriptors, known as "rights data", transmitted between processes
+ appear as though they had been dup(2)'d between the two. As Unix
+ domain sockets present a continuous stream of bytes to the receiver, the
+ rights data - which is transmitted out of band - must be "slotted" in at some
+ point. The rights data is logically associated with the first byte - called
+ the anchor byte - of the \l QUnixSocketMessage to which they are attached.
+ Received rights data will be available from the
+ \l QUnixSocketMessage::rights() method for the \l QUnixSocketMessage
+ instance that contains the anchor byte.
+
+ In addition to a \l QUnixSocket::write() that takes a \l QUnixSocketMessage
+ instance - allowing a client to transmit both byte and rights data - a
+ number of convenience overloads are provided for use when only transmitting
+ simple byte data. Unix requires that at least one byte of raw data be
+ transmitted in order to send rights data. A \l QUnixSocketMessage instance
+ with rights data, but no byte data, cannot be transmitted.
+
+ Unix sockets present a stream interface, such that, for example, a single
+ six byte transmission might be received as two three byte messages. Rights
+ data, on the other hand, is conceptually transmitted as unfragmentable
+ datagrams. If the receiving buffer is not large enough to contain all the
+ transmitted rights information, the data is truncated and irretreivably lost.
+ Users should use the \l QUnixSocket::setRightsBufferSize() method to control
+ the buffer size used for this data, and develop protocols that avoid the
+ problem. If the buffer size is too small and rights data is truncated,
+ the \l QUnixSocketMessage::rightsWereTruncated() flag will be set.
+
+ \sa QUnixSocketMessage QUnixSocketRights
+*/
+
+/*!
+ \enum QUnixSocket::SocketError
+
+ The SocketError enumeration represents the various errors that can occur on
+ a Unix domain socket. The most recent error for the socket is available
+ through the \l QUnixSocket::error() method.
+
+ \value NoError No error has occurred.
+ \value InvalidPath An invalid path endpoint was passed to
+ \l QUnixSocket::connect(). As defined by unix(7), invalid paths
+ include an empty path, or what more than 107 characters long.
+ \value ResourceError An error acquiring or manipulating the system's socket
+ resources occurred. For example, if the process runs out of available
+ socket descriptors, a ResourceError will occur.
+ \value NonexistentPath The endpoing passed to \l QUnixSocket::connect() does
+ not refer to a Unix domain socket entity on disk.
+ \value ConnectionRefused The connection to the specified endpoint was refused.
+ Generally this means that there is no server listening on that
+ endpoint.
+ \value UnknownError An unknown error has occurred.
+ \value ReadFailure An error occurred while reading bytes from the connection.
+ \value WriteFailure An error occurred while writing bytes into the connection.
+ */
+
+/*!
+ \enum QUnixSocket::SocketState
+
+ The SocketState enumeration represents the connection state of a QUnixSocket
+ instance.
+
+ \value UnconnectedState The connection is not established.
+ \value ConnectedState The connection is established.
+ \value ClosingState The connection is being closed, following a call to
+ \l QUnixSocket::close(). While closing, any pending data will be
+ transmitted, but further writes by the application will be refused.
+ */
+
+/*
+ \fn QUnixSocket::bytesWritten(qint64 bytes)
+
+ This signal is emitted every time a payload of data has been written to the
+ connection. The \a bytes argument is set to the number of bytes that were
+ written in this payload.
+
+ \sa QUnixSocket::readyRead()
+*/
+
+/*
+ \fn QUnixSocket::readyRead()
+
+ This signal is emitted once every time new data is available for reading from
+ the connection. It will only be emitted again once new data is available.
+
+ \sa QUnixSocket::bytesWritten()
+*/
+
+/*!
+ \fn QUnixSocket::stateChanged(SocketState socketState)
+
+ This signal is emitted each time the socket changes connection state.
+ \a socketState will be set to the socket's new state.
+*/
+
+class QUnixSocketPrivate : public QObject {
+Q_OBJECT
+public:
+ QUnixSocketPrivate(QUnixSocket * _me)
+ : me(_me), fd(-1), readNotifier(0), writeNotifier(0),
+ state(QUnixSocket::UnconnectedState), error(QUnixSocket::NoError),
+ writeQueueBytes(0), messageValid(false), dataBuffer(0),
+ dataBufferLength(0), dataBufferCapacity(0), ancillaryBuffer(0),
+ ancillaryBufferCount(0), closingTimer(0) {
+ QObject::connect(this, SIGNAL(readyRead()), me, SIGNAL(readyRead()));
+ QObject::connect(this, SIGNAL(bytesWritten(qint64)),
+ me, SIGNAL(bytesWritten(qint64)));
+ }
+ ~QUnixSocketPrivate()
+ {
+ if(dataBuffer)
+ delete [] dataBuffer;
+ if(ancillaryBuffer)
+ delete [] ancillaryBuffer;
+ }
+
+ enum { CausedAbort = 0x70000000 };
+
+ QUnixSocket * me;
+
+ int fd;
+
+ QSocketNotifier * readNotifier;
+ QSocketNotifier * writeNotifier;
+
+ QUnixSocket::SocketState state;
+ QUnixSocket::SocketError error;
+
+ QQueue<QUnixSocketMessage> writeQueue;
+ unsigned int writeQueueBytes;
+
+ bool messageValid;
+ ::msghdr message;
+ inline void flushAncillary()
+ {
+ if(!messageValid) return;
+ ::cmsghdr * h = (::cmsghdr *)CMSG_FIRSTHDR(&(message));
+ while(h) {
+
+ if(SCM_RIGHTS == h->cmsg_type) {
+ int * fds = (int *)CMSG_DATA(h);
+ int numFds = (h->cmsg_len - CMSG_LEN(0)) / sizeof(int);
+
+ for(int ii = 0; ii < numFds; ++ii)
+ ::close(fds[ii]);
+ }
+
+ h = (::cmsghdr *)CMSG_NXTHDR(&(message), h);
+ }
+
+ messageValid = false;
+ }
+
+
+ char * dataBuffer;
+ unsigned int dataBufferLength;
+ unsigned int dataBufferCapacity;
+
+ char * ancillaryBuffer;
+ inline unsigned int ancillaryBufferCapacity()
+ {
+ return CMSG_SPACE(sizeof(::ucred)) + CMSG_SPACE(sizeof(int) * ancillaryBufferCount);
+ }
+ unsigned int ancillaryBufferCount;
+
+ QByteArray address;
+
+ int closingTimer;
+
+ virtual void timerEvent(QTimerEvent *)
+ {
+ me->abort();
+ killTimer(closingTimer);
+ closingTimer = 0;
+ }
+signals:
+ void readyRead();
+ void bytesWritten(qint64);
+
+public slots:
+ void readActivated();
+ qint64 writeActivated();
+};
+
+/*!
+ Construct a QUnixSocket instance, with \a parent.
+
+ The read buffer is initially set to 1024 bytes, and the rights buffer to 0
+ entries.
+
+ \sa QUnixSocket::readBufferSize() QUnixSocket::rightsBufferSize()
+ */
+QUnixSocket::QUnixSocket(QObject * parent)
+: QIODevice(parent), d(new QUnixSocketPrivate(this))
+{
+ setOpenMode(QIODevice::NotOpen);
+ setReadBufferSize(QUNIXSOCKET_DEFAULT_READBUFFER);
+ setRightsBufferSize(QUNIXSOCKET_DEFAULT_ANCILLARYBUFFER);
+}
+
+/*!
+ Construct a QUnixSocket instance, with \a parent.
+
+ The read buffer is initially set to \a readBufferSize bytes, and the rights
+ buffer to \a rightsBufferSize entries.
+
+ \sa QUnixSocket::readBufferSize() QUnixSocket::rightsBufferSize()
+ */
+QUnixSocket::QUnixSocket(qint64 readBufferSize, qint64 rightsBufferSize,
+ QObject * parent)
+: QIODevice(parent), d(new QUnixSocketPrivate(this))
+{
+ Q_ASSERT(readBufferSize > 0 && rightsBufferSize >= 0);
+
+ setOpenMode(QIODevice::NotOpen);
+ setReadBufferSize(readBufferSize);
+ setRightsBufferSize(rightsBufferSize);
+}
+
+/*!
+ Destroys the QUnixSocket instance. Any unsent data is discarded.
+ */
+QUnixSocket::~QUnixSocket()
+{
+ abort();
+ delete d;
+}
+
+/*!
+ Attempt to connect to \a path.
+
+ This method is synchronous and will return true if the connection succeeds and
+ false otherwise. In the case of failure, \l QUnixSocket::error() will be set
+ accordingly.
+
+ Any existing connection will be aborted, and all pending data will be
+ discarded.
+
+ \sa QUnixSocket::close() QUnixSocket::abort() QUnixSocket::error()
+ */
+bool QUnixSocket::connect(const QByteArray & path)
+{
+ int _true;
+ int crv;
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug() << "QUnixSocket: Connect requested to '"
+ << path << "'";
+#endif
+
+ abort(); // Reset any existing connection
+
+ if(UnconnectedState != d->state) // abort() caused a signal and someone messed
+ // with us. We'll assume they know what
+ // they're doing and bail. Alternative is to
+ // have a special "Connecting" state
+ return false;
+
+
+ if(path.isEmpty() || path.size() > UNIX_PATH_MAX) {
+ d->error = InvalidPath;
+ return false;
+ }
+
+ // Create the socket
+ d->fd = ::socket(PF_UNIX, SOCK_STREAM, 0);
+ if(-1 == d->fd) {
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug() << "QUnixSocket: Unable to create socket ("
+ << strerror(errno) << ")";
+#endif
+ d->error = ResourceError;
+ goto connect_error;
+ }
+
+ // Set socket options
+ _true = 1;
+ crv = ::setsockopt(d->fd, SOL_SOCKET, SO_PASSCRED, (void *)&_true,
+ sizeof(int));
+ if(-1 == crv) {
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug() << "QUnixSocket: Unable to configure socket ("
+ << ::strerror(errno) << ")";
+#endif
+ d->error = ResourceError;
+
+ goto connect_error;
+ }
+
+ // Construct our unix address
+ struct ::sockaddr_un addr;
+ addr.sun_family = AF_UNIX;
+ ::memcpy(addr.sun_path, path.data(), path.size());
+ if(path.size() < UNIX_PATH_MAX)
+ addr.sun_path[path.size()] = '\0';
+
+ // Attempt the connect
+ crv = ::connect(d->fd, (sockaddr *)&addr, sizeof(sockaddr_un));
+ if(-1 == crv) {
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug() << "QUnixSocket: Unable to connect ("
+ << ::strerror(errno) << ")";
+#endif
+ if(ECONNREFUSED == errno)
+ d->error = ConnectionRefused;
+ else if(ENOENT == errno)
+ d->error = NonexistentPath;
+ else
+ d->error = UnknownError;
+
+ goto connect_error;
+ }
+
+ // We're connected!
+ d->address = path;
+ d->state = ConnectedState;
+ d->readNotifier = new QSocketNotifier(d->fd, QSocketNotifier::Read, d);
+ d->writeNotifier = new QSocketNotifier(d->fd, QSocketNotifier::Write, d);
+ QObject::connect(d->readNotifier, SIGNAL(activated(int)),
+ d, SLOT(readActivated()));
+ QObject::connect(d->writeNotifier, SIGNAL(activated(int)),
+ d, SLOT(writeActivated()));
+ d->readNotifier->setEnabled(true);
+ d->writeNotifier->setEnabled(false);
+ setOpenMode(QIODevice::ReadWrite);
+ emit stateChanged(ConnectedState);
+
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug() << "QUnixSocket: Connected to " << path;
+#endif
+ return true;
+
+connect_error: // Cleanup failed connection
+ if(-1 != d->fd) {
+#ifdef QUNIXSOCKET_DEBUG
+ int closerv =
+#endif
+ ::close(d->fd);
+#ifdef QUNIXSOCKET_DEBUG
+ if(0 != closerv) {
+ qDebug() << "QUnixSocket: Unable to close file descriptor after "
+ "failed connect (" << ::strerror(errno) << ")";
+ }
+#endif
+ }
+ d->fd = -1;
+ return false;
+}
+
+/*!
+ Sets the socket descriptor to use to \a socketDescriptor, bypassing
+ QUnixSocket's connection infrastructure, and return true on success and false
+ on failure. \a socketDescriptor must be in the connected state, and must be
+ a Unix domain socket descriptor. Following a successful call to this method,
+ the QUnixSocket instance will be in the Connected state and will have assumed
+ ownership of \a socketDescriptor.
+
+ Any existing connection will be aborted, and all pending data will be
+ discarded.
+
+ \sa QUnixSocket::connect()
+*/
+bool QUnixSocket::setSocketDescriptor(int socketDescriptor)
+{
+ abort();
+
+ if(UnconnectedState != state()) // See QUnixSocket::connect()
+ return false;
+
+ // Attempt to set the socket options
+ if(-1 == socketDescriptor) {
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug() << "QUnixSocket: User provided socket is invalid";
+#endif
+ d->error = ResourceError;
+ return false;
+ }
+
+ // Set socket options
+ int _true = 1;
+ int crv = ::setsockopt(socketDescriptor, SOL_SOCKET,
+ SO_PASSCRED, (void *)&_true, sizeof(int));
+ if(-1 == crv) {
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug() << "QUnixSocket: Unable to configure client provided socket ("
+ << ::strerror(errno) << ")";
+#endif
+ d->error = ResourceError;
+
+ return false;
+ }
+
+ d->fd = socketDescriptor;
+ d->state = ConnectedState;
+ d->address = QByteArray();
+ setOpenMode(QIODevice::ReadWrite);
+ d->readNotifier = new QSocketNotifier(d->fd, QSocketNotifier::Read, d);
+ d->writeNotifier = new QSocketNotifier(d->fd, QSocketNotifier::Write, d);
+ QObject::connect(d->readNotifier, SIGNAL(activated(int)),
+ d, SLOT(readActivated()));
+ QObject::connect(d->writeNotifier, SIGNAL(activated(int)),
+ d, SLOT(writeActivated()));
+ d->readNotifier->setEnabled(true);
+ d->writeNotifier->setEnabled(false);
+ emit stateChanged(d->state);
+
+ return true;
+}
+
+/*!
+ Returns the socket descriptor currently in use. This method will return -1
+ if the QUnixSocket instance is in the UnconnectedState \l {QUnixSocket::state()}{state. }
+
+ \sa QUnixSocket::setSocketDescriptor()
+ */
+int QUnixSocket::socketDescriptor() const
+{
+ return d->fd;
+}
+
+/*!
+ Abort the connection. This will immediately disconnect (if connected) and
+ discard any pending data. Following a call to QUnixSocket::abort() the
+ object will always be in the disconnected \link QUnixSocket::state() state.
+ \endlink
+
+ \sa QUnixSocket::close()
+*/
+void QUnixSocket::abort()
+{
+ setOpenMode(QIODevice::NotOpen);
+
+ // We want to be able to use QUnixSocket::abort() to cleanup our state but
+ // also preserve the error message that caused the abort. It is not
+ // possible to reorder code to do this:
+ // abort();
+ // d->error = SomeError
+ // as QUnixSocket::abort() might emit a signal and we need the error to be
+ // set within that signal. So, if we want an error message to be preserved
+ // across a *single* call to abort(), we set the
+ // QUnixSocketPrivate::CausedAbort flag in the error.
+ if(d->error & QUnixSocketPrivate::CausedAbort)
+ d->error = (QUnixSocket::SocketError)(d->error &
+ ~QUnixSocketPrivate::CausedAbort);
+ else
+ d->error = NoError;
+
+ if( UnconnectedState == d->state) return;
+
+#ifdef QUNIXSOCKET_DEBUG
+ int closerv =
+#endif
+ ::close(d->fd);
+#ifdef QUNIXSOCKET_DEBUG
+ if(0 != closerv) {
+ qDebug() << "QUnixSocket: Unable to close socket during abort ("
+ << strerror(errno) << ")";
+ }
+#endif
+
+ // Reset variables
+ d->fd = -1;
+ d->state = UnconnectedState;
+ d->dataBufferLength = 0;
+ d->flushAncillary();
+ d->address = QByteArray();
+ if(d->readNotifier) {
+ d->readNotifier->setEnabled(false);
+ d->readNotifier->deleteLater();
+ }
+ if(d->writeNotifier) {
+ d->writeNotifier->setEnabled(false);
+ d->writeNotifier->deleteLater();
+ }
+ d->readNotifier = 0;
+ d->writeNotifier = 0;
+ d->writeQueue.clear();
+ d->writeQueueBytes = 0;
+ if(d->closingTimer) {
+ d->killTimer(d->closingTimer);
+ }
+ d->closingTimer = 0;
+ emit stateChanged(d->state);
+}
+
+/*!
+ Close the connection. The instance will enter the Closing
+ \l {QUnixSocket::state()}{state } until all pending data has been
+ transmitted, at which point it will enter the Unconnected state.
+
+ Even if there is no pending data for transmission, the object will never
+ jump directly to Disconnect without first passing through the
+ Closing state.
+
+ \sa QUnixSocket::abort()
+ */
+void QUnixSocket::close()
+{
+ if(ConnectedState != state()) return;
+
+ d->state = ClosingState;
+ if(d->writeQueue.isEmpty()) {
+ d->closingTimer = d->startTimer(0); // Start a timer to "fake"
+ // completing writes
+ }
+ emit stateChanged(d->state);
+}
+
+/*!
+ This function writes as much as possible from the internal write buffer to
+ the underlying socket, without blocking. If any data was written, this
+ function returns true; otherwise false is returned.
+*/
+// Note! docs partially copied from QAbstractSocket::flush()
+bool QUnixSocket::flush()
+{
+ // This needs to have the same semantics as QAbstractSocket, if it is to
+ // be used interchangeably with that class.
+ if (d->writeQueue.isEmpty())
+ return false;
+
+ d->writeActivated();
+ return true;
+}
+
+/*!
+ Returns the last error to have occurred on this object. This method is not
+ destructive, so multiple calls to QUnixSocket::error() will return the same
+ value. The error is only reset by a call to \l QUnixSocket::connect() or
+ \l QUnixSocket::abort()
+ */
+QUnixSocket::SocketError QUnixSocket::error() const
+{
+ return (QUnixSocket::SocketError)
+ (d->error & ~QUnixSocketPrivate::CausedAbort);
+}
+
+/*!
+ Returns the connection state of this instance.
+ */
+QUnixSocket::SocketState QUnixSocket::state() const
+{
+ return d->state;
+}
+
+/*!
+ Returns the Unix path address passed to \l QUnixSocket::connect(). This
+ method will return an empty path if the object is in the Unconnected
+ \l {QUnixSocket::state()}{state } or was connected through a call
+ to \l QUnixSocket::setSocketDescriptor()
+
+ \sa QUnixSocket::connect() QUnixSocket::setSocketDescriptor()
+ */
+QByteArray QUnixSocket::address() const
+{
+ return d->address;
+}
+
+/*!
+ Returns the number of bytes available for immediate retrieval through a call
+ to \l QUnixSocket::read().
+ */
+qint64 QUnixSocket::bytesAvailable() const
+{
+ return QIODevice::bytesAvailable() + d->dataBufferLength;
+}
+
+/*!
+ Returns the number of enqueued bytes still to be written to the socket.
+ */
+qint64 QUnixSocket::bytesToWrite() const
+{
+ return d->writeQueueBytes;
+}
+
+/*!
+ Returns the size of the read buffer in bytes. The read buffer size
+ determines the amount of byte data that can be read from the socket in one go.
+ The read buffer size caps the maximum value that can be returned by
+ \l QUnixSocket::bytesAvailable() and will always be greater than zero. By
+ default, the read buffer size is 1024 bytes.
+
+ The size of the read buffer is independent of the rights buffer, which can be
+ queried by \l QUnixSocket::rightsBufferSize().
+
+ \sa QUnixSocket::setReadBufferSize()
+ */
+qint64 QUnixSocket::readBufferSize() const
+{
+ return d->dataBufferCapacity;
+}
+
+/*!
+ Sets the \a size of the socket's read buffer in bytes.
+
+ The size of the read buffer is independent of the rights buffer, which can be
+ set by \l QUnixSocket::setRightsBufferSize().
+
+ Attempting to reduce the buffer size while bytes are available for reading
+ (ie. while the buffer is in use) will fail.
+
+ \sa QUnixSocket::readBufferSize()
+ */
+void QUnixSocket::setReadBufferSize(qint64 size)
+{
+ Q_ASSERT(size > 0);
+ if(size == d->dataBufferCapacity || d->dataBufferLength) return;
+ if(d->dataBuffer) delete [] d->dataBuffer;
+ d->dataBuffer = new char[size];
+ d->dataBufferCapacity = size;
+}
+
+/*!
+ Returns the size of the rights buffer in rights entries. The rights buffer
+ size determines the number of rights transferences that can be received in
+ any message. Unlike byte stream data which can be fragmented into many
+ smaller messages if the \link QUnixSocket::readBufferSize() read buffer
+ \endlink is not large enough to contain all the available data, rights data
+ is transmitted as unfragmentable datagrams. If the rights buffer is not
+ large enough to contain this unfragmentable datagram, the datagram will be
+ truncated and rights data irretrievably lost. If truncation occurs, the
+ \l QUnixSocketMessage::rightsWereTruncated() flag will be set. By default
+ the rights buffer size is 0 entries - rights data cannot be received.
+
+ The size of the rights buffer is independent of the read buffer, which can be
+ queried by \l QUnixSocket::readBufferSize().
+
+ \sa QUnixSocket::setRightsBufferSize()
+ */
+qint64 QUnixSocket::rightsBufferSize() const
+{
+ return d->ancillaryBufferCount;
+}
+
+/*!
+ Sets the \a size of the socket's rights buffer in rights entries.
+
+ The size of the rights buffer is independent of the read buffer, which can be
+ set by \l QUnixSocket::setReadBufferSize().
+
+ Attempting to reduce the buffer size while bytes are available for reading
+ (ie. while the buffer is in use) will fail.
+
+ \sa QUnixSocket::rightsBufferSize()
+ */
+void QUnixSocket::setRightsBufferSize(qint64 size)
+{
+ Q_ASSERT(size >= 0);
+
+ if((size == d->ancillaryBufferCount || d->dataBufferLength) &&
+ d->ancillaryBuffer)
+ return;
+
+ qint64 byteSize = CMSG_SPACE(sizeof(::ucred)) +
+ CMSG_SPACE(size * sizeof(int));
+
+ if(d->ancillaryBuffer) delete [] d->ancillaryBuffer;
+ d->ancillaryBuffer = new char[byteSize];
+ d->ancillaryBufferCount = size;
+}
+
+/*!
+ \overload
+
+ Writes \a socketdata to the socket. In addition to failing if the socket
+ is not in the Connected state, writing will fail if \a socketdata is
+ \l {QUnixSocketMessage::isValid()}{invalid. }
+
+ Writes through the QUnixSocket class are asynchronous. Rather than being
+ written immediately, data is enqueued and written once the application
+ reenters the Qt event loop and the socket becomes available for writing.
+ Thus, this method will only fail if the socket is not in the Connected state
+ - it is illegal to attempt a write on a Unconnected or Closing socket.
+
+ Applications can monitor the progress of data writes through the
+ \l QUnixSocket::bytesWritten() signal and \l QUnixSocket::bytesToWrite()
+ method.
+
+ \sa QUnixSocketMessage
+ */
+qint64 QUnixSocket::write(const QUnixSocketMessage & socketdata)
+{
+ if(ConnectedState != state() || !socketdata.isValid()) return -1;
+ if(socketdata.d->size() == 0) return 0;
+
+ d->writeQueue.enqueue(socketdata);
+ d->writeQueueBytes += socketdata.d->size();
+ d->writeNotifier->setEnabled(true);
+
+ return socketdata.d->size();
+}
+
+/*!
+ Return the next available message, or an empty message if none is available.
+
+ To avoid retrieving empty messages, applications should connect to the
+ \l QUnixSocket::readyRead() signal to be notified when new messages are
+ available or periodically poll the \l QUnixSocket::bytesAvailable() method.
+
+ \sa QUnixSocket::readyRead() QUnixSocket::bytesAvailable()
+ */
+QUnixSocketMessage QUnixSocket::read()
+{
+ QUnixSocketMessage data;
+ if(!d->dataBufferLength)
+ return data;
+
+ data.d->state = QUnixSocketMessagePrivate::Credential;
+
+ // Bytes are easy
+ data.setBytes(QByteArray(d->dataBuffer, d->dataBufferLength));
+
+ // Extract ancillary data
+ QList<QUnixSocketRights> a;
+
+ ::cmsghdr * h = (::cmsghdr *)CMSG_FIRSTHDR(&(d->message));
+ while(h) {
+
+ if(SCM_CREDENTIALS == h->cmsg_type) {
+ ::ucred * cred = (::ucred *)CMSG_DATA(h);
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug( "Credentials recd: pid %lu - gid %lu - uid %lu",
+ cred->pid, cred->gid, cred->uid );
+#endif
+ data.d->pid = cred->pid;
+ data.d->gid = cred->gid;
+ data.d->uid = cred->uid;
+
+ } else if(SCM_RIGHTS == h->cmsg_type) {
+
+ int * fds = (int *)CMSG_DATA(h);
+ int numFds = (h->cmsg_len - CMSG_LEN(0)) / sizeof(int);
+
+ for(int ii = 0; ii < numFds; ++ii) {
+ QUnixSocketRights qusr(fds[ii], 0);
+ a.append(qusr);
+ }
+
+ } else {
+
+#ifdef QUNIXSOCKET_DEBUG
+ qFatal("QUnixSocket: Unknown ancillary data type (%d) received.",
+ h->cmsg_type);
+#endif
+
+ }
+
+ h = (::cmsghdr *)CMSG_NXTHDR(&(d->message), h);
+ }
+
+ if(d->message.msg_flags & MSG_CTRUNC) {
+ data.d->state = (QUnixSocketMessagePrivate::AncillaryDataState)(QUnixSocketMessagePrivate::Truncated |
+ QUnixSocketMessagePrivate::Credential );
+ }
+
+ if(!a.isEmpty())
+ data.d->rights = a;
+
+ d->dataBufferLength = 0;
+ d->messageValid = false;
+ d->readNotifier->setEnabled(true);
+
+ return data;
+}
+
+/*! \internal */
+bool QUnixSocket::isSequential() const
+{
+ return true;
+}
+
+/*! \internal */
+bool QUnixSocket::waitForReadyRead(int msecs)
+{
+ if(UnconnectedState == d->state)
+ return false;
+
+ if(d->messageValid) {
+ return true;
+ }
+
+ Q_ASSERT(-1 != d->fd);
+
+ int timeout = msecs;
+ struct timeval tv;
+ struct timeval *ptrTv = 0;
+ QTime stopWatch;
+
+ stopWatch.start();
+
+ do
+ {
+ fd_set readset;
+
+ FD_ZERO(&readset);
+ FD_SET(d->fd, &readset);
+
+ if(-1 != msecs) {
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ ptrTv = &tv;
+ }
+
+ int rv = ::select(d->fd + 1, &readset, 0, 0, ptrTv);
+ switch(rv) {
+ case 0:
+ // timeout
+ return false;
+ case 1:
+ // ok
+ d->readActivated();
+ return true;
+ default:
+ if (errno != EINTR)
+ abort(); // error
+ break;
+ }
+
+ timeout = msecs - stopWatch.elapsed();
+ }
+ while (timeout > 0);
+
+ return false;
+}
+
+bool QUnixSocket::waitForBytesWritten(int msecs)
+{
+ if(UnconnectedState == d->state)
+ return false;
+
+ Q_ASSERT(-1 != d->fd);
+
+ if ( d->writeQueue.isEmpty() )
+ return true;
+
+ QTime stopWatch;
+ stopWatch.start();
+
+ while ( true )
+ {
+ fd_set fdwrite;
+ FD_ZERO(&fdwrite);
+ FD_SET(d->fd, &fdwrite);
+ int timeout = msecs < 0 ? 0 : msecs - stopWatch.elapsed();
+ struct timeval tv;
+ struct timeval *ptrTv = 0;
+ if ( -1 != msecs )
+ {
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout % 1000) * 1000;
+ ptrTv = &tv;
+ }
+
+ int rv = ::select(d->fd + 1, 0, &fdwrite, 0, ptrTv);
+ switch ( rv )
+ {
+ case 0:
+ // timeout
+ return false;
+ case 1:
+ {
+ // ok to write
+ qint64 bytesWritten = d->writeActivated();
+ if (bytesWritten == 0) {
+ // We need to retry
+ int delay = 1;
+ do {
+ if (-1 != msecs) {
+ timeout = msecs - stopWatch.elapsed();
+ if (timeout <= 0) {
+ // We have exceeded our allotted time
+ return false;
+ } else {
+ if (delay > timeout)
+ delay = timeout;
+ }
+ }
+
+ // Pause before we make another attempt to send
+ ::usleep(delay * 1000);
+ if (delay < 1024)
+ delay *= 2;
+
+ bytesWritten = d->writeActivated();
+ } while (bytesWritten == 0);
+ }
+ return (bytesWritten != -1);
+ }
+ default:
+ // error - or an uncaught signal!!!!!!!!!
+ if ( rv == EINTR )
+ continue;
+ abort();
+ return false;
+ }
+ }
+ return false; // fix warnings
+}
+
+/*! \internal */
+bool QUnixSocket::canReadLine() const
+{
+ for(unsigned int ii = 0; ii < d->dataBufferLength; ++ii)
+ if(d->dataBuffer[ii] == '\n') return true;
+ return false;
+}
+
+/*! \internal */
+qint64 QUnixSocket::readData(char * data, qint64 maxSize)
+{
+ Q_ASSERT(data);
+ if(0 >= maxSize) return 0;
+ if(!d->dataBufferLength) return 0;
+
+ // Read data
+ unsigned int size = d->dataBufferLength>maxSize?maxSize:d->dataBufferLength;
+ memcpy(data, d->dataBuffer, size);
+ if(size == d->dataBufferLength) {
+ d->dataBufferLength = 0;
+ } else {
+ memmove(d->dataBuffer, d->dataBuffer + size, d->dataBufferLength - size);
+ d->dataBufferLength -= size;
+ }
+
+
+ // Flush ancillary
+ d->flushAncillary();
+
+ if(0 == d->dataBufferLength)
+ d->readNotifier->setEnabled(true);
+
+ return size;
+}
+
+/*! \internal */
+qint64 QUnixSocket::writeData (const char * data, qint64 maxSize)
+{
+ return write(QUnixSocketMessage(QByteArray(data, maxSize)));
+}
+
+qint64 QUnixSocketPrivate::writeActivated()
+{
+ writeNotifier->setEnabled(false);
+
+ QUnixSocketMessage & m = writeQueue.head();
+ const QList<QUnixSocketRights> & a = m.rights();
+
+ //
+ // Construct the message
+ //
+ ::iovec vec;
+ if ( !m.d->vec ) // message does not already have an iovec
+ {
+ vec.iov_base = (void *)m.bytes().constData();
+ vec.iov_len = m.bytes().size();
+ }
+
+ // Allocate the control buffer
+ ::msghdr sendmessage;
+ ::bzero(&sendmessage, sizeof(::msghdr));
+ if ( m.d->vec )
+ {
+ sendmessage.msg_iov = m.d->vec;
+ sendmessage.msg_iovlen = m.d->iovecLen;
+ }
+ else
+ {
+ sendmessage.msg_iov = &vec;
+ sendmessage.msg_iovlen = 1;
+ }
+ unsigned int required = CMSG_SPACE(sizeof(::ucred)) +
+ a.size() * CMSG_SPACE(sizeof(int));
+ sendmessage.msg_control = new char[required];
+ ::bzero(sendmessage.msg_control, required);
+ sendmessage.msg_controllen = required;
+
+ // Create ancillary buffer
+ ::cmsghdr * h = CMSG_FIRSTHDR(&sendmessage);
+
+ if(m.d->state & QUnixSocketMessagePrivate::Credential) {
+ h->cmsg_len = CMSG_LEN(sizeof(::ucred));
+ h->cmsg_level = SOL_SOCKET;
+ h->cmsg_type = SCM_CREDENTIALS;
+ ((::ucred *)CMSG_DATA(h))->pid = m.d->pid;
+ ((::ucred *)CMSG_DATA(h))->gid = m.d->gid;
+ ((::ucred *)CMSG_DATA(h))->uid = m.d->uid;
+ h = CMSG_NXTHDR(&sendmessage, h);
+ } else {
+ sendmessage.msg_controllen -= CMSG_SPACE(sizeof(::ucred));
+ }
+
+ for(int ii = 0; ii < a.count(); ++ii) {
+ const QUnixSocketRights & r = a.at(ii);
+
+ if(r.isValid()) {
+ h->cmsg_len = CMSG_LEN(sizeof(int));
+ h->cmsg_level = SOL_SOCKET;
+ h->cmsg_type = SCM_RIGHTS;
+ *((int *)CMSG_DATA(h)) = r.peekFd();
+ h = CMSG_NXTHDR(&sendmessage, h);
+ } else {
+ sendmessage.msg_controllen -= CMSG_SPACE(sizeof(int));
+ }
+ }
+
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug() << "QUnixSocket: Transmitting message (length" << m.d->size() << ")";
+#endif
+ ::ssize_t s = ::sendmsg(fd, &sendmessage, MSG_DONTWAIT | MSG_NOSIGNAL);
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug() << "QUnixSocket: Transmitted message (" << s << ")";
+#endif
+
+ if(-1 == s) {
+ if(EAGAIN == errno || EWOULDBLOCK == errno || EINTR == errno) {
+ writeNotifier->setEnabled(true);
+ } else if(EPIPE == errno) {
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug() << "QUnixSocket: Remote side disconnected during transmit "
+ "(" << ::strerror(errno) << ")";
+#endif
+ me->abort();
+ } else {
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug() << "QUnixSocket: Unable to transmit data ("
+ << ::strerror(errno) << ")";
+#endif
+ error = (QUnixSocket::SocketError)(QUnixSocket::WriteFailure |
+ CausedAbort);
+ me->abort();
+ }
+ } else if(s != m.d->size()) {
+
+ // A partial transmission
+ writeNotifier->setEnabled(true);
+ delete [] (char *)sendmessage.msg_control;
+ m.d->rights = QList<QUnixSocketRights>();
+ m.d->removeBytes( s );
+ writeQueueBytes -= s;
+ emit bytesWritten(s);
+ return s;
+
+ } else {
+
+ // Success!
+ writeQueue.dequeue();
+ Q_ASSERT(writeQueueBytes >= (unsigned)s);
+ writeQueueBytes -= s;
+ emit bytesWritten(s);
+
+ }
+
+ delete [] (char *)sendmessage.msg_control;
+ if(-1 != s && !writeQueue.isEmpty())
+ return writeActivated();
+ else if(QUnixSocket::ClosingState == me->state() && writeQueue.isEmpty())
+ me->abort();
+
+ if((-1 == s) && (EAGAIN == errno || EWOULDBLOCK == errno || EINTR == errno))
+ // Return zero bytes written to indicate retry may be required
+ return 0;
+ else
+ return s;
+}
+
+void QUnixSocketPrivate::readActivated()
+{
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug() << "QUnixSocket: readActivated";
+#endif
+ readNotifier->setEnabled(false);
+
+ ::iovec vec;
+ vec.iov_base = dataBuffer;
+ vec.iov_len = dataBufferCapacity;
+
+ bzero(&message, sizeof(::msghdr));
+ message.msg_iov = &vec;
+ message.msg_iovlen = 1;
+ message.msg_controllen = ancillaryBufferCapacity();
+ message.msg_control = ancillaryBuffer;
+
+ int recvrv = ::recvmsg(fd, &message, 0);
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug() << "QUnixSocket: Received message (" << recvrv << ")";
+#endif
+ if(-1 == recvrv) {
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug() << "QUnixSocket: Unable to receive data ("
+ << ::strerror(errno) << ")";
+#endif
+ error = (QUnixSocket::SocketError)(QUnixSocket::ReadFailure |
+ CausedAbort);
+ me->abort();
+ } else if(0 == recvrv) {
+ me->abort();
+ } else {
+ Q_ASSERT(recvrv);
+ Q_ASSERT((unsigned)recvrv <= dataBufferCapacity);
+ dataBufferLength = recvrv;
+ messageValid = true;
+
+#ifdef QUNIXSOCKET_DEBUG
+ qDebug() << "QUnixSocket: readyRead() " << dataBufferLength;
+#endif
+ emit readyRead();
+ }
+}
+
+QT_END_NAMESPACE
+
+#include "qunixsocket.moc"
diff --git a/src/gui/embedded/qunixsocket_p.h b/src/gui/embedded/qunixsocket_p.h
new file mode 100644
index 0000000000..6b9bf61cf7
--- /dev/null
+++ b/src/gui/embedded/qunixsocket_p.h
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUNIXSOCKET_P_H
+#define QUNIXSOCKET_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 <QtNetwork/qabstractsocket.h>
+#include <QtCore/qiodevice.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qshareddata.h>
+
+extern "C" {
+#include <sys/types.h>
+};
+
+QT_BEGIN_NAMESPACE
+
+class QUnixSocketRights;
+class QUnixSocketRightsPrivate;
+class QUnixSocketPrivate;
+class QUnixSocketMessagePrivate;
+struct iovec;
+
+class Q_GUI_EXPORT QUnixSocketRights {
+public:
+ QUnixSocketRights(int);
+ ~QUnixSocketRights();
+
+ QUnixSocketRights(const QUnixSocketRights &);
+ QUnixSocketRights & operator=(const QUnixSocketRights &);
+
+ bool isValid() const;
+
+ int dupFd() const;
+ int peekFd() const;
+
+private:
+ friend class QUnixSocket;
+ QUnixSocketRights(int,int);
+ QSharedDataPointer<QUnixSocketRightsPrivate> d;
+};
+
+class Q_GUI_EXPORT QUnixSocketMessage {
+public:
+ QUnixSocketMessage();
+ QUnixSocketMessage(const QByteArray &);
+ QUnixSocketMessage(const QByteArray &, const QList<QUnixSocketRights> &);
+ QUnixSocketMessage(const QUnixSocketMessage &);
+ QUnixSocketMessage(const iovec*, int);
+ QUnixSocketMessage & operator=(const QUnixSocketMessage &);
+ ~QUnixSocketMessage();
+
+ void setBytes(const QByteArray &);
+ void setRights(const QList<QUnixSocketRights> &);
+
+ const QList<QUnixSocketRights> & rights() const;
+ bool rightsWereTruncated() const;
+
+ const QByteArray & bytes() const;
+
+ pid_t processId() const;
+ uid_t userId() const;
+ gid_t groupId() const;
+
+ void setProcessId(pid_t);
+ void setUserId(uid_t);
+ void setGroupId(gid_t);
+
+ bool isValid() const;
+private:
+ friend class QUnixSocket;
+ friend class QUnixSocketPrivate;
+ QSharedDataPointer<QUnixSocketMessagePrivate> d;
+};
+
+class Q_GUI_EXPORT QUnixSocket : public QIODevice
+{
+ Q_OBJECT
+public:
+ QUnixSocket(QObject * = 0);
+ QUnixSocket(qint64, qint64, QObject * = 0);
+ virtual ~QUnixSocket();
+
+ enum SocketState {
+ UnconnectedState = QAbstractSocket::UnconnectedState,
+ HostLookupState = QAbstractSocket::HostLookupState,
+ ConnectingState = QAbstractSocket::ConnectingState,
+ ConnectedState = QAbstractSocket::ConnectedState,
+ BoundState = QAbstractSocket::BoundState,
+ ClosingState = QAbstractSocket::ClosingState,
+ ListeningState = QAbstractSocket::ListeningState,
+ };
+
+ enum SocketError { NoError, InvalidPath, ResourceError,
+ NonexistentPath, ConnectionRefused, UnknownError,
+ ReadFailure, WriteFailure };
+
+ bool connect(const QByteArray & path);
+ bool setSocketDescriptor(int socketDescriptor);
+ int socketDescriptor() const;
+ void abort();
+ void close();
+
+ bool flush();
+
+ SocketError error() const;
+
+ SocketState state() const;
+ QByteArray address() const;
+
+ qint64 bytesAvailable() const;
+ qint64 bytesToWrite() const;
+
+ qint64 readBufferSize() const;
+ void setReadBufferSize(qint64 size);
+ qint64 rightsBufferSize() const;
+ void setRightsBufferSize(qint64 size);
+
+ bool canReadLine() const;
+
+ qint64 write(const char * data, qint64 maxSize)
+ { return QIODevice::write(data, maxSize); }
+ qint64 write(const QByteArray & byteArray)
+ { return QIODevice::write(byteArray); }
+ qint64 read(char * data, qint64 maxSize)
+ { return QIODevice::read(data, maxSize); }
+ QByteArray read(qint64 maxSize)
+ { return QIODevice::read(maxSize); }
+
+ qint64 write(const QUnixSocketMessage &);
+ QUnixSocketMessage read();
+
+ virtual bool isSequential() const;
+ virtual bool waitForReadyRead(int msec = 300);
+ virtual bool waitForBytesWritten(int msec = 300);
+
+Q_SIGNALS:
+ void stateChanged(SocketState socketState);
+
+protected:
+ virtual qint64 readData(char * data, qint64 maxSize);
+ virtual qint64 writeData (const char * data, qint64 maxSize);
+
+private:
+ QUnixSocket(const QUnixSocket &);
+ QUnixSocket & operator=(const QUnixSocket &);
+
+ QUnixSocketPrivate * d;
+};
+
+QT_END_NAMESPACE
+
+#endif // QUNIXSOCKET_P_H
diff --git a/src/gui/embedded/qunixsocketserver.cpp b/src/gui/embedded/qunixsocketserver.cpp
new file mode 100644
index 0000000000..6e9347b8af
--- /dev/null
+++ b/src/gui/embedded/qunixsocketserver.cpp
@@ -0,0 +1,376 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qunixsocketserver_p.h"
+
+// #define QUNIXSOCKETSERVER_DEBUG
+
+#ifdef QUNIXSOCKETSERVER_DEBUG
+#include <QDebug>
+#endif
+
+#include <QtCore/qsocketnotifier.h>
+
+extern "C" {
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+#include <errno.h>
+};
+
+#define UNIX_PATH_MAX 108 // From unix(7)
+
+QT_BEGIN_NAMESPACE
+
+class QUnixSocketServerPrivate : public QObject
+{
+Q_OBJECT
+public:
+ QUnixSocketServerPrivate(QUnixSocketServer * parent)
+ : QObject(), me(parent), fd(-1), maxConns(30),
+ error(QUnixSocketServer::NoError), acceptNotifier(0)
+ {}
+
+ QUnixSocketServer * me;
+ int fd;
+ int maxConns;
+ QByteArray address;
+ QUnixSocketServer::ServerError error;
+ QSocketNotifier * acceptNotifier;
+public slots:
+ void acceptActivated();
+};
+
+/*!
+ \class QUnixSocketServer
+ \internal
+
+ \brief The QUnixSocketServer class provides a Unix domain socket based server.
+ \omit
+ \ingroup Platform::DeviceSpecific
+ \ingroup Platform::OS
+ \ingroup Platform::Communications
+ \endomit
+ \ingroup qws
+
+ This class makes it possible to accept incoming Unix domain socket
+ connections. Call \l QUnixSocketServer::listen() to have the server listen
+ for incoming connections on a specified path. The pure virtual
+ \l QUnixSocketServer::incomingConnection() is called each time a new
+ connection is established. Users must inherit from QUnixSocketServer and
+ implement this method.
+
+ If an error occurs, \l QUnixSocketServer::serverError() returns the type of
+ error. Errors can only occur during server establishment - that is, during a
+ call to \l QUnixSocketServer::listen(). Calling \l QUnixSocketServer::close()
+ causes QUnixSocketServer to stop listening for connections and reset its
+ state.
+
+ QUnixSocketServer is often used in conjunction with the \l QUnixSocket class.
+
+ \sa QUnixSocket
+*/
+
+/*!
+ \enum QUnixSocketServer::ServerError
+
+ The ServerError enumeration represents the errors that can occur during server
+ establishment. The most recent error can be retrieved through a call to
+ \l QUnixSocketServer::serverError().
+
+ \value NoError No error has occurred.
+ \value InvalidPath An invalid path endpoint was passed to
+ \l QUnixSocketServer::listen(). As defined by unix(7), invalid paths
+ include an empty path, or what more than 107 characters long.
+ \value ResourceError An error acquiring or manipulating the system's socket
+ resources occurred. For example, if the process runs out of available
+ socket descriptors, a ResourceError will occur.
+ \value BindError The server was unable to bind to the specified path.
+ \value ListenError The server was unable to listen on the specified path for
+ incoming connections.
+ */
+
+/*!
+ Create a new Unix socket server with the given \a parent.
+ */
+QUnixSocketServer::QUnixSocketServer(QObject *parent)
+: QObject(parent), d(0)
+{
+}
+
+/*!
+ Stops listening for incoming connection and destroys the Unix socket server.
+ */
+QUnixSocketServer::~QUnixSocketServer()
+{
+ close();
+ if(d)
+ delete d;
+}
+
+/*!
+ Stop listening for incoming connections and resets the Unix socket server's
+ state. Calling this method while \l {QUnixSocketServer::isListening()}{not listening } for incoming connections is a no-op.
+
+ \sa QUnixSocketServer::listen()
+ */
+void QUnixSocketServer::close()
+{
+ if(!d)
+ return;
+
+ if(d->acceptNotifier) {
+ d->acceptNotifier->setEnabled(false);
+ delete d->acceptNotifier;
+ }
+ d->acceptNotifier = 0;
+
+ if(-1 != d->fd) {
+#ifdef QUNIXSOCKET_DEBUG
+ int closerv =
+#endif
+ ::close(d->fd);
+#ifdef QUNIXSOCKET_DEBUG
+ if(0 != closerv) {
+ qDebug() << "QUnixSocketServer: Unable to close socket ("
+ << strerror(errno) << ")";
+ }
+#endif
+ }
+ d->fd = -1;
+ d->address = QByteArray();
+ d->error = NoError;
+}
+
+/*!
+ Returns the last server error. Errors may only occur within a call to
+ \l QUnixSocketServer::listen(), and only when such a call fails.
+
+ This method is not destructive, so multiple calls to
+ QUnixSocketServer::serverError() will return the same value. The error is
+ only reset by an explicit call to \l QUnixSocketServer::close() or
+ by further calls to \l QUnixSocketServer::listen().
+ */
+QUnixSocketServer::ServerError QUnixSocketServer::serverError() const
+{
+ if(!d)
+ return NoError;
+
+ return d->error;
+}
+
+/*!
+ Returns true if this server is listening for incoming connections, false
+ otherwise.
+
+ \sa QUnixSocketServer::listen()
+ */
+bool QUnixSocketServer::isListening() const
+{
+ if(!d)
+ return false;
+
+ return (-1 != d->fd);
+}
+
+/*!
+ Tells the server to listen for incoming connections on \a path. Returns true
+ if it successfully initializes, false otherwise. In the case of failure, the
+ \l QUnixSocketServer::serverError() error status is set accordingly.
+
+ Calling this method while the server is already running will result in the
+ server begin reset, and then attempting to listen on \a path. This will not
+ affect connections established prior to the server being reset, but further
+ incoming connections on the previous path will be refused.
+
+ The server can be explicitly reset by a call to \l QUnixSocketServer::close().
+
+ \sa QUnixSocketServer::close()
+ */
+bool QUnixSocketServer::listen(const QByteArray & path)
+{
+ if(d) {
+ close(); // Any existing server is destroyed
+ } else {
+ d = new QUnixSocketServerPrivate(this);
+ }
+
+ if(path.isEmpty() || path.size() > UNIX_PATH_MAX) {
+ d->error = InvalidPath;
+ return false;
+ }
+ unlink( path ); // ok if this fails
+
+ // Create the socket
+ d->fd = ::socket(PF_UNIX, SOCK_STREAM, 0);
+ if(-1 == d->fd) {
+#ifdef QUNIXSOCKETSERVER_DEBUG
+ qDebug() << "QUnixSocketServer: Unable to create socket ("
+ << strerror(errno) << ")";
+#endif
+ close();
+ d->error = ResourceError;
+ return false;
+ }
+
+ // Construct our unix address
+ struct ::sockaddr_un addr;
+ addr.sun_family = AF_UNIX;
+ ::memcpy(addr.sun_path, path.data(), path.size());
+ if(path.size() < UNIX_PATH_MAX)
+ addr.sun_path[path.size()] = '\0';
+
+ // Attempt to bind
+ if(-1 == ::bind(d->fd, (sockaddr *)&addr, sizeof(sockaddr_un))) {
+#ifdef QUNIXSOCKETSERVER_DEBUG
+ qDebug() << "QUnixSocketServer: Unable to bind socket ("
+ << strerror(errno) << ")";
+#endif
+ close();
+ d->error = BindError;
+ return false;
+ }
+
+ // Listen to socket
+ if(-1 == ::listen(d->fd, d->maxConns)) {
+#ifdef QUNIXSOCKETSERVER_DEBUG
+ qDebug() << "QUnixSocketServer: Unable to listen socket ("
+ << strerror(errno) << ")";
+#endif
+ close();
+ d->error = ListenError;
+ return false;
+ }
+
+ // Success!
+ d->address = path;
+ d->acceptNotifier = new QSocketNotifier(d->fd, QSocketNotifier::Read, d);
+ d->acceptNotifier->setEnabled(true);
+ QObject::connect(d->acceptNotifier, SIGNAL(activated(int)),
+ d, SLOT(acceptActivated()));
+
+ return true;
+}
+
+/*!
+ Returns the Unix path on which this server is listening. If this server is
+ not listening, and empty address will be returned.
+ */
+QByteArray QUnixSocketServer::serverAddress() const
+{
+ if(!d)
+ return QByteArray();
+ return d->address;
+}
+
+int QUnixSocketServer::socketDescriptor() const
+{
+ if (!d)
+ return -1;
+ return d->fd;
+}
+
+
+/*!
+ Returns the maximum length the queue of pending connections may grow to. That
+ is, the maximum number of clients attempting to connect for which the Unix
+ socket server has not yet accepted and passed to
+ \l QUnixSocketServer::incomingConnection(). If a connection request arrives
+ with the queue full, the client may receive a connection refused notification.
+
+ By default a queue length of 30 is used.
+
+ \sa QUnixSocketServer::setMaxPendingConnections()
+ */
+int QUnixSocketServer::maxPendingConnections() const
+{
+ if(!d)
+ return 30;
+
+ return d->maxConns;
+}
+
+/*!
+ Sets the maximum length the queue of pending connections may grow to
+ \a numConnections. This value will only apply to
+ \l QUnixSocketServer::listen() calls made following the value change - it will
+ not be retroactively applied.
+
+ \sa QUnixSocketServer::maxPendingConnections()
+ */
+void QUnixSocketServer::setMaxPendingConnections(int numConnections)
+{
+ Q_ASSERT(numConnections >= 1);
+ if(!d)
+ d = new QUnixSocketServerPrivate(this);
+
+ d->maxConns = numConnections;
+}
+
+/*!
+ \fn void QUnixSocketServer::incomingConnection(int socketDescriptor)
+
+ This method is invoked each time a new incoming connection is established with
+ the server. Clients must reimplement this function in their QUnixSocketServer
+ derived class to handle the connection.
+
+ A common approach to handling the connection is to pass \a socketDescriptor to
+ a QUnixSocket instance.
+
+ \sa QUnixSocket
+ */
+
+void QUnixSocketServerPrivate::acceptActivated()
+{
+ ::sockaddr_un r;
+ socklen_t len = sizeof(sockaddr_un);
+ int connsock = ::accept(fd, (sockaddr *)&r, &len);
+#ifdef QUNIXSOCKETSERVER_DEBUG
+ qDebug() << "QUnixSocketServer: Accept connection " << connsock;
+#endif
+ if(-1 != connsock)
+ me->incomingConnection(connsock);
+}
+
+QT_END_NAMESPACE
+
+#include "qunixsocketserver.moc"
diff --git a/src/gui/embedded/qunixsocketserver_p.h b/src/gui/embedded/qunixsocketserver_p.h
new file mode 100644
index 0000000000..60d4cfcbc4
--- /dev/null
+++ b/src/gui/embedded/qunixsocketserver_p.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QUNIXSOCKETSERVER_P_H
+#define QUNIXSOCKETSERVER_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/qobject.h>
+
+QT_BEGIN_NAMESPACE
+
+class QUnixSocketServerPrivate;
+class Q_GUI_EXPORT QUnixSocketServer : public QObject
+{
+ Q_OBJECT
+public:
+ enum ServerError { NoError, InvalidPath, ResourceError, BindError,
+ ListenError };
+
+ QUnixSocketServer(QObject *parent=0);
+ virtual ~QUnixSocketServer();
+
+ void close();
+
+ ServerError serverError() const;
+
+ bool isListening() const;
+ bool listen(const QByteArray & path);
+
+ int socketDescriptor() const;
+ QByteArray serverAddress() const;
+
+ int maxPendingConnections() const;
+ void setMaxPendingConnections(int numConnections);
+
+protected:
+ virtual void incomingConnection(int socketDescriptor) = 0;
+
+private:
+ QUnixSocketServer(const QUnixSocketServer &);
+ QUnixSocketServer & operator=(const QUnixSocketServer &);
+
+ friend class QUnixSocketServerPrivate;
+ QUnixSocketServerPrivate * d;
+};
+
+
+QT_END_NAMESPACE
+#endif // QUNIXSOCKETSERVER_P_H
+
diff --git a/src/gui/embedded/qvfbhdr.h b/src/gui/embedded/qvfbhdr.h
new file mode 100644
index 0000000000..421d991777
--- /dev/null
+++ b/src/gui/embedded/qvfbhdr.h
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVFBHDR_H
+#define QVFBHDR_H
+
+#include <QtGui/qcolor.h>
+#include <QtGui/qwindowdefs.h>
+#include <QtCore/qrect.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#define QT_VFB_MOUSE_PIPE "/tmp/.qtvfb_mouse-%1"
+#define QT_VFB_KEYBOARD_PIPE "/tmp/.qtvfb_keyboard-%1"
+#define QT_VFB_MAP "/tmp/.qtvfb_map-%1"
+
+struct QVFbHeader
+{
+ int width;
+ int height;
+ int depth;
+ int linestep;
+ int dataoffset;
+ QRect update;
+ bool dirty;
+ int numcols;
+ QRgb clut[256];
+ int viewerVersion;
+ int serverVersion;
+ int brightness; // since 4.4.0
+ WId windowId; // since 4.5.0
+};
+
+struct QVFbKeyData
+{
+ unsigned int keycode;
+ Qt::KeyboardModifiers modifiers;
+ unsigned short int unicode;
+ bool press;
+ bool repeat;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QVFBHDR_H
diff --git a/src/gui/embedded/qwindowsystem_p.h b/src/gui/embedded/qwindowsystem_p.h
new file mode 100644
index 0000000000..7782206fca
--- /dev/null
+++ b/src/gui/embedded/qwindowsystem_p.h
@@ -0,0 +1,315 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSYSTEM_QWS_P_H
+#define QWINDOWSYSTEM_QWS_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 QWSServer class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "private/qobject_p.h"
+#include "qwindowsystem_qws.h"
+#include "qbrush.h"
+#include "qwsproperty_qws.h"
+#include "qwscommand_qws_p.h"
+#include "QtCore/qbasictimer.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWSServerPrivate : public QObjectPrivate {
+ friend class QCopChannel;
+ friend class QWSMouseHandler;
+ friend class QWSWindow;
+ friend class QWSDisplay;
+ friend class QWSInputMethod;
+ Q_DECLARE_PUBLIC(QWSServer)
+
+public:
+ QWSServerPrivate()
+ : screensaverintervals(0)
+ , screensavereventblocklevel(-1), screensaverblockevents(false)
+ , saver(0), cursorClient(0), mouseState(0), nReserved(0)
+ , doClientIsActive(false)
+ {
+ }
+ ~QWSServerPrivate()
+ {
+ closeDisplay();
+
+ qDeleteAll(deletedWindows);
+ delete [] screensaverintervals;
+ delete saver;
+
+ qDeleteAll(windows);
+ windows.clear();
+
+ delete bgBrush;
+ bgBrush = 0;
+ }
+ QTime screensavertime;
+ QTimer* screensavertimer;
+ int* screensaverintervals;
+ int screensavereventblocklevel;
+ bool screensaverblockevents;
+ bool screensaverblockevent( int index, int *screensaverinterval, bool isDown );
+ QWSScreenSaver* saver;
+ QWSClient *cursorClient;
+ int mouseState;
+// bool prevWin;
+ QList<QWSWindow*> deletedWindows;
+ QList<int> crashedClientIds;
+
+ void update_regions();
+//private functions moved from class
+
+private:
+ void initServer(int flags);
+#ifndef QT_NO_COP
+ static void sendQCopEvent(QWSClient *c, const QString &ch,
+ const QString &msg, const QByteArray &data,
+ bool response = false);
+#endif
+ void move_region(const QWSRegionMoveCommand *);
+ void set_altitude(const QWSChangeAltitudeCommand *);
+ void set_opacity(const QWSSetOpacityCommand *);
+ void request_focus(const QWSRequestFocusCommand *);
+ QRegion reserve_region(QWSWindow *window, const QRegion &region);
+ void request_region(int winId, const QString &surfaceKey,
+ const QByteArray &surfaceData,
+ const QRegion &region);
+ void repaint_region(int winId, int windowFlags, bool opaque, const QRegion &);
+ void destroy_region(const QWSRegionDestroyCommand *);
+ void name_region(const QWSRegionNameCommand *);
+ void set_identity(const QWSIdentifyCommand *);
+#ifndef QT_NO_QWS_PROPERTIES
+ bool get_property(int winId, int property, const char *&data, int &len);
+#endif
+#ifndef QT_NO_QWS_INPUTMETHODS
+ void im_response(const QWSIMResponseCommand *);
+
+ void im_update(const QWSIMUpdateCommand *);
+
+ void send_im_mouse(const QWSIMMouseCommand *);
+#endif
+ // not in ifndef as this results in more readable functions.
+ static void sendKeyEventUnfiltered(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
+ bool isPress, bool autoRepeat);
+ static void sendMouseEventUnfiltered(const QPoint &pos, int state, int wheel = 0);
+ static void emergency_cleanup();
+
+ static QBrush *bgBrush;
+
+ void sendMaxWindowRectEvents(const QRect &rect);
+
+ void invokeIdentify(const QWSIdentifyCommand *cmd, QWSClient *client);
+ void invokeCreate(QWSCreateCommand *cmd, QWSClient *client);
+ void invokeRegionName(const QWSRegionNameCommand *cmd, QWSClient *client);
+ void invokeRegion(QWSRegionCommand *cmd, QWSClient *client);
+ void invokeRegionMove(const QWSRegionMoveCommand *cmd, QWSClient *client);
+ void invokeRegionDestroy(const QWSRegionDestroyCommand *cmd, QWSClient *client);
+ void invokeSetAltitude(const QWSChangeAltitudeCommand *cmd, QWSClient *client);
+ void invokeSetOpacity(const QWSSetOpacityCommand *cmd, QWSClient *client);
+#ifndef QT_NO_QWS_PROPERTIES
+ void invokeAddProperty(QWSAddPropertyCommand *cmd);
+ void invokeSetProperty(QWSSetPropertyCommand *cmd);
+ void invokeRemoveProperty(QWSRemovePropertyCommand *cmd);
+ void invokeGetProperty(QWSGetPropertyCommand *cmd, QWSClient *client);
+#endif //QT_NO_QWS_PROPERTIES
+ void invokeSetSelectionOwner(QWSSetSelectionOwnerCommand *cmd);
+ void invokeConvertSelection(QWSConvertSelectionCommand *cmd);
+ void invokeSetFocus(const QWSRequestFocusCommand *cmd, QWSClient *client);
+
+ void initIO();
+ void setFocus(QWSWindow*, bool gain);
+#ifndef QT_NO_QWS_CURSOR
+ void invokeDefineCursor(QWSDefineCursorCommand *cmd, QWSClient *client);
+ void invokeSelectCursor(QWSSelectCursorCommand *cmd, QWSClient *client);
+ void invokePositionCursor(QWSPositionCursorCommand *cmd, QWSClient *client);
+#endif
+ void invokeGrabMouse(QWSGrabMouseCommand *cmd, QWSClient *client);
+ void invokeGrabKeyboard(QWSGrabKeyboardCommand *cmd, QWSClient *client);
+#ifndef QT_NO_SOUND
+ void invokePlaySound(QWSPlaySoundCommand *cmd, QWSClient *client);
+#endif
+#ifndef QT_NO_COP
+ void invokeRegisterChannel(QWSQCopRegisterChannelCommand *cmd,
+ QWSClient *client);
+ void invokeQCopSend(QWSQCopSendCommand *cmd, QWSClient *client);
+#endif
+ void invokeRepaintRegion(QWSRepaintRegionCommand *cmd,
+ QWSClient *client);
+#ifndef QT_NO_QWSEMBEDWIDGET
+ void invokeEmbed(QWSEmbedCommand *cmd, QWSClient *client);
+#endif
+#ifndef QT_NO_QWS_INPUTMETHODS
+ void invokeIMResponse(const QWSIMResponseCommand *cmd,
+ QWSClient *client);
+ void invokeIMUpdate(const QWSIMUpdateCommand *cmd,
+ QWSClient *client);
+#endif
+ void invokeFont(const QWSFontCommand *cmd, QWSClient *client);
+ void invokeScreenTransform(const QWSScreenTransformCommand *cmd,
+ QWSClient *client);
+
+ QWSMouseHandler* newMouseHandler(const QString& spec);
+ void openDisplay();
+ void closeDisplay();
+
+ void showCursor();
+ void hideCursor();
+ void initializeCursor();
+
+ void resetEngine();
+
+//private Q_SLOTS:
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+ void _q_clientClosed();
+ void _q_doClient();
+ void _q_deleteWindowsLater();
+#endif
+
+ void _q_screenSaverWake();
+ void _q_screenSaverSleep();
+ void _q_screenSaverTimeout();
+#ifndef QT_NO_QWS_MULTIPROCESS
+ void _q_newConnection();
+#endif
+
+//other private moved from class
+
+ void disconnectClient(QWSClient *);
+ void screenSave(int level);
+ void doClient(QWSClient *);
+ typedef QMap<int,QWSClient*>::Iterator ClientIterator;
+ typedef QMap<int,QWSClient*> ClientMap;
+ void handleWindowClose(QWSWindow *w);
+ void releaseMouse(QWSWindow* w);
+ void releaseKeyboard(QWSWindow* w);
+ void updateClientCursorPos();
+
+ uchar* sharedram;
+ int ramlen;
+
+ ClientMap clientMap;
+#ifndef QT_NO_QWS_PROPERTIES
+ QWSPropertyManager propertyManager;
+#endif
+ struct SelectionOwner {
+ int windowid;
+ struct Time {
+ void set(int h, int m, int s, int s2) {
+ hour = h; minute = m; sec = s; ms = s2;
+ }
+ int hour, minute, sec, ms;
+ } time;
+ } selectionOwner;
+ QTime timer;
+ int* screensaverinterval;
+
+ QWSWindow *focusw;
+ QWSWindow *mouseGrabber;
+ bool mouseGrabbing;
+ bool inputMethodMouseGrabbed;
+ int swidth, sheight, sdepth;
+#ifndef QT_NO_QWS_CURSOR
+ bool haveviscurs;
+ QWSCursor *cursor; // cursor currently shown
+ QWSCursor *nextCursor; // cursor to show once grabbing is off
+#endif
+
+ bool disablePainting;
+ QList<QWSMouseHandler*> mousehandlers;
+#ifndef QT_NO_QWS_KEYBOARD
+ QList<QWSKeyboardHandler*> keyboardhandlers;
+#endif
+
+ QList<QWSCommandStruct*> commandQueue;
+
+ // Window management
+ QList<QWSWindow*> windows; // first=topmost
+ int nReserved;
+ QWSWindow* newWindow(int id, QWSClient* client);
+ QWSWindow* findWindow(int windowid, QWSClient* client = 0);
+ void moveWindowRegion(QWSWindow*, int dx, int dy);
+ void setWindowRegion(QWSWindow*, const QRegion &r);
+ void raiseWindow(QWSWindow *, int = 0);
+ void lowerWindow(QWSWindow *, int = -1);
+ void exposeRegion(const QRegion &, int index = 0);
+
+ void setCursor(QWSCursor *curs);
+
+ // multimedia
+#ifndef QT_NO_SOUND
+ QWSSoundServer *soundserver;
+#endif
+#ifndef QT_NO_COP
+ QMap<QString, QList<QWSClient*> > channels;
+#endif
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+ QWSServerSocket *ssocket;
+#endif
+
+ // filename -> refcount
+ QMap<QByteArray, int> fontReferenceCount;
+ QBasicTimer fontCleanupTimer;
+ void referenceFont(QWSClientPrivate *client, const QByteArray &font);
+ void dereferenceFont(QWSClientPrivate *client, const QByteArray &font);
+ void cleanupFonts(bool force = false);
+ void sendFontRemovedEvent(const QByteArray &font);
+
+ bool doClientIsActive;
+ QList<QWSClient*> pendingDoClients;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/embedded/qwindowsystem_qws.cpp b/src/gui/embedded/qwindowsystem_qws.cpp
new file mode 100644
index 0000000000..dffebf2781
--- /dev/null
+++ b/src/gui/embedded/qwindowsystem_qws.cpp
@@ -0,0 +1,4947 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwindowsystem_qws.h"
+#include "qwsevent_qws.h"
+#include "qwscommand_qws_p.h"
+#include "qtransportauth_qws_p.h"
+#include "qwsutils_qws.h"
+#include "qwscursor_qws.h"
+#include "qwsdisplay_qws.h"
+#include "qmouse_qws.h"
+#include "qcopchannel_qws.h"
+#include "qwssocket_qws.h"
+
+#include "qapplication.h"
+#include "private/qapplication_p.h"
+#include "qsocketnotifier.h"
+#include "qpolygon.h"
+#include "qimage.h"
+#include "qcursor.h"
+#include <private/qpaintengine_raster_p.h>
+#include "qscreen_qws.h"
+#include "qwindowdefs.h"
+#include "private/qlock_p.h"
+#include "qwslock_p.h"
+#include "qfile.h"
+#include "qtimer.h"
+#include "qpen.h"
+#include "qdesktopwidget.h"
+#include "qevent.h"
+#include "qinputcontext.h"
+#include "qpainter.h"
+
+#include <qdebug.h>
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#ifndef Q_OS_DARWIN
+# include <sys/sem.h>
+#endif
+#include <sys/param.h>
+#include <sys/mount.h>
+#endif
+#include <signal.h>
+#include <fcntl.h>
+
+#if !defined(QT_NO_SOUND) && !defined(Q_OS_DARWIN)
+#ifdef QT_USE_OLD_QWS_SOUND
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <sys/soundcard.h>
+#else
+#include "qsoundqss_qws.h"
+#endif
+#endif
+
+#include "qkbddriverfactory_qws.h"
+#include "qmousedriverfactory_qws.h"
+
+#include <qbuffer.h>
+#include <qdir.h>
+
+#include <private/qwindowsurface_qws_p.h>
+#include <private/qfontengine_qpf_p.h>
+
+#include "qwindowsystem_p.h"
+
+//#define QWS_DEBUG_FONTCLEANUP
+
+QT_BEGIN_NAMESPACE
+
+QWSServer Q_GUI_EXPORT *qwsServer=0;
+static QWSServerPrivate *qwsServerPrivate=0;
+
+#define MOUSE 0
+#define KEY 1
+//#define EVENT_BLOCK_DEBUG
+
+QWSScreenSaver::~QWSScreenSaver()
+{
+}
+
+extern QByteArray qws_display_spec;
+extern void qt_init_display(); //qapplication_qws.cpp
+extern QString qws_qtePipeFilename();
+
+extern void qt_client_enqueue(const QWSEvent *); //qapplication_qws.cpp
+extern QList<QWSCommand*> *qt_get_server_queue();
+
+Q_GLOBAL_STATIC_WITH_ARGS(QString, defaultMouse, (QLatin1String("Auto")))
+Q_GLOBAL_STATIC_WITH_ARGS(QString, defaultKeyboard, (QLatin1String("TTY")))
+static const int FontCleanupInterval = 60 * 1000;
+
+static int qws_keyModifiers = 0;
+
+static QWSWindow *keyboardGrabber;
+static bool keyboardGrabbing;
+
+static int get_object_id(int count = 1)
+{
+ static int next=1000;
+ int n = next;
+ next += count;
+ return n;
+}
+#ifndef QT_NO_QWS_INPUTMETHODS
+static QWSInputMethod *current_IM = 0;
+
+static QWSWindow *current_IM_composing_win = 0;
+static int current_IM_winId = -1;
+static bool force_reject_strokeIM = false;
+#endif
+
+static void cleanupFontsDir();
+
+//#define QWS_REGION_DEBUG
+
+/*!
+ \class QWSScreenSaver
+ \ingroup qws
+
+ \brief The QWSScreenSaver class is a base class for screensavers
+ in Qt for Embedded Linux.
+
+ When running \l{Qt for Embedded Linux} applications, it is the server
+ application that installs and controls the screensaver.
+ \l{Qt for Embedded Linux} supports multilevel screen saving; i.e., it is possible to
+ specify several different levels of screen responsiveness. For
+ example, you can choose to first turn off the light before you
+ fully activate the screensaver.
+
+ Note that there exists no default screensaver implementation.
+
+ To create a custom screensaver, derive from this class and
+ reimplement the restore() and save() functions. These functions
+ are called whenever the screensaver is activated or deactivated,
+ respectively. Once an instance of your custom screensaver is
+ created, you can use the QWSServer::setScreenSaver() function to
+ install it.
+
+ \sa QWSServer, QScreen, {Qt for Embedded Linux}
+*/
+
+/*!
+ \fn QWSScreenSaver::~QWSScreenSaver()
+
+ Reimplement this function to destroy the screensaver.
+*/
+
+/*!
+ \fn QWSScreenSaver::restore()
+
+ Implement this function to deactivate the screensaver, restoring
+ the previously saved screen.
+
+ \sa save(), QWSServer::screenSaverActivate()
+*/
+
+/*!
+ \fn QWSScreenSaver::save(int level)
+
+ Implement this function to activate the screensaver, saving the
+ current screen.
+
+ \l{Qt for Embedded Linux} supports multilevel screen saving; i.e., it is
+ possible to specify several different levels of screen
+ responsiveness. For example, you can choose to first turn off the
+ light before you fully activate the screensaver. Use the
+ QWSServer::setScreenSaverIntervals() to specify the time intervals
+ between the different levels.
+
+ This function should return true if the screensaver successfully
+ enters the given \a level; otherwise it should return false.
+
+ \sa restore(), QWSServer::screenSaverActivate()
+*/
+
+class QWSWindowPrivate
+{
+public:
+ QWSWindowPrivate();
+
+#ifdef QT_QWS_CLIENTBLIT
+ QRegion directPaintRegion;
+#endif
+ QRegion allocatedRegion;
+#ifndef QT_NO_QWSEMBEDWIDGET
+ QList<QWSWindow*> embedded;
+ QWSWindow *embedder;
+#endif
+ QWSWindow::State state;
+ Qt::WindowFlags windowFlags;
+ QRegion dirtyOnScreen;
+ bool painted;
+};
+
+QWSWindowPrivate::QWSWindowPrivate()
+ :
+#ifndef QT_NO_QWSEMBEDWIDGET
+ embedder(0), state(QWSWindow::NoState),
+#endif
+ painted(false)
+{
+}
+
+/*!
+ \class QWSWindow
+ \ingroup qws
+
+ \brief The QWSWindow class encapsulates a top-level window in
+ Qt for Embedded Linux.
+
+ When you run a \l{Qt for Embedded Linux} application, it either runs as a
+ server or connects to an existing server. As applications add and
+ remove windows, the server process maintains information about
+ each window. In \l{Qt for Embedded Linux}, top-level windows are
+ encapsulated as QWSWindow objects. Note that you should never
+ construct the QWSWindow class yourself; the current top-level
+ windows can be retrieved using the QWSServer::clientWindows()
+ function.
+
+ With a window at hand, you can retrieve its caption, name, opacity
+ and ID using the caption(), name(), opacity() and winId()
+ functions, respectively. Use the client() function to retrieve a
+ pointer to the client that owns the window.
+
+ Use the isVisible() function to find out if the window is
+ visible. You can find out if the window is completely obscured by
+ another window or by the bounds of the screen, using the
+ isFullyObscured() function. The isOpaque() function returns true
+ if the window has an alpha channel equal to 255. Finally, the
+ requestedRegion() function returns the region of the display the
+ window wants to draw on.
+
+ \sa QWSServer, QWSClient, {Qt for Embedded Linux Architecture}
+*/
+
+/*!
+ \fn int QWSWindow::winId() const
+
+ Returns the window's ID.
+
+ \sa name(), caption()
+*/
+
+/*!
+ \fn const QString &QWSWindow::name() const
+
+ Returns the window's name, which is taken from the \l {QWidget::}{objectName()}
+ at the time of \l {QWidget::}{show()}.
+
+ \sa caption(), winId()
+*/
+
+/*!
+ \fn const QString &QWSWindow::caption() const
+
+ Returns the window's caption.
+
+ \sa name(), winId()
+*/
+
+/*!
+ \fn QWSClient* QWSWindow::client() const
+
+ Returns a reference to the QWSClient object that owns this window.
+
+ \sa requestedRegion()
+*/
+
+/*!
+ \fn QRegion QWSWindow::requestedRegion() const
+
+ Returns the region that the window has requested to draw onto,
+ including any window decorations.
+
+ \sa client()
+*/
+
+/*!
+ \fn bool QWSWindow::isVisible() const
+
+ Returns true if the window is visible; otherwise returns false.
+
+ \sa isFullyObscured()
+*/
+
+/*!
+ \fn bool QWSWindow::isOpaque() const
+
+ Returns true if the window is opaque, i.e., if its alpha channel
+ equals 255; otherwise returns false.
+
+ \sa opacity()
+*/
+
+/*!
+ \fn uint QWSWindow::opacity () const
+
+ Returns the window's alpha channel value.
+
+ \sa isOpaque()
+*/
+
+/*!
+ \fn bool QWSWindow::isPartiallyObscured() const
+ \internal
+
+ Returns true if the window is partially obsured by another window
+ or by the bounds of the screen; otherwise returns false.
+*/
+
+/*!
+ \fn bool QWSWindow::isFullyObscured() const
+
+ Returns true if the window is completely obsured by another window
+ or by the bounds of the screen; otherwise returns false.
+
+ \sa isVisible()
+*/
+
+/*!
+ \fn QWSWindowSurface* QWSWindow::windowSurface() const
+ \internal
+*/
+
+QWSWindow::QWSWindow(int i, QWSClient* client)
+ : id(i), modified(false),
+ onTop(false), c(client), last_focus_time(0), _opacity(255),
+ opaque(true), d(new QWSWindowPrivate)
+{
+ surface = 0;
+}
+
+
+/*!
+ \enum QWSWindow::State
+
+ This enum describes the state of a window. Most of the
+ transitional states are set just before a call to
+ QScreen::exposeRegion() and reset immediately afterwards.
+
+ \value NoState Initial state before the window is properly initialized.
+ \value Hidden The window is not visible.
+ \value Showing The window is being shown.
+ \value Visible The window is visible, and not in a transition.
+ \value Hiding The window is being hidden.
+ \value Raising The windoe is being raised.
+ \value Lowering The window is being raised.
+ \value Moving The window is being moved.
+ \value ChangingGeometry The window's geometry is being changed.
+ \value Destroyed The window is destroyed.
+
+ \sa state(), QScreen::exposeRegion()
+*/
+
+/*!
+ Returns the current state of the window.
+
+ \since 4.3
+*/
+QWSWindow::State QWSWindow::state() const
+{
+ return d->state;
+}
+
+/*!
+ Returns the window flags of the window. This value is only available
+ after the first paint event.
+
+ \since 4.3
+*/
+Qt::WindowFlags QWSWindow::windowFlags() const
+{
+ return d->windowFlags;
+}
+
+/*!
+ Returns the region that has been repainted since the previous
+ QScreen::exposeRegion(), and needs to be copied to the screen.
+ \since 4.3
+*/
+QRegion QWSWindow::dirtyOnScreen() const
+{
+ return d->dirtyOnScreen;
+}
+
+void QWSWindow::createSurface(const QString &key, const QByteArray &data)
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (surface && !surface->isBuffered())
+ c->removeUnbufferedSurface();
+#endif
+
+ delete surface;
+ surface = qt_screen->createSurface(key);
+ surface->setPermanentState(data);
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (!surface->isBuffered())
+ c->addUnbufferedSurface();
+#endif
+}
+
+/*!
+ \internal
+ Raises the window above all other windows except "Stay on top" windows.
+*/
+void QWSWindow::raise()
+{
+ qwsServerPrivate->raiseWindow(this);
+#ifndef QT_NO_QWSEMBEDWIDGET
+ const int n = d->embedded.size();
+ for (int i = 0; i < n; ++i)
+ d->embedded.at(i)->raise();
+#endif
+}
+
+/*!
+ \internal
+ Lowers the window below other windows.
+*/
+void QWSWindow::lower()
+{
+ qwsServerPrivate->lowerWindow(this);
+#ifndef QT_NO_QWSEMBEDWIDGET
+ const int n = d->embedded.size();
+ for (int i = 0; i < n; ++i)
+ d->embedded.at(i)->lower();
+#endif
+}
+
+/*!
+ \internal
+ Shows the window.
+*/
+void QWSWindow::show()
+{
+ operation(QWSWindowOperationEvent::Show);
+#ifndef QT_NO_QWSEMBEDWIDGET
+ const int n = d->embedded.size();
+ for (int i = 0; i < n; ++i)
+ d->embedded.at(i)->show();
+#endif
+}
+
+/*!
+ \internal
+ Hides the window.
+*/
+void QWSWindow::hide()
+{
+ operation(QWSWindowOperationEvent::Hide);
+#ifndef QT_NO_QWSEMBEDWIDGET
+ const int n = d->embedded.size();
+ for (int i = 0; i < n; ++i)
+ d->embedded.at(i)->hide();
+#endif
+}
+
+/*!
+ \internal
+ Make this the active window (i.e., sets the keyboard focus to this
+ window).
+*/
+void QWSWindow::setActiveWindow()
+{
+ qwsServerPrivate->setFocus(this, true);
+#ifndef QT_NO_QWSEMBEDWIDGET
+ const int n = d->embedded.size();
+ for (int i = 0; i < n; ++i)
+ d->embedded.at(i)->setActiveWindow();
+#endif
+}
+
+void QWSWindow::setName(const QString &n)
+{
+ rgnName = n;
+}
+
+/*!
+ \internal
+ Sets the window's caption to \a c.
+*/
+void QWSWindow::setCaption(const QString &c)
+{
+ rgnCaption = c;
+}
+
+
+static int global_focus_time_counter=100;
+
+void QWSWindow::focus(bool get)
+{
+ if (get)
+ last_focus_time = global_focus_time_counter++;
+ if (c) {
+ QWSFocusEvent event;
+ event.simpleData.window = id;
+ event.simpleData.get_focus = get;
+ c->sendEvent(&event);
+ }
+}
+
+void QWSWindow::operation(QWSWindowOperationEvent::Operation o)
+{
+ if (!c)
+ return;
+ QWSWindowOperationEvent event;
+ event.simpleData.window = id;
+ event.simpleData.op = o;
+ c->sendEvent(&event);
+}
+
+/*!
+ \internal
+ Destructor.
+*/
+QWSWindow::~QWSWindow()
+{
+#ifndef QT_NO_QWS_INPUTMETHODS
+ if (current_IM_composing_win == this)
+ current_IM_composing_win = 0;
+#endif
+#ifndef QT_NO_QWSEMBEDWIDGET
+ QWSWindow *embedder = d->embedder;
+ if (embedder) {
+ embedder->d->embedded.removeAll(this);
+ d->embedder = 0;
+ }
+ while (!d->embedded.isEmpty())
+ stopEmbed(d->embedded.first());
+#endif
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (surface && !surface->isBuffered()) {
+ if (c && c->d_func()) // d_func() will be 0 if client is deleted
+ c->removeUnbufferedSurface();
+ }
+#endif
+
+ delete surface;
+ delete d;
+}
+
+/*!
+ \internal
+
+ Returns the region that the window is allowed to draw onto,
+ including any window decorations but excluding regions covered by
+ other windows.
+
+ \sa paintedRegion(), requestedRegion()
+*/
+QRegion QWSWindow::allocatedRegion() const
+{
+ return d->allocatedRegion;
+}
+
+#ifdef QT_QWS_CLIENTBLIT
+QRegion QWSWindow::directPaintRegion() const
+{
+ return d->directPaintRegion;
+}
+
+inline void QWSWindow::setDirectPaintRegion(const QRegion &r)
+{
+ d->directPaintRegion = r;
+}
+#endif
+
+/*!
+ \internal
+
+ Returns the region that the window is known to have drawn into.
+
+ \sa allocatedRegion(), requestedRegion()
+*/
+QRegion QWSWindow::paintedRegion() const
+{
+ return (d->painted ? d->allocatedRegion : QRegion());
+}
+
+inline void QWSWindow::setAllocatedRegion(const QRegion &region)
+{
+ d->allocatedRegion = region;
+}
+
+#ifndef QT_NO_QWSEMBEDWIDGET
+inline void QWSWindow::startEmbed(QWSWindow *w)
+{
+ d->embedded.append(w);
+ w->d->embedder = this;
+}
+
+inline void QWSWindow::stopEmbed(QWSWindow *w)
+{
+ w->d->embedder = 0;
+ w->client()->sendEmbedEvent(w->winId(), QWSEmbedEvent::Region, QRegion());
+ d->embedded.removeAll(w);
+}
+#endif // QT_NO_QWSEMBEDWIDGET
+
+/*********************************************************************
+ *
+ * Class: QWSClient
+ *
+ *********************************************************************/
+
+class QWSClientPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QWSClient)
+
+public:
+ QWSClientPrivate();
+ ~QWSClientPrivate();
+
+ void setLockId(int id);
+ void unlockCommunication();
+
+private:
+#ifndef QT_NO_QWS_MULTIPROCESS
+ QWSLock *clientLock;
+ bool shutdown;
+ int numUnbufferedSurfaces;
+#endif
+ QSet<QByteArray> usedFonts;
+ friend class QWSServerPrivate;
+};
+
+QWSClientPrivate::QWSClientPrivate()
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ clientLock = 0;
+ shutdown = false;
+ numUnbufferedSurfaces = 0;
+#endif
+}
+
+QWSClientPrivate::~QWSClientPrivate()
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ delete clientLock;
+#endif
+}
+
+void QWSClientPrivate::setLockId(int id)
+{
+#ifdef QT_NO_QWS_MULTIPROCESS
+ Q_UNUSED(id);
+#else
+ clientLock = new QWSLock(id);
+#endif
+}
+
+void QWSClientPrivate::unlockCommunication()
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (clientLock)
+ clientLock->unlock(QWSLock::Communication);
+#endif
+}
+
+/*!
+ \class QWSClient
+ \ingroup qws
+
+ \brief The QWSClient class encapsulates a client process in Qt for Embedded Linux.
+
+ When you run a \l{Qt for Embedded Linux} application, it either runs as a
+ server or connects to an existing server. The server and client
+ processes have different responsibilities: The client process
+ performs all application specific operations. The server process
+ is responsible for managing the clients as well as taking care of
+ the pointer handling, character input, and screen output. In
+ addition, the server provides functionality to handle input
+ methods.
+
+ As applications add and remove windows, the server process
+ maintains information about each window. In \l{Qt for Embedded Linux},
+ top-level windows are encapsulated as QWSWindow objects. A list of
+ the current windows can be retrieved using the
+ QWSServer::clientWindows() function, and each window can tell
+ which client that owns it through its QWSWindow::client()
+ function.
+
+ A QWSClient object has an unique ID that can be retrieved using
+ its clientId() function. QWSClient also provides the identity()
+ function which typically returns the name of this client's running
+ application.
+
+ \sa QWSServer, QWSWindow, {Qt for Embedded Linux Architecture}
+*/
+
+/*!
+ \internal
+*/
+//always use frame buffer
+QWSClient::QWSClient(QObject* parent, QWS_SOCK_BASE* sock, int id)
+ : QObject(*new QWSClientPrivate, parent), command(0), cid(id)
+{
+#ifdef QT_NO_QWS_MULTIPROCESS
+ Q_UNUSED(sock);
+ isClosed = false;
+#else
+ csocket = 0;
+ if (!sock) {
+ socketDescriptor = -1;
+ isClosed = false;
+ } else {
+ csocket = static_cast<QWSSocket*>(sock); //###
+ isClosed = false;
+
+ csocket->flush();
+ socketDescriptor = csocket->socketDescriptor();
+ connect(csocket, SIGNAL(readyRead()), this, SIGNAL(readyRead()));
+ connect(csocket, SIGNAL(disconnected()), this, SLOT(closeHandler()));
+ connect(csocket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(errorHandler()));
+ }
+#endif //QT_NO_QWS_MULTIPROCESS
+}
+
+/*!
+ \internal
+*/
+QWSClient::~QWSClient()
+{
+ qDeleteAll(cursors);
+ delete command;
+#ifndef QT_NO_QWS_MULTIPROCESS
+ delete csocket;
+#endif
+}
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+void QWSClient::removeUnbufferedSurface()
+{
+ Q_D(QWSClient);
+ --d->numUnbufferedSurfaces;
+}
+
+void QWSClient::addUnbufferedSurface()
+{
+ Q_D(QWSClient);
+ ++d->numUnbufferedSurfaces;
+}
+#endif // QT_NO_QWS_MULTIPROCESS
+
+/*!
+ \internal
+*/
+void QWSClient::setIdentity(const QString& i)
+{
+ id = i;
+}
+
+void QWSClient::closeHandler()
+{
+ isClosed = true;
+ emit connectionClosed();
+}
+
+void QWSClient::errorHandler()
+{
+#if defined(QWS_SOCKET_DEBUG)
+ qDebug("Client %p error %s", this, csocket ? csocket->errorString().toLatin1().constData() : "(no socket)");
+#endif
+ isClosed = true;
+//####Do we need to clean out the pipes?
+
+ emit connectionClosed();
+}
+
+/*!
+ \internal
+*/
+int QWSClient::socket() const
+{
+ return socketDescriptor;
+}
+
+/*!
+ \internal
+*/
+void QWSClient::sendEvent(QWSEvent* event)
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (csocket) {
+ // qDebug() << "QWSClient::sendEvent type " << event->type << " socket state " << csocket->state();
+ if ((QAbstractSocket::SocketState)(csocket->state()) == QAbstractSocket::ConnectedState) {
+ event->write(csocket);
+ }
+ }
+ else
+#endif
+ {
+ qt_client_enqueue(event);
+ }
+}
+
+/*!
+ \internal
+*/
+void QWSClient::sendRegionEvent(int winid, QRegion rgn, int type
+#ifdef QT_QWS_CLIENTBLIT
+ , int id
+#endif
+ )
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ Q_D(QWSClient);
+ if (d->clientLock)
+ d->clientLock->lock(QWSLock::RegionEvent);
+#endif
+
+ QWSRegionEvent event;
+ event.setData(winid, rgn, type);
+#ifdef QT_QWS_CLIENTBLIT
+ event.simpleData.id = id;
+#endif
+
+// qDebug() << "Sending Region event to" << winid << "rgn" << rgn << "type" << type;
+
+ sendEvent(&event);
+}
+
+extern int qt_servershmid;
+
+/*!
+ \internal
+*/
+void QWSClient::sendConnectedEvent(const char *display_spec)
+{
+ QWSConnectedEvent event;
+ event.simpleData.window = 0;
+ event.simpleData.len = strlen(display_spec) + 1;
+ event.simpleData.clientId = cid;
+ event.simpleData.servershmid = qt_servershmid;
+ char * tmp=(char *)display_spec;
+ event.setData(tmp, event.simpleData.len);
+ sendEvent(&event);
+}
+
+/*!
+ \internal
+*/
+void QWSClient::sendMaxWindowRectEvent(const QRect &rect)
+{
+ QWSMaxWindowRectEvent event;
+ event.simpleData.window = 0;
+ event.simpleData.rect = rect;
+ sendEvent(&event);
+}
+
+/*!
+ \internal
+*/
+#ifndef QT_NO_QWS_PROPERTIES
+void QWSClient::sendPropertyNotifyEvent(int property, int state)
+{
+ QWSPropertyNotifyEvent event;
+ event.simpleData.window = 0; // not used yet
+ event.simpleData.property = property;
+ event.simpleData.state = state;
+ sendEvent(&event);
+}
+
+/*!
+ \internal
+*/
+void QWSClient::sendPropertyReplyEvent(int property, int len, const char *data)
+{
+ QWSPropertyReplyEvent event;
+ event.simpleData.window = 0; // not used yet
+ event.simpleData.property = property;
+ event.simpleData.len = len;
+ event.setData(data, len);
+ sendEvent(&event);
+}
+#endif //QT_NO_QWS_PROPERTIES
+
+/*!
+ \internal
+*/
+void QWSClient::sendSelectionClearEvent(int windowid)
+{
+ QWSSelectionClearEvent event;
+ event.simpleData.window = windowid;
+ sendEvent(&event);
+}
+
+/*!
+ \internal
+*/
+void QWSClient::sendSelectionRequestEvent(QWSConvertSelectionCommand *cmd, int windowid)
+{
+ QWSSelectionRequestEvent event;
+ event.simpleData.window = windowid;
+ event.simpleData.requestor = cmd->simpleData.requestor;
+ event.simpleData.property = cmd->simpleData.selection;
+ event.simpleData.mimeTypes = cmd->simpleData.mimeTypes;
+ sendEvent(&event);
+}
+
+#ifndef QT_NO_QWSEMBEDWIDGET
+/*!
+ \internal
+*/
+void QWSClient::sendEmbedEvent(int windowid, QWSEmbedEvent::Type type,
+ const QRegion &region)
+{
+ QWSEmbedEvent event;
+ event.setData(windowid, type, region);
+ sendEvent(&event);
+}
+#endif // QT_NO_QWSEMBEDWIDGET
+
+/*!
+ \fn void QWSClient::connectionClosed()
+ \internal
+*/
+
+/*!
+ \fn void QWSClient::readyRead();
+ \internal
+*/
+
+/*!
+ \fn int QWSClient::clientId () const
+
+ Returns an integer uniquely identfying this client.
+*/
+
+/*!
+ \fn QString QWSClient::identity () const
+
+ Returns the name of this client's running application.
+*/
+/*********************************************************************
+ *
+ * Class: QWSServer
+ *
+ *********************************************************************/
+
+/*!
+ \class QWSServer
+ \brief The QWSServer class encapsulates a server process in Qt for Embedded Linux.
+
+ \ingroup qws
+
+ When you run a \l{Qt for Embedded Linux} application, it either runs as a
+ server or connects to an existing server. The server and client
+ processes have different responsibilities: The client process
+ performs all application specific operations. The server process
+ is responsible for managing the clients as well as taking care of
+ the pointer handling, character input, and screen output. In
+ addition, the server provides functionality to handle input
+ methods.
+
+ In \l{Qt for Embedded Linux}, all system generated events are passed to the
+ server application which then propagates the event to the
+ appropriate client. See the \l{Qt for Embedded Linux Architecture}
+ documentation for details.
+
+ Note that this class is instantiated by QApplication for
+ \l{Qt for Embedded Linux} server processes; you should never construct this
+ class yourself. Use the instance() function to retrieve a pointer
+ to the server object.
+
+ Note that the static functions of the QWSServer class can only be
+ used in the server process.
+
+ \tableofcontents
+
+ \section1 Client Administration
+
+ As applications add and remove windows, the server process
+ maintains information about each window. In \l{Qt for Embedded Linux},
+ top-level windows are encapsulated as QWSWindow objects. Each
+ window can tell which client that owns it through its
+ QWSWindow::client() function. Use the clientWindows() function to
+ retrieve a list of the current top-level windows. Given a
+ particular position on the display, the window containing it can
+ be retrieved using the windowAt() function.
+
+ QWSServer also provides the windowEvent() signal which is emitted
+ whenever something happens to a top level window; the WindowEvent
+ enum describes the various types of events that the signal
+ recognizes. In addition, the server class provides the
+ markedText() signal which is emitted whenever some text has been
+ selected in any of the windows, passing the selection as
+ parameter.
+
+ The QCopChannel class and the QCOP communication protocol enable
+ transfer of messages between clients. QWSServer provides the
+ newChannel() and removedChannel() signals that is emitted whenever
+ a new QCopChannel object is created or destroyed, respectively.
+
+ See also: QWSWindow, QWSClient and QCopChannel.
+
+
+ \section1 Mouse Handling
+
+ The mouse driver (represented by an instance of the
+ QWSMouseHandler class) is loaded by the server application when it
+ starts running, using Qt's \l {How to Create Qt Plugins}{plugin
+ system}. A mouse driver receives mouse events from the device and
+ encapsulates each event with an instance of the QWSEvent class
+ which it then passes to the server.
+
+ The openMouse() function opens the mouse devices specified by the
+ QWS_MOUSE_PROTO environment variable, and the setMouseHandler()
+ functions sets the primary mouse driver. Alternatively, the static
+ setDefaultMouse() function provides means of specifying the mouse
+ driver to use if the QWS_MOUSE_PROTO variable is not defined (note
+ that the default is otherwise platform dependent). The primary
+ mouse driver can be retrieved using the static mouseHandler()
+ function. Use the closeMouse() function to delete the mouse
+ drivers.
+
+ In addition, the QWSServer class can control the flow of mouse
+ input using the suspendMouse() and resumeMouse() functions.
+
+ See also: QWSMouseHandler and \l{Qt for Embedded Linux Pointer Handling}.
+
+ \section1 Keyboard Handling
+
+ The keyboard driver (represented by an instance of the
+ QWSKeyboardHandler class) is loaded by the server application when
+ it starts running, using Qt's \l {How to Create Qt Plugins}{plugin
+ system}. A keyboard driver receives keyboard events from the
+ device and encapsulates each event with an instance of the
+ QWSEvent class which it then passes to the server.
+
+ The openKeyboard() function opens the keyboard devices specified
+ by the QWS_KEYBOARD environment variable, and the
+ setKeyboardHandler() functions sets the primary keyboard
+ driver. Alternatively, the static setDefaultKeyboard() function
+ provides means of specifying the keyboard driver to use if the
+ QWS_KEYBOARD variable is not defined (note again that the default
+ is otherwise platform dependent). The primary keyboard driver can
+ be retrieved using the static keyboardHandler() function. Use the
+ closeKeyboard() function to delete the keyboard drivers.
+
+ In addition, the QWSServer class can handle key events from both
+ physical and virtual keyboards using the processKeyEvent() and
+ sendKeyEvent() functions, respectively. Use the
+ addKeyboardFilter() function to filter the key events from
+ physical keyboard drivers, the most recently added filter can be
+ removed and deleted using the removeKeyboardFilter() function.
+
+ See also: QWSKeyboardHandler and \l{Qt for Embedded Linux Character Input}.
+
+ \section1 Display Handling
+
+ When a screen update is required, the server runs through all the
+ top-level windows that intersect with the region that is about to
+ be updated, and ensures that the associated clients have updated
+ their memory buffer. Then the server uses the screen driver
+ (represented by an instance of the QScreen class) to copy the
+ content of the memory to the screen.
+
+ In addition, the QWSServer class provides some means of managing
+ the screen output: Use the refresh() function to refresh the
+ entire display, or alternatively a specified region of it. The
+ enablePainting() function can be used to disable (and enable)
+ painting onto the screen. QWSServer also provide the
+ setMaxWindowRect() function restricting the area of the screen
+ which \l{Qt for Embedded Linux} applications will consider to be the
+ maximum area to use for windows. To set the brush used as the
+ background in the absence of obscuring windows, QWSServer provides
+ the static setBackground() function. The corresponding
+ backgroundBrush() function returns the currently set brush.
+
+ QWSServer also controls the screen saver: Use the setScreenSaver()
+ to install a custom screen saver derived from the QWSScreenSaver
+ class. Once installed, the screensaver can be activated using the
+ screenSaverActivate() function, and the screenSaverActive()
+ function returns its current status. Use the
+ setScreenSaverInterval() function to specify the timeout interval.
+ \l{Qt for Embedded Linux} also supports multilevel screen saving, use the
+ setScreenSaverIntervals() function to specify the various levels
+ and their timeout intervals.
+
+ Finally, the QWSServer class controls the cursor's appearance,
+ i.e., use the setCursorVisible() function to hide or show the
+ cursor, and the isCursorVisible() function to determine whether
+ the cursor is visible on the display or not.
+
+ See also: QScreen and \l{Qt for Embedded Linux Display Management}.
+
+ \section1 Input Method Handling
+
+ Whenever the server receives an event, it queries its stack of
+ top-level windows to find the window containing the event's
+ position (each window can identify the client application that
+ created it). Then the server forwards the event to the appropriate
+ client. If an input method is installed, it is used as a filter
+ between the server and the client application.
+
+ Derive from the QWSInputMethod class to create custom input
+ methods, and use the server's setCurrentInputMethod() function to
+ install it. Use the sendIMEvent() and sendIMQuery() functions to
+ send input method events and queries.
+
+ QWSServer provides the IMMouse enum describing the various mouse
+ events recognized by the QWSInputMethod::mouseHandler()
+ function. The latter function allows subclasses of QWSInputMethod
+ to handle mouse events within the preedit text.
+
+ \sa QWSInputMethod
+*/
+
+/*!
+ \enum QWSServer::IMState
+ \obsolete
+
+ This enum describes the various states of an input method.
+
+ \value IMCompose Composing.
+ \value IMStart Equivalent to IMCompose.
+ \value IMEnd Finished composing.
+
+ \sa QWSInputMethod::sendIMEvent()
+*/
+
+/*!
+ \enum QWSServer::IMMouse
+
+ This enum describes the various types of mouse events recognized
+ by the QWSInputMethod::mouseHandler() function.
+
+ \value MousePress An event generated by pressing a mouse button.
+ \value MouseRelease An event generated by relasing a mouse button.
+ \value MouseMove An event generated by moving the mouse cursor.
+ \value MouseOutside This value is only reserved, i.e., it is not used in
+ current implementations.
+
+ \sa QWSInputMethod, setCurrentInputMethod()
+*/
+
+/*!
+ \enum QWSServer::ServerFlags
+ \internal
+
+ This enum is used to pass various options to the window system
+ server.
+
+ \value DisableKeyboard Ignore all keyboard input.
+ \value DisableMouse Ignore all mouse input.
+*/
+
+/*!
+ \enum QWSServer::WindowEvent
+
+ This enum specifies the various events that can occur in a
+ top-level window.
+
+ \value Create A new window has been created (by the QWidget constructor).
+ \value Destroy The window has been closed and deleted (by the QWidget destructor).
+ \value Hide The window has been hidden using the QWidget::hide() function.
+ \value Show The window has been shown using the QWidget::show() function or similar.
+ \value Raise The window has been raised to the top of the desktop.
+ \value Lower The window has been lowered.
+ \value Geometry The window has changed size or position.
+ \value Active The window has become the active window (i.e., it has keyboard focus).
+ \value Name The window has been named.
+
+ \sa windowEvent()
+*/
+
+/*!
+ \fn void QWSServer::markedText(const QString &selection)
+
+ This signal is emitted whenever some text is selected in any of
+ the running applications, passing the selected text in the \a
+ selection parameter.
+
+ \sa windowEvent()
+*/
+
+/*!
+ \fn const QList<QWSWindow*> &QWSServer::clientWindows()
+
+ Returns the list of current top-level windows.
+
+ Note that the collection of top-level windows changes as
+ applications add and remove widgets so it should not be stored for
+ future use. The windows are sorted in stacking order from top-most
+ to bottom-most.
+
+ Use the QWSWindow::client() function to retrieve the client
+ application that owns a given window.
+
+ \sa windowAt(), instance()
+*/
+
+/*!
+ \fn void QWSServer::newChannel(const QString& channel)
+
+ This signal is emitted whenever a new QCopChannel object is
+ created, passing the channel's name in the \a channel parameter.
+
+ \sa removedChannel()
+*/
+
+/*!
+ \fn void QWSServer::removedChannel(const QString& channel)
+
+ This signal is emitted immediately after the given the QCopChannel
+ object specified by \a channel, is destroyed.
+
+ Note that a channel is not destroyed until all its listeners have
+ been unregistered.
+
+ \sa newChannel()
+*/
+
+/*!
+ \fn QWSServer::QWSServer(int flags, QObject *parent)
+ \internal
+
+ Construct a QWSServer object with the given \a parent. The \a
+ flags are used for keyboard and mouse settings.
+
+ \warning This class is instantiated by QApplication for
+ \l{Qt for Embedded Linux} server processes. You should never construct
+ this class yourself.
+
+ \sa {Running Applications}
+*/
+
+/*!
+ \fn static QWSServer* QWSServer::instance()
+ \since 4.2
+
+ Returns a pointer to the server instance.
+
+ Note that the pointer will be 0 if the application is not the
+ server, i.e., if the QApplication::type() function doesn't return
+ QApplication::GuiServer.
+
+ \sa clientWindows(), windowAt()
+*/
+
+struct QWSCommandStruct
+{
+ QWSCommandStruct(QWSCommand *c, QWSClient *cl) :command(c),client(cl){}
+ ~QWSCommandStruct() { delete command; }
+
+ QWSCommand *command;
+ QWSClient *client;
+
+};
+
+QWSServer::QWSServer(int flags, QObject *parent) :
+ QObject(*new QWSServerPrivate, parent)
+{
+ Q_D(QWSServer);
+ d->initServer(flags);
+}
+
+#ifdef QT3_SUPPORT
+/*!
+ Use the two-argument overload and call the
+ QObject::setObjectName() function instead.
+*/
+QWSServer::QWSServer(int flags, QObject *parent, const char *name) :
+ QObject(*new QWSServerPrivate, parent)
+{
+ Q_D(QWSServer);
+ setObjectName(QString::fromAscii(name));
+ d->initServer(flags);
+}
+#endif
+
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+static void ignoreSignal(int) {} // Used to eat SIGPIPE signals below
+#endif
+
+bool QWSServerPrivate::screensaverblockevent( int index, int *screensaverinterval, bool isDown )
+{
+ static bool ignoreEvents[2] = { false, false };
+ if ( isDown ) {
+ if ( !ignoreEvents[index] ) {
+ bool wake = false;
+ if ( screensaverintervals ) {
+ if ( screensaverinterval != screensaverintervals ) {
+ wake = true;
+ }
+ }
+ if ( screensaverblockevents && wake ) {
+#ifdef EVENT_BLOCK_DEBUG
+ qDebug( "waking the screen" );
+#endif
+ ignoreEvents[index] = true;
+ } else if ( !screensaverblockevents ) {
+#ifdef EVENT_BLOCK_DEBUG
+ qDebug( "the screen was already awake" );
+#endif
+ ignoreEvents[index] = false;
+ }
+ }
+ } else {
+ if ( ignoreEvents[index] ) {
+#ifdef EVENT_BLOCK_DEBUG
+ qDebug( "mouseup?" );
+#endif
+ ignoreEvents[index] = false;
+ return true;
+ }
+ }
+ return ignoreEvents[index];
+}
+
+void QWSServerPrivate::initServer(int flags)
+{
+ Q_Q(QWSServer);
+ Q_ASSERT(!qwsServer);
+ qwsServer = q;
+ qwsServerPrivate = this;
+ disablePainting = false;
+#ifndef QT_NO_QWS_MULTIPROCESS
+ ssocket = new QWSServerSocket(qws_qtePipeFilename(), q);
+ QObject::connect(ssocket, SIGNAL(newConnection()), q, SLOT(_q_newConnection()));
+
+ if ( !ssocket->isListening()) {
+ perror("QWSServerPrivate::initServer: server socket not listening");
+ qFatal("Failed to bind to %s", qws_qtePipeFilename().toLatin1().constData());
+ }
+
+ struct linger tmp;
+ tmp.l_onoff=1;
+ tmp.l_linger=0;
+ setsockopt(ssocket->socketDescriptor(),SOL_SOCKET,SO_LINGER,(char *)&tmp,sizeof(tmp));
+
+
+ signal(SIGPIPE, ignoreSignal); //we get it when we read
+#endif
+ focusw = 0;
+ mouseGrabber = 0;
+ mouseGrabbing = false;
+ inputMethodMouseGrabbed = false;
+ keyboardGrabber = 0;
+ keyboardGrabbing = false;
+#ifndef QT_NO_QWS_CURSOR
+ haveviscurs = false;
+ cursor = 0;
+ nextCursor = 0;
+#endif
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+
+ if (!geteuid()) {
+#if !defined(Q_OS_FREEBSD) && !defined(Q_OS_SOLARIS) && !defined(Q_OS_DARWIN) && !defined(QT_LINUXBASE)
+ if(mount(0,"/var/shm", "shm", 0, 0)) {
+ /* This just confuses people with 2.2 kernels
+ if (errno != EBUSY)
+ qDebug("Failed mounting shm fs on /var/shm: %s",strerror(errno));
+ */
+ }
+#endif
+ }
+#endif
+
+ // no selection yet
+ selectionOwner.windowid = -1;
+ selectionOwner.time.set(-1, -1, -1, -1);
+
+ cleanupFontsDir();
+
+ // initialize the font database
+ // from qfontdatabase_qws.cpp
+ extern void qt_qws_init_fontdb();
+ qt_qws_init_fontdb();
+
+ openDisplay();
+
+ screensavertimer = new QTimer(q);
+ screensavertimer->setSingleShot(true);
+ QObject::connect(screensavertimer, SIGNAL(timeout()), q, SLOT(_q_screenSaverTimeout()));
+ _q_screenSaverWake();
+
+ clientMap[-1] = new QWSClient(q, 0, 0);
+
+ if (!bgBrush)
+ bgBrush = new QBrush(QColor(0x20, 0xb0, 0x50));
+
+ initializeCursor();
+
+ // input devices
+ if (!(flags&QWSServer::DisableMouse)) {
+ q->openMouse();
+ }
+#ifndef QT_NO_QWS_KEYBOARD
+ if (!(flags&QWSServer::DisableKeyboard)) {
+ q->openKeyboard();
+ }
+#endif
+
+#if !defined(QT_NO_SOUND) && !defined(QT_EXTERNAL_SOUND_SERVER) && !defined(Q_OS_DARWIN)
+ soundserver = new QWSSoundServer(q);
+#endif
+}
+
+/*!
+ \internal
+ Destructs this server.
+*/
+QWSServer::~QWSServer()
+{
+ closeMouse();
+#ifndef QT_NO_QWS_KEYBOARD
+ closeKeyboard();
+#endif
+ d_func()->cleanupFonts(/*force =*/true);
+}
+
+/*!
+ \internal
+ */
+void QWSServer::timerEvent(QTimerEvent *e)
+{
+ Q_D(QWSServer);
+ if (e->timerId() == d->fontCleanupTimer.timerId()) {
+ d->cleanupFonts();
+ d->fontCleanupTimer.stop();
+ } else {
+ QObject::timerEvent(e);
+ }
+}
+
+const QList<QWSWindow*> &QWSServer::clientWindows()
+{
+ Q_D(QWSServer);
+ return d->windows;
+}
+
+/*!
+ \internal
+*/
+void QWSServerPrivate::releaseMouse(QWSWindow* w)
+{
+ if (w && mouseGrabber == w) {
+ mouseGrabber = 0;
+ mouseGrabbing = false;
+#ifndef QT_NO_QWS_CURSOR
+ if (nextCursor) {
+ // Not grabbing -> set the correct cursor
+ setCursor(nextCursor);
+ nextCursor = 0;
+ }
+#endif
+ }
+}
+
+/*!
+ \internal
+*/
+void QWSServerPrivate::releaseKeyboard(QWSWindow* w)
+{
+ if (keyboardGrabber == w) {
+ keyboardGrabber = 0;
+ keyboardGrabbing = false;
+ }
+}
+
+void QWSServerPrivate::handleWindowClose(QWSWindow *w)
+{
+ w->shuttingDown();
+ if (focusw == w)
+ setFocus(w,false);
+ if (mouseGrabber == w)
+ releaseMouse(w);
+ if (keyboardGrabber == w)
+ releaseKeyboard(w);
+}
+
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+/*!
+ \internal
+*/
+void QWSServerPrivate::_q_newConnection()
+{
+ Q_Q(QWSServer);
+ while (QWS_SOCK_BASE *sock = ssocket->nextPendingConnection()) {
+ int socket = sock->socketDescriptor();
+ sock->setParent(0);
+
+ QWSClient *client = new QWSClient(q,sock, get_object_id());
+ clientMap[socket] = client;
+
+#ifndef QT_NO_SXE
+#ifdef QTRANSPORTAUTH_DEBUG
+ qDebug( "Transport auth connected: unix stream socket %d", socket );
+#endif
+ // get a handle to the per-process authentication service
+ QTransportAuth *a = QTransportAuth::getInstance();
+
+ // assert that this transport is trusted
+ QTransportAuth::Data *d = a->connectTransport(
+ QTransportAuth::UnixStreamSock |
+ QTransportAuth::Trusted, socket );
+
+ QAuthDevice *ad = a->recvBuf( d, sock );
+ ad->setClient(client);
+
+ QObject::connect(ad, SIGNAL(readyRead()),
+ q, SLOT(_q_doClient()));
+
+ QObject::connect(client, SIGNAL(connectionClosed()),
+ q, SLOT(_q_clientClosed()));
+#else
+ QObject::connect(client, SIGNAL(readyRead()),
+ q, SLOT(_q_doClient()));
+ QObject::connect(client, SIGNAL(connectionClosed()),
+ q, SLOT(_q_clientClosed()));
+#endif // QT_NO_SXE
+
+ client->sendConnectedEvent(qws_display_spec.constData());
+
+ if (clientMap.contains(socket)) {
+ QList<QScreen*> screens = qt_screen->subScreens();
+ if (screens.isEmpty())
+ screens.append(qt_screen);
+ for (int i = 0; i < screens.size(); ++i) {
+ const QApplicationPrivate *ap = QApplicationPrivate::instance();
+ QScreen *screen = screens.at(i);
+ const QRect rect = ap->maxWindowRect(screen);
+ if (!rect.isEmpty())
+ client->sendMaxWindowRectEvent(rect);
+ if (screen->isTransformed()) {
+ QWSScreenTransformationEvent event;
+ event.simpleData.screen = i;
+ event.simpleData.transformation = screen->transformOrientation();
+ client->sendEvent(&event);
+ }
+ }
+ }
+
+ // pre-provide some object id's
+ QWSCreateCommand cmd(30);
+ invokeCreate(&cmd, client);
+ }
+}
+/*!
+ \internal
+*/
+void QWSServerPrivate::_q_clientClosed()
+{
+ Q_Q(QWSServer);
+ QWSClient* cl = (QWSClient*)q->sender();
+
+ // Remove any queued commands for this client
+ int i = 0;
+ while (i < commandQueue.size()) {
+ QWSCommandStruct *cs = commandQueue.at(i);
+ if (cs->client == cl) {
+ commandQueue.removeAt(i);
+ delete cs;
+ } else {
+ ++i;
+ }
+ }
+
+#ifndef QT_NO_COP
+ // Enfore unsubscription from all channels.
+ QCopChannel::detach(cl);
+#endif
+
+ // Shut down all windows for this client
+ for (int i = 0; i < windows.size(); ++i) {
+ QWSWindow* w = windows.at(i);
+ if (w->forClient(cl))
+ w->shuttingDown();
+ }
+
+ // Delete all windows for this client
+ QRegion exposed;
+ i = 0;
+ while (i < windows.size()) {
+ QWSWindow* w = windows.at(i);
+ if (w->forClient(cl)) {
+ windows.takeAt(i);
+ w->c = 0; //so we don't send events to it anymore
+ releaseMouse(w);
+ releaseKeyboard(w);
+ exposed += w->allocatedRegion();
+// rgnMan->remove(w->allocationIndex());
+ if (focusw == w)
+ setFocus(focusw,0);
+ if (mouseGrabber == w)
+ releaseMouse(w);
+ if (i < nReserved)
+ --nReserved;
+#ifndef QT_NO_QWS_PROPERTIES
+ propertyManager.removeProperties(w->winId());
+#endif
+ emit q->windowEvent(w, QWSServer::Destroy);
+ w->d->state = QWSWindow::Destroyed; //???
+ deletedWindows.append(w);
+ } else {
+ ++i;
+ }
+ }
+ if (deletedWindows.count())
+ QTimer::singleShot(0, q, SLOT(_q_deleteWindowsLater()));
+
+ QWSClientPrivate *clientPrivate = cl->d_func();
+ if (!clientPrivate->shutdown) {
+#if defined(QWS_DEBUG_FONTCLEANUP)
+ qDebug() << "client" << cl->clientId() << "crashed";
+#endif
+ // this would be the place to emit a signal to notify about the
+ // crash of a client
+ crashedClientIds.append(cl->clientId());
+ fontCleanupTimer.start(10, q_func());
+ }
+ clientPrivate->shutdown = true;
+
+ while (!clientPrivate->usedFonts.isEmpty()) {
+ const QByteArray font = *clientPrivate->usedFonts.begin();
+#if defined(QWS_DEBUG_FONTCLEANUP)
+ qDebug() << "dereferencing font" << font << "from disconnected client";
+#endif
+ dereferenceFont(clientPrivate, font);
+ }
+ clientPrivate->usedFonts.clear();
+
+ //qDebug("removing client %d with socket %d", cl->clientId(), cl->socket());
+ clientMap.remove(cl->socket());
+ if (cl == cursorClient)
+ cursorClient = 0;
+ if (qt_screen->clearCacheFunc)
+ (qt_screen->clearCacheFunc)(qt_screen, cl->clientId()); // remove any remaining cache entries.
+ cl->deleteLater();
+
+ update_regions();
+ exposeRegion(exposed);
+}
+
+void QWSServerPrivate::_q_deleteWindowsLater()
+{
+ qDeleteAll(deletedWindows);
+ deletedWindows.clear();
+}
+
+#endif //QT_NO_QWS_MULTIPROCESS
+
+void QWSServerPrivate::referenceFont(QWSClientPrivate *client, const QByteArray &font)
+{
+ if (!client->usedFonts.contains(font)) {
+ client->usedFonts.insert(font);
+
+ ++fontReferenceCount[font];
+#if defined(QWS_DEBUG_FONTCLEANUP)
+ qDebug() << "Client" << client->q_func()->clientId() << "added font" << font;
+ qDebug() << "Refcount is" << fontReferenceCount[font];
+#endif
+ }
+}
+
+void QWSServerPrivate::dereferenceFont(QWSClientPrivate *client, const QByteArray &font)
+{
+ if (client->usedFonts.contains(font)) {
+ client->usedFonts.remove(font);
+
+ Q_ASSERT(fontReferenceCount[font]);
+ if (!--fontReferenceCount[font] && !fontCleanupTimer.isActive())
+ fontCleanupTimer.start(FontCleanupInterval, q_func());
+
+#if defined(QWS_DEBUG_FONTCLEANUP)
+ qDebug() << "Client" << client->q_func()->clientId() << "removed font" << font;
+ qDebug() << "Refcount is" << fontReferenceCount[font];
+#endif
+ }
+}
+
+static void cleanupFontsDir()
+{
+ static bool dontDelete = !qgetenv("QWS_KEEP_FONTS").isEmpty();
+ if (dontDelete)
+ return;
+
+ extern QString qws_fontCacheDir();
+ QDir dir(qws_fontCacheDir(), QLatin1String("*.qsf"));
+ for (uint i = 0; i < dir.count(); ++i) {
+#if defined(QWS_DEBUG_FONTCLEANUP)
+ qDebug() << "removing stale font file" << dir[i];
+#endif
+ dir.remove(dir[i]);
+ }
+}
+
+void QWSServerPrivate::cleanupFonts(bool force)
+{
+ static bool dontDelete = !qgetenv("QWS_KEEP_FONTS").isEmpty();
+ if (dontDelete)
+ return;
+
+#if defined(QWS_DEBUG_FONTCLEANUP)
+ qDebug() << "cleanupFonts()";
+#endif
+ QMap<QByteArray, int>::Iterator it = fontReferenceCount.begin();
+ while (it != fontReferenceCount.end()) {
+ if (it.value() && !force) {
+ ++it;
+ continue;
+ }
+
+ const QByteArray &fontName = it.key();
+#if defined(QWS_DEBUG_FONTCLEANUP)
+ qDebug() << "removing unused font file" << fontName;
+#endif
+ QFile::remove(QFile::decodeName(fontName));
+ sendFontRemovedEvent(fontName);
+
+ it = fontReferenceCount.erase(it);
+ }
+
+ if (crashedClientIds.isEmpty())
+ return;
+
+ QList<QByteArray> removedFonts;
+#if !defined(QT_NO_QWS_QPF2) && !defined(QT_FONTS_ARE_RESOURCES)
+ removedFonts = QFontEngineQPF::cleanUpAfterClientCrash(crashedClientIds);
+#endif
+ crashedClientIds.clear();
+
+ for (int i = 0; i < removedFonts.count(); ++i)
+ sendFontRemovedEvent(removedFonts.at(i));
+}
+
+void QWSServerPrivate::sendFontRemovedEvent(const QByteArray &font)
+{
+ QWSFontEvent event;
+ event.simpleData.type = QWSFontEvent::FontRemoved;
+ event.setData(font.constData(), font.length(), false);
+
+ QMap<int,QWSClient*>::const_iterator it = clientMap.constBegin();
+ for (; it != clientMap.constEnd(); ++it)
+ (*it)->sendEvent(&event);
+}
+
+/*!
+ \internal
+*/
+QWSCommand* QWSClient::readMoreCommand()
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ QIODevice *socket = 0;
+#endif
+#ifndef QT_NO_SXE
+ if (socketDescriptor != -1) // not server socket
+ socket = QTransportAuth::getInstance()->passThroughByClient( this );
+#if QTRANSPORTAUTH_DEBUG
+ if (socket) {
+ char displaybuf[1024];
+ qint64 bytes = socket->bytesAvailable();
+ if ( bytes > 511 ) bytes = 511;
+ hexstring( displaybuf, ((unsigned char *)(reinterpret_cast<QAuthDevice*>(socket)->buffer().constData())), bytes );
+ qDebug( "readMoreCommand: %lli bytes - %s", socket->bytesAvailable(), displaybuf );
+ }
+#endif
+#endif // QT_NO_SXE
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (!socket)
+ socket = csocket; // server socket
+ if (socket) {
+ // read next command
+ if (!command) {
+ int command_type = qws_read_uint(socket);
+
+ if (command_type >= 0)
+ command = QWSCommand::factory(command_type);
+ }
+ if (command) {
+ if (command->read(socket)) {
+ // Finished reading a whole command.
+ QWSCommand* result = command;
+ command = 0;
+ return result;
+ }
+ }
+
+ // Not finished reading a whole command.
+ return 0;
+ } else
+#endif // QT_NO_QWS_MULTIPROCESS
+ {
+ QList<QWSCommand*> *serverQueue = qt_get_server_queue();
+ return serverQueue->isEmpty() ? 0 : serverQueue->takeFirst();
+ }
+}
+
+
+/*!
+ \internal
+*/
+void QWSServer::processEventQueue()
+{
+ if (qwsServerPrivate)
+ qwsServerPrivate->doClient(qwsServerPrivate->clientMap.value(-1));
+}
+
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+void QWSServerPrivate::_q_doClient()
+{
+ Q_Q(QWSServer);
+
+ QWSClient* client;
+#ifndef QT_NO_SXE
+ QAuthDevice *ad = qobject_cast<QAuthDevice*>(q->sender());
+ if (ad)
+ client = (QWSClient*)ad->client();
+ else
+#endif
+ client = (QWSClient*)q->sender();
+
+ if (doClientIsActive) {
+ pendingDoClients.append(client);
+ return;
+ }
+ doClientIsActive = true;
+
+ doClient(client);
+
+ while (!pendingDoClients.isEmpty()) {
+ doClient(pendingDoClients.takeFirst());
+ }
+
+ doClientIsActive = false;
+}
+#endif // QT_NO_QWS_MULTIPROCESS
+
+void QWSServerPrivate::doClient(QWSClient *client)
+{
+ QWSCommand* command=client->readMoreCommand();
+
+ while (command) {
+ QWSCommandStruct *cs = new QWSCommandStruct(command, client);
+ commandQueue.append(cs);
+ // Try for some more...
+ command=client->readMoreCommand();
+ }
+
+ while (!commandQueue.isEmpty()) {
+ QWSCommandStruct *cs = commandQueue.takeAt(0);
+ switch (cs->command->type) {
+ case QWSCommand::Identify:
+ invokeIdentify((QWSIdentifyCommand*)cs->command, cs->client);
+ break;
+ case QWSCommand::Create:
+ invokeCreate((QWSCreateCommand*)cs->command, cs->client);
+ break;
+#ifndef QT_NO_QWS_MULTIPROCESS
+ case QWSCommand::Shutdown:
+ cs->client->d_func()->shutdown = true;
+ break;
+#endif
+ case QWSCommand::RegionName:
+ invokeRegionName((QWSRegionNameCommand*)cs->command, cs->client);
+ break;
+ case QWSCommand::Region:
+ invokeRegion((QWSRegionCommand*)cs->command, cs->client);
+ cs->client->d_func()->unlockCommunication();
+ break;
+ case QWSCommand::RegionMove:
+ invokeRegionMove((QWSRegionMoveCommand*)cs->command, cs->client);
+ cs->client->d_func()->unlockCommunication();
+ break;
+ case QWSCommand::RegionDestroy:
+ invokeRegionDestroy((QWSRegionDestroyCommand*)cs->command, cs->client);
+ break;
+#ifndef QT_NO_QWS_PROPERTIES
+ case QWSCommand::AddProperty:
+ invokeAddProperty((QWSAddPropertyCommand*)cs->command);
+ break;
+ case QWSCommand::SetProperty:
+ invokeSetProperty((QWSSetPropertyCommand*)cs->command);
+ break;
+ case QWSCommand::RemoveProperty:
+ invokeRemoveProperty((QWSRemovePropertyCommand*)cs->command);
+ break;
+ case QWSCommand::GetProperty:
+ invokeGetProperty((QWSGetPropertyCommand*)cs->command, cs->client);
+ break;
+#endif
+ case QWSCommand::SetSelectionOwner:
+ invokeSetSelectionOwner((QWSSetSelectionOwnerCommand*)cs->command);
+ break;
+ case QWSCommand::RequestFocus:
+ invokeSetFocus((QWSRequestFocusCommand*)cs->command, cs->client);
+ break;
+ case QWSCommand::ChangeAltitude:
+ invokeSetAltitude((QWSChangeAltitudeCommand*)cs->command,
+ cs->client);
+ cs->client->d_func()->unlockCommunication();
+ break;
+ case QWSCommand::SetOpacity:
+ invokeSetOpacity((QWSSetOpacityCommand*)cs->command,
+ cs->client);
+ break;
+
+#ifndef QT_NO_QWS_CURSOR
+ case QWSCommand::DefineCursor:
+ invokeDefineCursor((QWSDefineCursorCommand*)cs->command, cs->client);
+ break;
+ case QWSCommand::SelectCursor:
+ invokeSelectCursor((QWSSelectCursorCommand*)cs->command, cs->client);
+ break;
+ case QWSCommand::PositionCursor:
+ invokePositionCursor((QWSPositionCursorCommand*)cs->command, cs->client);
+ break;
+#endif
+ case QWSCommand::GrabMouse:
+ invokeGrabMouse((QWSGrabMouseCommand*)cs->command, cs->client);
+ break;
+ case QWSCommand::GrabKeyboard:
+ invokeGrabKeyboard((QWSGrabKeyboardCommand*)cs->command, cs->client);
+ break;
+#if !defined(QT_NO_SOUND) && !defined(Q_OS_DARWIN)
+ case QWSCommand::PlaySound:
+ invokePlaySound((QWSPlaySoundCommand*)cs->command, cs->client);
+ break;
+#endif
+#ifndef QT_NO_COP
+ case QWSCommand::QCopRegisterChannel:
+ invokeRegisterChannel((QWSQCopRegisterChannelCommand*)cs->command,
+ cs->client);
+ break;
+ case QWSCommand::QCopSend:
+ invokeQCopSend((QWSQCopSendCommand*)cs->command, cs->client);
+ break;
+#endif
+#ifndef QT_NO_QWS_INPUTMETHODS
+ case QWSCommand::IMUpdate:
+ invokeIMUpdate((QWSIMUpdateCommand*)cs->command, cs->client);
+ break;
+ case QWSCommand::IMResponse:
+ invokeIMResponse((QWSIMResponseCommand*)cs->command, cs->client);
+ break;
+ case QWSCommand::IMMouse:
+ {
+ if (current_IM) {
+ QWSIMMouseCommand *cmd = (QWSIMMouseCommand *) cs->command;
+ current_IM->mouseHandler(cmd->simpleData.index,
+ cmd->simpleData.state);
+ }
+ }
+ break;
+#endif
+ case QWSCommand::Font:
+ invokeFont((QWSFontCommand *)cs->command, cs->client);
+ break;
+ case QWSCommand::RepaintRegion:
+ invokeRepaintRegion((QWSRepaintRegionCommand*)cs->command,
+ cs->client);
+ cs->client->d_func()->unlockCommunication();
+ break;
+#ifndef QT_NO_QWSEMBEDWIDGET
+ case QWSCommand::Embed:
+ invokeEmbed(static_cast<QWSEmbedCommand*>(cs->command),
+ cs->client);
+ break;
+#endif
+ case QWSCommand::ScreenTransform:
+ invokeScreenTransform(static_cast<QWSScreenTransformCommand*>(cs->command),
+ cs->client);
+ break;
+ }
+ delete cs;
+ }
+}
+
+
+void QWSServerPrivate::showCursor()
+{
+#ifndef QT_NO_QWS_CURSOR
+ if (qt_screencursor)
+ qt_screencursor->show();
+#endif
+}
+
+void QWSServerPrivate::hideCursor()
+{
+#ifndef QT_NO_QWS_CURSOR
+ if (qt_screencursor)
+ qt_screencursor->hide();
+#endif
+}
+
+/*!
+ \fn void QWSServer::enablePainting(bool enable)
+
+ Enables painting onto the screen if \a enable is true; otherwise
+ painting is disabled.
+
+ \sa {Qt for Embedded Linux Architecture#Drawing on Screen}{Qt for Embedded Linux
+ Architecture}
+*/
+void QWSServer::enablePainting(bool enable)
+{
+ Q_D(QWSServer);
+
+ if (d->disablePainting == !enable)
+ return;
+
+ d->disablePainting = !enable;
+
+ if (enable) {
+ // Reset the server side allocated regions to ensure update_regions()
+ // will send out region events.
+ for (int i = 0; i < d->windows.size(); ++i) {
+ QWSWindow *w = d->windows.at(i);
+ w->setAllocatedRegion(QRegion());
+#ifdef QT_QWS_CLIENTBLIT
+ w->setDirectPaintRegion(QRegion());
+#endif
+ }
+ d->update_regions();
+ d->showCursor();
+ } else {
+ // Disable painting by clients by taking away their allocated region.
+ // To ensure mouse events are still delivered to the correct windows,
+ // the allocated regions are not modified on the server.
+ for (int i = 0; i < d->windows.size(); ++i) {
+ QWSWindow *w = d->windows.at(i);
+ w->client()->sendRegionEvent(w->winId(), QRegion(),
+ QWSRegionEvent::Allocation);
+#ifdef QT_QWS_CLIENTBLIT
+ w->client()->sendRegionEvent(w->winId(), QRegion(),
+ QWSRegionEvent::DirectPaint);
+#endif
+ }
+ d->hideCursor();
+ }
+}
+
+/*!
+ Refreshes the display by making the screen driver update the
+ entire display.
+
+ \sa QScreen::exposeRegion()
+*/
+void QWSServer::refresh()
+{
+ Q_D(QWSServer);
+ d->exposeRegion(QScreen::instance()->region());
+//### send repaint to non-buffered windows
+}
+
+/*!
+ \fn void QWSServer::refresh(QRegion & region)
+ \overload
+
+ Refreshes the given \a region of the display.
+*/
+void QWSServer::refresh(QRegion & r)
+{
+ Q_D(QWSServer);
+ d->exposeRegion(r);
+//### send repaint to non-buffered windows
+}
+
+/*!
+ \fn void QWSServer::setMaxWindowRect(const QRect& rectangle)
+
+ Sets the maximum area of the screen that \l{Qt for Embedded Linux}
+ applications can use, to be the given \a rectangle.
+
+ Note that this function can only be used in the server process.
+
+ \sa QWidget::showMaximized()
+*/
+void QWSServer::setMaxWindowRect(const QRect &rect)
+{
+ QList<QScreen*> subScreens = qt_screen->subScreens();
+ if (subScreens.isEmpty() && qt_screen != 0)
+ subScreens.append(qt_screen);
+
+ for (int i = 0; i < subScreens.size(); ++i) {
+ const QScreen *screen = subScreens.at(i);
+ const QRect r = (screen->region() & rect).boundingRect();
+ if (r.isEmpty())
+ continue;
+
+ QApplicationPrivate *ap = QApplicationPrivate::instance();
+ if (ap->maxWindowRect(screen) != r) {
+ ap->setMaxWindowRect(screen, i, r);
+ qwsServerPrivate->sendMaxWindowRectEvents(r);
+ }
+ }
+}
+
+/*!
+ \internal
+*/
+void QWSServerPrivate::sendMaxWindowRectEvents(const QRect &rect)
+{
+ QMap<int,QWSClient*>::const_iterator it = clientMap.constBegin();
+ for (; it != clientMap.constEnd(); ++it)
+ (*it)->sendMaxWindowRectEvent(rect);
+}
+
+/*!
+ \fn void QWSServer::setDefaultMouse(const char *mouseDriver)
+
+ Sets the mouse driver that will be used if the QWS_MOUSE_PROTO
+ environment variable is not defined, to be the given \a
+ mouseDriver.
+
+ Note that the default is platform-dependent. This function can
+ only be used in the server process.
+
+
+ \sa setMouseHandler(), {Qt for Embedded Linux Pointer Handling}
+*/
+void QWSServer::setDefaultMouse(const char *m)
+{
+ *defaultMouse() = QString::fromAscii(m);
+}
+
+/*!
+ \fn void QWSServer::setDefaultKeyboard(const char *keyboardDriver)
+
+ Sets the keyboard driver that will be used if the QWS_KEYBOARD
+ environment variable is not defined, to be the given \a
+ keyboardDriver.
+
+ Note that the default is platform-dependent. This function can
+ only be used in the server process.
+
+ \sa setKeyboardHandler(), {Qt for Embedded Linux Character Input}
+*/
+void QWSServer::setDefaultKeyboard(const char *k)
+{
+ *defaultKeyboard() = QString::fromAscii(k);
+}
+
+#ifndef QT_NO_QWS_CURSOR
+static bool prevWin;
+#endif
+
+
+extern int *qt_last_x,*qt_last_y;
+
+
+/*!
+ \internal
+
+ Send a mouse event. \a pos is the screen position where the mouse
+ event occurred and \a state is a mask indicating which buttons are
+ pressed.
+
+ \a pos is in device coordinates
+*/
+void QWSServer::sendMouseEvent(const QPoint& pos, int state, int wheel)
+{
+ bool block = qwsServerPrivate->screensaverblockevent(MOUSE, qwsServerPrivate->screensaverinterval, state);
+#ifdef EVENT_BLOCK_DEBUG
+ qDebug() << "sendMouseEvent" << pos.x() << pos.y() << state << (block?"block":"pass");
+#endif
+
+ if (state || wheel)
+ qwsServerPrivate->_q_screenSaverWake();
+
+ if ( block )
+ return;
+
+ QPoint tpos;
+ // transformations
+ if (qt_screen->isTransformed()) {
+ QSize s = QSize(qt_screen->deviceWidth(), qt_screen->deviceHeight());
+ tpos = qt_screen->mapFromDevice(pos, s);
+ } else {
+ tpos = pos;
+ }
+
+ if (qt_last_x) {
+ *qt_last_x = tpos.x();
+ *qt_last_y = tpos.y();
+ }
+ QWSServer::mousePosition = tpos;
+ qwsServerPrivate->mouseState = state;
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+ const int btnMask = Qt::LeftButton | Qt::RightButton | Qt::MidButton;
+ int stroke_count; // number of strokes to keep shown.
+ if (force_reject_strokeIM || !current_IM)
+ {
+ stroke_count = 0;
+ } else {
+ stroke_count = current_IM->filter(tpos, state, wheel);
+ }
+
+ if (stroke_count == 0) {
+ if (state&btnMask)
+ force_reject_strokeIM = true;
+ QWSServerPrivate::sendMouseEventUnfiltered(tpos, state, wheel);
+ }
+ // stop force reject after stroke ends.
+ if (state&btnMask && force_reject_strokeIM)
+ force_reject_strokeIM = false;
+ // on end of stroke, force_rejct
+ // and once a stroke is rejected, do not try again till pen is lifted
+#else
+ QWSServerPrivate::sendMouseEventUnfiltered(tpos, state, wheel);
+#endif // end QT_NO_QWS_FSIM
+}
+
+void QWSServerPrivate::sendMouseEventUnfiltered(const QPoint &pos, int state, int wheel)
+{
+ const int btnMask = Qt::LeftButton | Qt::RightButton | Qt::MidButton;
+ QWSMouseEvent event;
+
+ QWSWindow *win = qwsServer->windowAt(pos);
+
+ QWSClient *serverClient = qwsServerPrivate->clientMap.value(-1);
+ QWSClient *winClient = win ? win->client() : 0;
+
+
+ bool imMouse = false;
+#ifndef QT_NO_QWS_INPUTMETHODS
+ // check for input method window
+ if (current_IM && current_IM_winId != -1) {
+ QWSWindow *kbw = keyboardGrabber ? keyboardGrabber :
+ qwsServerPrivate->focusw;
+
+ imMouse = kbw == win;
+ if ( !imMouse ) {
+ QWidget *target = winClient == serverClient ?
+ QApplication::widgetAt(pos) : 0;
+ imMouse = target && (target->testAttribute(Qt::WA_InputMethodTransparent));
+ }
+ }
+#endif
+
+ //If grabbing window disappears, grab is still active until
+ //after mouse release.
+ if ( qwsServerPrivate->mouseGrabber && (!imMouse || qwsServerPrivate->inputMethodMouseGrabbed)) {
+ win = qwsServerPrivate->mouseGrabber;
+ winClient = win ? win->client() : 0;
+ }
+ event.simpleData.window = win ? win->id : 0;
+
+#ifndef QT_NO_QWS_CURSOR
+ if (qt_screencursor)
+ qt_screencursor->move(pos.x(),pos.y());
+
+ // Arrow cursor over desktop
+ // prevWin remembers if the last event was over a window
+ if (!win && prevWin) {
+ if (!qwsServerPrivate->mouseGrabber)
+ qwsServerPrivate->setCursor(QWSCursor::systemCursor(Qt::ArrowCursor));
+ else
+ qwsServerPrivate->nextCursor = QWSCursor::systemCursor(Qt::ArrowCursor);
+ prevWin = false;
+ }
+ // reset prevWin
+ if (win && !prevWin)
+ prevWin = true;
+#endif
+
+ if ((state&btnMask) && !qwsServerPrivate->mouseGrabbing) {
+ qwsServerPrivate->mouseGrabber = win;
+ if (imMouse)
+ qwsServerPrivate->inputMethodMouseGrabbed = true;
+ }
+ if (!(state&btnMask))
+ qwsServerPrivate->inputMethodMouseGrabbed = false;
+
+ event.simpleData.x_root=pos.x();
+ event.simpleData.y_root=pos.y();
+ event.simpleData.state=state | qws_keyModifiers;
+ event.simpleData.delta = wheel;
+ event.simpleData.time=qwsServerPrivate->timer.elapsed();
+
+ static int oldstate = 0;
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+ //tell the input method if we click on a different window that is not IM transparent
+ bool isPress = state > oldstate;
+ if (isPress && !imMouse && current_IM && current_IM_winId != -1)
+ current_IM->mouseHandler(-1, QWSServer::MouseOutside);
+#endif
+
+ if (serverClient)
+ serverClient->sendEvent(&event);
+ if (winClient && winClient != serverClient)
+ winClient->sendEvent(&event);
+
+ if ( !imMouse ) {
+ // Make sure that if we leave a window, that window gets one last mouse
+ // event so that it knows the mouse has left.
+ QWSClient *oldClient = qwsServer->d_func()->cursorClient;
+ if (oldClient && oldClient != winClient && oldClient != serverClient) {
+ event.simpleData.state = oldstate | qws_keyModifiers;
+ oldClient->sendEvent(&event);
+ }
+ }
+
+ oldstate = state;
+ if ( !imMouse )
+ qwsServer->d_func()->cursorClient = winClient;
+
+ if (!(state&btnMask) && !qwsServerPrivate->mouseGrabbing)
+ qwsServerPrivate->releaseMouse(qwsServerPrivate->mouseGrabber);
+}
+
+/*!
+ Returns the primary mouse driver.
+
+ Note that this function can only be used in the server process.
+
+ \sa setMouseHandler(), openMouse(), closeMouse()
+*/
+QWSMouseHandler *QWSServer::mouseHandler()
+{
+ if (qwsServerPrivate->mousehandlers.empty())
+ return 0;
+ return qwsServerPrivate->mousehandlers.first();
+}
+
+/*!
+ \since 4.5
+
+ Returns list of all mouse handlers
+
+ Note that this function can only be used in the server process.
+
+ \sa mouseHandler(), setMouseHandler(), openMouse(), closeMouse()
+*/
+const QList<QWSMouseHandler*>& QWSServer::mouseHandlers()
+{
+ return qwsServerPrivate->mousehandlers;
+}
+
+
+// called by QWSMouseHandler constructor, not user code.
+/*!
+ \fn void QWSServer::setMouseHandler(QWSMouseHandler* driver)
+
+ Sets the primary mouse driver to be the given \a driver.
+
+ \l{Qt for Embedded Linux} provides several ready-made mouse drivers, and
+ custom drivers are typically added using Qt's plugin
+ mechanism. See the \l{Qt for Embedded Linux Pointer Handling} documentation
+ for details.
+
+ Note that this function can only be used in the server process.
+
+ \sa mouseHandler(), setDefaultMouse()
+*/
+void QWSServer::setMouseHandler(QWSMouseHandler* mh)
+{
+ if (!mh)
+ return;
+ qwsServerPrivate->mousehandlers.removeAll(mh);
+ qwsServerPrivate->mousehandlers.prepend(mh);
+}
+
+/*!
+ \internal
+ \obsolete
+ Caller owns data in list, and must delete contents
+*/
+QList<QWSInternalWindowInfo*> * QWSServer::windowList()
+{
+ QList<QWSInternalWindowInfo*> * ret=new QList<QWSInternalWindowInfo*>;
+ for (int i=0; i < qwsServerPrivate->windows.size(); ++i) {
+ QWSWindow *window = qwsServerPrivate->windows.at(i);
+ QWSInternalWindowInfo * qwi=new QWSInternalWindowInfo();
+ qwi->winid=window->winId();
+ qwi->clientid=window->client()->clientId();
+ ret->append(qwi);
+ }
+ return ret;
+}
+
+#ifndef QT_NO_COP
+/*!
+ \internal
+*/
+void QWSServerPrivate::sendQCopEvent(QWSClient *c, const QString &ch,
+ const QString &msg, const QByteArray &data,
+ bool response)
+{
+ Q_ASSERT(c);
+
+ QWSQCopMessageEvent event;
+ event.channel = ch.toLatin1();
+ event.message = msg.toLatin1();
+ event.data = data;
+ event.simpleData.is_response = response;
+ event.simpleData.lchannel = ch.length();
+ event.simpleData.lmessage = msg.length();
+ event.simpleData.ldata = data.size();
+ int l = event.simpleData.lchannel + event.simpleData.lmessage +
+ event.simpleData.ldata;
+
+ // combine channel, message and data into one block of raw bytes
+ char *tmp = new char [l];
+ char *d = tmp;
+ memcpy(d, event.channel.constData(), event.simpleData.lchannel);
+ d += event.simpleData.lchannel;
+ memcpy(d, event.message.constData(), event.simpleData.lmessage);
+ d += event.simpleData.lmessage;
+ memcpy(d, data.constData(), event.simpleData.ldata);
+
+ event.setDataDirect(tmp, l);
+
+ c->sendEvent(&event);
+}
+#endif
+
+/*!
+ \fn QWSWindow *QWSServer::windowAt(const QPoint& position)
+
+ Returns the window containing the given \a position.
+
+ Note that if there is no window under the specified point this
+ function returns 0.
+
+ \sa clientWindows(), instance()
+*/
+QWSWindow *QWSServer::windowAt(const QPoint& pos)
+{
+ Q_D(QWSServer);
+ for (int i=0; i<d->windows.size(); ++i) {
+ QWSWindow* w = d->windows.at(i);
+ if (w->allocatedRegion().contains(pos))
+ return w;
+ }
+ return 0;
+}
+
+#ifndef QT_NO_QWS_KEYBOARD
+static int keyUnicode(int keycode)
+{
+ int code = 0xffff;
+
+ if (keycode >= Qt::Key_A && keycode <= Qt::Key_Z)
+ code = keycode - Qt::Key_A + 'a';
+ else if (keycode >= Qt::Key_0 && keycode <= Qt::Key_9)
+ code = keycode - Qt::Key_0 + '0';
+
+ return code;
+}
+#endif
+
+/*!
+ Sends the given key event. The key is identified by its \a unicode
+ value and the given \a keycode, \a modifiers, \a isPress and \a
+ autoRepeat parameters.
+
+ Use this function to send key events generated by "virtual
+ keyboards" (note that the processKeyEvent() function is
+ impelemented using this function).
+
+ The \a keycode parameter is the Qt keycode value as defined by the
+ Qt::Key enum. The \a modifiers is an OR combination of
+ Qt::KeyboardModifier values, indicating whether \gui
+ Shift/Alt/Ctrl keys are pressed. The \a isPress parameter is true
+ if the event is a key press event and \a autoRepeat is true if the
+ event is caused by an auto-repeat mechanism and not an actual key
+ press.
+
+ Note that this function can only be used in the server process.
+
+ \sa processKeyEvent(), {Qt for Embedded Linux Character Input}
+*/
+void QWSServer::sendKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
+ bool isPress, bool autoRepeat)
+{
+ qws_keyModifiers = modifiers;
+
+ if (isPress) {
+ if (keycode != Qt::Key_F34 && keycode != Qt::Key_F35)
+ qwsServerPrivate->_q_screenSaverWake();
+ }
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+
+ if (!current_IM || !current_IM->filter(unicode, keycode, modifiers, isPress, autoRepeat))
+ QWSServerPrivate::sendKeyEventUnfiltered(unicode, keycode, modifiers, isPress, autoRepeat);
+#else
+ QWSServerPrivate::sendKeyEventUnfiltered(unicode, keycode, modifiers, isPress, autoRepeat);
+#endif
+}
+
+void QWSServerPrivate::sendKeyEventUnfiltered(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
+ bool isPress, bool autoRepeat)
+{
+
+ QWSKeyEvent event;
+ QWSWindow *win = keyboardGrabber ? keyboardGrabber :
+ qwsServerPrivate->focusw;
+
+ event.simpleData.window = win ? win->winId() : 0;
+
+ event.simpleData.unicode =
+#ifndef QT_NO_QWS_KEYBOARD
+ unicode < 0 ? keyUnicode(keycode) :
+#endif
+ unicode;
+ event.simpleData.keycode = keycode;
+ event.simpleData.modifiers = modifiers;
+ event.simpleData.is_press = isPress;
+ event.simpleData.is_auto_repeat = autoRepeat;
+
+ QWSClient *serverClient = qwsServerPrivate->clientMap.value(-1);
+ QWSClient *winClient = win ? win->client() : 0;
+ if (serverClient)
+ serverClient->sendEvent(&event);
+ if (winClient && winClient != serverClient)
+ winClient->sendEvent(&event);
+}
+
+/*!
+ \internal
+*/
+void QWSServer::beginDisplayReconfigure()
+{
+ qwsServer->enablePainting(false);
+#ifndef QT_NO_QWS_CURSOR
+ if (qt_screencursor)
+ qt_screencursor->hide();
+#endif
+ QWSDisplay::grab(true);
+ qt_screen->disconnect();
+}
+
+/*!
+ \internal
+*/
+void QWSServer::endDisplayReconfigure()
+{
+ qt_screen->connect(QString());
+ qwsServerPrivate->swidth = qt_screen->deviceWidth();
+ qwsServerPrivate->sheight = qt_screen->deviceHeight();
+
+ QWSDisplay::ungrab();
+#ifndef QT_NO_QWS_CURSOR
+ if (qt_screencursor)
+ qt_screencursor->show();
+#endif
+ QApplicationPrivate *ap = QApplicationPrivate::instance();
+ ap->setMaxWindowRect(qt_screen, 0,
+ QRect(0, 0, qt_screen->width(), qt_screen->height()));
+ QSize olds = qApp->desktop()->size();
+ qApp->desktop()->resize(qt_screen->width(), qt_screen->height());
+ qApp->postEvent(qApp->desktop(), new QResizeEvent(qApp->desktop()->size(), olds));
+ qwsServer->enablePainting(true);
+ qwsServer->refresh();
+ qDebug("Desktop size: %dx%d", qApp->desktop()->width(), qApp->desktop()->height());
+}
+
+void QWSServerPrivate::resetEngine()
+{
+#ifndef QT_NO_QWS_CURSOR
+ if (!qt_screencursor)
+ return;
+ qt_screencursor->hide();
+ qt_screencursor->show();
+#endif
+}
+
+
+#ifndef QT_NO_QWS_CURSOR
+/*!
+ \fn void QWSServer::setCursorVisible(bool visible)
+
+ Shows the cursor if \a visible is true: otherwise the cursor is
+ hidden.
+
+ Note that this function can only be used in the server process.
+
+ \sa isCursorVisible()
+*/
+void QWSServer::setCursorVisible(bool vis)
+{
+ if (qwsServerPrivate && qwsServerPrivate->haveviscurs != vis) {
+ QWSCursor* c = qwsServerPrivate->cursor;
+ qwsServerPrivate->setCursor(QWSCursor::systemCursor(Qt::BlankCursor));
+ qwsServerPrivate->haveviscurs = vis;
+ qwsServerPrivate->setCursor(c);
+ }
+}
+
+/*!
+ Returns true if the cursor is visible; otherwise returns false.
+
+ Note that this function can only be used in the server process.
+
+ \sa setCursorVisible()
+*/
+bool QWSServer::isCursorVisible()
+{
+ return qwsServerPrivate ? qwsServerPrivate->haveviscurs : true;
+}
+#endif
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+
+
+/*!
+ \fn void QWSServer::sendIMEvent(const QInputMethodEvent *event)
+
+ Sends the given input method \a event.
+
+ The \c QInputMethodEvent class is derived from QWSEvent, i.e., it
+ is a QWSEvent object of the QWSEvent::IMEvent type.
+
+ If there is a window actively composing the preedit string, the
+ event is sent to that window. Otherwise, the event is sent to the
+ window currently in focus.
+
+ \sa sendIMQuery(), QWSInputMethod::sendEvent()
+*/
+void QWSServer::sendIMEvent(const QInputMethodEvent *ime)
+{
+ QWSIMEvent event;
+
+ QWSWindow *win = keyboardGrabber ? keyboardGrabber :
+ qwsServerPrivate->focusw;
+
+ //if currently composing then event must go to the composing window
+
+ if (current_IM_composing_win)
+ win = current_IM_composing_win;
+
+ event.simpleData.window = win ? win->winId() : 0;
+ event.simpleData.replaceFrom = ime->replacementStart();;
+ event.simpleData.replaceLength = ime->replacementLength();
+
+ QBuffer buffer;
+ buffer.open(QIODevice::WriteOnly);
+ QDataStream out(&buffer);
+
+ out << ime->preeditString();
+ out << ime->commitString();
+
+ const QList<QInputMethodEvent::Attribute> &attributes = ime->attributes();
+ for (int i = 0; i < attributes.count(); ++i) {
+ const QInputMethodEvent::Attribute &a = attributes.at(i);
+ out << a.type << a.start << a.length << a.value;
+ }
+ event.setData(buffer.data(), buffer.size());
+ QWSClient *serverClient = qwsServerPrivate->clientMap.value(-1);
+ if (serverClient)
+ serverClient->sendEvent(&event);
+ if (win && win->client() && win->client() != serverClient)
+ win->client()->sendEvent(&event);
+
+ current_IM_composing_win = ime->preeditString().isEmpty() ? 0 : win;
+ current_IM_winId = win ? win->winId() : 0;
+}
+
+
+/*!
+ Sends an input method query for the given \a property.
+
+ To receive responses to input method queries, the virtual
+ QWSInputMethod::queryResponse() function must be reimplemented in
+ a QWSInputMethod subclass that is activated using the
+ setCurrentInputMethod() function.
+
+ \sa sendIMEvent(), setCurrentInputMethod()
+*/
+void QWSServer::sendIMQuery(int property)
+{
+ QWSIMQueryEvent event;
+
+ QWSWindow *win = keyboardGrabber ? keyboardGrabber :
+ qwsServerPrivate->focusw;
+ if (current_IM_composing_win)
+ win = current_IM_composing_win;
+
+ event.simpleData.window = win ? win->winId() : 0;
+ event.simpleData.property = property;
+ if (win && win->client())
+ win->client()->sendEvent(&event);
+}
+
+
+
+/*!
+ \fn void QWSServer::setCurrentInputMethod(QWSInputMethod *method)
+
+ Sets the current input method to be the given \a method.
+
+ Note that this function can only be used in the server process.
+
+ \sa sendIMQuery(), sendIMEvent()
+*/
+void QWSServer::setCurrentInputMethod(QWSInputMethod *im)
+{
+ if (current_IM)
+ current_IM->reset(); //??? send an update event instead ?
+ current_IM = im;
+}
+
+/*!
+ \fn static void QWSServer::resetInputMethod()
+
+ \internal
+*/
+
+#endif //QT_NO_QWS_INPUTMETHODS
+
+#ifndef QT_NO_QWS_PROPERTIES
+/*!
+ \internal
+*/
+void QWSServer::sendPropertyNotifyEvent(int property, int state)
+{
+ Q_D(QWSServer);
+ QWSServerPrivate::ClientIterator it = d->clientMap.begin();
+ while (it != d->clientMap.end()) {
+ QWSClient *cl = *it;
+ ++it;
+ cl->sendPropertyNotifyEvent(property, state);
+ }
+}
+#endif
+
+void QWSServerPrivate::invokeIdentify(const QWSIdentifyCommand *cmd, QWSClient *client)
+{
+ client->setIdentity(cmd->id);
+#ifndef QT_NO_QWS_MULTIPROCESS
+ if (client->clientId() > 0)
+ client->d_func()->setLockId(cmd->simpleData.idLock);
+#endif
+}
+
+void QWSServerPrivate::invokeCreate(QWSCreateCommand *cmd, QWSClient *client)
+{
+ QWSCreationEvent event;
+ event.simpleData.objectid = get_object_id(cmd->count);
+ event.simpleData.count = cmd->count;
+ client->sendEvent(&event);
+}
+
+void QWSServerPrivate::invokeRegionName(const QWSRegionNameCommand *cmd, QWSClient *client)
+{
+ Q_Q(QWSServer);
+ QWSWindow* changingw = findWindow(cmd->simpleData.windowid, client);
+ if (changingw && (changingw->name() != cmd->name || changingw->caption() !=cmd->caption)) {
+ changingw->setName(cmd->name);
+ changingw->setCaption(cmd->caption);
+ emit q->windowEvent(changingw, QWSServer::Name);
+ }
+}
+
+void QWSServerPrivate::invokeRegion(QWSRegionCommand *cmd, QWSClient *client)
+{
+#ifdef QWS_REGION_DEBUG
+ qDebug("QWSServer::invokeRegion %d rects (%d)",
+ cmd->simpleData.nrectangles, cmd->simpleData.windowid);
+#endif
+
+ QWSWindow* changingw = findWindow(cmd->simpleData.windowid, 0);
+ if (!changingw) {
+ qWarning("Invalid window handle %08x",cmd->simpleData.windowid);
+ return;
+ }
+ if (!changingw->forClient(client)) {
+ qWarning("Disabled: clients changing other client's window region");
+ return;
+ }
+
+ request_region(cmd->simpleData.windowid, cmd->surfaceKey, cmd->surfaceData,
+ cmd->region);
+}
+
+void QWSServerPrivate::invokeRegionMove(const QWSRegionMoveCommand *cmd, QWSClient *client)
+{
+ Q_Q(QWSServer);
+ QWSWindow* changingw = findWindow(cmd->simpleData.windowid, 0);
+ if (!changingw) {
+ qWarning("invokeRegionMove: Invalid window handle %d",cmd->simpleData.windowid);
+ return;
+ }
+ if (!changingw->forClient(client)) {
+ qWarning("Disabled: clients changing other client's window region");
+ return;
+ }
+
+// changingw->setNeedAck(true);
+ moveWindowRegion(changingw, cmd->simpleData.dx, cmd->simpleData.dy);
+ emit q->windowEvent(changingw, QWSServer::Geometry);
+}
+
+void QWSServerPrivate::invokeRegionDestroy(const QWSRegionDestroyCommand *cmd, QWSClient *client)
+{
+ Q_Q(QWSServer);
+ QWSWindow* changingw = findWindow(cmd->simpleData.windowid, 0);
+ if (!changingw) {
+ qWarning("invokeRegionDestroy: Invalid window handle %d",cmd->simpleData.windowid);
+ return;
+ }
+ if (!changingw->forClient(client)) {
+ qWarning("Disabled: clients changing other client's window region");
+ return;
+ }
+
+ setWindowRegion(changingw, QRegion());
+// rgnMan->remove(changingw->allocationIndex());
+ for (int i = 0; i < windows.size(); ++i) {
+ if (windows.at(i) == changingw) {
+ windows.takeAt(i);
+ if (i < nReserved)
+ --nReserved;
+ break;
+ }
+ }
+
+ handleWindowClose(changingw);
+#ifndef QT_NO_QWS_PROPERTIES
+ propertyManager.removeProperties(changingw->winId());
+#endif
+ emit q->windowEvent(changingw, QWSServer::Destroy);
+ delete changingw;
+}
+
+void QWSServerPrivate::invokeSetFocus(const QWSRequestFocusCommand *cmd, QWSClient *client)
+{
+ int winId = cmd->simpleData.windowid;
+ int gain = cmd->simpleData.flag;
+
+ if (gain != 0 && gain != 1) {
+ qWarning("Only 0(lose) and 1(gain) supported");
+ return;
+ }
+
+ QWSWindow* changingw = findWindow(winId, 0);
+ if (!changingw)
+ return;
+
+ if (!changingw->forClient(client)) {
+ qWarning("Disabled: clients changing other client's focus");
+ return;
+ }
+
+ setFocus(changingw, gain);
+}
+
+void QWSServerPrivate::setFocus(QWSWindow* changingw, bool gain)
+{
+ Q_Q(QWSServer);
+#ifndef QT_NO_QWS_INPUTMETHODS
+ /*
+ This is the logic:
+ QWSWindow *loser = 0;
+ if (gain && focusw != changingw)
+ loser = focusw;
+ else if (!gain && focusw == changingw)
+ loser = focusw;
+ But these five lines can be reduced to one:
+ */
+ if (current_IM) {
+ QWSWindow *loser = (!gain == (focusw==changingw)) ? focusw : 0;
+ if (loser && loser->winId() == current_IM_winId)
+ current_IM->updateHandler(QWSInputMethod::FocusOut);
+ }
+#endif
+ if (gain) {
+ if (focusw != changingw) {
+ if (focusw) focusw->focus(0);
+ focusw = changingw;
+ focusw->focus(1);
+ emit q->windowEvent(focusw, QWSServer::Active);
+ }
+ } else if (focusw == changingw) {
+ if (changingw->client())
+ changingw->focus(0);
+ focusw = 0;
+ // pass focus to window which most recently got it...
+ QWSWindow* bestw=0;
+ for (int i=0; i<windows.size(); ++i) {
+ QWSWindow* w = windows.at(i);
+ if (w != changingw && !w->hidden() &&
+ (!bestw || bestw->focusPriority() < w->focusPriority()))
+ bestw = w;
+ }
+ if (!bestw && changingw->focusPriority()) { // accept focus back?
+ bestw = changingw; // must be the only one
+ }
+ focusw = bestw;
+ if (focusw) {
+ focusw->focus(1);
+ emit q->windowEvent(focusw, QWSServer::Active);
+ }
+ }
+}
+
+
+
+void QWSServerPrivate::invokeSetOpacity(const QWSSetOpacityCommand *cmd, QWSClient *client)
+{
+ Q_UNUSED( client );
+ int winId = cmd->simpleData.windowid;
+ int opacity = cmd->simpleData.opacity;
+
+ QWSWindow* changingw = findWindow(winId, 0);
+
+ if (!changingw) {
+ qWarning("invokeSetOpacity: Invalid window handle %d", winId);
+ return;
+ }
+
+ int altitude = windows.indexOf(changingw);
+ const bool wasOpaque = changingw->isOpaque();
+ changingw->_opacity = opacity;
+ if (wasOpaque != changingw->isOpaque())
+ update_regions();
+ exposeRegion(changingw->allocatedRegion(), altitude);
+}
+
+void QWSServerPrivate::invokeSetAltitude(const QWSChangeAltitudeCommand *cmd,
+ QWSClient *client)
+{
+ Q_UNUSED(client);
+
+ int winId = cmd->simpleData.windowid;
+ int alt = cmd->simpleData.altitude;
+ bool fixed = cmd->simpleData.fixed;
+#if 0
+ qDebug("QWSServer::invokeSetAltitude winId %d alt %d)", winId, alt);
+#endif
+
+ if (alt < -1 || alt > 1) {
+ qWarning("QWSServer::invokeSetAltitude Only lower, raise and stays-on-top supported");
+ return;
+ }
+
+ QWSWindow* changingw = findWindow(winId, 0);
+ if (!changingw) {
+ qWarning("invokeSetAltitude: Invalid window handle %d", winId);
+ return;
+ }
+
+ if (fixed && alt >= 1) {
+ changingw->onTop = true;
+ }
+ if (alt == QWSChangeAltitudeCommand::Lower)
+ changingw->lower();
+ else
+ changingw->raise();
+
+// if (!changingw->forClient(client)) {
+// refresh();
+// }
+}
+
+#ifndef QT_NO_QWS_PROPERTIES
+void QWSServerPrivate::invokeAddProperty(QWSAddPropertyCommand *cmd)
+{
+ propertyManager.addProperty(cmd->simpleData.windowid, cmd->simpleData.property);
+}
+
+void QWSServerPrivate::invokeSetProperty(QWSSetPropertyCommand *cmd)
+{
+ Q_Q(QWSServer);
+ if (propertyManager.setProperty(cmd->simpleData.windowid,
+ cmd->simpleData.property,
+ cmd->simpleData.mode,
+ cmd->data,
+ cmd->rawLen)) {
+ q->sendPropertyNotifyEvent(cmd->simpleData.property,
+ QWSPropertyNotifyEvent::PropertyNewValue);
+#ifndef QT_NO_QWS_INPUTMETHODS
+ if (cmd->simpleData.property == QT_QWS_PROPERTY_MARKEDTEXT) {
+ QString s((const QChar*)cmd->data, cmd->rawLen/2);
+ emit q->markedText(s);
+ }
+#endif
+ }
+}
+
+void QWSServerPrivate::invokeRemoveProperty(QWSRemovePropertyCommand *cmd)
+{
+ Q_Q(QWSServer);
+ if (propertyManager.removeProperty(cmd->simpleData.windowid,
+ cmd->simpleData.property)) {
+ q->sendPropertyNotifyEvent(cmd->simpleData.property,
+ QWSPropertyNotifyEvent::PropertyDeleted);
+ }
+}
+
+
+bool QWSServerPrivate:: get_property(int winId, int property, const char *&data, int &len)
+{
+ return propertyManager.getProperty(winId, property, data, len);
+}
+
+
+void QWSServerPrivate::invokeGetProperty(QWSGetPropertyCommand *cmd, QWSClient *client)
+{
+ const char *data;
+ int len;
+
+ if (propertyManager.getProperty(cmd->simpleData.windowid,
+ cmd->simpleData.property,
+ data, len)) {
+ client->sendPropertyReplyEvent(cmd->simpleData.property, len, data);
+ } else {
+ client->sendPropertyReplyEvent(cmd->simpleData.property, -1, 0);
+ }
+}
+#endif //QT_NO_QWS_PROPERTIES
+
+void QWSServerPrivate::invokeSetSelectionOwner(QWSSetSelectionOwnerCommand *cmd)
+{
+ qDebug("QWSServer::invokeSetSelectionOwner");
+
+ SelectionOwner so;
+ so.windowid = cmd->simpleData.windowid;
+ so.time.set(cmd->simpleData.hour, cmd->simpleData.minute,
+ cmd->simpleData.sec, cmd->simpleData.ms);
+
+ if (selectionOwner.windowid != -1) {
+ QWSWindow *win = findWindow(selectionOwner.windowid, 0);
+ if (win)
+ win->client()->sendSelectionClearEvent(selectionOwner.windowid);
+ else
+ qDebug("couldn't find window %d", selectionOwner.windowid);
+ }
+
+ selectionOwner = so;
+}
+
+void QWSServerPrivate::invokeConvertSelection(QWSConvertSelectionCommand *cmd)
+{
+ qDebug("QWSServer::invokeConvertSelection");
+
+ if (selectionOwner.windowid != -1) {
+ QWSWindow *win = findWindow(selectionOwner.windowid, 0);
+ if (win)
+ win->client()->sendSelectionRequestEvent(cmd, selectionOwner.windowid);
+ else
+ qDebug("couldn't find window %d", selectionOwner.windowid);
+ }
+}
+
+#ifndef QT_NO_QWS_CURSOR
+void QWSServerPrivate::invokeDefineCursor(QWSDefineCursorCommand *cmd, QWSClient *client)
+{
+ if (cmd->simpleData.height > 64 || cmd->simpleData.width > 64) {
+ qDebug("Cannot define cursor size > 64x64");
+ return;
+ }
+
+ delete client->cursors.take(cmd->simpleData.id);
+
+ int dataLen = cmd->simpleData.height * ((cmd->simpleData.width+7) / 8);
+
+ if (dataLen > 0 && cmd->data) {
+ QWSCursor *curs = new QWSCursor(cmd->data, cmd->data + dataLen,
+ cmd->simpleData.width, cmd->simpleData.height,
+ cmd->simpleData.hotX, cmd->simpleData.hotY);
+ client->cursors.insert(cmd->simpleData.id, curs);
+ }
+}
+
+void QWSServerPrivate::invokeSelectCursor(QWSSelectCursorCommand *cmd, QWSClient *client)
+{
+ int id = cmd->simpleData.id;
+ QWSCursor *curs = 0;
+ if (id <= Qt::LastCursor) {
+ curs = QWSCursor::systemCursor(id);
+ }
+ else {
+ QWSCursorMap cursMap = client->cursors;
+ QWSCursorMap::Iterator it = cursMap.find(id);
+ if (it != cursMap.end()) {
+ curs = it.value();
+ }
+ }
+ if (curs == 0) {
+ curs = QWSCursor::systemCursor(Qt::ArrowCursor);
+ }
+
+ QWSWindow* win = findWindow(cmd->simpleData.windowid, 0);
+ if (mouseGrabber) {
+ // If the mouse is being grabbed, we don't want just anyone to
+ // be able to change the cursor. We do want the cursor to be set
+ // correctly once mouse grabbing is stopped though.
+ if (win != mouseGrabber)
+ nextCursor = curs;
+ else
+ setCursor(curs);
+ } else if (win && win->allocatedRegion().contains(QWSServer::mousePosition)) { //##################### cursor
+ // A non-grabbing window can only set the cursor shape if the
+ // cursor is within its allocated region.
+ setCursor(curs);
+ }
+}
+
+void QWSServerPrivate::invokePositionCursor(QWSPositionCursorCommand *cmd, QWSClient *)
+{
+ Q_Q(QWSServer);
+ QPoint newPos(cmd->simpleData.newX, cmd->simpleData.newY);
+ if (newPos != QWSServer::mousePosition)
+ q->sendMouseEvent(newPos, qwsServer->d_func()->mouseState);
+}
+#endif
+
+void QWSServerPrivate::invokeGrabMouse(QWSGrabMouseCommand *cmd, QWSClient *client)
+{
+ QWSWindow* win = findWindow(cmd->simpleData.windowid, 0);
+ if (!win)
+ return;
+
+ if (cmd->simpleData.grab) {
+ if (!mouseGrabber || mouseGrabber->client() == client) {
+ mouseGrabbing = true;
+ mouseGrabber = win;
+ }
+ } else {
+ releaseMouse(mouseGrabber);
+ }
+}
+
+void QWSServerPrivate::invokeGrabKeyboard(QWSGrabKeyboardCommand *cmd, QWSClient *client)
+{
+ QWSWindow* win = findWindow(cmd->simpleData.windowid, 0);
+ if (!win)
+ return;
+
+ if (cmd->simpleData.grab) {
+ if (!keyboardGrabber || (keyboardGrabber->client() == client)) {
+ keyboardGrabbing = true;
+ keyboardGrabber = win;
+ }
+ } else {
+ releaseKeyboard(keyboardGrabber);
+ }
+}
+
+#if !defined(QT_NO_SOUND)
+void QWSServerPrivate::invokePlaySound(QWSPlaySoundCommand *cmd, QWSClient *)
+{
+#if !defined(QT_EXTERNAL_SOUND_SERVER) && !defined(Q_OS_DARWIN)
+ soundserver->playFile( 1, cmd->filename );
+#else
+ Q_UNUSED(cmd);
+#endif
+}
+#endif
+
+#ifndef QT_NO_COP
+void QWSServerPrivate::invokeRegisterChannel(QWSQCopRegisterChannelCommand *cmd,
+ QWSClient *client)
+{
+ // QCopChannel will force us to emit the newChannel signal if this channel
+ // didn't already exist.
+ QCopChannel::registerChannel(cmd->channel, client);
+}
+
+void QWSServerPrivate::invokeQCopSend(QWSQCopSendCommand *cmd, QWSClient *client)
+{
+ QCopChannel::answer(client, cmd->channel, cmd->message, cmd->data);
+}
+
+#endif
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+void QWSServer::resetInputMethod()
+{
+ if (current_IM && qwsServer) {
+ current_IM->reset();
+ }
+}
+
+void QWSServerPrivate::invokeIMResponse(const QWSIMResponseCommand *cmd,
+ QWSClient *)
+{
+ if (current_IM)
+ current_IM->queryResponse(cmd->simpleData.property, cmd->result);
+}
+
+void QWSServerPrivate::invokeIMUpdate(const QWSIMUpdateCommand *cmd,
+ QWSClient *)
+{
+ if (cmd->simpleData.type == QWSInputMethod::FocusIn)
+ current_IM_winId = cmd->simpleData.windowid;
+
+ if (current_IM && (current_IM_winId == cmd->simpleData.windowid || cmd->simpleData.windowid == -1))
+ current_IM->updateHandler(cmd->simpleData.type);
+}
+
+#endif
+
+void QWSServerPrivate::invokeFont(const QWSFontCommand *cmd, QWSClient *client)
+{
+ QWSClientPrivate *priv = client->d_func();
+ if (cmd->simpleData.type == QWSFontCommand::StartedUsingFont) {
+ referenceFont(priv, cmd->fontName);
+ } else if (cmd->simpleData.type == QWSFontCommand::StoppedUsingFont) {
+ dereferenceFont(priv, cmd->fontName);
+ }
+}
+
+void QWSServerPrivate::invokeRepaintRegion(QWSRepaintRegionCommand * cmd,
+ QWSClient *)
+{
+ QRegion r;
+ r.setRects(cmd->rectangles,cmd->simpleData.nrectangles);
+ repaint_region(cmd->simpleData.windowid, cmd->simpleData.windowFlags, cmd->simpleData.opaque, r);
+}
+
+#ifndef QT_NO_QWSEMBEDWIDGET
+void QWSServerPrivate::invokeEmbed(QWSEmbedCommand *cmd, QWSClient *client)
+{
+ // Should find these two windows in a single loop
+ QWSWindow *embedder = findWindow(cmd->simpleData.embedder, client);
+ QWSWindow *embedded = findWindow(cmd->simpleData.embedded);
+
+ if (!embedder) {
+ qWarning("QWSServer: Embed command from window %i failed: No such id.",
+ static_cast<int>(cmd->simpleData.embedder));
+ return;
+ }
+
+ if (!embedded) {
+ qWarning("QWSServer: Embed command on window %i failed: No such id.",
+ static_cast<int>(cmd->simpleData.embedded));
+ return;
+ }
+
+ switch (cmd->simpleData.type) {
+ case QWSEmbedEvent::StartEmbed:
+ embedder->startEmbed(embedded);
+ windows.removeAll(embedded);
+ windows.insert(windows.indexOf(embedder), embedded);
+ break;
+ case QWSEmbedEvent::StopEmbed:
+ embedder->stopEmbed(embedded);
+ break;
+ case QWSEmbedEvent::Region:
+ break;
+ }
+
+ embedded->client()->sendEmbedEvent(embedded->winId(),
+ cmd->simpleData.type, cmd->region);
+ const QRegion oldAllocated = embedded->allocatedRegion();
+ update_regions();
+ exposeRegion(oldAllocated - embedded->allocatedRegion(),
+ windows.indexOf(embedded));
+}
+#endif // QT_NO_QWSEMBEDWIDGET
+
+void QWSServerPrivate::invokeScreenTransform(const QWSScreenTransformCommand *cmd,
+ QWSClient *client)
+{
+ Q_UNUSED(client);
+
+ QWSScreenTransformationEvent event;
+ event.simpleData.screen = cmd->simpleData.screen;
+ event.simpleData.transformation = cmd->simpleData.transformation;
+
+ QMap<int, QWSClient*>::const_iterator it = clientMap.constBegin();
+ for (; it != clientMap.constEnd(); ++it)
+ (*it)->sendEvent(&event);
+}
+
+QWSWindow* QWSServerPrivate::newWindow(int id, QWSClient* client)
+{
+ Q_Q(QWSServer);
+ // Make a new window, put it on top.
+ QWSWindow* w = new QWSWindow(id,client);
+
+ // insert after "stays on top" windows
+ bool added = false;
+ for (int i = nReserved; i < windows.size(); ++i) {
+ QWSWindow *win = windows.at(i);
+ if (!win->onTop) {
+ windows.insert(i, w);
+ added = true;
+ break;
+ }
+ }
+ if (!added)
+ windows.append(w);
+ emit q->windowEvent(w, QWSServer::Create);
+ return w;
+}
+
+QWSWindow* QWSServerPrivate::findWindow(int windowid, QWSClient* client)
+{
+ for (int i=0; i<windows.size(); ++i) {
+ QWSWindow* w = windows.at(i);
+ if (w->winId() == windowid)
+ return w;
+ }
+ if (client)
+ return newWindow(windowid,client);
+ else
+ return 0;
+}
+
+void QWSServerPrivate::raiseWindow(QWSWindow *changingw, int /*alt*/)
+{
+ Q_Q(QWSServer);
+ if (changingw == windows.first())
+ return;
+ QWSWindow::State oldstate = changingw->d->state;
+ changingw->d->state = QWSWindow::Raising;
+ // Expose regions previously overlapped by transparent windows
+ const QRegion bound = changingw->allocatedRegion();
+ QRegion expose;
+ int windowPos = 0;
+
+ //change position in list:
+ for (int i = 0; i < windows.size(); ++i) {
+ QWSWindow *w = windows.at(i);
+ if (w == changingw) {
+ windowPos = i;
+ windows.takeAt(i);
+ break;
+ }
+ if (!w->isOpaque())
+ expose += (w->allocatedRegion() & bound);
+ }
+
+ bool onTop = changingw->onTop;
+
+#ifndef QT_NO_QWSEMBEDWIDGET
+ // an embedded window is on top if the embedder is on top
+ QWSWindow *embedder = changingw->d->embedder;
+ while (!onTop && embedder) {
+ onTop = embedder->onTop;
+ embedder = embedder->d->embedder;
+ }
+#endif
+
+ int newPos = -1;
+ if (onTop) {
+ windows.insert(nReserved, changingw);
+ newPos = nReserved;
+ } else {
+ // insert after "stays on top" windows
+ bool in = false;
+ for (int i = nReserved; i < windows.size(); ++i) {
+ QWSWindow *w = windows.at(i);
+ if (!w->onTop) {
+ windows.insert(i, changingw);
+ in = true;
+ newPos = i;
+ break;
+ }
+ }
+ if (!in) {
+ windows.append(changingw);
+ newPos = windows.size()-1;
+ }
+ }
+
+ if (windowPos != newPos) {
+ update_regions();
+ if (!expose.isEmpty())
+ exposeRegion(expose, newPos);
+ }
+ changingw->d->state = oldstate;
+ emit q->windowEvent(changingw, QWSServer::Raise);
+}
+
+void QWSServerPrivate::lowerWindow(QWSWindow *changingw, int /*alt*/)
+{
+ Q_Q(QWSServer);
+ if (changingw == windows.last())
+ return;
+ QWSWindow::State oldstate = changingw->d->state;
+ changingw->d->state = QWSWindow::Lowering;
+
+ int i = windows.indexOf(changingw);
+ int newIdx = windows.size()-1;
+ windows.move(i, newIdx);
+
+ const QRegion bound = changingw->allocatedRegion();
+
+ update_regions();
+
+ // Expose regions previously overlapped by transparent window
+ if (!changingw->isOpaque()) {
+ QRegion expose;
+ for (int j = i; j < windows.size() - 1; ++j)
+ expose += (windows.at(j)->allocatedRegion() & bound);
+ if (!expose.isEmpty())
+ exposeRegion(expose, newIdx);
+ }
+
+ changingw->d->state = oldstate;
+ emit q->windowEvent(changingw, QWSServer::Lower);
+}
+
+void QWSServerPrivate::update_regions()
+{
+ if (disablePainting)
+ return;
+
+ QRegion available = QRect(0, 0, qt_screen->width(), qt_screen->height());
+ QRegion transparentRegion;
+
+ // only really needed if there are unbuffered surfaces...
+ const bool doLock = (clientMap.size() > 1);
+ if (doLock)
+ QWSDisplay::grab(true);
+
+ for (int i = 0; i < windows.count(); ++i) {
+ QWSWindow *w = windows.at(i);
+ QRegion r = (w->requested_region & available);
+
+#ifndef QT_NO_QWSEMBEDWIDGET
+ // Subtract regions needed for embedded windows
+ const int n = w->d->embedded.size();
+ for (int i = 0; i < n; ++i)
+ r -= w->d->embedded.at(i)->allocatedRegion();
+
+ // Limited to the embedder region
+ if (w->d->embedder)
+ r &= w->d->embedder->requested_region;
+#endif // QT_NO_QWSEMBEDWIDGET
+
+ QWSWindowSurface *surface = w->windowSurface();
+ const bool opaque = w->isOpaque()
+ && (w->d->painted || !surface || !surface->isBuffered());
+
+ if (!opaque) {
+ transparentRegion += r;
+ } else {
+ if (surface && (surface->isRegionReserved() || !surface->isBuffered()))
+ r -= transparentRegion;
+ available -= r;
+ }
+
+ if (r != w->allocatedRegion()) {
+ w->setAllocatedRegion(r);
+ w->client()->sendRegionEvent(w->winId(), r,
+ QWSRegionEvent::Allocation);
+ }
+
+#ifdef QT_QWS_CLIENTBLIT
+#ifdef QT_NO_QWS_CURSOR
+ // This optimization only really works when there isn't a crazy cursor
+ // wizzing around.
+ QRegion directPaint = (r - transparentRegion); // in gloal coords
+ if(directPaint != w->directPaintRegion()) {
+ w->setDirectPaintRegion(directPaint);
+ static int id = 0;
+ surface->setDirectRegion(directPaint, ++id);
+ w->client()->sendRegionEvent(w->winId(), directPaint,
+ QWSRegionEvent::DirectPaint, id);
+ }
+#endif
+#endif
+ }
+
+ if (doLock)
+ QWSDisplay::ungrab();
+}
+
+void QWSServerPrivate::moveWindowRegion(QWSWindow *changingw, int dx, int dy)
+{
+ if (!changingw)
+ return;
+
+ QWSWindow::State oldState = changingw->d->state;
+ changingw->d->state = QWSWindow::Moving;
+ const QRegion oldRegion(changingw->allocatedRegion());
+ changingw->requested_region.translate(dx, dy);
+
+ // hw: Even if the allocated region doesn't change, the requested region
+ // region has changed and we need to send region events.
+ // Resetting the allocated region to force update_regions to send events.
+ changingw->setAllocatedRegion(QRegion());
+ update_regions();
+ const QRegion newRegion(changingw->allocatedRegion());
+
+ QWSWindowSurface *surface = changingw->windowSurface();
+ QRegion expose;
+ if (surface)
+ expose = surface->move(QPoint(dx, dy), changingw->allocatedRegion());
+ else
+ expose = oldRegion + newRegion;
+
+ if (!changingw->d->painted && !expose.isEmpty())
+ expose = oldRegion - newRegion;
+
+ int idx = windows.indexOf(changingw);
+ exposeRegion(expose, idx);
+ changingw->d->state = oldState;
+}
+
+/*!
+ Changes the requested region of window \a changingw to \a r
+ If \a changingw is 0, the server's reserved region is changed.
+*/
+void QWSServerPrivate::setWindowRegion(QWSWindow* changingw, const QRegion &r)
+{
+ if (!changingw) {
+ qWarning("Not implemented in this release");
+ return;
+ }
+
+ if (changingw->requested_region == r)
+ return;
+
+ const QRegion oldRegion(changingw->allocatedRegion());
+ changingw->requested_region = r;
+ update_regions();
+ const QRegion newRegion(changingw->allocatedRegion());
+
+ int idx = windows.indexOf(changingw);
+ exposeRegion(oldRegion - newRegion, idx);
+}
+
+
+void QWSServerPrivate::exposeRegion(const QRegion &r, int changing)
+{
+ if (disablePainting)
+ return;
+
+ if (r.isEmpty())
+ return;
+
+ static bool initial = true;
+ if (initial) {
+ changing = 0;
+ initial = false;
+ qt_screen->exposeRegion(qt_screen->region(), changing);
+ } else {
+ qt_screen->exposeRegion(r, changing);
+ }
+}
+
+/*!
+ Closes all pointer devices (specified by the QWS_MOUSE_PROTO
+ environment variable) by deleting the associated mouse drivers.
+
+ \sa openMouse(), mouseHandler()
+*/
+void QWSServer::closeMouse()
+{
+ Q_D(QWSServer);
+ qDeleteAll(d->mousehandlers);
+ d->mousehandlers.clear();
+}
+
+/*!
+ Opens the mouse devices specified by the QWS_MOUSE_PROTO
+ environment variable. Be advised that closeMouse() is called first
+ to delete all the existing mouse handlers. This behaviour could be
+ the cause of problems if you were not expecting it.
+
+ \sa closeMouse(), mouseHandler()
+*/
+void QWSServer::openMouse()
+{
+ Q_D(QWSServer);
+ QString mice = QString::fromLatin1(qgetenv("QWS_MOUSE_PROTO"));
+#if defined(QT_QWS_CASSIOPEIA)
+ if (mice.isEmpty())
+ mice = QLatin1String("TPanel:/dev/tpanel");
+#endif
+ if (mice.isEmpty())
+ mice = *defaultMouse();
+ closeMouse();
+ bool needviscurs = true;
+ if (mice != QLatin1String("None")) {
+ const QStringList mouse = mice.split(QLatin1Char(' '));
+ for (int i = mouse.size() - 1; i >= 0; --i) {
+ QWSMouseHandler *handler = d->newMouseHandler(mouse.at(i));
+ setMouseHandler(handler);
+ /* XXX handle mouse cursor visibility sensibly
+ if (!h->inherits("QCalibratedMouseHandler"))
+ needviscurs = true;
+ */
+ }
+ }
+#ifndef QT_NO_QWS_CURSOR
+ setCursorVisible(needviscurs);
+#else
+ Q_UNUSED(needviscurs)
+#endif
+}
+
+/*!
+ Suspends pointer handling by deactivating all the mouse drivers
+ registered by the QWS_MOUSE_PROTO environment variable.
+
+
+ \sa resumeMouse(), QWSMouseHandler::suspend()
+*/
+void QWSServer::suspendMouse()
+{
+ Q_D(QWSServer);
+ for (int i=0; i < d->mousehandlers.size(); ++i)
+ d->mousehandlers.at(i)->suspend();
+}
+
+/*!
+ Resumes pointer handling by reactivating all the mouse drivers
+ registered by the QWS_MOUSE_PROTO environment variable.
+
+ \sa suspendMouse(), QWSMouseHandler::resume()
+*/
+void QWSServer::resumeMouse()
+{
+ Q_D(QWSServer);
+ for (int i=0; i < d->mousehandlers.size(); ++i)
+ d->mousehandlers.at(i)->resume();
+}
+
+
+
+QWSMouseHandler* QWSServerPrivate::newMouseHandler(const QString& spec)
+{
+ int c = spec.indexOf(QLatin1Char(':'));
+ QString mouseProto;
+ QString mouseDev;
+ if (c >= 0) {
+ mouseProto = spec.left(c);
+ mouseDev = spec.mid(c+1);
+ } else {
+ mouseProto = spec;
+ }
+
+ int screen = -1;
+ const QList<QRegExp> regexps = QList<QRegExp>()
+ << QRegExp(QLatin1String(":screen=(\\d+)\\b"))
+ << QRegExp(QLatin1String("\\bscreen=(\\d+):"));
+ for (int i = 0; i < regexps.size(); ++i) {
+ QRegExp regexp = regexps.at(i);
+ if (regexp.indexIn(mouseDev) == -1)
+ continue;
+ screen = regexp.cap(1).toInt();
+ mouseDev.remove(regexp.pos(0), regexp.matchedLength());
+ break;
+ }
+
+ QWSMouseHandler *handler = 0;
+ handler = QMouseDriverFactory::create(mouseProto, mouseDev);
+ if (screen != -1)
+ handler->setScreen(qt_screen->subScreens().at(screen));
+
+ return handler;
+}
+
+#ifndef QT_NO_QWS_KEYBOARD
+
+/*!
+ Closes all the keyboard devices (specified by the QWS_KEYBOARD
+ environment variable) by deleting the associated keyboard
+ drivers.
+
+ \sa openKeyboard(), keyboardHandler()
+*/
+void QWSServer::closeKeyboard()
+{
+ Q_D(QWSServer);
+ qDeleteAll(d->keyboardhandlers);
+ d->keyboardhandlers.clear();
+}
+
+/*!
+ Returns the primary keyboard driver.
+
+ Note that this function can only be used in the server process.
+
+ \sa setKeyboardHandler(), openKeyboard(), closeKeyboard()
+*/
+QWSKeyboardHandler* QWSServer::keyboardHandler()
+{
+ return qwsServerPrivate->keyboardhandlers.first();
+}
+
+/*!
+ \fn void QWSServer::setKeyboardHandler(QWSKeyboardHandler* driver)
+
+ Sets the primary keyboard driver to be the given \a driver.
+
+ \l{Qt for Embedded Linux} provides several ready-made keyboard drivers, and
+ custom drivers are typically added using Qt's plugin
+ mechanism. See the \l{Qt for Embedded Linux Character Input} documentation
+ for details.
+
+ Note that this function can only be used in the server process.
+
+ \sa keyboardHandler(), setDefaultKeyboard()
+*/
+void QWSServer::setKeyboardHandler(QWSKeyboardHandler* kh)
+{
+ if (!kh)
+ return;
+ qwsServerPrivate->keyboardhandlers.removeAll(kh);
+ qwsServerPrivate->keyboardhandlers.prepend(kh);
+}
+
+/*!
+ Opens the keyboard devices specified by the QWS_KEYBOARD
+ environment variable.
+
+ \sa closeKeyboard(), keyboardHandler()
+*/
+void QWSServer::openKeyboard()
+{
+ QString keyboards = QString::fromLatin1(qgetenv("QWS_KEYBOARD"));
+#if defined(QT_QWS_CASSIOPEIA)
+ if (keyboards.isEmpty())
+ keyboards = QLatin1String("Buttons");
+#endif
+ if (keyboards.isEmpty())
+ keyboards = *defaultKeyboard();
+
+ closeKeyboard();
+ if (keyboards == QLatin1String("None"))
+ return;
+
+ QString device;
+ QString type;
+ QStringList keyboard = keyboards.split(QLatin1Char(' '));
+ for (int i = keyboard.size() - 1; i >= 0; --i) {
+ const QString spec = keyboard.at(i);
+ int colon=spec.indexOf(QLatin1Char(':'));
+ if (colon>=0) {
+ type = spec.left(colon);
+ device = spec.mid(colon+1);
+ } else {
+ type = spec;
+ device = QString();
+ }
+ QWSKeyboardHandler *handler = QKbdDriverFactory::create(type, device);
+ setKeyboardHandler(handler);
+ }
+}
+
+#endif //QT_NO_QWS_KEYBOARD
+
+QPoint QWSServer::mousePosition;
+QBrush *QWSServerPrivate::bgBrush = 0;
+
+void QWSServerPrivate::move_region(const QWSRegionMoveCommand *cmd)
+{
+ QWSClient *serverClient = clientMap.value(-1);
+ invokeRegionMove(cmd, serverClient);
+}
+
+void QWSServerPrivate::set_altitude(const QWSChangeAltitudeCommand *cmd)
+{
+ QWSClient *serverClient = clientMap.value(-1);
+ invokeSetAltitude(cmd, serverClient);
+}
+
+void QWSServerPrivate::set_opacity(const QWSSetOpacityCommand *cmd)
+{
+ QWSClient *serverClient = clientMap.value(-1);
+ invokeSetOpacity(cmd, serverClient);
+}
+
+
+void QWSServerPrivate::request_focus(const QWSRequestFocusCommand *cmd)
+{
+ invokeSetFocus(cmd, clientMap.value(-1));
+}
+
+void QWSServerPrivate::set_identity(const QWSIdentifyCommand *cmd)
+{
+ invokeIdentify(cmd, clientMap.value(-1));
+}
+
+void QWSServerPrivate::repaint_region(int wid, int windowFlags, bool opaque,
+ const QRegion &region)
+{
+ QWSWindow* changingw = findWindow(wid, 0);
+ if (!changingw) {
+ return;
+ }
+
+ const bool isOpaque = changingw->opaque;
+ const bool wasPainted = changingw->d->painted;
+ changingw->opaque = opaque;
+ changingw->d->windowFlags = QFlag(windowFlags);
+ changingw->d->dirtyOnScreen |= region;
+ changingw->d->painted = true;
+ if (isOpaque != opaque || !wasPainted)
+ update_regions();
+
+ int level = windows.indexOf(changingw);
+ exposeRegion(region, level);
+ changingw->d->dirtyOnScreen = QRegion();
+}
+
+QRegion QWSServerPrivate::reserve_region(QWSWindow *win, const QRegion &region)
+{
+ QRegion r = region;
+
+ int oldPos = windows.indexOf(win);
+ int newPos = oldPos < nReserved ? nReserved - 1 : nReserved;
+ for (int i = 0; i < nReserved; ++i) {
+ if (i != oldPos) {
+ QWSWindow *w = windows.at(i);
+ r -= w->requested_region;
+ }
+ }
+ windows.move(oldPos, newPos);
+ nReserved = newPos + 1;
+
+ return r;
+}
+
+void QWSServerPrivate::request_region(int wid, const QString &surfaceKey,
+ const QByteArray &surfaceData,
+ const QRegion &region)
+{
+ QWSWindow *changingw = findWindow(wid, 0);
+ if (!changingw)
+ return;
+
+ Q_Q(QWSServer);
+ QWSWindow::State windowState = QWSWindow::NoState;
+
+ if (region.isEmpty()) {
+ windowState = QWSWindow::Hiding;
+ emit q->windowEvent(changingw, QWSServer::Hide);
+ }
+
+ const bool wasOpaque = changingw->opaque;
+
+ changingw->createSurface(surfaceKey, surfaceData);
+ QWSWindowSurface *surface = changingw->windowSurface();
+
+ changingw->opaque = surface->isOpaque();
+
+ QRegion r;
+ if (surface->isRegionReserved())
+ r = reserve_region(changingw, region);
+ else
+ r = region;
+
+ if (!region.isEmpty()) {
+ if (changingw->isVisible())
+ windowState = QWSWindow::ChangingGeometry;
+ else
+ windowState = QWSWindow::Showing;
+ }
+ changingw->d->state = windowState;
+
+ if (!r.isEmpty() && wasOpaque != changingw->opaque && surface->isBuffered())
+ changingw->requested_region = QRegion(); // XXX: force update_regions
+
+ const QRegion oldAllocated = changingw->allocatedRegion();
+ setWindowRegion(changingw, r);
+ if (oldAllocated == changingw->allocatedRegion()) {
+ // Always send region event to the requesting window even if the
+ // region didn't change. This is necessary as the client will reset
+ // the clip region until an event is received.
+ changingw->client()->sendRegionEvent(wid, changingw->allocatedRegion(),
+ QWSRegionEvent::Allocation);
+ }
+
+ surface->QWindowSurface::setGeometry(r.boundingRect());
+
+ if (windowState == QWSWindow::Showing)
+ emit q->windowEvent(changingw, QWSServer::Show);
+ else if (windowState == QWSWindow::ChangingGeometry)
+ emit q->windowEvent(changingw, QWSServer::Geometry);
+ if (windowState == QWSWindow::Hiding) {
+ handleWindowClose(changingw);
+ changingw->d->state = QWSWindow::Hidden;
+ changingw->d->painted = false;
+ } else {
+ changingw->d->state = QWSWindow::Visible;
+ }
+}
+
+void QWSServerPrivate::destroy_region(const QWSRegionDestroyCommand *cmd)
+{
+ invokeRegionDestroy(cmd, clientMap.value(-1));
+}
+
+void QWSServerPrivate::name_region(const QWSRegionNameCommand *cmd)
+{
+ invokeRegionName(cmd, clientMap.value(-1));
+}
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+void QWSServerPrivate::im_response(const QWSIMResponseCommand *cmd)
+ {
+ invokeIMResponse(cmd, clientMap.value(-1));
+}
+
+void QWSServerPrivate::im_update(const QWSIMUpdateCommand *cmd)
+{
+ invokeIMUpdate(cmd, clientMap.value(-1));
+}
+
+void QWSServerPrivate::send_im_mouse(const QWSIMMouseCommand *cmd)
+{
+ if (current_IM)
+ current_IM->mouseHandler(cmd->simpleData.index, cmd->simpleData.state);
+}
+#endif
+
+void QWSServerPrivate::openDisplay()
+{
+ qt_init_display();
+
+// rgnMan = qt_fbdpy->regionManager();
+ swidth = qt_screen->deviceWidth();
+ sheight = qt_screen->deviceHeight();
+}
+
+void QWSServerPrivate::closeDisplay()
+{
+ qt_screen->shutdownDevice();
+}
+
+/*!
+ Returns the brush used as background in the absence of obscuring
+ windows.
+
+ \sa setBackground()
+*/
+const QBrush &QWSServer::backgroundBrush() const
+{
+ return *QWSServerPrivate::bgBrush;
+}
+
+/*!
+ Sets the brush used as background in the absence of obscuring
+ windows, to be the given \a brush.
+
+ Note that this function can only be used in the server process.
+
+ \sa backgroundBrush()
+*/
+void QWSServer::setBackground(const QBrush &brush)
+{
+ if (!QWSServerPrivate::bgBrush)
+ QWSServerPrivate::bgBrush = new QBrush(brush);
+ else
+ *QWSServerPrivate::bgBrush = brush;
+ if (!qwsServer)
+ return;
+ qt_screen->exposeRegion(QRect(0,0,qt_screen->width(), qt_screen->height()), 0);
+}
+
+
+#ifdef QT3_SUPPORT
+/*!
+ \fn void QWSServer::setDesktopBackground(const QImage &image)
+
+ Sets the image used as background in the absence of obscuring
+ windows, to be the given \a image.
+
+ Use the setBackground() function instead.
+
+ \oldcode
+ QImage image;
+ setDesktopBackground(image);
+ \newcode
+ QImage image;
+ setBackground(QBrush(image));
+ \endcode
+*/
+void QWSServer::setDesktopBackground(const QImage &img)
+{
+ if (img.isNull())
+ setBackground(Qt::NoBrush);
+ else
+ setBackground(QBrush(QPixmap::fromImage(img)));
+}
+
+/*!
+ \fn void QWSServer::setDesktopBackground(const QColor &color)
+ \overload
+
+ Sets the color used as background in the absence of obscuring
+ windows, to be the given \a color.
+
+ Use the setBackground() function instead.
+
+ \oldcode
+ QColor color;
+ setDesktopBackground(color);
+ \newcode
+ QColor color;
+ setBackground(QBrush(color));
+ \endcode
+*/
+void QWSServer::setDesktopBackground(const QColor &c)
+{
+ setDesktopBackground(QBrush(c));
+}
+#endif //QT3_SUPPORT
+
+/*!
+ \internal
+ */
+void QWSServer::startup(int flags)
+{
+ if (qwsServer)
+ return;
+ unlink(qws_qtePipeFilename().toLatin1().constData());
+ (void)new QWSServer(flags);
+}
+
+/*!
+ \internal
+*/
+
+void QWSServer::closedown()
+{
+ unlink(qws_qtePipeFilename().toLatin1().constData());
+ delete qwsServer;
+ qwsServer = 0;
+}
+
+void QWSServerPrivate::emergency_cleanup()
+{
+#ifndef QT_NO_QWS_KEYBOARD
+ if (qwsServer)
+ qwsServer->closeKeyboard();
+#endif
+}
+
+#ifndef QT_NO_QWS_KEYBOARD
+static QList<QWSServer::KeyboardFilter*> *keyFilters = 0;
+
+/*!
+ Processes the given key event. The key is identified by its \a
+ unicode value and the given \a keycode, \a modifiers, \a isPress
+ and \a autoRepeat parameters.
+
+ The \a keycode parameter is the Qt keycode value as defined by the
+ Qt::Key enum. The \a modifiers is an OR combination of
+ Qt::KeyboardModifier values, indicating whether \gui
+ Shift/Alt/Ctrl keys are pressed. The \a isPress parameter is true
+ if the event is a key press event and \a autoRepeat is true if the
+ event is caused by an auto-repeat mechanism and not an actual key
+ press.
+
+ This function is typically called internally by keyboard drivers.
+ Note that this function can only be used in the server process.
+
+ \sa sendKeyEvent(), {Qt for Embedded Linux Character Input}
+*/
+void QWSServer::processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
+ bool isPress, bool autoRepeat)
+{
+ bool block;
+ // Don't block the POWER or LIGHT keys
+ if ( keycode == Qt::Key_F34 || keycode == Qt::Key_F35 )
+ block = false;
+ else
+ block = qwsServerPrivate->screensaverblockevent(KEY, qwsServerPrivate->screensaverinterval, isPress);
+
+#ifdef EVENT_BLOCK_DEBUG
+ qDebug() << "processKeyEvent" << unicode << keycode << modifiers << isPress << autoRepeat << (block?"block":"pass");
+#endif
+
+ // If we press a key and it's going to be blocked, wake up the screen
+ if ( block && isPress )
+ qwsServerPrivate->_q_screenSaverWake();
+
+ if ( block )
+ return;
+
+ if (keyFilters) {
+ for (int i = 0; i < keyFilters->size(); ++i) {
+ QWSServer::KeyboardFilter *keyFilter = keyFilters->at(i);
+ if (keyFilter->filter(unicode, keycode, modifiers, isPress, autoRepeat))
+ return;
+ }
+ }
+ sendKeyEvent(unicode, keycode, modifiers, isPress, autoRepeat);
+}
+
+/*!
+ \fn void QWSServer::addKeyboardFilter(KeyboardFilter *filter)
+
+ Activates the given keyboard \a filter all key events generated by
+ physical keyboard drivers (i.e., events sent using the
+ processKeyEvent() function).
+
+ Note that the filter is not invoked for keys generated by \e
+ virtual keyboard drivers (i.e., events sent using the
+ sendKeyEvent() function).
+
+ Note that this function can only be used in the server process.
+
+ \sa removeKeyboardFilter()
+*/
+void QWSServer::addKeyboardFilter(KeyboardFilter *f)
+{
+ if (!keyFilters)
+ keyFilters = new QList<QWSServer::KeyboardFilter*>;
+ if (f) {
+ keyFilters->prepend(f);
+ }
+}
+
+/*
+//#######
+ We should probably obsolete the whole keyboard filter thing since
+ it's not useful for input methods anyway
+
+ We could do removeKeyboardFilter(KeyboardFilter *f), but
+ the "remove and delete the filter" concept does not match "user
+ remembers the pointer".
+*/
+
+/*!
+ Removes and deletes the most recently added filter.
+
+ Note that the programmer is responsible for removing each added
+ keyboard filter.
+
+ Note that this function can only be used in the server process.
+
+ \sa addKeyboardFilter()
+*/
+void QWSServer::removeKeyboardFilter()
+{
+ if (!keyFilters || keyFilters->isEmpty())
+ return;
+ delete keyFilters->takeAt(0);
+}
+#endif // QT_NO_QWS_KEYBOARD
+
+/*!
+ \fn void QWSServer::setScreenSaverIntervals(int* intervals)
+
+ Specifies the time \a intervals (in milliseconds) between the
+ different levels of screen responsiveness.
+
+ \l{Qt for Embedded Linux} supports multilevel screen saving, i.e., it is
+ possible to specify several different levels of screen
+ responsiveness by implementing the QWSScreenSaver::save()
+ function. For example, you can choose to first turn off the light
+ before you fully activate the screensaver. See the QWSScreenSaver
+ documentation for details.
+
+ Note that an interval of 0 milliseconds will turn off the
+ screensaver, and that the \a intervals array must be 0-terminated.
+ This function can only be used in the server process.
+
+ \sa setScreenSaverInterval(), setScreenSaverBlockLevel()
+*/
+void QWSServer::setScreenSaverIntervals(int* ms)
+{
+ if (!qwsServerPrivate)
+ return;
+
+ delete [] qwsServerPrivate->screensaverintervals;
+ if (ms) {
+ int* t=ms;
+ int n=0;
+ while (*t++) n++;
+ if (n) {
+ n++; // the 0
+ qwsServerPrivate->screensaverintervals = new int[n];
+ memcpy(qwsServerPrivate->screensaverintervals, ms, n*sizeof(int));
+ } else {
+ qwsServerPrivate->screensaverintervals = 0;
+ }
+ } else {
+ qwsServerPrivate->screensaverintervals = 0;
+ }
+ qwsServerPrivate->screensaverinterval = 0;
+
+ qwsServerPrivate->screensavertimer->stop();
+ qt_screen->blank(false);
+ qwsServerPrivate->_q_screenSaverWake();
+}
+
+/*!
+ \fn void QWSServer::setScreenSaverInterval(int milliseconds)
+
+ Sets the timeout interval for the screensaver to the specified \a
+ milliseconds. To turn off the screensaver, set the timout interval
+ to 0.
+
+ Note that this function can only be used in the server process.
+
+ \sa setScreenSaverIntervals(), setScreenSaverBlockLevel()
+*/
+void QWSServer::setScreenSaverInterval(int ms)
+{
+ int v[2];
+ v[0] = ms;
+ v[1] = 0;
+ setScreenSaverIntervals(v);
+}
+
+/*!
+ Block the key or mouse event that wakes the system from level \a eventBlockLevel or higher.
+ To completely disable event blocking (the default behavior), set \a eventBlockLevel to -1.
+
+ The algorithm blocks the "down", "up" as well as any "repeat" events for the same key
+ but will not block other key events after the initial "down" event. For mouse events, the
+ algorithm blocks all mouse events until an event with no buttons pressed is received.
+
+ There are 2 keys that are never blocked, Qt::Key_F34 (POWER) and Qt::Key_F35 (LIGHT).
+
+ Example usage:
+
+ \snippet doc/src/snippets/code/src_gui_embedded_qwindowsystem_qws.cpp 0
+
+ Note that this function can only be used in the server process.
+
+ \sa setScreenSaverIntervals(), setScreenSaverInterval()
+*/
+void QWSServer::setScreenSaverBlockLevel(int eventBlockLevel)
+{
+ if (!qwsServerPrivate)
+ return;
+ qwsServerPrivate->screensavereventblocklevel = eventBlockLevel;
+#ifdef EVENT_BLOCK_DEBUG
+ qDebug() << "QWSServer::setScreenSaverBlockLevel() " << eventBlockLevel;
+#endif
+}
+
+extern bool qt_disable_lowpriority_timers; //in qeventloop_unix.cpp
+
+void QWSServerPrivate::_q_screenSaverWake()
+{
+ if (screensaverintervals) {
+ if (screensaverinterval != screensaverintervals) {
+ if (saver) saver->restore();
+ screensaverinterval = screensaverintervals;
+ screensaverblockevents = false;
+ } else {
+ if (!screensavertimer->isActive()) {
+ qt_screen->blank(false);
+ if (saver) saver->restore();
+ }
+ }
+ screensavertimer->start(*screensaverinterval);
+ screensavertime.start();
+ }
+ qt_disable_lowpriority_timers=false;
+}
+
+void QWSServerPrivate::_q_screenSaverSleep()
+{
+ qt_screen->blank(true);
+#if !defined(QT_QWS_IPAQ) && !defined(QT_QWS_EBX)
+ screensavertimer->stop();
+#else
+ if (screensaverinterval) {
+ screensavertimer->start(*screensaverinterval);
+ screensavertime.start();
+ } else {
+ screensavertimer->stop();
+ }
+#endif
+ qt_disable_lowpriority_timers=true;
+}
+
+/*!
+ \fn void QWSServer::setScreenSaver(QWSScreenSaver* screenSaver)
+
+ Installs the given \a screenSaver, deleting the current screen
+ saver.
+
+ Note that this function can only be used in the server process.
+
+ \sa screenSaverActivate(), setScreenSaverInterval(), setScreenSaverIntervals(), setScreenSaverBlockLevel()
+*/
+void QWSServer::setScreenSaver(QWSScreenSaver* ss)
+{
+ QWSServerPrivate *qd = qwsServer->d_func();
+ delete qd->saver;
+ qd->saver = ss;
+}
+
+void QWSServerPrivate::screenSave(int level)
+{
+ if (saver) {
+ // saver->save() may call QCoreApplication::processEvents,
+ // block event before calling saver->save().
+ bool oldScreensaverblockevents = screensaverblockevents;
+ if (*screensaverinterval >= 1000) {
+ screensaverblockevents = (screensavereventblocklevel >= 0 && screensavereventblocklevel <= level);
+#ifdef EVENT_BLOCK_DEBUG
+ if (screensaverblockevents)
+ qDebug("ready to block events");
+#endif
+ }
+ int *oldScreensaverinterval = screensaverinterval;
+ if (saver->save(level)) {
+ // only update screensaverinterval if it hasn't already changed
+ if (oldScreensaverinterval == screensaverinterval) {
+ if (screensaverinterval && screensaverinterval[1]) {
+ screensavertimer->start(*++screensaverinterval);
+ screensavertime.start();
+ } else {
+ screensaverinterval = 0;
+ }
+ }
+ } else {
+ // restore previous state
+ screensaverblockevents = oldScreensaverblockevents;
+
+ // for some reason, the saver don't want us to change to the
+ // next level, so we'll stay at this level for another interval
+ if (screensaverinterval && *screensaverinterval) {
+ screensavertimer->start(*screensaverinterval);
+ screensavertime.start();
+ }
+ }
+ } else {
+ screensaverinterval = 0;//screensaverintervals;
+ screensaverblockevents = false;
+ _q_screenSaverSleep();
+ }
+}
+
+void QWSServerPrivate::_q_screenSaverTimeout()
+{
+ if (screensaverinterval) {
+ if (screensavertime.elapsed() > *screensaverinterval*2) {
+ // bogus (eg. unsuspend, system time changed)
+ _q_screenSaverWake(); // try again
+ return;
+ }
+ screenSave(screensaverinterval - screensaverintervals);
+ }
+}
+
+/*!
+ Returns true if the screen saver is active; otherwise returns
+ false.
+
+ Note that this function can only be used in the server process.
+
+ \sa screenSaverActivate()
+*/
+bool QWSServer::screenSaverActive()
+{
+ return qwsServerPrivate->screensaverinterval
+ && !qwsServerPrivate->screensavertimer->isActive();
+}
+
+/*!
+ \internal
+*/
+void QWSServer::updateWindowRegions() const
+{
+ qwsServerPrivate->update_regions();
+}
+
+/*!
+ Activates the screen saver if \a activate is true; otherwise it is
+ deactivated.
+
+ Note that this function can only be used in the server process.
+
+ \sa screenSaverActive(), setScreenSaver()
+*/
+void QWSServer::screenSaverActivate(bool activate)
+{
+ if (activate)
+ qwsServerPrivate->_q_screenSaverSleep();
+ else
+ qwsServerPrivate->_q_screenSaverWake();
+}
+
+void QWSServerPrivate::disconnectClient(QWSClient *c)
+{
+ QTimer::singleShot(0, c, SLOT(closeHandler()));
+}
+
+void QWSServerPrivate::updateClientCursorPos()
+{
+ Q_Q(QWSServer);
+ QWSWindow *win = qwsServerPrivate->mouseGrabber ? qwsServerPrivate->mouseGrabber : qwsServer->windowAt(QWSServer::mousePosition);
+ QWSClient *winClient = win ? win->client() : 0;
+ if (winClient && winClient != cursorClient)
+ q->sendMouseEvent(QWSServer::mousePosition, mouseState);
+}
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+
+/*!
+ \class QWSInputMethod
+ \preliminary
+ \ingroup qws
+
+ \brief The QWSInputMethod class provides international input methods
+ in Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ A \l{Qt for Embedded Linux} application requires a server application to be
+ running, or to be the server application itself. All system
+ generated events, including keyboard and mouse events, are passed
+ to the server application which then propagates the event to the
+ appropriate client.
+
+ An input method consists of a filter and optionally a graphical
+ interface, and is used to filter input events between the server
+ and the client application.
+
+ \tableofcontents
+
+ \section1 Creating Custom Input Methods
+
+ To implement a custom input method, derive from the QWSInputMethod
+ class, and use the server's \l
+ {QWSServer::}{setCurrentInputMethod()} function to install it.
+
+ When subclassing QWSInputMethod, you can reimplement the filter()
+ functions to handle input from both physical and virtual keyboards
+ as well as mouse devices. Note that the default implementations do
+ nothing. Use the setInputResolution() function to control the
+ number of bits shifted when filtering mouse input, i.e., when
+ going from pointer resolution to screen resolution (the current
+ resolution can be retrieved using the inputResolutionShift()
+ function).
+
+ Reimplement the reset() function to restore the state of the input
+ method. Note that the default implementation calls the sendEvent()
+ function with empty preedit and commit strings if the input method
+ is in compose mode (i.e., if the input method is actively
+ composing a preedit string).
+
+ To receive replies to an input method query (sent using the
+ sendQuery() function), you must reimplement the queryResponse()
+ function, while the mouseHandler() function must be reimplemented
+ if you want to handle mouse events within the preedit
+ text. Reimplement the updateHandler() function to handle update
+ events including resets and focus changes. The UpdateType enum
+ describes the various types of update events recognized by the
+ input method.
+
+ \section1 Using Input Methods
+
+ In addition to the filter(), reset(), queryResponse(),
+ mouseHandler() and updateHandler() function mentioned in the
+ previous section, the QWSInputMethod provides several other
+ functions helping the window system to manage the installed input
+ methods.
+
+ The sendEvent() function sends the given event to the focus
+ widget, while the sendPreeditString() function sends the given
+ preedit text (encapsulated by an event). QWSInputMethod also
+ provides the sendCommitString() convenience function which sends
+ an event encapsulating the given commit string to the current
+ focus widget, and the sendMouseEvent() function which sends the
+ given mouse event.
+
+ Finally, the QWSInputMethod class provides the sendQuery()
+ function for sending input method queries. This function
+ encapsulates the event with a QWSEvent instance of the \l
+ {QWSEvent::}{IMQuery} type.
+
+ \sa QWSServer, {Qt for Embedded Linux Architecture}
+*/
+
+/*!
+ Constructs a new input method.
+
+ Use the QWSServer::setCurrentInputMethod() function to install it.
+*/
+
+QWSInputMethod::QWSInputMethod()
+{
+
+}
+
+/*!
+ Destroys this input method, uninstalling it if it is installed.
+*/
+QWSInputMethod::~QWSInputMethod()
+{
+ if (current_IM == this)
+ current_IM = 0;
+}
+
+/*!
+ Filters the key input identified by the given \a unicode, \a
+ keycode, \a modifiers, \a isPress and \a autoRepeat parameters.
+
+ Note that the default implementation does nothing; reimplement
+ this function to handle input from both physical and virtual
+ devices.
+
+ The \a keycode is a Qt::Key value, and the \a modifiers is an OR
+ combination of Qt::KeyboardModifiers. The \a isPress parameter is
+ telling whether the input is a key press or key release, and the
+ \a autoRepeat parameter determines whether the input is
+ autorepeated ( i.e., in which case the
+ QWSKeyboardHandler::beginAutoRepeat() function has been called).
+
+ To block the event from further processing, return true when
+ reimplementing this function; the default implementation returns
+ false.
+
+ \sa setInputResolution(), inputResolutionShift()
+*/
+bool QWSInputMethod::filter(int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat)
+{
+ Q_UNUSED(unicode);
+ Q_UNUSED(keycode);
+ Q_UNUSED(modifiers);
+ Q_UNUSED(isPress);
+ Q_UNUSED(autoRepeat);
+ return false;
+}
+
+/*!
+ \overload
+
+ Filters the mouse input identified by the given \a position, \a
+ state, and \a wheel parameters.
+*/
+bool QWSInputMethod::filter(const QPoint &position, int state, int wheel)
+{
+ Q_UNUSED(position);
+ Q_UNUSED(state);
+ Q_UNUSED(wheel);
+ return false;
+}
+
+/*!
+ Resets the state of the input method.
+
+ If the input method is in compose mode, i.e., the input method is
+ actively composing a preedit string, the default implementation
+ calls sendEvent() with empty preedit and commit strings; otherwise
+ it does nothing. Reimplement this function to alter this behavior.
+
+ \sa sendEvent()
+*/
+void QWSInputMethod::reset()
+{
+ if (current_IM_composing_win) {
+ QInputMethodEvent ime;
+ sendEvent(&ime);
+ }
+}
+
+/*!
+ \enum QWSInputMethod::UpdateType
+
+ This enum describes the various types of update events recognized
+ by the input method.
+
+ \value Update The input widget is updated in some way; use sendQuery() with
+ Qt::ImMicroFocus as an argument for more information.
+ \value FocusIn A new input widget receives focus.
+ \value FocusOut The input widget loses focus.
+ \value Reset The input method should be reset.
+ \value Destroyed The input widget is destroyed.
+
+ \sa updateHandler()
+*/
+
+/*!
+ Handles update events including resets and focus changes. The
+ update events are specified by the given \a type which is one of
+ the UpdateType enum values.
+
+ Note that reimplementations of this function must call the base
+ implementation for all cases that it does not handle itself.
+
+ \sa UpdateType
+*/
+void QWSInputMethod::updateHandler(int type)
+{
+ switch (type) {
+ case FocusOut:
+ case Reset:
+ reset();
+ break;
+
+ default:
+ break;
+ }
+}
+
+
+/*!
+ Receive replies to an input method query.
+
+ Note that the default implementation does nothing; reimplement
+ this function to receive such replies.
+
+ Internally, an input method query is passed encapsulated by an \l
+ {QWSEvent::IMQuery}{IMQuery} event generated by the sendQuery()
+ function. The queried property and the result is passed in the \a
+ property and \a result parameters.
+
+ \sa sendQuery(), QWSServer::sendIMQuery()
+*/
+void QWSInputMethod::queryResponse(int property, const QVariant &result)
+{
+ Q_UNUSED(property);
+ Q_UNUSED(result);
+}
+
+
+
+/*!
+ \fn void QWSInputMethod::mouseHandler(int offset, int state)
+
+ Handles mouse events within the preedit text.
+
+ Note that the default implementation resets the input method on
+ all mouse presses; reimplement this function to alter this
+ behavior.
+
+ The \a offset parameter specifies the position of the mouse event
+ within the string, and \a state specifies the type of the mouse
+ event as described by the QWSServer::IMMouse enum. If \a state is
+ less than 0, the mouse event is inside the associated widget, but
+ outside the preedit text. When clicking in a different widget, the
+ \a state is QWSServer::MouseOutside.
+
+ \sa sendPreeditString(), reset()
+*/
+void QWSInputMethod::mouseHandler(int, int state)
+{
+ if (state == QWSServer::MousePress || state == QWSServer::MouseOutside)
+ reset();
+}
+
+
+/*!
+ Sends an event encapsulating the given \a preeditString, to the
+ focus widget.
+
+ The specified \a selectionLength is the number of characters to be
+ marked as selected (starting at the given \a cursorPosition). If
+ \a selectionLength is negative, the text \e before \a
+ cursorPosition is marked.
+
+ The preedit string is marked with QInputContext::PreeditFormat,
+ and the selected part is marked with
+ QInputContext::SelectionFormat.
+
+ Sending an input method event with a non-empty preedit string will
+ cause the input method to enter compose mode. Sending an input
+ method event with an empty preedit string will cause the input
+ method to leave compose mode, i.e., the input method will no longer
+ be actively composing the preedit string.
+
+ Internally, the event is represented by a QWSEvent object of the
+ \l {QWSEvent::IMEvent}{IMEvent} type.
+
+ \sa sendEvent(), sendCommitString()
+*/
+
+void QWSInputMethod::sendPreeditString(const QString &preeditString, int cursorPosition, int selectionLength)
+{
+ QList<QInputMethodEvent::Attribute> attributes;
+
+ int selPos = cursorPosition;
+ if (selectionLength == 0) {
+ selPos = 0;
+ } else if (selectionLength < 0) {
+ selPos += selectionLength;
+ selectionLength = -selectionLength;
+ }
+ if (selPos > 0)
+ attributes += QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, 0, selPos,
+ QVariant(int(QInputContext::PreeditFormat)));
+
+ if (selectionLength)
+ attributes += QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, selPos, selectionLength,
+ QVariant(int(QInputContext::SelectionFormat)));
+
+ if (selPos + selectionLength < preeditString.length())
+ attributes += QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat,
+ selPos + selectionLength,
+ preeditString.length() - selPos - selectionLength,
+ QVariant(int(QInputContext::PreeditFormat)));
+
+ attributes += QInputMethodEvent::Attribute(QInputMethodEvent::Cursor, cursorPosition, 0, QVariant());
+
+ QInputMethodEvent ime(preeditString, attributes);
+ qwsServer->sendIMEvent(&ime);
+}
+
+/*!
+ \fn void QWSInputMethod::sendCommitString(const QString &commitString, int replaceFromPosition, int replaceLength)
+
+ Sends an event encapsulating the given \a commitString, to the
+ focus widget.
+
+ Note that this will cause the input method to leave compose mode,
+ i.e., the input method will no longer be actively composing the
+ preedit string.
+
+ If the specified \a replaceLength is greater than 0, the commit
+ string will replace the given number of characters of the
+ receiving widget's previous text, starting at the given \a
+ replaceFromPosition relative to the start of the current preedit
+ string.
+
+ Internally, the event is represented by a QWSEvent object of the
+ \l {QWSEvent::IMEvent}{IMEvent} type.
+
+ \sa sendEvent(), sendPreeditString()
+*/
+void QWSInputMethod::sendCommitString(const QString &commitString, int replaceFrom, int replaceLength)
+{
+ QInputMethodEvent ime;
+ ime.setCommitString(commitString, replaceFrom, replaceLength);
+ qwsServer->sendIMEvent(&ime);
+}
+
+/*!
+ \fn QWSInputMethod::sendIMEvent(QWSServer::IMState state, const QString &text, int cursorPosition, int selectionLength)
+ \obsolete
+
+ Sends a QInputMethodEvent object to the focus widget.
+
+ If the specified \a state is QWSServer::IMCompose, \a text is a
+ preedit string, \a cursorPosition is the cursor's position within
+ the preedit string, and \a selectionLength is the number of
+ characters (starting at \a cursorPosition) that should be marked
+ as selected by the input widget receiving the event. If the
+ specified \a state is QWSServer::IMEnd, \a text is a commit
+ string.
+
+ Use sendEvent(), sendPreeditString() or sendCommitString() instead.
+*/
+
+/*!
+ \fn QWSInputMethod::sendEvent(const QInputMethodEvent *event)
+
+ Sends the given \a event to the focus widget.
+
+ The \c QInputMethodEvent class is derived from QWSEvent, i.e., the
+ given \a event is a QWSEvent object of the \l
+ {QWSEvent::IMEvent}{IMEvent} type.
+
+ \sa sendPreeditString(), sendCommitString(), reset()
+*/
+
+
+/*!
+ \fn void QWSInputMethod::sendQuery(int property)
+
+ Sends an input method query (internally encapsulated by a QWSEvent
+ of the \l {QWSEvent::IMQuery}{IMQuery} type) for the specified \a
+ property.
+
+ To receive responses to input method queries, the virtual
+ queryResponse() function must be reimplemented.
+
+ \sa queryResponse(), QWSServer::sendIMQuery()
+*/
+
+/*!
+ Sets and returns the number of bits shifted to go from pointer
+ resolution to screen resolution when filtering mouse input.
+
+ If \a isHigh is true and the device has a pointer device
+ resolution twice or more of the screen resolution, the positions
+ passed to the filter() function will be presented at the higher
+ resolution; otherwise the resolution will be equal to that of the
+ screen resolution.
+
+ \sa inputResolutionShift(), filter()
+*/
+uint QWSInputMethod::setInputResolution(bool isHigh)
+{
+ mIResolution = isHigh;
+ return inputResolutionShift();
+}
+
+/*!
+ Returns the number of bits shifted to go from pointer resolution
+ to screen resolution when filtering mouse input.
+
+ \sa setInputResolution(), filter()
+*/
+uint QWSInputMethod::inputResolutionShift() const
+{
+ return 0; // default for devices with single resolution.
+}
+
+/*!
+ \fn void QWSInputMethod::sendMouseEvent( const QPoint &position, int state, int wheel )
+
+ Sends a mouse event specified by the given \a position, \a state
+ and \a wheel parameters.
+
+ The given \a position will be transformed if the screen
+ coordinates do not match the pointer device coordinates.
+
+ Note that the event will be not be tested by the active input
+ method, but calling the QWSServer::sendMouseEvent() function will
+ make the current input method filter the event.
+
+ \sa mouseHandler(), sendEvent()
+*/
+void QWSInputMethod::sendMouseEvent( const QPoint &pos, int state, int wheel )
+{
+ if (qt_last_x) {
+ *qt_last_x = pos.x();
+ *qt_last_y = pos.y();
+ }
+ QWSServer::mousePosition = pos;
+ qwsServerPrivate->mouseState = state;
+ QWSServerPrivate::sendMouseEventUnfiltered(pos, state, wheel);
+}
+#endif // QT_NO_QWS_INPUTMETHODS
+
+/*!
+ \fn QWSWindow::QWSWindow(int i, QWSClient * client)
+ \internal
+
+ Constructs a new top-level window, associated with the client \a
+ client and giving it the id \a i.
+*/
+
+/*!
+ \fn QWSServer::windowEvent(QWSWindow * window, QWSServer::WindowEvent eventType)
+
+ This signal is emitted whenever something happens to a top-level
+ window (e.g., it's created or destroyed), passing a pointer to the
+ window and the event's type in the \a window and \a eventType
+ parameters, respectively.
+
+ \sa markedText()
+*/
+
+/*!
+ \class QWSServer::KeyboardFilter
+ \ingroup qws
+
+ \brief The KeyboardFilter class is a base class for global
+ keyboard event filters in Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ In \l{Qt for Embedded Linux}, all system generated events, including
+ keyboard events, are passed to the server application which then
+ propagates the event to the appropriate client. The KeyboardFilter
+ class is used to implement a global, low-level filter on the
+ server side. The server applies the filter to all keyboard events
+ before passing them on to the clients:
+
+ \image qwsserver_keyboardfilter.png
+
+ This feature can, for example, be used to filter things like APM
+ (advanced power management) suspended from a button without having
+ to filter for it in all applications.
+
+ To add a new keyboard filter you must first create the filter by
+ deriving from this class, reimplementing the pure virtual filter()
+ function. Then you can install the filter on the server using
+ QWSServer's \l {QWSServer::}{addKeyboardFilter()}
+ function. QWSServer also provides a \l
+ {QWSServer::}{removeKeyboardFilter()} function.
+
+ \sa {Qt for Embedded Linux Architecture}, QWSServer, QWSInputMethod
+*/
+
+/*!
+ \fn QWSServer::KeyboardFilter::~KeyboardFilter()
+
+ Destroys the keyboard filter.
+*/
+
+/*!
+ \fn bool QWSServer::KeyboardFilter::filter(int unicode, int keycode, int modifiers, bool isPress, bool autoRepeat)
+
+ Implement this function to return true if a given key event should
+ be stopped from being processed any further; otherwise it should
+ return false.
+
+ A key event can be identified by the given \a unicode value and
+ the \a keycode, \a modifiers, \a isPress and \a autoRepeat
+ parameters.
+
+ The \a keycode parameter is the Qt keycode value as defined by the
+ Qt::Key enum. The \a modifiers is an OR combination of
+ Qt::KeyboardModifier values, indicating whether \gui
+ Shift/Alt/Ctrl keys are pressed. The \a isPress parameter is true
+ if the event is a key press event and \a autoRepeat is true if the
+ event is caused by an auto-repeat mechanism and not an actual key
+ press.
+*/
+
+QT_END_NAMESPACE
+
+#include "moc_qwindowsystem_qws.cpp"
diff --git a/src/gui/embedded/qwindowsystem_qws.h b/src/gui/embedded/qwindowsystem_qws.h
new file mode 100644
index 0000000000..8af59a3aa9
--- /dev/null
+++ b/src/gui/embedded/qwindowsystem_qws.h
@@ -0,0 +1,508 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWINDOWSYSTEM_QWS_H
+#define QWINDOWSYSTEM_QWS_H
+
+#include <QtCore/qbytearray.h>
+#include <QtCore/qmap.h>
+#include <QtCore/qdatetime.h>
+#include <QtCore/qlist.h>
+
+#include <QtGui/qwsevent_qws.h>
+#include <QtGui/qkbd_qws.h>
+#include <QtGui/qregion.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+struct QWSWindowPrivate;
+class QWSCursor;
+class QWSClient;
+class QWSRegionManager;
+class QBrush;
+class QVariant;
+class QInputMethodEvent;
+class QWSInputMethod;
+class QWSBackingStore;
+class QWSWindowSurface;
+
+#ifdef QT3_SUPPORT
+class QImage;
+class QColor;
+#endif
+
+class QWSInternalWindowInfo
+{
+public:
+ int winid;
+ unsigned int clientid;
+ QString name; // Corresponds to QObject name of top-level widget
+};
+
+
+class Q_GUI_EXPORT QWSScreenSaver
+{
+public:
+ virtual ~QWSScreenSaver();
+ virtual void restore()=0;
+ virtual bool save(int level)=0;
+};
+
+
+class Q_GUI_EXPORT QWSWindow
+{
+ friend class QWSServer;
+ friend class QWSServerPrivate;
+
+public:
+ QWSWindow(int i, QWSClient* client);
+ ~QWSWindow();
+
+ int winId() const { return id; }
+ const QString &name() const { return rgnName; }
+ const QString &caption() const { return rgnCaption; }
+ QWSClient* client() const { return c; }
+ const QRegion &requestedRegion() const { return requested_region; }
+ QRegion allocatedRegion() const;
+ QRegion paintedRegion() const;
+ bool isVisible() const { return !requested_region.isEmpty(); }
+ bool isPartiallyObscured() const { return requested_region != allocatedRegion(); }
+ bool isFullyObscured() const { return allocatedRegion().isEmpty(); }
+
+ enum State { NoState, Hidden, Showing, Visible, Hiding, Raising, Lowering, Moving, ChangingGeometry, Destroyed };
+ State state() const;
+ Qt::WindowFlags windowFlags() const;
+ QRegion dirtyOnScreen() const;
+
+ void raise();
+ void lower();
+ void show();
+ void hide();
+ void setActiveWindow();
+
+ bool isOpaque() const {return opaque && _opacity == 255;}
+ uint opacity() const { return _opacity; }
+
+ QWSWindowSurface* windowSurface() const { return surface; }
+
+private:
+ bool hidden() const { return requested_region.isEmpty(); }
+ bool forClient(const QWSClient* cl) const { return cl==c; }
+
+ void setName(const QString &n);
+ void setCaption(const QString &c);
+
+ void focus(bool get);
+ int focusPriority() const { return last_focus_time; }
+ void operation(QWSWindowOperationEvent::Operation o);
+ void shuttingDown() { last_focus_time=0; }
+
+#ifdef QT_QWS_CLIENTBLIT
+ QRegion directPaintRegion() const;
+ inline void setDirectPaintRegion(const QRegion &topmost);
+#endif
+ inline void setAllocatedRegion(const QRegion &region);
+
+ void createSurface(const QString &key, const QByteArray &data);
+
+#ifndef QT_NO_QWSEMBEDWIDGET
+ void startEmbed(QWSWindow *window);
+ void stopEmbed(QWSWindow *window);
+#endif
+
+private:
+ int id;
+ QString rgnName;
+ QString rgnCaption;
+ bool modified;
+ bool onTop;
+ QWSClient* c;
+ QRegion requested_region;
+ QRegion exposed;
+ int last_focus_time;
+ QWSWindowSurface *surface;
+ uint _opacity;
+ bool opaque;
+ QWSWindowPrivate *d;
+#ifdef QT3_SUPPORT
+ inline QT3_SUPPORT QRegion requested() const { return requested_region; }
+// inline QT3_SUPPORT QRegion allocation() const { return allocated_region; }
+#endif
+};
+
+
+#ifndef QT_NO_SOUND
+class QWSSoundServer;
+#ifdef QT_USE_OLD_QWS_SOUND
+class QWSSoundServerData;
+
+class Q_GUI_EXPORT QWSSoundServer : public QObject {
+ Q_OBJECT
+public:
+ QWSSoundServer(QObject* parent);
+ ~QWSSoundServer();
+ void playFile(const QString& filename);
+private Q_SLOTS:
+ void feedDevice(int fd);
+private:
+ QWSSoundServerData* d;
+};
+#endif
+#endif
+
+
+/*********************************************************************
+ *
+ * Class: QWSServer
+ *
+ *********************************************************************/
+
+class QWSMouseHandler;
+struct QWSCommandStruct;
+class QWSServerPrivate;
+class QWSServer;
+
+extern Q_GUI_EXPORT QWSServer *qwsServer;
+
+class Q_GUI_EXPORT QWSServer : public QObject
+{
+ friend class QCopChannel;
+ friend class QWSMouseHandler;
+ friend class QWSWindow;
+ friend class QWSDisplay;
+ friend class QWSInputMethod;
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWSServer)
+public:
+ explicit QWSServer(int flags = 0, QObject *parent=0);
+#ifdef QT3_SUPPORT
+ QT3_SUPPORT_CONSTRUCTOR QWSServer(int flags, QObject *parent, const char *name);
+#endif
+ ~QWSServer();
+ enum ServerFlags { DisableKeyboard = 0x01,
+ DisableMouse = 0x02 };
+
+ static void sendKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
+ bool isPress, bool autoRepeat);
+#ifndef QT_NO_QWS_KEYBOARD
+ static void processKeyEvent(int unicode, int keycode, Qt::KeyboardModifiers modifiers,
+ bool isPress, bool autoRepeat);
+#endif
+
+ static QWSServer* instance() { return qwsServer; }
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+#ifdef QT3_SUPPORT
+ enum IMState { IMCompose, IMEnd, IMStart = IMCompose };
+#endif
+ enum IMMouse { MousePress, MouseRelease, MouseMove, MouseOutside }; //MouseMove reserved but not used
+ void sendIMEvent(const QInputMethodEvent*);
+ void sendIMQuery(int property);
+#endif
+
+#ifndef QT_NO_QWS_KEYBOARD
+ class KeyboardFilter
+ {
+ public:
+ virtual ~KeyboardFilter() {}
+ virtual bool filter(int unicode, int keycode, int modifiers,
+ bool isPress, bool autoRepeat)=0;
+ };
+ static void addKeyboardFilter(KeyboardFilter *f);
+ static void removeKeyboardFilter();
+#endif
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+ static void setCurrentInputMethod(QWSInputMethod *im);
+ static void resetInputMethod();
+#endif
+
+ static void setDefaultMouse(const char *);
+ static void setDefaultKeyboard(const char *);
+ static void setMaxWindowRect(const QRect&);
+ static void sendMouseEvent(const QPoint& pos, int state, int wheel = 0);
+
+ static void setBackground(const QBrush &);
+#ifdef QT3_SUPPORT
+ static QT3_SUPPORT void setDesktopBackground(const QImage &img);
+ static QT3_SUPPORT void setDesktopBackground(const QColor &);
+#endif
+ static QWSMouseHandler *mouseHandler();
+ static const QList<QWSMouseHandler*>& mouseHandlers();
+ static void setMouseHandler(QWSMouseHandler*);
+#ifndef QT_NO_QWS_KEYBOARD
+ static QWSKeyboardHandler* keyboardHandler();
+ static void setKeyboardHandler(QWSKeyboardHandler* kh);
+#endif
+ QWSWindow *windowAt(const QPoint& pos);
+
+ const QList<QWSWindow*> &clientWindows();
+
+ void openMouse();
+ void closeMouse();
+ void suspendMouse();
+ void resumeMouse();
+#ifndef QT_NO_QWS_KEYBOARD
+ void openKeyboard();
+ void closeKeyboard();
+#endif
+
+ static void setScreenSaver(QWSScreenSaver*);
+ static void setScreenSaverIntervals(int* ms);
+ static void setScreenSaverInterval(int);
+ static void setScreenSaverBlockLevel(int);
+ static bool screenSaverActive();
+ static void screenSaverActivate(bool);
+
+ // the following are internal.
+ void refresh();
+ void refresh(QRegion &);
+
+ void enablePainting(bool);
+ static void processEventQueue();
+ static QList<QWSInternalWindowInfo*> * windowList();
+
+ void sendPropertyNotifyEvent(int property, int state);
+
+ static QPoint mousePosition;
+
+ static void startup(int flags);
+ static void closedown();
+
+ static void beginDisplayReconfigure();
+ static void endDisplayReconfigure();
+
+#ifndef QT_NO_QWS_CURSOR
+ static void setCursorVisible(bool);
+ static bool isCursorVisible();
+#endif
+
+ const QBrush &backgroundBrush() const;
+
+ enum WindowEvent { Create=0x0001, Destroy=0x0002, Hide=0x0004, Show=0x0008,
+ Raise=0x0010, Lower=0x0020, Geometry=0x0040, Active = 0x0080,
+ Name=0x0100 };
+
+Q_SIGNALS:
+ void windowEvent(QWSWindow *w, QWSServer::WindowEvent e);
+
+#ifndef QT_NO_COP
+ void newChannel(const QString& channel);
+ void removedChannel(const QString& channel);
+
+#endif
+#ifndef QT_NO_QWS_INPUTMETHODS
+ void markedText(const QString &);
+#endif
+
+protected:
+ void timerEvent(QTimerEvent *e);
+
+private:
+ friend class QApplicationPrivate;
+ void updateWindowRegions() const;
+
+#ifdef QT3_SUPPORT
+#ifndef QT_NO_QWS_KEYBOARD
+ static inline QT3_SUPPORT void setKeyboardFilter(QWSServer::KeyboardFilter *f)
+ { if (f) addKeyboardFilter(f); else removeKeyboardFilter(); }
+#endif
+#endif
+
+private:
+#ifndef QT_NO_QWS_MULTIPROCESS
+ Q_PRIVATE_SLOT(d_func(), void _q_clientClosed())
+ Q_PRIVATE_SLOT(d_func(), void _q_doClient())
+ Q_PRIVATE_SLOT(d_func(), void _q_deleteWindowsLater())
+#endif
+
+ Q_PRIVATE_SLOT(d_func(), void _q_screenSaverWake())
+ Q_PRIVATE_SLOT(d_func(), void _q_screenSaverSleep())
+ Q_PRIVATE_SLOT(d_func(), void _q_screenSaverTimeout())
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+ Q_PRIVATE_SLOT(d_func(), void _q_newConnection())
+#endif
+};
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+class Q_GUI_EXPORT QWSInputMethod : public QObject
+{
+ Q_OBJECT
+public:
+ QWSInputMethod();
+ virtual ~QWSInputMethod();
+
+ enum UpdateType {Update, FocusIn, FocusOut, Reset, Destroyed};
+
+ virtual bool filter(int unicode, int keycode, int modifiers,
+ bool isPress, bool autoRepeat);
+
+ virtual bool filter(const QPoint &, int state, int wheel);
+
+ virtual void reset();
+ virtual void updateHandler(int type);
+ virtual void mouseHandler(int pos, int state);
+ virtual void queryResponse(int property, const QVariant&);
+
+protected:
+ uint setInputResolution(bool isHigh);
+ uint inputResolutionShift() const;
+ // needed for required transform
+ void sendMouseEvent(const QPoint &pos, int state, int wheel);
+
+ void sendEvent(const QInputMethodEvent*);
+ void sendPreeditString(const QString &preeditString, int cursorPosition, int selectionLength = 0);
+ void sendCommitString(const QString &commitString, int replaceFrom = 0, int replaceLength = 0);
+ void sendQuery(int property);
+
+#ifdef QT3_SUPPORT
+ inline void sendIMEvent(QWSServer::IMState, const QString& txt, int cpos, int selLen = 0);
+#endif
+private:
+ bool mIResolution;
+};
+
+inline void QWSInputMethod::sendEvent(const QInputMethodEvent *ime)
+{
+ qwsServer->sendIMEvent(ime);
+}
+#ifdef QT3_SUPPORT
+inline void QWSInputMethod::sendIMEvent(QWSServer::IMState state, const QString& txt, int cpos, int selLen)
+{
+ if (state == QWSServer::IMCompose) sendPreeditString(txt, cpos, selLen); else sendCommitString(txt);
+}
+#endif
+
+inline void QWSInputMethod::sendQuery(int property)
+{
+ qwsServer->sendIMQuery(property);
+}
+
+// mouse events not inline as involve transformations.
+#endif // QT_NO_QWS_INPUTMETHODS
+
+
+
+/*********************************************************************
+ *
+ * Class: QWSClient
+ *
+ *********************************************************************/
+
+struct QWSMouseEvent;
+
+typedef QMap<int, QWSCursor*> QWSCursorMap;
+
+class QWSClientPrivate;
+class QWSCommand;
+class QWSConvertSelectionCommand;
+
+class Q_GUI_EXPORT QWSClient : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWSClient)
+public:
+ QWSClient(QObject* parent, QWS_SOCK_BASE *, int id);
+ ~QWSClient();
+
+ int socket() const;
+
+ void setIdentity(const QString&);
+ QString identity() const { return id; }
+
+ void sendEvent(QWSEvent* event);
+ void sendConnectedEvent(const char *display_spec);
+ void sendMaxWindowRectEvent(const QRect &rect);
+ void sendPropertyNotifyEvent(int property, int state);
+ void sendPropertyReplyEvent(int property, int len, const char *data);
+ void sendSelectionClearEvent(int windowid);
+ void sendSelectionRequestEvent(QWSConvertSelectionCommand *cmd, int windowid);
+#ifndef QT_QWS_CLIENTBLIT
+ void sendRegionEvent(int winid, QRegion rgn, int type);
+#else
+ void sendRegionEvent(int winid, QRegion rgn, int type, int id = 0);
+#endif
+#ifndef QT_NO_QWSEMBEDWIDGET
+ void sendEmbedEvent(int winid, QWSEmbedEvent::Type type,
+ const QRegion &region = QRegion());
+#endif
+ QWSCommand* readMoreCommand();
+
+ int clientId() const { return cid; }
+
+ QWSCursorMap cursors; // cursors defined by this client
+Q_SIGNALS:
+ void connectionClosed();
+ void readyRead();
+private Q_SLOTS:
+ void closeHandler();
+ void errorHandler();
+
+private:
+#ifndef QT_NO_QWS_MULTIPROCESS
+ friend class QWSWindow;
+ void removeUnbufferedSurface();
+ void addUnbufferedSurface();
+#endif
+
+private:
+ int socketDescriptor;
+#ifndef QT_NO_QWS_MULTIPROCESS
+ QWSSocket *csocket;
+#endif
+ QWSCommand* command;
+ uint isClosed : 1;
+ QString id;
+ int cid;
+
+ friend class QWSServerPrivate;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWINDOWSYSTEM_QWS_H
diff --git a/src/gui/embedded/qwscommand_qws.cpp b/src/gui/embedded/qwscommand_qws.cpp
new file mode 100644
index 0000000000..88e33a35e4
--- /dev/null
+++ b/src/gui/embedded/qwscommand_qws.cpp
@@ -0,0 +1,610 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwscommand_qws_p.h"
+#include "qtransportauth_qws.h"
+#include "qtransportauth_qws_p.h"
+
+#include <sys/uio.h>
+#include <unistd.h>
+
+// #define QWSCOMMAND_DEBUG 1 // Uncomment to debug client/server communication
+
+#ifdef QWSCOMMAND_DEBUG
+# include <qdebug.h>
+# include "qfile.h"
+# include <ctype.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QWSCOMMAND_DEBUG
+// QWSHexDump -[ start ]---------------------------------------------
+# define QWSHEXDUMP_MAX 32
+class QWSHexDump
+{
+public:
+
+ QWSHexDump(const void *address, int len, int wrapAt = 16)
+ : wrap(wrapAt), dataSize(len)
+ {
+ init();
+ data = reinterpret_cast<const char*>(address);
+ if (len < 0)
+ dataSize = 0;
+ }
+
+ QWSHexDump(const char *str, int len = -1, int wrapAt = 16)
+ : wrap(wrapAt), dataSize(len)
+ {
+ init();
+ data = str;
+ if (len == -1)
+ dataSize = str ? strlen(str) : 0;
+ }
+
+ QWSHexDump(const QByteArray &array, int wrapAt = 16)
+ : wrap(wrapAt)
+ {
+ init();
+ data = array.data();
+ dataSize = array.size();
+ }
+
+ // Sets a customized prefix for the hexdump
+ void setPrefix(const char *str) { prefix = str; }
+
+ // Sets number of bytes to cluster together
+ void setClusterSize(uint num) { clustering = num; }
+
+ // Output hexdump to a text stream
+ void intoTextStream(QTextStream &strm) {
+ outstrm = &strm;
+ hexDump();
+ }
+
+ // Output hexdump to a QString
+ QString toString();
+
+protected:
+ void init();
+ void hexDump();
+ void sideviewDump(int at);
+
+private:
+ uint wrap;
+ uint clustering;
+ uint dataSize;
+ int dataWidth;
+ const char *data;
+ const char *prefix;
+ bool dirty;
+
+ char sideviewLayout[QWSHEXDUMP_MAX + 1];
+ char sideview[15];
+
+ QTextStream *outstrm;
+};
+
+void QWSHexDump::init()
+{
+ prefix = "> "; // Standard line prefix
+ clustering = 2; // Word-size clustering by default
+ if (wrap > QWSHEXDUMP_MAX) // No wider than QWSHexDump_MAX bytes
+ wrap = QWSHEXDUMP_MAX;
+}
+
+void QWSHexDump::hexDump()
+{
+ *outstrm << "(" << dataSize << " bytes):\n" << prefix;
+ sprintf(sideviewLayout, " [%%-%us]", wrap);
+ dataWidth = (2 * wrap) + (wrap / clustering);
+
+ dirty = false;
+ uint wrapIndex = 0;
+ for (uint i = 0; i < dataSize; i++) {
+ uint c = static_cast<uchar>(data[i]);
+ sideview[wrapIndex = i%wrap] = isprint(c) ? c : '.';
+
+ if (wrapIndex && (wrapIndex % clustering == 0))
+ *outstrm << " ";
+
+ outstrm->setFieldWidth(2);
+ outstrm->setPadChar('0');
+ outstrm->setNumberFlags( QTextStream::ShowBase );
+ *outstrm << hex << c;
+ dirty = true;
+
+ if (wrapIndex == wrap-1) {
+ sideviewDump(wrapIndex);
+ wrapIndex = 0;
+ if (i+1 < dataSize)
+ *outstrm << endl << prefix;
+ }
+
+ }
+ sideviewDump(wrapIndex);
+}
+
+void QWSHexDump::sideviewDump(int at)
+{
+ if (dirty) {
+ dirty = false;
+ ++at;
+ sideview[at] = '\0';
+ int currentWidth = (2 * at) + (at / clustering) - (at%clustering?0:1);
+ int missing = qMax(dataWidth - currentWidth, 0);
+ while (missing--)
+ *outstrm << " ";
+
+ *outstrm << " [";
+ outstrm->setPadChar(' ');
+ outstrm->setFieldWidth(wrap);
+ outstrm->setFieldAlignment( QTextStream::AlignLeft );
+ *outstrm << sideview;
+ *outstrm << "]";
+ }
+}
+
+// Output hexdump to a QString
+QString QWSHexDump::toString() {
+ QString result;
+ QTextStream strm(&result, QFile::WriteOnly);
+ outstrm = &strm;
+ hexDump();
+ return result;
+}
+
+#ifndef QT_NO_DEBUG
+QDebug &operator<<(QDebug &dbg, QWSHexDump *hd) {
+ if (!hd)
+ return dbg << "QWSHexDump(0x0)";
+ QString result = hd->toString();
+ dbg.nospace() << result;
+ return dbg.space();
+}
+
+// GCC & Intel wont handle references here
+QDebug operator<<(QDebug dbg, QWSHexDump hd) {
+ return dbg << &hd;
+}
+#endif
+// QWSHexDump -[ end ]-----------------------------------------------
+
+
+QDebug &operator<<(QDebug &dbg, QWSCommand::Type tp)
+{
+ dbg << qws_getCommandTypeString( tp );
+ return dbg;
+}
+
+#define N_EVENTS 19
+const char * eventNames[N_EVENTS] = {
+ "NoEvent",
+ "Connected",
+ "Mouse", "Focus", "Key",
+ "Region",
+ "Creation",
+ "PropertyNotify",
+ "PropertyReply",
+ "SelectionClear",
+ "SelectionRequest",
+ "SelectionNotify",
+ "MaxWindowRect",
+ "QCopMessage",
+ "WindowOperation",
+ "IMEvent",
+ "IMQuery",
+ "IMInit",
+ "Font"
+ };
+
+class QWSServer;
+extern QWSServer *qwsServer;
+#endif
+
+const char *qws_getCommandTypeString( QWSCommand::Type tp )
+{
+ const char *typeStr;
+ switch(tp) {
+ case QWSCommand::Create:
+ typeStr = "Create";
+ break;
+ case QWSCommand::Shutdown:
+ typeStr = "Shutdown";
+ break;
+ case QWSCommand::Region:
+ typeStr = "Region";
+ break;
+ case QWSCommand::RegionMove:
+ typeStr = "RegionMove";
+ break;
+ case QWSCommand::RegionDestroy:
+ typeStr = "RegionDestroy";
+ break;
+ case QWSCommand::SetProperty:
+ typeStr = "SetProperty";
+ break;
+ case QWSCommand::AddProperty:
+ typeStr = "AddProperty";
+ break;
+ case QWSCommand::RemoveProperty:
+ typeStr = "RemoveProperty";
+ break;
+ case QWSCommand::GetProperty:
+ typeStr = "GetProperty";
+ break;
+ case QWSCommand::SetSelectionOwner:
+ typeStr = "SetSelectionOwner";
+ break;
+ case QWSCommand::ConvertSelection:
+ typeStr = "ConvertSelection";
+ break;
+ case QWSCommand::RequestFocus:
+ typeStr = "RequestFocus";
+ break;
+ case QWSCommand::ChangeAltitude:
+ typeStr = "ChangeAltitude";
+ break;
+ case QWSCommand::SetOpacity:
+ typeStr = "SetOpacity";
+ break;
+ case QWSCommand::DefineCursor:
+ typeStr = "DefineCursor";
+ break;
+ case QWSCommand::SelectCursor:
+ typeStr = "SelectCursor";
+ break;
+ case QWSCommand::PositionCursor:
+ typeStr = "PositionCursor";
+ break;
+ case QWSCommand::GrabMouse:
+ typeStr = "GrabMouse";
+ break;
+ case QWSCommand::PlaySound:
+ typeStr = "PlaySound";
+ break;
+ case QWSCommand::QCopRegisterChannel:
+ typeStr = "QCopRegisterChannel";
+ break;
+ case QWSCommand::QCopSend:
+ typeStr = "QCopSend";
+ break;
+ case QWSCommand::RegionName:
+ typeStr = "RegionName";
+ break;
+ case QWSCommand::Identify:
+ typeStr = "Identify";
+ break;
+ case QWSCommand::GrabKeyboard:
+ typeStr = "GrabKeyboard";
+ break;
+ case QWSCommand::RepaintRegion:
+ typeStr = "RepaintRegion";
+ break;
+ case QWSCommand::IMMouse:
+ typeStr = "IMMouse";
+ break;
+ case QWSCommand::IMUpdate:
+ typeStr = "IMUpdate";
+ break;
+ case QWSCommand::IMResponse:
+ typeStr = "IMResponse";
+ break;
+ case QWSCommand::Font:
+ typeStr = "Font";
+ break;
+ case QWSCommand::Unknown:
+ default:
+ typeStr = "Unknown";
+ break;
+ }
+ return typeStr;
+}
+
+
+/*********************************************************************
+ *
+ * Functions to read/write commands on/from a socket
+ *
+ *********************************************************************/
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+void qws_write_command(QIODevice *socket, int type, char *simpleData, int simpleLen,
+ char *rawData, int rawLen)
+{
+#ifdef QWSCOMMAND_DEBUG
+ if (simpleLen) qDebug() << "WRITE simpleData " << QWSHexDump(simpleData, simpleLen);
+ if (rawLen > 0) qDebug() << "WRITE rawData " << QWSHexDump(rawData, rawLen);
+#endif
+
+#ifndef QT_NO_SXE
+ QTransportAuth *a = QTransportAuth::getInstance();
+ // ###### as soon as public API can be modified get rid of horrible casts
+ QIODevice *ad = a->passThroughByClient(reinterpret_cast<QWSClient*>(socket));
+ if (ad)
+ socket = ad;
+#endif
+
+ qws_write_uint(socket, type);
+
+ if (rawLen > MAX_COMMAND_SIZE) {
+ qWarning("qws_write_command: Message of size %d too big. "
+ "Truncated to %d", rawLen, MAX_COMMAND_SIZE);
+ rawLen = MAX_COMMAND_SIZE;
+ }
+
+ qws_write_uint(socket, rawLen == -1 ? 0 : rawLen);
+
+ if (simpleData && simpleLen)
+ socket->write(simpleData, simpleLen);
+
+ if (rawLen && rawData)
+ socket->write(rawData, rawLen);
+}
+
+/*
+ command format: [type][rawLen][simpleData][rawData]
+ type is already read when entering this function
+*/
+
+bool qws_read_command(QIODevice *socket, char *&simpleData, int &simpleLen,
+ char *&rawData, int &rawLen, int &bytesRead)
+{
+
+ // read rawLen
+ if (rawLen == -1) {
+ rawLen = qws_read_uint(socket);
+ if (rawLen == -1)
+ return false;
+ }
+
+ // read simpleData, assumes socket is capable of buffering all the data
+ if (simpleLen && !rawData) {
+ if (socket->bytesAvailable() < uint(simpleLen))
+ return false;
+ int tmp = socket->read(simpleData, simpleLen);
+ Q_ASSERT(tmp == simpleLen);
+ Q_UNUSED(tmp);
+ }
+
+ if (rawLen > MAX_COMMAND_SIZE) {
+ socket->close();
+ qWarning("qws_read_command: Won't read command of length %d, "
+ "connection closed.", rawLen);
+ return false;
+ }
+
+ // read rawData
+ if (rawLen && !rawData) {
+ rawData = new char[rawLen];
+ bytesRead = 0;
+ }
+ if (bytesRead < rawLen && socket->bytesAvailable())
+ bytesRead += socket->read(rawData + bytesRead, rawLen - bytesRead);
+
+ return (bytesRead == rawLen);
+}
+#endif
+
+/*********************************************************************
+ *
+ * QWSCommand base class - only use derived classes from that
+ *
+ *********************************************************************/
+QWSProtocolItem::~QWSProtocolItem() {
+ if (deleteRaw)
+ delete []rawDataPtr;
+}
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+void QWSProtocolItem::write(QIODevice *s) {
+#ifdef QWSCOMMAND_DEBUG
+ if (!qwsServer)
+ qDebug() << "QWSProtocolItem::write sending type " << static_cast<QWSCommand::Type>(type);
+ else
+ qDebug() << "QWSProtocolItem::write sending event " << (type < N_EVENTS ? eventNames[type] : "unknown");
+#endif
+ qws_write_command(s, type, simpleDataPtr, simpleLen, rawDataPtr, rawLen);
+}
+
+bool QWSProtocolItem::read(QIODevice *s) {
+#ifdef QWSCOMMAND_DEBUG
+ QLatin1String reread( (rawLen == -1) ? "" : "REREAD");
+ if (qwsServer)
+ qDebug() << "QWSProtocolItem::read reading type " << static_cast<QWSCommand::Type>(type) << reread;
+ else
+ qDebug() << "QWSProtocolItem::read reading event " << (type < N_EVENTS ? eventNames[type] : "unknown") << reread;
+ //qDebug("QWSProtocolItem::read reading event %s", type < N_EVENTS ? eventNames[type] : "unknown");
+#endif
+ bool b = qws_read_command(s, simpleDataPtr, simpleLen, rawDataPtr, rawLen, bytesRead);
+ if (b) {
+ setData(rawDataPtr, rawLen, false);
+ deleteRaw = true;
+ }
+#ifdef QWSCOMMAND_DEBUG
+ else
+ {
+ qDebug() << "error in reading command " << static_cast<QWSCommand::Type>(type);
+ }
+#endif
+ return b;
+}
+#endif // QT_NO_QWS_MULTIPROCESS
+
+void QWSProtocolItem::copyFrom(const QWSProtocolItem *item) {
+ if (this == item)
+ return;
+ simpleLen = item->simpleLen;
+ memcpy(simpleDataPtr, item->simpleDataPtr, simpleLen);
+ setData(item->rawDataPtr, item->rawLen);
+}
+
+void QWSProtocolItem::setData(const char *data, int len, bool allocateMem) {
+ if (deleteRaw)
+ delete [] rawDataPtr;
+ if (!data || len <= 0) {
+ rawDataPtr = 0;
+ rawLen = 0;
+ return;
+ }
+ if (allocateMem) {
+ rawDataPtr = new char[len];
+ memcpy(rawDataPtr, data, len);
+ deleteRaw = true;
+ } else {
+ rawDataPtr = const_cast<char *>(data);
+ deleteRaw = false;
+ }
+ rawLen = len;
+}
+
+QWSCommand *QWSCommand::factory(int type)
+{
+ QWSCommand *command = 0;
+ switch (type) {
+ case QWSCommand::Create:
+ command = new QWSCreateCommand;
+ break;
+ case QWSCommand::Shutdown:
+ command = new QWSCommand(type, 0, 0);
+ break;
+ case QWSCommand::Region:
+ command = new QWSRegionCommand;
+ break;
+ case QWSCommand::RegionMove:
+ command = new QWSRegionMoveCommand;
+ break;
+ case QWSCommand::RegionDestroy:
+ command = new QWSRegionDestroyCommand;
+ break;
+ case QWSCommand::AddProperty:
+ command = new QWSAddPropertyCommand;
+ break;
+ case QWSCommand::SetProperty:
+ command = new QWSSetPropertyCommand;
+ break;
+ case QWSCommand::RemoveProperty:
+ command = new QWSRemovePropertyCommand;
+ break;
+ case QWSCommand::GetProperty:
+ command = new QWSGetPropertyCommand;
+ break;
+ case QWSCommand::SetSelectionOwner:
+ command = new QWSSetSelectionOwnerCommand;
+ break;
+ case QWSCommand::RequestFocus:
+ command = new QWSRequestFocusCommand;
+ break;
+ case QWSCommand::ChangeAltitude:
+ command = new QWSChangeAltitudeCommand;
+ break;
+ case QWSCommand::SetOpacity:
+ command = new QWSSetOpacityCommand;
+ break;
+ case QWSCommand::DefineCursor:
+ command = new QWSDefineCursorCommand;
+ break;
+ case QWSCommand::SelectCursor:
+ command = new QWSSelectCursorCommand;
+ break;
+ case QWSCommand::GrabMouse:
+ command = new QWSGrabMouseCommand;
+ break;
+ case QWSCommand::GrabKeyboard:
+ command = new QWSGrabKeyboardCommand;
+ break;
+#ifndef QT_NO_SOUND
+ case QWSCommand::PlaySound:
+ command = new QWSPlaySoundCommand;
+ break;
+#endif
+#ifndef QT_NO_COP
+ case QWSCommand::QCopRegisterChannel:
+ command = new QWSQCopRegisterChannelCommand;
+ break;
+ case QWSCommand::QCopSend:
+ command = new QWSQCopSendCommand;
+ break;
+#endif
+ case QWSCommand::RegionName:
+ command = new QWSRegionNameCommand;
+ break;
+ case QWSCommand::Identify:
+ command = new QWSIdentifyCommand;
+ break;
+ case QWSCommand::RepaintRegion:
+ command = new QWSRepaintRegionCommand;
+ break;
+#ifndef QT_NO_QWS_INPUTMETHODS
+ case QWSCommand::IMUpdate:
+ command = new QWSIMUpdateCommand;
+ break;
+
+ case QWSCommand::IMMouse:
+ command = new QWSIMMouseCommand;
+ break;
+
+ case QWSCommand::IMResponse:
+ command = new QWSIMResponseCommand;
+ break;
+#endif
+ case QWSCommand::PositionCursor:
+ command = new QWSPositionCursorCommand;
+ break;
+#ifndef QT_NO_QWSEMBEDWIDGET
+ case QWSCommand::Embed:
+ command = new QWSEmbedCommand;
+ break;
+#endif
+ case QWSCommand::Font:
+ command = new QWSFontCommand;
+ break;
+ case QWSCommand::ScreenTransform:
+ command = new QWSScreenTransformCommand;
+ break;
+ default:
+ qWarning("QWSCommand::factory : Type error - got %08x!", type);
+ }
+ return command;
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qwscommand_qws_p.h b/src/gui/embedded/qwscommand_qws_p.h
new file mode 100644
index 0000000000..2155333281
--- /dev/null
+++ b/src/gui/embedded/qwscommand_qws_p.h
@@ -0,0 +1,853 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSCOMMAND_QWS_P_H
+#define QWSCOMMAND_QWS_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.
+//
+
+// When reading commands "off the wire" in the server, the rawLen is read
+// and then that many bytes are allocated. If the rawLen is corrupted (or
+// the protocol is being attacked) too many bytes can be allocated. Set
+// a hard limit here for security.
+#define MAX_COMMAND_SIZE (16 * 1024)
+
+#include <QtCore/qbytearray.h>
+#include <QtGui/qwsutils_qws.h>
+#include <QtGui/qfont.h>
+#include <QtCore/qdatastream.h>
+#include <QtCore/qvariant.h>
+#include <QtCore/qrect.h>
+#include <QtGui/qregion.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtGui/qwsevent_qws.h>
+#include "qwsprotocolitem_qws.h"
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#define QTE_PIPE "QtEmbedded-%1"
+
+class QRect;
+
+/*********************************************************************
+ *
+ * Functions to read/write commands on/from a socket
+ *
+ *********************************************************************/
+#ifndef QT_NO_QWS_MULTIPROCESS
+void qws_write_command(QIODevice *socket, int type, char *simpleData, int simpleLen, char *rawData, int rawLen);
+bool qws_read_command(QIODevice *socket, char *&simpleData, int &simpleLen, char *&rawData, int &rawLen, int &bytesRead);
+#endif
+
+struct QWSCommand : QWSProtocolItem
+{
+ QWSCommand(int t, int len, char *ptr) : QWSProtocolItem(t,len,ptr) {}
+
+ enum Type {
+ Unknown = 0,
+ Create,
+ Shutdown,
+ Region,
+ RegionMove,
+ RegionDestroy,
+ SetProperty,
+ AddProperty,
+ RemoveProperty,
+ GetProperty,
+ SetSelectionOwner,
+ ConvertSelection,
+ RequestFocus,
+ ChangeAltitude,
+ SetOpacity,
+ DefineCursor,
+ SelectCursor,
+ PositionCursor,
+ GrabMouse,
+ PlaySound,
+ QCopRegisterChannel,
+ QCopSend,
+ RegionName,
+ Identify,
+ GrabKeyboard,
+ RepaintRegion,
+ IMMouse,
+ IMUpdate,
+ IMResponse,
+ Embed,
+ Font,
+ ScreenTransform
+ };
+ static QWSCommand *factory(int type);
+};
+
+const char *qws_getCommandTypeString( QWSCommand::Type tp );
+
+#ifndef QT_NO_DEBUG
+class QDebug;
+QDebug &operator<<(QDebug &dbg, QWSCommand::Type tp);
+#endif // QT_NO_DEBUG
+
+/*********************************************************************
+ *
+ * Commands
+ *
+ *********************************************************************/
+
+struct QWSIdentifyCommand : public QWSCommand
+{
+ QWSIdentifyCommand() :
+ QWSCommand(QWSCommand::Identify,
+ sizeof(simpleData), reinterpret_cast<char *>(&simpleData))
+ {
+ simpleData.idLen = 0;
+ simpleData.idLock = -1;
+ }
+
+ void setData(const char *d, int len, bool allocateMem) {
+ QWSCommand::setData(d, len, allocateMem);
+ if ( simpleData.idLen > MAX_COMMAND_SIZE )
+ {
+ qWarning( "Identify command - name length %d - too big!", simpleData.idLen );
+ simpleData.idLen = MAX_COMMAND_SIZE;
+ }
+ if ( simpleData.idLen * int(sizeof(QChar)) > len )
+ {
+ qWarning( "Identify command - name length %d - buffer size %d - buffer overrun!", simpleData.idLen, len );
+ }
+ else
+ {
+ id = QString(reinterpret_cast<const QChar*>(d), simpleData.idLen);
+ }
+ }
+
+ void setId(const QString& i, int lock)
+ {
+ id = i;
+ simpleData.idLen = id.length();
+ simpleData.idLock = lock;
+ setData(reinterpret_cast<const char*>(id.unicode()), simpleData.idLen*2, true);
+ }
+
+ struct SimpleData {
+ int idLen;
+ int idLock;
+ } simpleData;
+ QString id;
+};
+
+struct QWSCreateCommand : public QWSCommand
+{
+ QWSCreateCommand(int n = 1) :
+ QWSCommand(QWSCommand::Create, sizeof(count),
+ reinterpret_cast<char *>(&count)), count(n) {}
+ int count;
+};
+
+struct QWSRegionNameCommand : public QWSCommand
+{
+ QWSRegionNameCommand() :
+ QWSCommand(QWSCommand::RegionName,
+ sizeof(simpleData), reinterpret_cast<char *>(&simpleData)) {}
+
+ void setData(const char *d, int len, bool allocateMem) {
+ QWSCommand::setData(d, len, allocateMem);
+ if ( simpleData.nameLen > MAX_COMMAND_SIZE )
+ {
+ qWarning( "region name command - name length too big!" );
+ simpleData.nameLen = MAX_COMMAND_SIZE;
+ }
+ if ( simpleData.captionLen > MAX_COMMAND_SIZE )
+ {
+ qWarning( "region name command - caption length too big!" );
+ simpleData.captionLen = MAX_COMMAND_SIZE;
+ }
+ if ( simpleData.nameLen + simpleData.captionLen > len )
+ {
+ qWarning( "region name command - name length %d - caption length %d - buffer size %d - buffer overrun!",
+ simpleData.nameLen, simpleData.captionLen, len );
+
+ }
+ else
+ {
+ name = QString(reinterpret_cast<const QChar*>(d), simpleData.nameLen/2);
+ d += simpleData.nameLen;
+ caption = QString(reinterpret_cast<const QChar*>(d), simpleData.captionLen/2);
+ }
+ }
+
+ void setName(const QString& n, const QString &c)
+ {
+ name = n;
+ caption = c;
+ int l = simpleData.nameLen = name.length()*2;
+ l += simpleData.captionLen = caption.length()*2;
+ char *d = new char[l];
+ memcpy(d, name.unicode(), simpleData.nameLen);
+ memcpy(d+simpleData.nameLen, caption.unicode(), simpleData.captionLen);
+ setData(d, l, true);
+ delete[] d;
+ }
+
+ struct SimpleData {
+ int windowid;
+ int nameLen;
+ int captionLen;
+ } simpleData;
+ QString name;
+ QString caption;
+};
+
+struct QWSRegionCommand : public QWSCommand
+{
+ QWSRegionCommand() :
+ QWSCommand(QWSCommand::Region, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+
+ void setData(const char *d, int len, bool allocateMem = true) {
+ QWSCommand::setData(d, len, allocateMem);
+
+ if( simpleData.nrectangles * int(sizeof(QRect)) + simpleData.surfacekeylength * int(sizeof(QChar)) + simpleData.surfacedatalength * int(sizeof(char)) > len )
+ {
+ qWarning( "region command - rectangle count %d - surface key length %d - region data size %d - buffer size %d - buffer overrun!",
+ simpleData.nrectangles, simpleData.surfacekeylength, simpleData.surfacedatalength, len );
+ }
+ else
+ {
+ char *ptr = rawDataPtr;
+
+ region.setRects(reinterpret_cast<QRect*>(ptr), simpleData.nrectangles);
+ ptr += simpleData.nrectangles * sizeof(QRect);
+
+ surfaceKey = QString(reinterpret_cast<QChar*>(ptr),
+ simpleData.surfacekeylength);
+ ptr += simpleData.surfacekeylength * sizeof(QChar);
+
+ surfaceData = QByteArray(ptr, simpleData.surfacedatalength);
+ }
+ }
+
+ void setData(int id, const QString &key, const QByteArray &data,
+ const QRegion &reg)
+ {
+ surfaceKey = key;
+ surfaceData = data;
+ region = reg;
+
+ const QVector<QRect> rects = reg.rects();
+
+ simpleData.windowid = id;
+ simpleData.surfacekeylength = key.size();
+ simpleData.surfacedatalength = data.size();
+ simpleData.nrectangles = rects.count();
+
+ QVarLengthArray<char, 256> buffer;
+ buffer.append(reinterpret_cast<const char*>(rects.constData()),
+ rects.count() * sizeof(QRect));
+ buffer.append(reinterpret_cast<const char*>(key.constData()),
+ key.size() * sizeof(QChar));
+ buffer.append(data, data.size());
+
+ QWSCommand::setData(buffer.constData(), buffer.size(), true);
+ }
+
+ /* XXX this will pad out in a compiler dependent way,
+ should move nrectangles to before windowtype, and
+ add reserved bytes.
+ Symptom will be valgrind reported uninitialized memory usage
+ */
+ struct SimpleData {
+ int windowid;
+ int surfacekeylength;
+ int surfacedatalength;
+ int nrectangles;
+ } simpleData;
+
+ QString surfaceKey;
+ QByteArray surfaceData;
+ QRegion region;
+};
+
+struct QWSSetOpacityCommand : public QWSCommand
+{
+ QWSSetOpacityCommand() :
+ QWSCommand(QWSCommand::SetOpacity, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+
+ struct SimpleData {
+ int windowid;
+ uchar opacity;
+ } simpleData;
+};
+
+struct QWSRegionMoveCommand : public QWSCommand
+{
+ QWSRegionMoveCommand() :
+ QWSCommand(QWSCommand::RegionMove, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+
+ struct SimpleData {
+ int windowid;
+ int dx;
+ int dy;
+ } simpleData;
+
+};
+
+struct QWSRegionDestroyCommand : public QWSCommand
+{
+ QWSRegionDestroyCommand() :
+ QWSCommand(QWSCommand::RegionDestroy, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+
+ struct SimpleData {
+ int windowid;
+ } simpleData;
+
+};
+
+struct QWSRequestFocusCommand : public QWSCommand
+{
+ QWSRequestFocusCommand() :
+ QWSCommand(QWSCommand::RequestFocus, sizeof(simpleData), reinterpret_cast<char*>(&simpleData)) {}
+
+ struct SimpleData {
+ int windowid;
+ int flag;
+ } simpleData;
+};
+
+struct QWSChangeAltitudeCommand : public QWSCommand
+{
+ QWSChangeAltitudeCommand() :
+ QWSCommand(QWSCommand::ChangeAltitude, sizeof(simpleData), reinterpret_cast<char*>(&simpleData)) {}
+
+ enum Altitude {
+ Lower = -1,
+ Raise = 0,
+ StaysOnTop = 1
+ };
+
+ struct SimpleData {
+ int windowid;
+ Altitude altitude;
+ bool fixed;
+ } simpleData;
+
+};
+
+
+struct QWSAddPropertyCommand : public QWSCommand
+{
+ QWSAddPropertyCommand() :
+ QWSCommand(QWSCommand::AddProperty, sizeof(simpleData), reinterpret_cast<char*>(&simpleData)) {}
+
+ struct SimpleData {
+ int windowid, property;
+ } simpleData;
+
+};
+
+struct QWSSetPropertyCommand : public QWSCommand
+{
+ QWSSetPropertyCommand() :
+ QWSCommand(QWSCommand::SetProperty, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) { data = 0; }
+
+ void setData(const char *d, int len, bool allocateMem = true) {
+ QWSCommand::setData(d, len, allocateMem);
+ data = rawDataPtr;
+ }
+
+ struct SimpleData {
+ int windowid, property, mode;
+ } simpleData;
+
+ char *data;
+};
+
+struct QWSRepaintRegionCommand : public QWSCommand
+{
+ QWSRepaintRegionCommand() :
+ QWSCommand(QWSCommand::RepaintRegion, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+
+ void setData(const char *d, int len, bool allocateMem = true) {
+ QWSCommand::setData(d, len, allocateMem);
+
+ if( simpleData.nrectangles * int(sizeof(QRect)) > len )
+ {
+ qWarning( "repaint region command - region rectangle count %d - buffer size %d - buffer overrun",
+ simpleData.nrectangles, len );
+
+ simpleData.nrectangles = len / sizeof(QRect);
+ }
+ rectangles = reinterpret_cast<QRect *>(rawDataPtr);
+ }
+
+ struct SimpleData {
+ int windowid;
+ int windowFlags;
+ bool opaque;
+ int nrectangles;
+ } simpleData;
+
+ QRect * rectangles;
+
+};
+
+struct QWSRemovePropertyCommand : public QWSCommand
+{
+ QWSRemovePropertyCommand() :
+ QWSCommand(QWSCommand::RemoveProperty, sizeof(simpleData), reinterpret_cast<char*>(&simpleData)) {}
+
+ struct SimpleData {
+ int windowid, property;
+ } simpleData;
+
+};
+
+struct QWSGetPropertyCommand : public QWSCommand
+{
+ QWSGetPropertyCommand() :
+ QWSCommand(QWSCommand::GetProperty, sizeof(simpleData), reinterpret_cast<char*>(&simpleData)) {}
+
+ struct SimpleData {
+ int windowid, property;
+ } simpleData;
+
+};
+
+struct QWSSetSelectionOwnerCommand : public QWSCommand
+{
+ QWSSetSelectionOwnerCommand() :
+ QWSCommand(QWSCommand::SetSelectionOwner,
+ sizeof(simpleData), reinterpret_cast<char*>(&simpleData)) {}
+
+ struct SimpleData {
+ int windowid;
+ int hour, minute, sec, ms; // time
+ } simpleData;
+
+};
+
+struct QWSConvertSelectionCommand : public QWSCommand
+{
+ QWSConvertSelectionCommand() :
+ QWSCommand(QWSCommand::ConvertSelection,
+ sizeof(simpleData), reinterpret_cast<char*>(&simpleData)) {}
+
+ struct SimpleData {
+ int requestor; // requestor window of the selection
+ int selection; // property on requestor into which the selection should be stored
+ int mimeTypes; // property ion requestor in which the mimetypes, in which the selection may be, are stored
+ } simpleData;
+
+};
+
+struct QWSDefineCursorCommand : public QWSCommand
+{
+ QWSDefineCursorCommand() :
+ QWSCommand(QWSCommand::DefineCursor,
+ sizeof(simpleData), reinterpret_cast<char *>(&simpleData)) {}
+
+ void setData(const char *d, int len, bool allocateMem = true) {
+ QWSCommand::setData(d, len, allocateMem);
+ data = reinterpret_cast<unsigned char *>(rawDataPtr);
+ if (simpleData.height * ((simpleData.width+7) / 8) > len) {
+ qWarning("define cursor command - width %d height %d- buffer size %d - buffer overrun",
+ simpleData.width, simpleData.height, len );
+ simpleData.width = simpleData.height = 0;
+ }
+ }
+
+ struct SimpleData {
+ int width;
+ int height;
+ int hotX;
+ int hotY;
+ int id;
+ } simpleData;
+
+ unsigned char *data;
+};
+
+struct QWSSelectCursorCommand : public QWSCommand
+{
+ QWSSelectCursorCommand() :
+ QWSCommand(QWSCommand::SelectCursor,
+ sizeof(simpleData), reinterpret_cast<char *>(&simpleData)) {}
+
+ struct SimpleData {
+ int windowid;
+ int id;
+ } simpleData;
+};
+
+struct QWSPositionCursorCommand : public QWSCommand
+{
+ QWSPositionCursorCommand() :
+ QWSCommand(QWSCommand::PositionCursor,
+ sizeof(simpleData), reinterpret_cast<char *>(&simpleData)) {}
+
+ struct SimpleData {
+ int newX;
+ int newY;
+ } simpleData;
+};
+
+struct QWSGrabMouseCommand : public QWSCommand
+{
+ QWSGrabMouseCommand() :
+ QWSCommand(QWSCommand::GrabMouse,
+ sizeof(simpleData), reinterpret_cast<char *>(&simpleData)) {}
+
+ struct SimpleData {
+ int windowid;
+ bool grab; // grab or ungrab?
+ } simpleData;
+};
+
+struct QWSGrabKeyboardCommand : public QWSCommand
+{
+ QWSGrabKeyboardCommand() :
+ QWSCommand(QWSCommand::GrabKeyboard,
+ sizeof(simpleData), reinterpret_cast<char *>(&simpleData)) {}
+
+ struct SimpleData {
+ int windowid;
+ bool grab; // grab or ungrab?
+ } simpleData;
+};
+
+#ifndef QT_NO_SOUND
+struct QWSPlaySoundCommand : public QWSCommand
+{
+ QWSPlaySoundCommand() :
+ QWSCommand(QWSCommand::PlaySound,
+ sizeof(simpleData), reinterpret_cast<char *>(&simpleData)) {}
+
+ void setData(const char *d, int len, bool allocateMem) {
+ QWSCommand::setData(d, len, allocateMem);
+ filename = QString(reinterpret_cast<QChar*>(rawDataPtr),len/2);
+ }
+ void setFileName(const QString& n)
+ {
+ setData(reinterpret_cast<const char*>(n.unicode()), n.length()*2, true);
+ }
+
+ struct SimpleData {
+ int windowid;
+ } simpleData;
+ QString filename;
+};
+#endif
+
+
+#ifndef QT_NO_COP
+struct QWSQCopRegisterChannelCommand : public QWSCommand
+{
+ QWSQCopRegisterChannelCommand() :
+ QWSCommand(QWSCommand::QCopRegisterChannel,
+ sizeof(simpleData), reinterpret_cast<char *>(&simpleData)) {}
+
+ void setData(const char *d, int len, bool allocateMem) {
+ QWSCommand::setData(d, len, allocateMem);
+ if ( simpleData.chLen > MAX_COMMAND_SIZE )
+ {
+ qWarning( "Command channel name too large!" );
+ simpleData.chLen = MAX_COMMAND_SIZE;
+ }
+ if( simpleData.chLen * int(sizeof(QChar)) > len )
+ {
+ qWarning( "register qcop channel command - channel name length %d - buffer size %d - buffer overrun!", simpleData.chLen, len );
+ }
+ else
+ {
+ channel = QString(reinterpret_cast<const QChar*>(d), simpleData.chLen);
+ }
+ }
+
+ void setChannel(const QString& n)
+ {
+ channel = n;
+ simpleData.chLen = channel.length();
+ setData(reinterpret_cast<const char*>(channel.unicode()), simpleData.chLen*2, true);
+ }
+
+ struct SimpleData {
+ int chLen;
+ } simpleData;
+ QString channel;
+};
+
+struct QWSQCopSendCommand : public QWSCommand
+{
+ QWSQCopSendCommand() :
+ QWSCommand(QWSCommand::QCopSend,
+ sizeof(simpleData), reinterpret_cast<char *>(&simpleData)) {}
+
+ void setData(const char *d, int len, bool allocateMem) {
+ QWSCommand::setData(d, len, allocateMem);
+
+ if( simpleData.clen * int(sizeof(QChar)) + simpleData.mlen * int(sizeof(QChar)) + simpleData.dlen * int(sizeof(char)) > len )
+ {
+ qWarning( "qcop send command - channel name length %d - message name length %d - data size %d - buffer size %d - buffer overrun!",
+ simpleData.clen, simpleData.mlen, simpleData.dlen, len );
+ }
+ else
+ {
+ const QChar *cd = reinterpret_cast<const QChar*>(d);
+ channel = QString(cd,simpleData.clen); cd += simpleData.clen;
+ message = QString(cd,simpleData.mlen);
+ d += simpleData.clen*sizeof(QChar) + simpleData.mlen*sizeof(QChar);
+ data = QByteArray(d, simpleData.dlen);
+ }
+ }
+
+ void setMessage(const QString &c, const QString &m,
+ const QByteArray &data)
+ {
+ this->channel = c;
+ this->message = m;
+ this->data = data;
+ simpleData.clen = c.length();
+ simpleData.mlen = m.length();
+ simpleData.dlen = data.size();
+ int l = simpleData.clen*sizeof(QChar);
+ l += simpleData.mlen*sizeof(QChar);
+ l += simpleData.dlen;
+ char *tmp = new char[l];
+ char *d = tmp;
+ memcpy(d, c.unicode(), simpleData.clen*sizeof(QChar));
+ d += simpleData.clen*sizeof(QChar);
+ memcpy(d, m.unicode(), simpleData.mlen*sizeof(QChar));
+ d += simpleData.mlen*sizeof(QChar);
+ memcpy(d, data.data(), simpleData.dlen);
+ QWSCommand::setData(tmp, l, false);
+ deleteRaw = true;
+ }
+
+ struct SimpleData {
+ int clen;
+ int mlen;
+ int dlen;
+ } simpleData;
+ QString channel;
+ QString message;
+ QByteArray data;
+};
+
+#endif
+
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+
+struct QWSIMMouseCommand : public QWSCommand
+{
+ QWSIMMouseCommand() :
+ QWSCommand(QWSCommand::IMMouse,
+ sizeof(simpleData), reinterpret_cast<char *>(&simpleData)) {}
+
+ struct SimpleData {
+ int windowid;
+ int state;
+ int index;
+ } simpleData;
+};
+
+
+struct QWSIMResponseCommand : public QWSCommand
+{
+ QWSIMResponseCommand() :
+ QWSCommand(QWSCommand::IMResponse,
+ sizeof(simpleData), reinterpret_cast<char *>(&simpleData)) {}
+
+ void setData(const char *d, int len, bool allocateMem) {
+ QWSCommand::setData(d, len, allocateMem);
+
+ QByteArray tmp = QByteArray::fromRawData(d, len);
+ QDataStream s(tmp);
+ s >> result;
+ }
+
+ void setResult(const QVariant & v)
+ {
+ QByteArray tmp;
+ QDataStream s(&tmp, QIODevice::WriteOnly);
+ s << v;
+ setData(tmp.data(), tmp.size(), true);
+ }
+
+ struct SimpleData {
+ int windowid;
+ int property;
+ } simpleData;
+
+ QVariant result;
+};
+
+struct QWSIMUpdateCommand: public QWSCommand
+{
+ QWSIMUpdateCommand() :
+ QWSCommand(QWSCommand::IMUpdate,
+ sizeof(simpleData), reinterpret_cast<char *>(&simpleData)) {}
+
+ struct SimpleData {
+ int windowid;
+ int type;
+ int widgetid;
+ } simpleData;
+};
+
+#endif
+
+#ifndef QT_NO_QWSEMBEDWIDGET
+struct QWSEmbedCommand : public QWSCommand
+{
+ QWSEmbedCommand() : QWSCommand(QWSCommand::Embed,
+ sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData))
+ {}
+
+ void setData(const char *d, int len, bool allocateMem = true)
+ {
+ QWSCommand::setData(d, len, allocateMem);
+
+ if( simpleData.rects * int(sizeof(QRect)) > len )
+ {
+ qWarning( "embed command - region rectangle count %d - buffer size %d - buffer overrun!",
+ simpleData.rects, len );
+ }
+ else
+ {
+ region.setRects(reinterpret_cast<QRect*>(rawDataPtr),
+ simpleData.rects);
+ }
+ }
+
+ void setData(WId embedder, WId embedded, QWSEmbedEvent::Type type,
+ const QRegion reg = QRegion())
+ {
+ simpleData.embedder = embedder;
+ simpleData.embedded = embedded;
+ simpleData.type = type;
+
+ region = reg;
+ const QVector<QRect> rects = reg.rects();
+ simpleData.rects = rects.count();
+
+ QWSCommand::setData(reinterpret_cast<const char*>(rects.constData()),
+ rects.count() * sizeof(QRect));
+ }
+
+ struct {
+ WId embedder;
+ WId embedded;
+ QWSEmbedEvent::Type type;
+ int rects;
+ } simpleData;
+
+ QRegion region;
+};
+#endif // QT_NO_QWSEMBEDWIDGET
+
+struct QWSFontCommand : public QWSCommand
+{
+ enum CommandType {
+ StartedUsingFont,
+ StoppedUsingFont
+ };
+
+ QWSFontCommand() :
+ QWSCommand(QWSCommand::Font,
+ sizeof(simpleData), reinterpret_cast<char *>(&simpleData)) {}
+
+ void setData(const char *d, int len, bool allocateMem) {
+ QWSCommand::setData(d, len, allocateMem);
+
+ fontName = QByteArray(d, len);
+ }
+
+ void setFontName(const QByteArray &name)
+ {
+ setData(name.constData(), name.size(), true);
+ }
+
+ struct SimpleData {
+ int type;
+ } simpleData;
+
+ QByteArray fontName;
+};
+
+struct QWSScreenTransformCommand : public QWSCommand
+{
+ QWSScreenTransformCommand() :
+ QWSCommand(QWSCommand::ScreenTransform,
+ sizeof(simpleData), reinterpret_cast<char *>(&simpleData)) {}
+
+ void setTransformation(int screen, int transformation)
+ {
+ simpleData.screen = screen;
+ simpleData.transformation = transformation;
+ }
+
+ struct SimpleData {
+ int screen;
+ int transformation;
+ } simpleData;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWSCOMMAND_QWS_P_H
diff --git a/src/gui/embedded/qwscursor_qws.cpp b/src/gui/embedded/qwscursor_qws.cpp
new file mode 100644
index 0000000000..3a5bd2cb66
--- /dev/null
+++ b/src/gui/embedded/qwscursor_qws.cpp
@@ -0,0 +1,654 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcursor.h"
+#include "qbitmap.h"
+#include "qscreen_qws.h"
+#include "qapplication.h"
+#include "qwindowsystem_qws.h"
+#include "qwindowsystem_p.h"
+#include "qwscursor_qws.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_QWS_CURSOR
+static QWSCursor *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 };
+static const uchar cur_blank_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, 0x00, 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};
+
+#endif
+
+void QWSServerPrivate::initializeCursor()
+{
+ Q_Q(QWSServer);
+ // setup system cursors
+#ifndef QT_NO_QWS_CURSOR
+// qt_screen->initCursor(sharedram + ramlen,true);
+
+ // default cursor
+ cursor = 0;
+ setCursor(QWSCursor::systemCursor(Qt::ArrowCursor));
+#endif
+ q->sendMouseEvent(QPoint(swidth/2, sheight/2), 0);
+}
+
+void QWSServerPrivate::setCursor(QWSCursor *curs)
+{
+#ifdef QT_NO_QWS_CURSOR
+ Q_UNUSED(curs);
+#else
+ if (cursor == curs)
+ return;
+
+ cursor = curs;
+
+ if (!haveviscurs || !curs)
+ curs = QWSCursor::systemCursor(Qt::BlankCursor);
+
+ if (qt_screencursor) {
+ qt_screencursor->set(curs->image(),
+ curs->hotSpot().x(),
+ curs->hotSpot().y());
+ }
+#endif
+}
+
+#ifndef QT_NO_QWS_CURSOR
+static void cleanupSystemCursorTable()
+{
+ for (int i = 0; i <= Qt::LastCursor; i++)
+ if (systemCursorTable[i]) {
+ delete systemCursorTable[i];
+ systemCursorTable[i] = 0;
+ }
+}
+#endif
+
+void QWSCursor::createSystemCursor(int id)
+{
+#ifdef QT_NO_QWS_CURSOR
+ Q_UNUSED(id);
+#else
+ if (!systemCursorTableInit) {
+ for (int i = 0; i <= Qt::LastCursor; i++)
+ systemCursorTable[i] = 0;
+ qAddPostRoutine(cleanupSystemCursorTable);
+ systemCursorTableInit = true;
+ }
+ switch (id) {
+ // 16x16 cursors
+ case Qt::ArrowCursor:
+ systemCursorTable[Qt::ArrowCursor] =
+ new QWSCursor(cur_arrow_bits, mcur_arrow_bits, 16, 16, 0, 0);
+ break;
+
+ case Qt::UpArrowCursor:
+ systemCursorTable[Qt::UpArrowCursor] =
+ new QWSCursor(cur_up_arrow_bits, mcur_up_arrow_bits, 16, 16, 7, 0);
+ break;
+
+ case Qt::CrossCursor:
+ systemCursorTable[Qt::CrossCursor] =
+ new QWSCursor(cur_cross_bits, mcur_cross_bits, 16, 16, 7, 7);
+ break;
+
+ case Qt::IBeamCursor:
+ systemCursorTable[Qt::IBeamCursor] =
+ new QWSCursor(cur_ibeam_bits, mcur_ibeam_bits, 16, 16, 7, 7);
+ break;
+
+ case Qt::SizeVerCursor:
+ systemCursorTable[Qt::SizeVerCursor] =
+ new QWSCursor(cur_ver_bits, mcur_ver_bits, 16, 16, 7, 7);
+ break;
+
+ case Qt::SizeHorCursor:
+ systemCursorTable[Qt::SizeHorCursor] =
+ new QWSCursor(cur_hor_bits, mcur_hor_bits, 16, 16, 7, 7);
+ break;
+
+ case Qt::SizeBDiagCursor:
+ systemCursorTable[Qt::SizeBDiagCursor] =
+ new QWSCursor(cur_bdiag_bits, mcur_bdiag_bits, 16, 16, 7, 7);
+ break;
+
+ case Qt::SizeFDiagCursor:
+ systemCursorTable[Qt::SizeFDiagCursor] =
+ new QWSCursor(cur_fdiag_bits, mcur_fdiag_bits, 16, 16, 7, 7);
+ break;
+
+ case Qt::BlankCursor:
+ systemCursorTable[Qt::BlankCursor] =
+ new QWSCursor(0, 0, 0, 0, 0, 0);
+ break;
+
+ // 20x20 cursors
+ case Qt::ForbiddenCursor:
+ systemCursorTable[Qt::ForbiddenCursor] =
+ new QWSCursor(forbidden_bits, forbiddenm_bits, 20, 20, 10, 10);
+ break;
+
+ // 32x32 cursors
+ case Qt::WaitCursor:
+ systemCursorTable[Qt::WaitCursor] =
+ new QWSCursor(wait_data_bits, wait_mask_bits, 32, 32, 15, 15);
+ break;
+
+ case Qt::SplitVCursor:
+ systemCursorTable[Qt::SplitVCursor] =
+ new QWSCursor(vsplit_bits, vsplitm_bits, 32, 32, 15, 15);
+ break;
+
+ case Qt::SplitHCursor:
+ systemCursorTable[Qt::SplitHCursor] =
+ new QWSCursor(hsplit_bits, hsplitm_bits, 32, 32, 15, 15);
+ break;
+
+ case Qt::SizeAllCursor:
+ systemCursorTable[Qt::SizeAllCursor] =
+ new QWSCursor(size_all_data_bits, size_all_mask_bits, 32, 32, 15, 15);
+ break;
+
+ case Qt::PointingHandCursor:
+ systemCursorTable[Qt::PointingHandCursor] =
+ new QWSCursor(phand_bits, phandm_bits, 32, 32, 0, 0);
+ break;
+
+ case Qt::WhatsThisCursor:
+ systemCursorTable[Qt::WhatsThisCursor] =
+ new QWSCursor(whatsthis_bits, whatsthism_bits, 32, 32, 0, 0);
+ break;
+ case Qt::BusyCursor:
+ systemCursorTable[Qt::BusyCursor] =
+ new QWSCursor(busy_bits, busym_bits, 32, 32, 0, 0);
+ break;
+
+ case Qt::OpenHandCursor:
+ systemCursorTable[Qt::OpenHandCursor] =
+ new QWSCursor(openhand_bits, openhandm_bits, 16, 16, 8, 8);
+ break;
+ case Qt::ClosedHandCursor:
+ systemCursorTable[Qt::ClosedHandCursor] =
+ new QWSCursor(closedhand_bits, closedhandm_bits, 16, 16, 8, 8);
+ break;
+ default:
+ qWarning("Unknown system cursor %d", id);
+ }
+#endif
+}
+
+QWSCursor *QWSCursor::systemCursor(int id)
+{
+ QWSCursor *cursor = 0;
+#ifdef QT_NO_QWS_CURSOR
+ Q_UNUSED(id);
+#else
+ 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];
+ }
+#endif
+ return cursor;
+}
+
+void QWSCursor::set(const uchar *data, const uchar *mask,
+ int width, int height, int hx, int hy)
+{
+#ifdef QT_NO_QWS_CURSOR
+ Q_UNUSED(data);
+ Q_UNUSED(mask);
+ Q_UNUSED(width);
+ Q_UNUSED(height);
+ Q_UNUSED(hx);
+ Q_UNUSED(hy);
+#else
+ hot.setX(hx);
+ hot.setY(hy);
+
+ cursor = QImage(width,height, QImage::Format_Indexed8);
+
+ if (!width || !height || !data || !mask)
+ return;
+
+ cursor.setNumColors(3);
+ cursor.setColor(0, 0xff000000);
+ cursor.setColor(1, 0xffffffff);
+ cursor.setColor(2, 0x00000000);
+
+ int bytesPerLine = (width + 7) / 8;
+ int p = 0;
+ int d, m;
+
+ int x = -1, w = 0;
+
+ uchar *cursor_data = cursor.bits();
+ int bpl = cursor.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;
+ }
+
+ if (qt_screencursor && qt_screencursor->supportsAlphaCursor())
+ createDropShadow(5, 2);
+#endif
+}
+
+// now we're really silly
+void QWSCursor::createDropShadow(int dropx, int dropy)
+{
+ //####
+#if 1 || defined(QT_NO_QWS_CURSOR) || defined(QT_NO_QWS_ALHPA_CURSOR)
+ Q_UNUSED(dropx);
+ Q_UNUSED(dropy);
+#else
+ if (cursor.width() + dropx > 64 || cursor.height() + dropy > 64)
+ return;
+
+ if (!cursor.hasAlphaBuffer()) {
+ cursor.setAlphaBuffer(true);
+
+ const int nblur=4;
+ const int darkness=140;
+
+ QImage drop(cursor.width()+dropx+nblur, cursor.height()+dropy+nblur, 8, 18);
+ drop.setColor(0, 0xff000000); // bg (black)
+ drop.setColor(1, 0xffffffff); // fg (white)
+ for (int i=0; i<16; i++) {
+ drop.setColor(2+i, (darkness*i/16)<<24);
+ }
+ drop.fill(2); // all trans
+ QImage drop2 = drop.copy();
+
+ int cp;
+
+ // made solid shadow
+ for (int row = 0; row < cursor.height(); row++) {
+ for (int col = 0; col < cursor.width(); col++) {
+ cp = cursor.pixelIndex(col, row);
+ if (cp != 2)
+ drop.setPixel(col+dropx, row+dropy, 17);
+ }
+ }
+
+ // blur shadow
+ for (int blur=0; blur<nblur; blur++) {
+ QImage& to((blur&1)?drop:drop2);
+ QImage& from((blur&1)?drop2:drop);
+ for (int row = 1; row < drop.height()-1; row++) {
+ for (int col = 1; col < drop.width()-1; col++) {
+ int t=0;
+ for (int dx=-1; dx<=1; dx++) {
+ for (int dy=-1; dy<=1; dy++) {
+ t += from.pixelIndex(col+dx,row+dy)-2;
+ }
+ }
+ to.setPixel(col,row,2+t/9);
+ }
+ }
+ }
+
+ // copy cursor
+ for (int row = 0; row < cursor.height(); row++) {
+ for (int col = 0; col < cursor.width(); col++) {
+ cp = cursor.pixelIndex(col, row);
+ if (cp != 2)
+ drop.setPixel(col, row, cp);
+ }
+ }
+
+ cursor = drop;
+ }
+#endif
+}
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qwscursor_qws.h b/src/gui/embedded/qwscursor_qws.h
new file mode 100644
index 0000000000..6d19c31aa0
--- /dev/null
+++ b/src/gui/embedded/qwscursor_qws.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSCURSOR_QWS_H
+#define QWSCURSOR_QWS_H
+
+#include <QtGui/qimage.h>
+#include <QtGui/qregion.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QWSCursor
+{
+public:
+ QWSCursor() {}
+ QWSCursor(const uchar *data, const uchar *mask, int width, int height,
+ int hotX, int hotY)
+ { set(data, mask, width, height, hotX, hotY); }
+
+ void set(const uchar *data, const uchar *mask,
+ int width, int height, int hotX, int hotY);
+
+ QPoint hotSpot() const { return hot; }
+ QImage &image() { return cursor; }
+
+ static QWSCursor *systemCursor(int id);
+
+private:
+ static void createSystemCursor(int id);
+ void createDropShadow(int dropx, int dropy);
+
+private:
+ QPoint hot;
+ QImage cursor;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWSCURSOR_QWS_H
diff --git a/src/gui/embedded/qwsdisplay_qws.h b/src/gui/embedded/qwsdisplay_qws.h
new file mode 100644
index 0000000000..455d46db5d
--- /dev/null
+++ b/src/gui/embedded/qwsdisplay_qws.h
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSDISPLAY_QWS_H
+#define QWSDISPLAY_QWS_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qbytearray.h>
+#include <QtGui/qregion.h>
+#include <QtGui/qimage.h>
+#include <QtGui/qwindowdefs.h>
+#include <QtCore/qlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QWSEvent;
+class QWSMouseEvent;
+class QWSQCopMessageEvent;
+class QVariant;
+class QLock;
+
+class QWSWindowInfo
+{
+
+public:
+
+ int winid;
+ unsigned int clientid;
+ QString name;
+
+};
+
+#define QT_QWS_PROPERTY_CONVERTSELECTION 999
+#define QT_QWS_PROPERTY_WINDOWNAME 998
+#define QT_QWS_PROPERTY_MARKEDTEXT 997
+
+class QWSDisplay;
+extern Q_GUI_EXPORT QWSDisplay *qt_fbdpy;
+
+class Q_GUI_EXPORT QWSDisplay
+{
+public:
+ QWSDisplay();
+ ~QWSDisplay();
+
+ static QWSDisplay* instance() { return qt_fbdpy; }
+
+ bool eventPending() const;
+ QWSEvent *getEvent();
+// QWSRegionManager *regionManager() const;
+
+ uchar* frameBuffer() const;
+ int width() const;
+ int height() const;
+ int depth() const;
+ int pixmapDepth() const;
+ bool supportsDepth(int) const;
+
+ uchar *sharedRam() const;
+ int sharedRamSize() const;
+
+#ifndef QT_NO_QWS_PROPERTIES
+ void addProperty(int winId, int property);
+ void setProperty(int winId, int property, int mode, const QByteArray &data);
+ void setProperty(int winId, int property, int mode, const char * data);
+ void removeProperty(int winId, int property);
+ bool getProperty(int winId, int property, char *&data, int &len);
+#endif // QT_NO_QWS_PROPERTIES
+
+ QList<QWSWindowInfo> windowList();
+ int windowAt(const QPoint &);
+
+ void setIdentity(const QString &appName);
+ void nameRegion(int winId, const QString& n, const QString &c);
+ void requestRegion(int winId, const QString &surfacekey,
+ const QByteArray &surfaceData,
+ const QRegion &region);
+ void repaintRegion(int winId, int windowFlags, bool opaque, QRegion);
+ void moveRegion(int winId, int dx, int dy);
+ void destroyRegion(int winId);
+ void requestFocus(int winId, bool get);
+ void setAltitude(int winId, int altitude, bool fixed = false);
+ void setOpacity(int winId, int opacity);
+ int takeId();
+ void setSelectionOwner(int winId, const QTime &time);
+ void convertSelection(int winId, int selectionProperty, const QString &mimeTypes);
+ void defineCursor(int id, const QBitmap &curs, const QBitmap &mask,
+ int hotX, int hotY);
+ void destroyCursor(int id);
+ void selectCursor(QWidget *w, unsigned int id);
+ void setCursorPosition(int x, int y);
+ void grabMouse(QWidget *w, bool grab);
+ void grabKeyboard(QWidget *w, bool grab);
+ void playSoundFile(const QString&);
+ void registerChannel(const QString &channel);
+ void sendMessage(const QString &channel, const QString &msg,
+ const QByteArray &data);
+ void flushCommands();
+#ifndef QT_NO_QWS_INPUTMETHODS
+ void sendIMUpdate(int type, int winId, int widgetid);
+ void resetIM();
+ void sendIMResponse(int winId, int property, const QVariant &result);
+ void sendIMMouseEvent(int index, bool isPress);
+#endif
+ QWSQCopMessageEvent* waitForQCopResponse();
+ void sendFontCommand(int type, const QByteArray &fontName);
+
+ void setWindowCaption(QWidget *w, const QString &);
+
+ // Lock display for access only by this process
+ static bool initLock(const QString &filename, bool create = false);
+ static bool grabbed();
+ static void grab();
+ static void grab(bool write);
+ static void ungrab();
+
+ static void setTransformation(int transformation, int screenNo = -1);
+ static void setRawMouseEventFilter(void (*filter)(QWSMouseEvent *));
+
+private:
+ friend int qt_fork_qapplication();
+ friend void qt_app_reinit( const QString& newAppName );
+ friend class QApplication;
+ friend class QCopChannel;
+ friend class QWSEmbedWidget;
+ friend class QWSEmbedWidgetPrivate;
+ class Data;
+ friend class Data;
+ Data *d;
+
+ friend class QWSMemorySurface;
+ friend class QWSOnScreenSurface;
+ friend class QWSDirectPainterSurface;
+ int getPropertyLen;
+ char *getPropertyData;
+ static QLock *lock;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWSDISPLAY_QWS_H
diff --git a/src/gui/embedded/qwsdisplay_qws_p.h b/src/gui/embedded/qwsdisplay_qws_p.h
new file mode 100644
index 0000000000..819b826d69
--- /dev/null
+++ b/src/gui/embedded/qwsdisplay_qws_p.h
@@ -0,0 +1,161 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSDISPLAY_QWS_P_H
+#define QWSDISPLAY_QWS_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 "qwsdisplay_qws.h"
+#include "qwssocket_qws.h"
+#include "qwsevent_qws.h"
+#include <private/qwssharedmemory_p.h>
+#include "qwscommand_qws_p.h"
+#include "qwslock_p.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWSDisplay::Data
+{
+public:
+ Data(QObject* parent, bool singleProcess = false);
+ ~Data();
+
+ void flush();
+
+ bool queueNotEmpty();
+ QWSEvent *dequeue();
+ QWSEvent *peek();
+
+ bool directServerConnection();
+ void fillQueue();
+#ifndef QT_NO_QWS_MULTIPROCESS
+ void connectToPipe();
+ void waitForConnection();
+ void waitForPropertyReply();
+ void waitForRegionAck(int winId);
+ void waitForRegionEvents(int winId, bool ungrabDisplay);
+ bool hasPendingRegionEvents() const;
+#endif
+ void waitForCreation();
+#ifndef QT_NO_COP
+ void waitForQCopResponse();
+#endif
+ void init();
+ void reinit( const QString& newAppName );
+ void create(int n = 1);
+
+ void flushCommands();
+ void sendCommand(QWSCommand & cmd);
+ void sendSynchronousCommand(QWSCommand & cmd);
+
+ QWSEvent *readMore();
+
+ int takeId();
+
+ void setMouseFilter(void (*filter)(QWSMouseEvent*));
+
+ //####public data members
+
+// QWSRegionManager *rgnMan;
+ uchar *sharedRam;
+#ifndef QT_NO_QWS_MULTIPROCESS
+ QWSSharedMemory shm;
+#endif
+ int sharedRamSize;
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+ static QWSLock *clientLock;
+
+ static bool lockClient(QWSLock::LockType, int timeout = -1);
+ static void unlockClient(QWSLock::LockType);
+ static bool waitClient(QWSLock::LockType, int timeout = -1);
+ static QWSLock* getClientLock();
+#endif // QT_NO_QWS_MULTIPROCESS
+
+private:
+#ifndef QT_NO_QWS_MULTIPROCESS
+ QWSSocket *csocket;
+#endif
+ QList<QWSEvent*> queue;
+
+#if 0
+ void debugQueue() {
+ for (int i = 0; i < queue.size(); ++i) {
+ QWSEvent *e = queue.at(i);
+ qDebug( " ev %d type %d sl %d rl %d", i, e->type, e->simpleLen, e->rawLen);
+ }
+ }
+#endif
+
+ QWSConnectedEvent* connected_event;
+ QWSMouseEvent* mouse_event;
+ int region_events_count;
+ int mouse_state;
+ int mouse_winid;
+ QPoint region_offset;
+ int region_offset_window;
+#ifndef QT_NO_COP
+ QWSQCopMessageEvent *qcop_response;
+#endif
+ QWSEvent* current_event;
+ QList<int> unused_identifiers;
+#ifdef QAPPLICATION_EXTRA_DEBUG
+ int mouse_event_count;
+#endif
+ void (*mouseFilter)(QWSMouseEvent *);
+
+ enum { VariableEvent=-1 };
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QWSDISPLAY_QWS_P_H
diff --git a/src/gui/embedded/qwsembedwidget.cpp b/src/gui/embedded/qwsembedwidget.cpp
new file mode 100644
index 0000000000..a449c65f06
--- /dev/null
+++ b/src/gui/embedded/qwsembedwidget.cpp
@@ -0,0 +1,227 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwsembedwidget.h"
+
+#ifndef QT_NO_QWSEMBEDWIDGET
+
+#include <qwsdisplay_qws.h>
+#include <private/qwidget_p.h>
+#include <private/qwsdisplay_qws_p.h>
+#include <private/qwscommand_qws_p.h>
+
+QT_BEGIN_NAMESPACE
+
+// TODO:
+// Must remove window decorations from the embedded window
+// Focus In/Out, Keyboard/Mouse...
+//
+// BUG: what if my parent change parent?
+
+class QWSEmbedWidgetPrivate : public QWidgetPrivate
+{
+ Q_DECLARE_PUBLIC(QWSEmbedWidget);
+
+public:
+ QWSEmbedWidgetPrivate(int winId);
+ void updateWindow();
+ void resize(const QSize &size);
+
+ QWidget *window;
+ WId windowId;
+ WId embeddedId;
+};
+
+QWSEmbedWidgetPrivate::QWSEmbedWidgetPrivate(int winId)
+ : window(0), windowId(0), embeddedId(winId)
+{
+}
+
+void QWSEmbedWidgetPrivate::updateWindow()
+{
+ Q_Q(QWSEmbedWidget);
+
+ QWidget *win = q->window();
+ if (win == window)
+ return;
+
+ if (window) {
+ window->removeEventFilter(q);
+ QWSEmbedCommand command;
+ command.setData(windowId, embeddedId, QWSEmbedEvent::StopEmbed);
+ QWSDisplay::instance()->d->sendCommand(command);
+ }
+
+ window = win;
+ if (!window)
+ return;
+ windowId = window->winId();
+
+ QWSEmbedCommand command;
+ command.setData(windowId, embeddedId, QWSEmbedEvent::StartEmbed);
+ QWSDisplay::instance()->d->sendCommand(command);
+ window->installEventFilter(q);
+ q->installEventFilter(q);
+}
+
+void QWSEmbedWidgetPrivate::resize(const QSize &size)
+{
+ if (!window)
+ return;
+
+ Q_Q(QWSEmbedWidget);
+
+ QWSEmbedCommand command;
+ command.setData(windowId, embeddedId, QWSEmbedEvent::Region,
+ QRect(q->mapToGlobal(QPoint(0, 0)), size));
+ QWSDisplay::instance()->d->sendCommand(command);
+}
+
+/*!
+ \class QWSEmbedWidget
+ \since 4.2
+ \ingroup qws
+ \ingroup advanced
+
+ \brief The QWSEmbedWidget class enables embedded top-level widgets
+ in Qt for Embedded Linux.
+
+ Note that this class is only available in \l{Qt for Embedded Linux}.
+
+ QWSEmbedWidget inherits QWidget and acts as any other widget, but
+ in addition it is capable of embedding another top-level widget.
+
+ An example of use is when painting directly onto the screen using
+ the QDirectPainter class. Then the reserved region can be embedded
+ into an instance of the QWSEmbedWidget class, providing for
+ example event handling and size policies for the reserved region.
+
+ All that is required to embed a top-level widget is its window ID.
+
+ \sa {Qt for Embedded Linux Architecture}
+*/
+
+/*!
+ Constructs a widget with the given \a parent, embedding the widget
+ identified by the given window \a id.
+*/
+QWSEmbedWidget::QWSEmbedWidget(WId id, QWidget *parent)
+ : QWidget(*new QWSEmbedWidgetPrivate(id), parent, 0)
+{
+ Q_D(QWSEmbedWidget);
+ d->updateWindow();
+}
+
+/*!
+ Destroys this widget.
+*/
+QWSEmbedWidget::~QWSEmbedWidget()
+{
+ Q_D(QWSEmbedWidget);
+ if (!d->window)
+ return;
+
+ QWSEmbedCommand command;
+ command.setData(d->windowId, d->embeddedId, QWSEmbedEvent::StopEmbed);
+ QWSDisplay::instance()->d->sendCommand(command);
+}
+
+/*!
+ \reimp
+*/
+bool QWSEmbedWidget::eventFilter(QObject *object, QEvent *event)
+{
+ Q_D(QWSEmbedWidget);
+ if (object == d->window && event->type() == QEvent::Move)
+ resizeEvent(0);
+ else if (object == this && event->type() == QEvent::Hide)
+ d->resize(QSize());
+ return QWidget::eventFilter(object, event);
+}
+
+/*!
+ \reimp
+*/
+void QWSEmbedWidget::changeEvent(QEvent *event)
+{
+ Q_D(QWSEmbedWidget);
+ if (event->type() == QEvent::ParentChange)
+ d->updateWindow();
+}
+
+/*!
+ \reimp
+*/
+void QWSEmbedWidget::resizeEvent(QResizeEvent*)
+{
+ Q_D(QWSEmbedWidget);
+ d->resize(rect().size());
+}
+
+/*!
+ \reimp
+*/
+void QWSEmbedWidget::moveEvent(QMoveEvent*)
+{
+ resizeEvent(0);
+}
+
+/*!
+ \reimp
+*/
+void QWSEmbedWidget::hideEvent(QHideEvent*)
+{
+ Q_D(QWSEmbedWidget);
+ d->resize(QSize());
+}
+
+/*!
+ \reimp
+*/
+void QWSEmbedWidget::showEvent(QShowEvent*)
+{
+ Q_D(QWSEmbedWidget);
+ d->resize(rect().size());
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QWSEMBEDWIDGET
diff --git a/src/gui/embedded/qwsembedwidget.h b/src/gui/embedded/qwsembedwidget.h
new file mode 100644
index 0000000000..6badf76c2c
--- /dev/null
+++ b/src/gui/embedded/qwsembedwidget.h
@@ -0,0 +1,82 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSEMBEDWIDGET_H
+#define QWSEMBEDWIDGET_H
+
+#include <QtGui/qwidget.h>
+
+#ifndef QT_NO_QWSEMBEDWIDGET
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QWSEmbedWidgetPrivate;
+
+class Q_GUI_EXPORT QWSEmbedWidget : public QWidget
+{
+ Q_OBJECT
+
+public:
+ QWSEmbedWidget(WId winId, QWidget *parent = 0);
+ ~QWSEmbedWidget();
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event);
+ void changeEvent(QEvent *event);
+ void resizeEvent(QResizeEvent *event);
+ void moveEvent(QMoveEvent *event);
+ void hideEvent(QHideEvent *event);
+ void showEvent(QShowEvent *event);
+
+private:
+ Q_DECLARE_PRIVATE(QWSEmbedWidget)
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_QWSEMBEDWIDGET
+#endif // QWSEMBEDWIDGET_H
diff --git a/src/gui/embedded/qwsevent_qws.cpp b/src/gui/embedded/qwsevent_qws.cpp
new file mode 100644
index 0000000000..e23eacd5dd
--- /dev/null
+++ b/src/gui/embedded/qwsevent_qws.cpp
@@ -0,0 +1,216 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwsevent_qws.h"
+
+QT_BEGIN_NAMESPACE
+
+QWSEvent *QWSEvent::factory(int type)
+{
+ QWSEvent *event = 0;
+ switch (type) {
+ case QWSEvent::Connected:
+ event = new QWSConnectedEvent;
+ break;
+ case QWSEvent::MaxWindowRect:
+ event = new QWSMaxWindowRectEvent;
+ break;
+ case QWSEvent::Mouse:
+ event = new QWSMouseEvent;
+ break;
+ case QWSEvent::Focus:
+ event = new QWSFocusEvent;
+ break;
+ case QWSEvent::Key:
+ event = new QWSKeyEvent;
+ break;
+ case QWSEvent::Region:
+ event = new QWSRegionEvent;
+ break;
+ case QWSEvent::Creation:
+ event = new QWSCreationEvent;
+ break;
+#ifndef QT_NO_QWS_PROPERTIES
+ case QWSEvent::PropertyNotify:
+ event = new QWSPropertyNotifyEvent;
+ break;
+ case QWSEvent::PropertyReply:
+ event = new QWSPropertyReplyEvent;
+ break;
+#endif // QT_NO_QWS_PROPERTIES
+ case QWSEvent::SelectionClear:
+ event = new QWSSelectionClearEvent;
+ break;
+ case QWSEvent::SelectionRequest:
+ event = new QWSSelectionRequestEvent;
+ break;
+ case QWSEvent::SelectionNotify:
+ event = new QWSSelectionNotifyEvent;
+ break;
+#ifndef QT_NO_COP
+ case QWSEvent::QCopMessage:
+ event = new QWSQCopMessageEvent;
+ break;
+#endif
+ case QWSEvent::WindowOperation:
+ event = new QWSWindowOperationEvent;
+ break;
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+ case QWSEvent::IMEvent:
+ event = new QWSIMEvent;
+ break;
+ case QWSEvent::IMQuery:
+ event = new QWSIMQueryEvent;
+ break;
+ case QWSEvent::IMInit:
+ event = new QWSIMInitEvent;
+ break;
+#endif
+#ifndef QT_NO_QWSEMBEDWIDGET
+ case QWSEvent::Embed:
+ event = new QWSEmbedEvent;
+ break;
+#endif
+ case QWSEvent::Font:
+ event = new QWSFontEvent;
+ break;
+ case QWSEvent::ScreenTransformation:
+ event = new QWSScreenTransformationEvent;
+ break;
+ default:
+ qCritical("QWSEvent::factory() : Unknown event type %08x!", type);
+ }
+ return event;
+}
+
+/*!
+ \class QWSEvent
+ \ingroup qws
+
+ \brief The QWSEvent class encapsulates an event in Qt for Embedded Linux.
+
+ When running a \l{Qt for Embedded Linux} application, it either runs as a
+ server or connects to an existing server. All system generated
+ events are passed to the server application which then propagates
+ the event to the appropriate client.
+
+ Whenever the server receives an event, it queries its stack of
+ top-level windows to find the window containing the event's
+ position. Each window can identify the client application that
+ created it, and returns its ID to the server upon
+ request. Finally, the server forwards the event, encapsulated by
+ an instance of the QWSEvent class, to the appropriate client.
+
+ \image qt-embedded-client.png
+
+ The server communicates with the client applications over the UNIX
+ domain socket. You can retrieve direct access to all the events a
+ client receives from the server, by reimplementing QApplication's
+ \l {QApplication::}{qwsEventFilter()} function.
+
+ QWSEvent provides the \l Type enum specifying the origin of the
+ event. Internally, each type is represented by a QWSEvent
+ subclass, e.g., \c QWSKeyEvent.
+
+ \sa QWSServer, QWSClient, {Qt for Embedded Linux Architecture}
+*/
+
+/*!
+ \enum QWSEvent::Type
+
+ This enum describes the origin of the event.
+
+ \value NoEvent No event has occurred.
+ \value Connected An application has connected to the server.
+ \value Mouse A mouse button is pressed or released, or the mouse cursor is moved.
+ See also \l{Qt for Embedded Linux Pointer Handling}.
+ \value Focus A window has lost or received focus.
+ \value Key A key is pressed or released. See also \l{Qt for Embedded Linux Character Input}.
+ \value Region A region has changed.
+ \value Creation The server has created an ID, typically for a window.
+ \value PropertyNotify A property has changed.
+ \value PropertyReply The server is responding to a request for a property's value.
+ \value SelectionClear A selection is deleted.
+ \value SelectionRequest The server has queried for a selection.
+ \value SelectionNotify A new selection has been created.
+ \value MaxWindowRect The server has changed the maximum window for an application.
+ \value QCopMessage A new Qt Cop message has appeared. See also QCopChannel
+ \value WindowOperation A window operation, e.g. resizing, has occurred.
+ \value IMEvent An input method has been used to enter text for languages with
+ non-Latin alphabets. See also QWSInputMethod.
+ \value IMQuery An input method query for a specified property has occurred.
+ See also QWSInputMethod.
+ \value NEvent The number of events has changed.
+ \value Embed An event used internally to implement embedded windows. See also
+ QWSEmbedWidget.
+ \value ScreenTransformation An event used internally to notify the client processes
+ that the screen has changed for example, rotation, etc.
+ \omitvalue Font
+ \omitvalue IMInit
+*/
+
+/*!
+ \fn QWSMouseEvent *QWSEvent::asMouse()
+ \internal
+*/
+
+/*!
+ \fn int QWSEvent::window()
+ \internal
+*/
+
+/*!
+ \fn int QWSEvent::window() const
+ \internal
+*/
+
+/*!
+ \fn QWSEvent *QWSEvent::factory(int type)
+ \internal
+*/
+
+/*!
+ \fn QWSEvent::QWSEvent( int t, int len, char * ptr)
+ \internal
+*/
+
+QT_END_NAMESPACE
diff --git a/src/gui/embedded/qwsevent_qws.h b/src/gui/embedded/qwsevent_qws.h
new file mode 100644
index 0000000000..f231db2133
--- /dev/null
+++ b/src/gui/embedded/qwsevent_qws.h
@@ -0,0 +1,459 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSEVENT_QWS_H
+#define QWSEVENT_QWS_H
+
+#include <QtGui/qwsutils_qws.h>
+#include <QtGui/qwsprotocolitem_qws.h>
+#include <QtCore/qrect.h>
+#include <QtGui/qregion.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+struct QWSMouseEvent;
+
+struct QWSEvent : QWSProtocolItem {
+
+ QWSEvent(int t, int len, char *ptr) : QWSProtocolItem(t,len,ptr) {}
+
+
+
+ enum Type {
+ NoEvent,
+ Connected,
+ Mouse,
+ Focus,
+ Key,
+ Region,
+ Creation,
+ PropertyNotify,
+ PropertyReply,
+ SelectionClear,
+ SelectionRequest,
+ SelectionNotify,
+ MaxWindowRect,
+ QCopMessage,
+ WindowOperation,
+ IMEvent,
+ IMQuery,
+ IMInit,
+ Embed,
+ Font,
+ ScreenTransformation,
+ NEvent
+ };
+
+ QWSMouseEvent *asMouse()
+ { return type == Mouse ? reinterpret_cast<QWSMouseEvent*>(this) : 0; }
+ int window() { return *(reinterpret_cast<int*>(simpleDataPtr)); }
+ int window() const { return *(reinterpret_cast<int*>(simpleDataPtr)); }
+ static QWSEvent *factory(int type);
+};
+
+
+//All events must start with windowID
+
+struct QWSConnectedEvent : QWSEvent {
+ QWSConnectedEvent()
+ : QWSEvent(QWSEvent::Connected, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+
+ void setData(const char *d, int len, bool allocateMem = true) {
+ QWSEvent::setData(d, len, allocateMem);
+ display = reinterpret_cast<char*>(rawDataPtr);
+ }
+
+ struct SimpleData {
+ int window;
+ int len;
+ int clientId;
+ int servershmid;
+ } simpleData;
+
+ char *display;
+};
+
+struct QWSMaxWindowRectEvent : QWSEvent {
+ QWSMaxWindowRectEvent()
+ : QWSEvent(MaxWindowRect, sizeof(simpleData), reinterpret_cast<char*>(&simpleData)) { }
+ struct SimpleData {
+ int window;
+ QRect rect;
+ } simpleData;
+};
+
+struct QWSMouseEvent : QWSEvent {
+ QWSMouseEvent()
+ : QWSEvent(QWSEvent::Mouse, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+ struct SimpleData {
+ int window;
+ int x_root, y_root, state, delta;
+ int time; // milliseconds
+ } simpleData;
+};
+
+struct QWSFocusEvent : QWSEvent {
+ QWSFocusEvent()
+ : QWSEvent(QWSEvent::Focus, sizeof(simpleData), reinterpret_cast<char*>(&simpleData))
+ { memset(reinterpret_cast<char*>(&simpleData),0,sizeof(simpleData)); }
+ struct SimpleData {
+ int window;
+ uint get_focus:1;
+ } simpleData;
+};
+
+struct QWSKeyEvent: QWSEvent {
+ QWSKeyEvent()
+ : QWSEvent(QWSEvent::Key, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+ struct SimpleData {
+ int window;
+ uint keycode;
+ Qt::KeyboardModifiers modifiers;
+ ushort unicode;
+ uint is_press:1;
+ uint is_auto_repeat:1;
+ } simpleData;
+};
+
+
+struct QWSCreationEvent : QWSEvent {
+ QWSCreationEvent()
+ : QWSEvent(QWSEvent::Creation, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+ struct SimpleData {
+ int objectid;
+ int count;
+ } simpleData;
+};
+
+#ifndef QT_NO_QWS_PROPERTIES
+struct QWSPropertyNotifyEvent : QWSEvent {
+ QWSPropertyNotifyEvent()
+ : QWSEvent(QWSEvent::PropertyNotify, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+ enum State {
+ PropertyNewValue,
+ PropertyDeleted
+ };
+ struct SimpleData {
+ int window;
+ int property;
+ int state;
+ } simpleData;
+};
+#endif
+
+struct QWSSelectionClearEvent : QWSEvent {
+ QWSSelectionClearEvent()
+ : QWSEvent(QWSEvent::SelectionClear, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+ struct SimpleData {
+ int window;
+ } simpleData;
+};
+
+struct QWSSelectionRequestEvent : QWSEvent {
+ QWSSelectionRequestEvent()
+ : QWSEvent(QWSEvent::SelectionRequest, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+ struct SimpleData {
+ int window;
+ int requestor; // window which wants the selection
+ int property; // property on requestor into which the selection should be stored, normally QWSProperty::PropSelection
+ int mimeTypes; // Value is stored in the property mimeType on the requestor window. This value may contain
+ // multiple mimeTypes separated by ;; where the order reflects the priority
+ } simpleData;
+};
+
+struct QWSSelectionNotifyEvent : QWSEvent {
+ QWSSelectionNotifyEvent()
+ : QWSEvent(QWSEvent::SelectionNotify, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+ struct SimpleData {
+ int window;
+ int requestor; // the window which wanted the selection and to which this event is sent
+ int property; // property of requestor in which the data of the selection is stored
+ int mimeType; // a property on the requestor in which the mime type in which the selection is, is stored
+ } simpleData;
+};
+
+//complex events:
+
+struct QWSRegionEvent : QWSEvent {
+ QWSRegionEvent()
+ : QWSEvent(QWSEvent::Region, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData))
+ { memset(reinterpret_cast<char*>(&simpleData),0,sizeof(simpleData)); }
+
+ void setData(const char *d, int len, bool allocateMem = true) {
+ QWSEvent::setData(d, len, allocateMem);
+ rectangles = reinterpret_cast<QRect*>(rawDataPtr);
+ }
+
+ void setData(int winId, const QRegion &region, uint type) {
+ const QVector<QRect> rects = region.rects();
+ setData(reinterpret_cast<const char*>(rects.constData()),
+ rects.size() * sizeof(QRect));
+ simpleData.window = winId;
+ simpleData.nrectangles = rects.size();
+ simpleData.type = type;
+#ifdef QT_QWS_CLIENTBLIT
+ simpleData.id = 0;
+#endif
+ }
+
+ enum Type {Allocation
+#ifdef QT_QWS_CLIENTBLIT
+ , DirectPaint
+#endif
+ };
+ struct SimpleData {
+ int window;
+ int nrectangles;
+#ifdef QT_QWS_CLIENTBLIT
+ int id;
+#endif
+ uint type:8;
+ } simpleData;
+
+ QRect *rectangles;
+};
+
+#ifndef QT_NO_QWSEMBEDWIDGET
+struct QWSEmbedEvent : QWSEvent
+{
+ QWSEmbedEvent() : QWSEvent(QWSEvent::Embed, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData))
+ {}
+
+ enum Type { StartEmbed = 1, StopEmbed = 2, Region = 4 };
+
+ void setData(const char *d, int len, bool allocateMem = true) {
+ QWSEvent::setData(d, len, allocateMem);
+ region.setRects(reinterpret_cast<const QRect *>(rawDataPtr),
+ simpleData.nrectangles);
+ }
+
+ void setData(int winId, Type type, const QRegion &reg = QRegion()) {
+ simpleData.window = winId;
+ simpleData.nrectangles = reg.rects().size();
+ simpleData.type = type;
+ region = reg;
+ const QVector<QRect> rects = reg.rects();
+ QWSEvent::setData(reinterpret_cast<const char*>(rects.data()),
+ rects.size() * sizeof(QRect));
+ }
+
+ struct SimpleData {
+ int window;
+ int nrectangles;
+ Type type;
+ } simpleData;
+
+ QRegion region;
+};
+#endif // QT_NO_QWSEMBEDWIDGET
+
+#ifndef QT_NO_QWS_PROPERTIES
+struct QWSPropertyReplyEvent : QWSEvent {
+ QWSPropertyReplyEvent()
+ : QWSEvent(QWSEvent::PropertyReply, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+
+ void setData(const char *d, int len, bool allocateMem = true) {
+ QWSEvent::setData(d, len, allocateMem);
+ data = reinterpret_cast<char*>(rawDataPtr);
+ }
+
+ struct SimpleData {
+ int window;
+ int property;
+ int len;
+ } simpleData;
+ char *data;
+};
+#endif //QT_NO_QWS_PROPERTIES
+
+#ifndef QT_NO_COP
+struct QWSQCopMessageEvent : QWSEvent {
+ QWSQCopMessageEvent()
+ : QWSEvent(QWSEvent::QCopMessage, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData))
+ { memset(reinterpret_cast<char*>(&simpleData),0,sizeof(simpleData)); }
+
+ void setData(const char *d, int len, bool allocateMem = true) {
+ QWSEvent::setData(d, len, allocateMem);
+ char* p = rawDataPtr;
+ channel = QByteArray(p, simpleData.lchannel);
+ p += simpleData.lchannel;
+ message = QByteArray(p, simpleData.lmessage);
+ p += simpleData.lmessage;
+ data = QByteArray(p, simpleData.ldata);
+ }
+
+ void setDataDirect(const char *d, int len) {
+ QWSEvent::setData(d, len, false);
+ deleteRaw = true;
+ }
+
+ struct SimpleData {
+ bool is_response;
+ int lchannel;
+ int lmessage;
+ int ldata;
+ } simpleData;
+
+ QByteArray channel;
+ QByteArray message;
+ QByteArray data;
+};
+
+#endif
+
+struct QWSWindowOperationEvent : QWSEvent {
+ QWSWindowOperationEvent()
+ : QWSEvent(WindowOperation, sizeof(simpleData), reinterpret_cast<char*>(&simpleData)) { }
+
+ enum Operation { Show, Hide, ShowMaximized, ShowNormal, ShowMinimized, Close };
+ struct SimpleData {
+ int window;
+ Operation op;
+ } simpleData;
+};
+
+#ifndef QT_NO_QWS_INPUTMETHODS
+
+
+struct QWSIMEvent : QWSEvent {
+ QWSIMEvent()
+ : QWSEvent(IMEvent, sizeof(simpleData), reinterpret_cast<char*>(&simpleData))
+ { memset(reinterpret_cast<char*>(&simpleData),0,sizeof(simpleData)); }
+
+ struct SimpleData {
+ int window;
+ int replaceFrom;
+ int replaceLength;
+ } simpleData;
+
+ void setData(const char *d, int len, bool allocateMem = true) {
+ QWSEvent::setData(d, len, allocateMem);
+ streamingData = QByteArray::fromRawData(rawDataPtr, len);
+ }
+ QByteArray streamingData;
+};
+
+
+struct QWSIMInitEvent : QWSEvent {
+ QWSIMInitEvent()
+ : QWSEvent(IMInit, sizeof(simpleData), reinterpret_cast<char*>(&simpleData))
+ { memset(reinterpret_cast<char*>(&simpleData),0,sizeof(simpleData)); }
+
+ struct SimpleData {
+ int window;
+ int existence;
+ } simpleData;
+
+ void setData(const char *d, int len, bool allocateMem = true) {
+ QWSEvent::setData(d, len, allocateMem);
+ streamingData = QByteArray::fromRawData(rawDataPtr, len);
+ }
+ QByteArray streamingData;
+};
+
+
+struct QWSIMQueryEvent : QWSEvent {
+ QWSIMQueryEvent()
+ : QWSEvent(QWSEvent::IMQuery, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+
+ struct SimpleData {
+ int window;
+ int property;
+ } simpleData;
+
+};
+
+#endif
+
+struct QWSFontEvent : QWSEvent {
+ QWSFontEvent()
+ : QWSEvent(QWSEvent::Font, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+
+ enum EventType {
+ FontRemoved
+ };
+
+ void setData(const char *d, int len, bool allocateMem = true) {
+ QWSEvent::setData(d, len, allocateMem);
+ fontName = QByteArray::fromRawData(rawDataPtr, len);
+ }
+
+ struct SimpleData {
+ uchar type;
+ } simpleData;
+ QByteArray fontName;
+};
+
+struct QWSScreenTransformationEvent : QWSEvent {
+ QWSScreenTransformationEvent()
+ : QWSEvent(QWSEvent::ScreenTransformation, sizeof(simpleData),
+ reinterpret_cast<char*>(&simpleData)) {}
+
+ struct SimpleData {
+ int screen;
+ int transformation;
+ } simpleData;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWSEVENT_QWS_H
diff --git a/src/gui/embedded/qwslock.cpp b/src/gui/embedded/qwslock.cpp
new file mode 100644
index 0000000000..5fb588c6d7
--- /dev/null
+++ b/src/gui/embedded/qwslock.cpp
@@ -0,0 +1,243 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwslock_p.h"
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+
+#include "qwssignalhandler_p.h"
+
+#include <qglobal.h>
+#include <qdebug.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <sys/time.h>
+#include <time.h>
+#ifdef Q_OS_LINUX
+#include <linux/version.h>
+#endif
+#include <unistd.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_NO_SEMAPHORE
+#error QWSLock currently requires semaphores
+#endif
+
+#ifndef Q_OS_BSD4
+union semun {
+ int val;
+ struct semid_ds *buf;
+ unsigned short *array;
+ struct seminfo *__buf;
+};
+#endif
+
+QWSLock::QWSLock()
+{
+ semId = semget(IPC_PRIVATE, 3, IPC_CREAT | 0666);
+
+ if (semId == -1) {
+ perror("QWSLock::QWSLock");
+ qFatal("Unable to create semaphore");
+ }
+ QWSSignalHandler::instance()->addSemaphore(semId);
+
+ semun semval;
+ semval.val = 1;
+
+ if (semctl(semId, BackingStore, SETVAL, semval) == -1) {
+ perror("QWSLock::QWSLock");
+ qFatal("Unable to initialize backingstore semaphore");
+ }
+ lockCount[BackingStore] = 0;
+
+ if (semctl(semId, Communication, SETVAL, semval) == -1) {
+ perror("QWSLock::QWSLock");
+ qFatal("Unable to initialize communication semaphore");
+ }
+ lockCount[Communication] = 0;
+
+ semval.val = 0;
+ if (semctl(semId, RegionEvent, SETVAL, semval) == -1) {
+ perror("QWSLock::QWSLock");
+ qFatal("Unable to initialize region event semaphore");
+ }
+}
+
+QWSLock::QWSLock(int id)
+{
+ semId = id;
+ QWSSignalHandler::instance()->addSemaphore(semId);
+ lockCount[0] = lockCount[1] = 0;
+}
+
+QWSLock::~QWSLock()
+{
+ if (semId == -1)
+ return;
+ QWSSignalHandler::instance()->removeSemaphore(semId);
+}
+
+static bool forceLock(int semId, int semNum, int)
+{
+ int ret;
+ do {
+ sembuf sops = { semNum, -1, 0 };
+
+ // As the BackingStore lock is a mutex, and only one process may own
+ // the lock, it's safe to use SEM_UNDO. On the other hand, the
+ // Communication lock is locked by the client but unlocked by the
+ // server and therefore can't use SEM_UNDO.
+ if (semNum == QWSLock::BackingStore)
+ sops.sem_flg |= SEM_UNDO;
+
+ ret = semop(semId, &sops, 1);
+ if (ret == -1 && errno != EINTR)
+ qDebug("QWSLock::lock: %s", strerror(errno));
+ } while (ret == -1 && errno == EINTR);
+
+ return (ret != -1);
+}
+
+static bool up(int semId, int semNum)
+{
+ int ret;
+ do {
+ sembuf sops = { semNum, 1, 0 };
+ ret = semop(semId, &sops, 1);
+ if (ret == -1 && errno != EINTR)
+ qDebug("QWSLock::up: %s", strerror(errno));
+ } while (ret == -1 && errno == EINTR);
+
+ return (ret != -1);
+}
+
+static bool down(int semId, int semNum)
+{
+ int ret;
+ do {
+ sembuf sops = { semNum, -1, 0 };
+ ret = semop(semId, &sops, 1);
+ if (ret == -1 && errno != EINTR)
+ qDebug("QWSLock::down: %s", strerror(errno));
+ } while (ret == -1 && errno == EINTR);
+
+ return (ret != -1);
+}
+
+static int getValue(int semId, int semNum)
+{
+ int ret;
+ do {
+ ret = semctl(semId, semNum, GETVAL, 0);
+ if (ret == -1 && errno != EINTR)
+ qDebug("QWSLock::getValue: %s", strerror(errno));
+ } while (ret == -1 && errno == EINTR);
+
+ return ret;
+}
+
+bool QWSLock::lock(LockType type, int timeout)
+{
+ if (type == RegionEvent)
+ return up(semId, RegionEvent);
+
+ if (hasLock(type)) {
+ ++lockCount[type];
+ return true;
+ }
+
+ if (!forceLock(semId, type, timeout))
+ return false;
+ ++lockCount[type];
+ return true;
+}
+
+bool QWSLock::hasLock(LockType type)
+{
+ if (type == RegionEvent)
+ return (getValue(semId, RegionEvent) == 0);
+
+ return (lockCount[type] > 0);
+}
+
+void QWSLock::unlock(LockType type)
+{
+ if (type == RegionEvent) {
+ down(semId, RegionEvent);
+ return;
+ }
+
+ if (hasLock(type)) {
+ --lockCount[type];
+ if (hasLock(type))
+ return;
+ }
+
+ const int semNum = type;
+ int ret;
+ do {
+ sembuf sops = {semNum, 1, 0};
+ if (semNum == QWSLock::BackingStore)
+ sops.sem_flg |= SEM_UNDO;
+
+ ret = semop(semId, &sops, 1);
+ if (ret == -1 && errno != EINTR)
+ qDebug("QWSLock::unlock: %s", strerror(errno));
+ } while (ret == -1 && errno == EINTR);
+}
+
+bool QWSLock::wait(LockType type, int timeout)
+{
+ bool ok = forceLock(semId, type, timeout);
+ if (ok)
+ unlock(type);
+ return ok;
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QWS_MULTIPROCESS
diff --git a/src/gui/embedded/qwslock_p.h b/src/gui/embedded/qwslock_p.h
new file mode 100644
index 0000000000..4dc873248e
--- /dev/null
+++ b/src/gui/embedded/qwslock_p.h
@@ -0,0 +1,85 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSLOCK_P_H
+#define QWSLOCK_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. This header file may
+// change from version to version without notice, or even be
+// removed.
+//
+// We mean it.
+//
+
+#include <qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+
+class QWSLock
+{
+public:
+ enum LockType { BackingStore, Communication, RegionEvent };
+
+ QWSLock();
+ QWSLock(int lockId);
+ ~QWSLock();
+
+ bool lock(LockType type, int timeout = -1);
+ void unlock(LockType type);
+ bool wait(LockType type, int timeout = -1);
+ bool hasLock(LockType type);
+ int id() const { return semId; }
+
+private:
+ int semId;
+ int lockCount[2];
+};
+
+
+QT_END_NAMESPACE
+#endif // QT_NO_QWS_MULTIPROCESS
+#endif // QWSLOCK_P_H
diff --git a/src/gui/embedded/qwsmanager_p.h b/src/gui/embedded/qwsmanager_p.h
new file mode 100644
index 0000000000..a891a75484
--- /dev/null
+++ b/src/gui/embedded/qwsmanager_p.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSMANAGER_P_H
+#define QWSMANAGER_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 "QtGui/qregion.h"
+#include "QtGui/qdecoration_qws.h"
+
+#ifndef QT_NO_QWS_MANAGER
+
+#include "QtCore/qhash.h"
+
+QT_BEGIN_NAMESPACE
+
+class QWidget;
+class QMenu;
+
+class QWSManagerPrivate : public QObjectPrivate
+{
+ Q_DECLARE_PUBLIC(QWSManager)
+public:
+ QWSManagerPrivate();
+
+ int activeRegion;
+ QWidget *managed;
+ QMenu *popup;
+
+ enum MenuAction {
+ NormalizeAction,
+ TitleAction,
+ BottomRightAction,
+ MinimizeAction,
+ MaximizeAction,
+ CloseAction,
+ LastMenuAction
+ };
+ QAction *menuActions[LastMenuAction];
+
+ static QWidget *active;
+ static QPoint mousePos;
+
+ // Region caching to avoid getting a regiontype's
+ // QRegion for each mouse move event
+ int previousRegionType;
+ bool previousRegionRepainted; // Hover/Press handled
+ bool entireDecorationNeedsRepaint;
+ struct RegionCaching {
+ int regionType;
+ QRegion region;
+ Qt::WindowFlags windowFlags;
+ QRect windowGeometry;
+ } cached_region;
+
+ bool newCachedRegion(const QPoint &pos);
+ int cachedRegionAt()
+ { return cached_region.regionType; }
+
+ void dirtyRegion(int decorationRegion,
+ QDecoration::DecorationState state,
+ const QRegion &clip = QRegion());
+ void clearDirtyRegions();
+
+ QList<int> dirtyRegions;
+ QList<QDecoration::DecorationState> dirtyStates;
+ QRegion dirtyClip;
+};
+
+#endif // QT_NO_QWS_MANAGER
+
+QT_END_NAMESPACE
+
+#endif // QWSMANAGER_P_H
diff --git a/src/gui/embedded/qwsmanager_qws.cpp b/src/gui/embedded/qwsmanager_qws.cpp
new file mode 100644
index 0000000000..96abf3fdcb
--- /dev/null
+++ b/src/gui/embedded/qwsmanager_qws.cpp
@@ -0,0 +1,535 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwsmanager_qws.h"
+
+#ifndef QT_NO_QWS_MANAGER
+
+#include "qdrawutil.h"
+#include "qapplication.h"
+#include "qstyle.h"
+#include "qwidget.h"
+#include "qmenu.h"
+#include "qpainter.h"
+#include "private/qpainter_p.h"
+#include "qregion.h"
+#include "qevent.h"
+#include "qcursor.h"
+#include "qwsdisplay_qws.h"
+#include "qdesktopwidget.h"
+
+#include <private/qapplication_p.h>
+#include <private/qwidget_p.h>
+#include <private/qbackingstore_p.h>
+#include <private/qwindowsurface_qws_p.h>
+#include "qdecorationfactory_qws.h"
+
+#include "qlayout.h"
+
+#include "qwsmanager_p.h"
+
+#include <qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QWidget *QWSManagerPrivate::active = 0;
+QPoint QWSManagerPrivate::mousePos;
+
+
+QWSManagerPrivate::QWSManagerPrivate()
+ : QObjectPrivate(), activeRegion(QDecoration::None), managed(0), popup(0),
+ previousRegionType(0), previousRegionRepainted(false), entireDecorationNeedsRepaint(false)
+{
+ cached_region.regionType = 0;
+}
+
+QRegion &QWSManager::cachedRegion()
+{
+ return d_func()->cached_region.region;
+}
+
+/*!
+ \class QWSManager
+ \ingroup qws
+ \internal
+*/
+
+/*!
+
+*/
+QWSManager::QWSManager(QWidget *w)
+ : QObject(*new QWSManagerPrivate, (QObject*)0)
+{
+ d_func()->managed = w;
+
+}
+
+QWSManager::~QWSManager()
+{
+ Q_D(QWSManager);
+#ifndef QT_NO_MENU
+ if (d->popup)
+ delete d->popup;
+#endif
+ if (d->managed == QWSManagerPrivate::active)
+ QWSManagerPrivate::active = 0;
+}
+
+QWidget *QWSManager::widget()
+{
+ Q_D(QWSManager);
+ return d->managed;
+}
+
+QWidget *QWSManager::grabbedMouse()
+{
+ return QWSManagerPrivate::active;
+}
+
+QRegion QWSManager::region()
+{
+ Q_D(QWSManager);
+ return QApplication::qwsDecoration().region(d->managed, d->managed->geometry());
+}
+
+bool QWSManager::event(QEvent *e)
+{
+ if (QObject::event(e))
+ return true;
+
+ switch (e->type()) {
+ case QEvent::MouseMove:
+ mouseMoveEvent((QMouseEvent*)e);
+ break;
+
+ case QEvent::MouseButtonPress:
+ mousePressEvent((QMouseEvent*)e);
+ break;
+
+ case QEvent::MouseButtonRelease:
+ mouseReleaseEvent((QMouseEvent*)e);
+ break;
+
+ case QEvent::MouseButtonDblClick:
+ mouseDoubleClickEvent((QMouseEvent*)e);
+ break;
+
+ case QEvent::Paint:
+ paintEvent((QPaintEvent*)e);
+ break;
+
+ default:
+ return false;
+ break;
+ }
+
+ return true;
+}
+
+void QWSManager::mousePressEvent(QMouseEvent *e)
+{
+ Q_D(QWSManager);
+ d->mousePos = e->globalPos();
+ d->activeRegion = QApplication::qwsDecoration().regionAt(d->managed, d->mousePos);
+ if(d->cached_region.regionType)
+ d->previousRegionRepainted |= repaintRegion(d->cached_region.regionType, QDecoration::Pressed);
+
+ if (d->activeRegion == QDecoration::Menu) {
+ QPoint pos = (QApplication::layoutDirection() == Qt::LeftToRight
+ ? d->managed->geometry().topLeft()
+ : d->managed->geometry().topRight());
+ menu(pos);
+ }
+ if (d->activeRegion != QDecoration::None &&
+ d->activeRegion != QDecoration::Menu) {
+ d->active = d->managed;
+ d->managed->grabMouse();
+ }
+ if (d->activeRegion != QDecoration::None &&
+ d->activeRegion != QDecoration::Close &&
+ d->activeRegion != QDecoration::Minimize &&
+ d->activeRegion != QDecoration::Menu) {
+ d->managed->raise();
+ }
+
+ if (e->button() == Qt::RightButton) {
+ menu(e->globalPos());
+ }
+}
+
+void QWSManager::mouseReleaseEvent(QMouseEvent *e)
+{
+ Q_D(QWSManager);
+ d->managed->releaseMouse();
+ if (d->cached_region.regionType && d->previousRegionRepainted && QApplication::mouseButtons() == 0) {
+ bool doesHover = repaintRegion(d->cached_region.regionType, QDecoration::Hover);
+ if (!doesHover) {
+ repaintRegion(d->cached_region.regionType, QDecoration::Normal);
+ d->previousRegionRepainted = false;
+ }
+ }
+
+ if (e->button() == Qt::LeftButton) {
+ //handleMove();
+ int itm = QApplication::qwsDecoration().regionAt(d->managed, e->globalPos());
+ int activatedItem = d->activeRegion;
+ d->activeRegion = QDecoration::None;
+ d->active = 0;
+ if (activatedItem == itm)
+ QApplication::qwsDecoration().regionClicked(d->managed, itm);
+ } else if (d->activeRegion == QDecoration::None) {
+ d->active = 0;
+ }
+}
+
+void QWSManager::mouseDoubleClickEvent(QMouseEvent *e)
+{
+ Q_D(QWSManager);
+ if (e->button() == Qt::LeftButton)
+ QApplication::qwsDecoration().regionDoubleClicked(d->managed,
+ QApplication::qwsDecoration().regionAt(d->managed, e->globalPos()));
+}
+
+static inline Qt::CursorShape regionToShape(int region)
+{
+ if (region == QDecoration::None)
+ return Qt::ArrowCursor;
+
+ static const struct {
+ int region;
+ Qt::CursorShape shape;
+ } r2s[] = {
+ { QDecoration::TopLeft, Qt::SizeFDiagCursor },
+ { QDecoration::Top, Qt::SizeVerCursor},
+ { QDecoration::TopRight, Qt::SizeBDiagCursor},
+ { QDecoration::Left, Qt::SizeHorCursor},
+ { QDecoration::Right, Qt::SizeHorCursor},
+ { QDecoration::BottomLeft, Qt::SizeBDiagCursor},
+ { QDecoration::Bottom, Qt::SizeVerCursor},
+ { QDecoration::BottomRight, Qt::SizeFDiagCursor},
+ { QDecoration::None, Qt::ArrowCursor}
+ };
+
+ int i = 0;
+ while (region != r2s[i].region && r2s[i].region)
+ ++i;
+ return r2s[i].shape;
+}
+
+void QWSManager::mouseMoveEvent(QMouseEvent *e)
+{
+ Q_D(QWSManager);
+ if (d->newCachedRegion(e->globalPos())) {
+ if(d->previousRegionType && d->previousRegionRepainted)
+ repaintRegion(d->previousRegionType, QDecoration::Normal);
+ if(d->cached_region.regionType) {
+ d->previousRegionRepainted = repaintRegion(d->cached_region.regionType, QDecoration::Hover);
+ }
+ }
+
+
+#ifndef QT_NO_CURSOR
+ QWSDisplay *qwsd = QApplication::desktop()->qwsDisplay();
+ qwsd->selectCursor(d->managed, regionToShape(d->cachedRegionAt()));
+#endif //QT_NO_CURSOR
+
+ if (d->activeRegion)
+ handleMove(e->globalPos());
+}
+
+void QWSManager::handleMove(QPoint g)
+{
+ Q_D(QWSManager);
+
+ // don't allow dragging to where the user probably cannot click!
+ QApplicationPrivate *ap = QApplicationPrivate::instance();
+ const QRect maxWindowRect = ap->maxWindowRect(qt_screen);
+ if (maxWindowRect.isValid()) {
+ if (g.x() < maxWindowRect.x())
+ g.setX(maxWindowRect.x());
+ if (g.y() < maxWindowRect.y())
+ g.setY(maxWindowRect.y());
+ if (g.x() > maxWindowRect.right())
+ g.setX(maxWindowRect.right());
+ if (g.y() > maxWindowRect.bottom())
+ g.setY(maxWindowRect.bottom());
+ }
+
+ if (g == d->mousePos)
+ return;
+
+ if ( d->managed->isMaximized() )
+ return;
+
+ int x = d->managed->geometry().x();
+ int y = d->managed->geometry().y();
+ int w = d->managed->width();
+ int h = d->managed->height();
+
+ QRect geom(d->managed->geometry());
+
+ QPoint delta = g - d->mousePos;
+ d->mousePos = g;
+
+ if (d->activeRegion == QDecoration::Title) {
+ geom = QRect(x + delta.x(), y + delta.y(), w, h);
+ } else {
+ bool keepTop = true;
+ bool keepLeft = true;
+ switch (d->activeRegion) {
+ case QDecoration::Top:
+ geom.setTop(geom.top() + delta.y());
+ keepTop = false;
+ break;
+ case QDecoration::Bottom:
+ geom.setBottom(geom.bottom() + delta.y());
+ keepTop = true;
+ break;
+ case QDecoration::Left:
+ geom.setLeft(geom.left() + delta.x());
+ keepLeft = false;
+ break;
+ case QDecoration::Right:
+ geom.setRight(geom.right() + delta.x());
+ keepLeft = true;
+ break;
+ case QDecoration::TopRight:
+ geom.setTopRight(geom.topRight() + delta);
+ keepLeft = true;
+ keepTop = false;
+ break;
+ case QDecoration::TopLeft:
+ geom.setTopLeft(geom.topLeft() + delta);
+ keepLeft = false;
+ keepTop = false;
+ break;
+ case QDecoration::BottomLeft:
+ geom.setBottomLeft(geom.bottomLeft() + delta);
+ keepLeft = false;
+ keepTop = true;
+ break;
+ case QDecoration::BottomRight:
+ geom.setBottomRight(geom.bottomRight() + delta);
+ keepLeft = true;
+ keepTop = true;
+ break;
+ default:
+ return;
+ }
+
+ QSize newSize = QLayout::closestAcceptableSize(d->managed, geom.size());
+
+ int dx = newSize.width() - geom.width();
+ int dy = newSize.height() - geom.height();
+
+ if (keepTop) {
+ geom.setBottom(geom.bottom() + dy);
+ d->mousePos.ry() += dy;
+ } else {
+ geom.setTop(geom.top() - dy);
+ d->mousePos.ry() -= dy;
+ }
+ if (keepLeft) {
+ geom.setRight(geom.right() + dx);
+ d->mousePos.rx() += dx;
+ } else {
+ geom.setLeft(geom.left() - dx);
+ d->mousePos.rx() -= dx;
+ }
+ }
+ if (geom != d->managed->geometry()) {
+ QApplication::sendPostedEvents();
+ d->managed->setGeometry(geom);
+ }
+}
+
+void QWSManager::paintEvent(QPaintEvent *)
+{
+ Q_D(QWSManager);
+ d->dirtyRegion(QDecoration::All, QDecoration::Normal);
+}
+
+void QWSManagerPrivate::dirtyRegion(int decorationRegion,
+ QDecoration::DecorationState state,
+ const QRegion &clip)
+{
+ QTLWExtra *topextra = managed->d_func()->extra->topextra;
+ QWidgetBackingStore *bs = topextra->backingStore;
+ const bool pendingUpdateRequest = bs->isDirty();
+
+ if (decorationRegion == QDecoration::All) {
+ if (clip.isEmpty())
+ entireDecorationNeedsRepaint = true;
+ dirtyRegions.clear();
+ dirtyStates.clear();
+ }
+ int i = dirtyRegions.indexOf(decorationRegion);
+ if (i >= 0) {
+ dirtyRegions.removeAt(i);
+ dirtyStates.removeAt(i);
+ }
+
+ dirtyRegions.append(decorationRegion);
+ dirtyStates.append(state);
+ if (!entireDecorationNeedsRepaint)
+ dirtyClip += clip;
+
+ if (!pendingUpdateRequest)
+ QApplication::postEvent(managed, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);
+}
+
+void QWSManagerPrivate::clearDirtyRegions()
+{
+ dirtyRegions.clear();
+ dirtyStates.clear();
+ dirtyClip = QRegion();
+ entireDecorationNeedsRepaint = false;
+}
+
+bool QWSManager::repaintRegion(int decorationRegion, QDecoration::DecorationState state)
+{
+ Q_D(QWSManager);
+
+ d->dirtyRegion(decorationRegion, state);
+ return true;
+}
+
+void QWSManager::menu(const QPoint &pos)
+{
+#ifdef QT_NO_MENU
+ Q_UNUSED(pos);
+#else
+ Q_D(QWSManager);
+ if (d->popup)
+ delete d->popup;
+
+ // Basic window operation menu
+ d->popup = new QMenu();
+ QApplication::qwsDecoration().buildSysMenu(d->managed, d->popup);
+ connect(d->popup, SIGNAL(triggered(QAction*)), SLOT(menuTriggered(QAction*)));
+
+ d->popup->popup(pos);
+ d->activeRegion = QDecoration::None;
+#endif // QT_NO_MENU
+}
+
+void QWSManager::menuTriggered(QAction *action)
+{
+#ifdef QT_NO_MENU
+ Q_UNUSED(action);
+#else
+ Q_D(QWSManager);
+ QApplication::qwsDecoration().menuTriggered(d->managed, action);
+ d->popup->deleteLater();
+ d->popup = 0;
+#endif
+}
+
+void QWSManager::startMove()
+{
+ Q_D(QWSManager);
+ d->mousePos = QCursor::pos();
+ d->activeRegion = QDecoration::Title;
+ d->active = d->managed;
+ d->managed->grabMouse();
+}
+
+void QWSManager::startResize()
+{
+ Q_D(QWSManager);
+ d->activeRegion = QDecoration::BottomRight;
+ d->active = d->managed;
+ d->managed->grabMouse();
+}
+
+void QWSManager::maximize()
+{
+ Q_D(QWSManager);
+ // find out how much space the decoration needs
+ const int screen = QApplication::desktop()->screenNumber(d->managed);
+ const QRect desk = QApplication::desktop()->availableGeometry(screen);
+ QRect dummy(0, 0, 1, 1);
+ QRect nr;
+ QRegion r = QApplication::qwsDecoration().region(d->managed, dummy);
+ if (r.isEmpty()) {
+ nr = desk;
+ } else {
+ r += dummy; // make sure we get the full window region in case of 0 width borders
+ QRect rect = r.boundingRect();
+ nr = QRect(desk.x()-rect.x(), desk.y()-rect.y(),
+ desk.width() - (rect.width()==1 ? 0 : rect.width()-1), // ==1 -> dummy
+ desk.height() - (rect.height()==1 ? 0 : rect.height()-1));
+ }
+ d->managed->setGeometry(nr);
+}
+
+bool QWSManagerPrivate::newCachedRegion(const QPoint &pos)
+{
+ // Check if anything has changed that would affect the region caching
+ if (managed->windowFlags() == cached_region.windowFlags
+ && managed->geometry() == cached_region.windowGeometry
+ && cached_region.region.contains(pos))
+ return false;
+
+ // Update the cached region
+ int reg = QApplication::qwsDecoration().regionAt(managed, pos);
+ if (QWidget::mouseGrabber())
+ reg = QDecoration::None;
+
+ previousRegionType = cached_region.regionType;
+ cached_region.regionType = reg;
+ cached_region.region = QApplication::qwsDecoration().region(managed, managed->geometry(),
+ reg);
+ // Make room for borders around the widget, even if the decoration doesn't have a frame.
+ if (reg && !(reg & int(QDecoration::Borders))) {
+ cached_region.region -= QApplication::qwsDecoration().region(managed, managed->geometry(), QDecoration::Borders);
+ }
+ cached_region.windowFlags = managed->windowFlags();
+ cached_region.windowGeometry = managed->geometry();
+// QRect rec = cached_region.region.boundingRect();
+// qDebug("Updated cached region: 0x%04x (%d, %d) (%d, %d, %d, %d)",
+// reg, pos.x(), pos.y(), rec.x(), rec.y(), rec.right(), rec.bottom());
+ return true;
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_QWS_MANAGER
diff --git a/src/gui/embedded/qwsmanager_qws.h b/src/gui/embedded/qwsmanager_qws.h
new file mode 100644
index 0000000000..d342ae085a
--- /dev/null
+++ b/src/gui/embedded/qwsmanager_qws.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSMANAGER_QWS_H
+#define QWSMANAGER_QWS_H
+
+#include <QtGui/qpixmap.h>
+#include <QtCore/qobject.h>
+#include <QtGui/qdecoration_qws.h>
+#include <QtGui/qevent.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QWS_MANAGER
+
+class QAction;
+class QPixmap;
+class QWidget;
+class QPopupMenu;
+class QRegion;
+class QMouseEvent;
+class QWSManagerPrivate;
+
+class Q_GUI_EXPORT QWSManager : public QObject
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QWSManager)
+public:
+ explicit QWSManager(QWidget *);
+ ~QWSManager();
+
+ static QDecoration *newDefaultDecoration();
+
+ QWidget *widget();
+ static QWidget *grabbedMouse();
+ void maximize();
+ void startMove();
+ void startResize();
+
+ QRegion region();
+ QRegion &cachedRegion();
+
+protected Q_SLOTS:
+ void menuTriggered(QAction *action);
+
+protected:
+ void handleMove(QPoint g);
+
+ virtual bool event(QEvent *e);
+ virtual void mouseMoveEvent(QMouseEvent *);
+ virtual void mousePressEvent(QMouseEvent *);
+ virtual void mouseReleaseEvent(QMouseEvent *);
+ virtual void mouseDoubleClickEvent(QMouseEvent *);
+ virtual void paintEvent(QPaintEvent *);
+ bool repaintRegion(int region, QDecoration::DecorationState state);
+
+ void menu(const QPoint &);
+
+private:
+ friend class QWidget;
+ friend class QETWidget;
+ friend class QWidgetPrivate;
+ friend class QApplication;
+ friend class QApplicationPrivate;
+ friend class QWidgetBackingStore;
+ friend class QWSWindowSurface;
+ friend class QGLDrawable;
+};
+
+QT_BEGIN_INCLUDE_NAMESPACE
+#include <QtGui/qdecorationdefault_qws.h>
+QT_END_INCLUDE_NAMESPACE
+
+#endif // QT_NO_QWS_MANAGER
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWSMANAGER_QWS_H
diff --git a/src/gui/embedded/qwsproperty_qws.cpp b/src/gui/embedded/qwsproperty_qws.cpp
new file mode 100644
index 0000000000..1c44506101
--- /dev/null
+++ b/src/gui/embedded/qwsproperty_qws.cpp
@@ -0,0 +1,145 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwsproperty_qws.h"
+
+#ifndef QT_NO_QWS_PROPERTIES
+#include "qwscommand_qws_p.h"
+#include "qwindowsystem_qws.h"
+#include "qhash.h"
+#include "qalgorithms.h"
+#include "qbytearray.h"
+
+#include <stdio.h>
+
+QT_BEGIN_NAMESPACE
+
+class QWSPropertyManager::Data {
+public:
+ QByteArray find(int winId, int property)
+ {
+ return properties.value(winId).value(property);
+ }
+
+ typedef QHash<int, QHash<int, QByteArray> > PropertyHash;
+ PropertyHash properties;
+};
+
+/*********************************************************************
+ *
+ * Class: QWSPropertyManager
+ *
+ *********************************************************************/
+
+QWSPropertyManager::QWSPropertyManager()
+{
+ d = new Data;
+}
+
+QWSPropertyManager::~QWSPropertyManager()
+{
+ delete d;
+}
+
+bool QWSPropertyManager::setProperty(int winId, int property, int mode, const char *data, int len)
+{
+ QHash<int, QByteArray> props = d->properties.value(winId);
+ QHash<int, QByteArray>::iterator it = props.find(property);
+ if (it == props.end())
+ return false;
+
+ switch (mode) {
+ case PropReplace:
+ d->properties[winId][property] = QByteArray(data, len);
+ break;
+ case PropAppend:
+ d->properties[winId][property].append(data);
+ break;
+ case PropPrepend:
+ d->properties[winId][property].prepend(data);
+ break;
+ }
+ return true;
+}
+
+bool QWSPropertyManager::hasProperty(int winId, int property)
+{
+ return d->properties.value(winId).contains(property);
+}
+
+bool QWSPropertyManager::removeProperty(int winId, int property)
+{
+ QWSPropertyManager::Data::PropertyHash::iterator it = d->properties.find(winId);
+ if (it == d->properties.end())
+ return false;
+ return d->properties[winId].remove( property );
+}
+
+bool QWSPropertyManager::addProperty(int winId, int property)
+{
+ if( !d->properties[winId].contains(property) )
+ d->properties[winId][property] = QByteArray(); // only add if it doesn't exist
+ return true;
+}
+
+bool QWSPropertyManager::getProperty(int winId, int property, const char *&data, int &len)
+{
+ QHash<int, QByteArray> props = d->properties.value(winId);
+ QHash<int, QByteArray>::iterator it = props.find(property);
+ if (it == props.end()) {
+ data = 0;
+ len = -1;
+ return false;
+ }
+ data = it.value().constData();
+ len = it.value().length();
+
+ return true;
+}
+
+bool QWSPropertyManager::removeProperties(int winId)
+{
+ return d->properties.remove(winId);
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_QWS_PROPERTIES
diff --git a/src/gui/embedded/qwsproperty_qws.h b/src/gui/embedded/qwsproperty_qws.h
new file mode 100644
index 0000000000..27f0c65a88
--- /dev/null
+++ b/src/gui/embedded/qwsproperty_qws.h
@@ -0,0 +1,96 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSPROPERTY_QWS_H
+#define QWSPROPERTY_QWS_H
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+/*********************************************************************
+ *
+ * Class: QWSPropertyManager
+ *
+ *********************************************************************/
+
+#ifndef QT_NO_QWS_PROPERTIES
+
+class QWSPropertyManager
+{
+public:
+ enum Mode {
+ PropReplace = 0,
+ PropPrepend,
+ PropAppend
+ };
+
+ // pre-defined properties
+ enum Atom {
+ PropSelection = 0
+ };
+
+ QWSPropertyManager();
+ ~QWSPropertyManager();
+
+ bool setProperty(int winId, int property, int mode, const char *data, int len);
+ bool hasProperty(int winId, int property);
+ bool removeProperty(int winId, int property);
+ bool addProperty(int winId, int property);
+ bool getProperty(int winId, int property, const char *&data, int &len);
+ bool removeProperties(int winId);
+
+private:
+ class Data;
+ Data* d;
+};
+
+#endif // QT_NO_QWS_PROPERTIES
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWSPROPERTY_QWS_H
diff --git a/src/gui/embedded/qwsprotocolitem_qws.h b/src/gui/embedded/qwsprotocolitem_qws.h
new file mode 100644
index 0000000000..71f70ddf09
--- /dev/null
+++ b/src/gui/embedded/qwsprotocolitem_qws.h
@@ -0,0 +1,100 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSPROTOCOLITEM_QWS_H
+#define QWSPROTOCOLITEM_QWS_H
+
+/*********************************************************************
+ *
+ * QWSCommand base class - only use derived classes from that
+ *
+ *********************************************************************/
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QIODevice;
+
+struct QWSProtocolItem
+{
+ // ctor - dtor
+ QWSProtocolItem(int t, int len, char *ptr) : type(t),
+ simpleLen(len), rawLen(-1), deleteRaw(false), simpleDataPtr(ptr),
+ rawDataPtr(0), bytesRead(0) { }
+ virtual ~QWSProtocolItem();
+
+ // data
+ int type;
+ int simpleLen;
+ int rawLen;
+ bool deleteRaw;
+
+ // functions
+#ifndef QT_NO_QWS_MULTIPROCESS
+ void write(QIODevice *s);
+ bool read(QIODevice *s);
+#endif
+ void copyFrom(const QWSProtocolItem *item);
+
+ virtual void setData(const char *data, int len, bool allocateMem = true);
+
+ char *simpleDataPtr;
+ char *rawDataPtr;
+ // temp variables
+ int bytesRead;
+};
+
+// This should probably be a method on QWSProtocolItem, but this way avoids
+// changing the API of this apparently public header
+// size = (int)type + (int)rawLenSize + simpleLen + rawLen
+#define QWS_PROTOCOL_ITEM_SIZE( item ) \
+ (2 * sizeof(int)) + ((item).simpleDataPtr ? (item).simpleLen : 0) + ((item).rawDataPtr ? (item).rawLen : 0)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWSPROTOCOLITEM_QWS_H
diff --git a/src/gui/embedded/qwssharedmemory.cpp b/src/gui/embedded/qwssharedmemory.cpp
new file mode 100644
index 0000000000..8afbe9b5c7
--- /dev/null
+++ b/src/gui/embedded/qwssharedmemory.cpp
@@ -0,0 +1,185 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwssharedmemory_p.h"
+
+#if !defined(QT_NO_QWS_MULTIPROCESS)
+
+#include <sys/shm.h>
+
+QT_BEGIN_NAMESPACE
+
+QWSSharedMemory::QWSSharedMemory()
+ : shmBase(0), shmSize(0), character(0), shmId(-1), key(-1)
+{
+}
+
+
+QWSSharedMemory::~QWSSharedMemory()
+{
+ detach();
+}
+
+/*
+ man page says:
+ On Linux, it is possible to attach a shared memory segment even if it
+ is already marked to be deleted. However, POSIX.1-2001 does not spec-
+ ify this behaviour and many other implementations do not support it.
+*/
+
+bool QWSSharedMemory::create(int size)
+{
+ if (shmId != -1)
+ detach();
+ shmId = shmget(IPC_PRIVATE, size, IPC_CREAT|0600);
+
+ if (shmId == -1) {
+#ifdef QT_SHM_DEBUG
+ perror("QWSSharedMemory::create allocating shared memory");
+ qWarning("Error allocating shared memory of size %d", size);
+#endif
+ return false;
+ }
+ shmBase = shmat(shmId,0,0);
+ shmctl(shmId, IPC_RMID, 0);
+ if (shmBase == (void*)-1) {
+#ifdef QT_SHM_DEBUG
+ perror("QWSSharedMemory::create attaching to shared memory");
+ qWarning("Error attaching to shared memory id %d", shmId);
+#endif
+ shmBase = 0;
+ return false;
+ }
+ return true;
+}
+
+bool QWSSharedMemory::attach(int id)
+{
+ if (shmId == id)
+ return id != -1;
+ if (shmId != -1)
+ detach();
+
+ shmBase = shmat(id,0,0);
+ if (shmBase == (void*)-1) {
+#ifdef QT_SHM_DEBUG
+ perror("QWSSharedMemory::attach attaching to shared memory");
+ qWarning("Error attaching to shared memory 0x%x of size %d",
+ id, size());
+#endif
+ shmBase = 0;
+ return false;
+ }
+ shmId = id;
+ return true;
+}
+
+
+void QWSSharedMemory::detach ()
+{
+ if (!shmBase)
+ return;
+ shmdt (shmBase);
+ shmBase = 0;
+ shmSize = 0;
+ shmId = -1;
+}
+
+void QWSSharedMemory::setPermissions (mode_t mode)
+{
+ struct shmid_ds shm;
+ shmctl (shmId, IPC_STAT, &shm);
+ shm.shm_perm.mode = mode;
+ shmctl (shmId, IPC_SET, &shm);
+}
+
+int QWSSharedMemory::size () const
+{
+ struct shmid_ds shm;
+ shmctl (shmId, IPC_STAT, &shm);
+ return shm.shm_segsz;
+}
+
+
+// old API
+
+
+
+QWSSharedMemory::QWSSharedMemory (int size, const QString &filename, char c)
+{
+ shmSize = size;
+ shmFile = filename;
+ shmBase = 0;
+ shmId = -1;
+ character = c;
+ key = ftok (shmFile.toLatin1().constData(), c);
+}
+
+
+
+bool QWSSharedMemory::create ()
+{
+ shmId = shmget (key, shmSize, IPC_CREAT | 0666);
+ return (shmId != -1);
+}
+
+void QWSSharedMemory::destroy ()
+{
+ if (shmId != -1)
+ shmctl(shmId, IPC_RMID, 0);
+}
+
+bool QWSSharedMemory::attach ()
+{
+ if (shmId == -1)
+ shmId = shmget (key, shmSize, 0);
+
+ shmBase = shmat (shmId, 0, 0);
+ if ((long)shmBase == -1)
+ shmBase = 0;
+
+ return (long)shmBase != 0;
+}
+
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QWS_MULTIPROCESS
diff --git a/src/gui/embedded/qwssharedmemory_p.h b/src/gui/embedded/qwssharedmemory_p.h
new file mode 100644
index 0000000000..6b58605986
--- /dev/null
+++ b/src/gui/embedded/qwssharedmemory_p.h
@@ -0,0 +1,105 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSSHAREDMEMORY_P_H
+#define QWSSHAREDMEMORY_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 "qplatformdefs.h"
+#include "QtCore/qstring.h"
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_NO_QWS_MULTIPROCESS)
+
+class QWSSharedMemory {
+public:
+
+ QWSSharedMemory();
+ ~QWSSharedMemory();
+
+ void setPermissions(mode_t mode);
+ int size() const;
+ void *address() { return shmBase; };
+
+ int id() const { return shmId; }
+
+ void detach();
+
+ bool create(int size);
+ bool attach(int id);
+
+ //bool create(int size, const QString &filename, char c = 'Q');
+ //bool attach(const QString &filename, char c = 'Q');
+// old API
+
+ QWSSharedMemory(int, const QString &, char c = 'Q');
+ void * base() { return address(); };
+
+ bool create();
+ void destroy();
+
+ bool attach();
+
+private:
+ void *shmBase;
+ int shmSize;
+ QString shmFile;
+ char character;
+ int shmId;
+ key_t key;
+};
+
+#endif // QT_NO_QWS_MULTIPROCESS
+
+QT_END_NAMESPACE
+
+#endif // QWSSHAREDMEMORY_P_H
diff --git a/src/gui/embedded/qwssignalhandler.cpp b/src/gui/embedded/qwssignalhandler.cpp
new file mode 100644
index 0000000000..0946fb62bf
--- /dev/null
+++ b/src/gui/embedded/qwssignalhandler.cpp
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwssignalhandler_p.h"
+
+#ifndef QT_NO_QWS_SIGNALHANDLER
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <signal.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef Q_OS_BSD4
+union semun {
+ int val;
+ struct semid_ds *buf;
+ unsigned short *array;
+ struct seminfo *__buf;
+};
+#endif
+
+
+class QWSSignalHandlerPrivate : public QWSSignalHandler
+{
+public:
+ QWSSignalHandlerPrivate() : QWSSignalHandler() {}
+};
+
+
+Q_GLOBAL_STATIC(QWSSignalHandlerPrivate, signalHandlerInstance);
+
+
+QWSSignalHandler* QWSSignalHandler::instance()
+{
+ return signalHandlerInstance();
+}
+
+QWSSignalHandler::QWSSignalHandler()
+{
+ const int signums[] = { SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, SIGFPE,
+ SIGSEGV, SIGTERM, SIGBUS };
+ const int n = sizeof(signums)/sizeof(int);
+
+ for (int i = 0; i < n; ++i) {
+ const int signum = signums[i];
+ qt_sighandler_t old = signal(signum, handleSignal);
+ if (old == SIG_IGN) // don't remove shm and semaphores when ignored
+ signal(signum, old);
+ else
+ oldHandlers[signum] = (old == SIG_ERR ? SIG_DFL : old);
+ }
+}
+
+QWSSignalHandler::~QWSSignalHandler()
+{
+#ifndef QT_NO_QWS_MULTIPROCESS
+ while (!semaphores.isEmpty())
+ removeSemaphore(semaphores.last());
+#endif
+}
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+void QWSSignalHandler::removeSemaphore(int semno)
+{
+ const int index = semaphores.lastIndexOf(semno);
+ if (index != -1) {
+ semun semval;
+ semval.val = 0;
+ semctl(semaphores.at(index), 0, IPC_RMID, semval);
+ semaphores.remove(index);
+ }
+}
+#endif // QT_NO_QWS_MULTIPROCESS
+
+void QWSSignalHandler::handleSignal(int signum)
+{
+ QWSSignalHandler *h = instance();
+
+ signal(signum, h->oldHandlers[signum]);
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+ semun semval;
+ semval.val = 0;
+ for (int i = 0; i < h->semaphores.size(); ++i)
+ semctl(h->semaphores.at(i), 0, IPC_RMID, semval);
+#endif
+
+ h->objects.clear();
+ raise(signum);
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_QWS_NO_SIGNALHANDLER
diff --git a/src/gui/embedded/qwssignalhandler_p.h b/src/gui/embedded/qwssignalhandler_p.h
new file mode 100644
index 0000000000..f2228e1461
--- /dev/null
+++ b/src/gui/embedded/qwssignalhandler_p.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSSIGNALHANDLER_P_H
+#define QWSSIGNALHANDLER_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/qglobal.h>
+
+#ifndef QT_NO_QWS_SIGNALHANDLER
+
+#include <QtCore/qmap.h>
+#include <QtCore/qvector.h>
+#include <QtCore/qobjectcleanuphandler.h>
+
+QT_BEGIN_NAMESPACE
+
+typedef void (*qt_sighandler_t)(int);
+
+class QWSSignalHandlerPrivate;
+
+class Q_GUI_EXPORT QWSSignalHandler
+{
+public:
+ static QWSSignalHandler* instance();
+
+ ~QWSSignalHandler();
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+ inline void addSemaphore(int semno) { semaphores.append(semno); }
+ void removeSemaphore(int semno);
+#endif
+ inline void addObject(QObject *object) { (void)objects.add(object); }
+
+private:
+ QWSSignalHandler();
+ static void handleSignal(int signal);
+ QMap<int, qt_sighandler_t> oldHandlers;
+#ifndef QT_NO_QWS_MULTIPROCESS
+ QVector<int> semaphores;
+#endif
+ QObjectCleanupHandler objects;
+
+ friend class QWSSignalHandlerPrivate;
+};
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_QWS_SIGNALHANDLER
+
+#endif // QWSSIGNALHANDLER_P_H
diff --git a/src/gui/embedded/qwssocket_qws.cpp b/src/gui/embedded/qwssocket_qws.cpp
new file mode 100644
index 0000000000..bebd98e6b3
--- /dev/null
+++ b/src/gui/embedded/qwssocket_qws.cpp
@@ -0,0 +1,280 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qplatformdefs.h"
+#include "qwssocket_qws.h"
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+
+#include <fcntl.h>
+#include <netdb.h>
+#include <errno.h>
+#include <stdio.h>
+#include <sys/file.h>
+#include <sys/time.h>
+#include <sys/un.h>
+
+#ifdef __MIPSEL__
+# ifndef SOCK_DGRAM
+# define SOCK_DGRAM 1
+# endif
+# ifndef SOCK_STREAM
+# define SOCK_STREAM 2
+# endif
+#endif
+
+#if defined(Q_OS_SOLARIS) || defined (QT_LINUXBASE)
+// uff-da apparently Solaris doesn't have the SUN_LEN macro, here is
+// an implementation of it...
+# ifndef SUN_LEN
+# define SUN_LEN(su) \
+ sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path)
+# endif
+
+// nor the POSIX names of UNIX domain sockets *sigh*
+# ifndef AF_LOCAL
+# define AF_LOCAL AF_UNIX
+# endif
+# ifndef PF_LOCAL
+# define PF_LOCAL PF_UNIX
+# endif
+#endif // Q_OS_SOLARIS || QT_LINUXBASE
+
+QT_BEGIN_NAMESPACE
+
+/***********************************************************************
+ *
+ * QWSSocket
+ *
+ **********************************************************************/
+QWSSocket::QWSSocket(QObject *parent)
+ : QWS_SOCK_BASE(parent)
+{
+#ifndef QT_NO_SXE
+ QObject::connect( this, SIGNAL(stateChanged(SocketState)),
+ this, SLOT(forwardStateChange(SocketState)));
+#endif
+}
+
+QWSSocket::~QWSSocket()
+{
+}
+
+#ifndef QT_NO_SXE
+QString QWSSocket::errorString()
+{
+ switch (QUnixSocket::error()) {
+ case NoError:
+ return QString();
+ case InvalidPath:
+ case NonexistentPath:
+ return QLatin1String("Bad path"); // NO_TR
+ default:
+ return QLatin1String("Bad socket"); // NO TR
+ }
+}
+
+void QWSSocket::forwardStateChange(QUnixSocket::SocketState st )
+{
+ switch ( st )
+ {
+ case ConnectedState:
+ emit connected();
+ break;
+ case ClosingState:
+ break;
+ case UnconnectedState:
+ emit disconnected();
+ break;
+ default:
+ // nothing
+ break;
+ }
+ if ( QUnixSocket::error() != NoError )
+ emit error((QAbstractSocket::SocketError)0);
+}
+#endif
+
+bool QWSSocket::connectToLocalFile(const QString &file)
+{
+#ifndef QT_NO_SXE
+ bool result = QUnixSocket::connect( file.toLocal8Bit() );
+ if ( !result )
+ {
+ perror( "QWSSocketAuth::connectToLocalFile could not connect:" );
+ emit error(QAbstractSocket::ConnectionRefusedError);
+ return false;
+ }
+ return true;
+#else
+ // create socket
+ int s = ::socket(PF_LOCAL, SOCK_STREAM, 0);
+
+ // connect to socket
+ struct sockaddr_un a;
+ memset(&a, 0, sizeof(a));
+ a.sun_family = PF_LOCAL;
+ strncpy(a.sun_path, file.toLocal8Bit().constData(), sizeof(a.sun_path) - 1);
+ int r = ::connect(s, (struct sockaddr*)&a, SUN_LEN(&a));
+ if (r == 0) {
+ setSocketDescriptor(s);
+ } else {
+ perror("QWSSocket::connectToLocalFile could not connect:");
+ ::close(s);
+ emit error(ConnectionRefusedError);
+ return false;
+ }
+#endif
+ return true;
+}
+
+
+/***********************************************************************
+ *
+ * QWSServerSocket
+ *
+ **********************************************************************/
+QWSServerSocket::QWSServerSocket(const QString& file, QObject *parent)
+#ifndef QT_NO_SXE
+ : QUnixSocketServer(parent)
+#else
+ : QTcpServer(parent)
+#endif
+{
+ init(file);
+}
+
+void QWSServerSocket::init(const QString &file)
+{
+#ifndef QT_NO_SXE
+ QByteArray fn = file.toLocal8Bit();
+ bool result = QUnixSocketServer::listen( fn );
+ if ( !result )
+ {
+ QUnixSocketServer::ServerError err = serverError();
+ switch ( err )
+ {
+ case InvalidPath:
+ qWarning("QWSServerSocket:: invalid path %s", qPrintable(file));
+ break;
+ case ResourceError:
+ case BindError:
+ case ListenError:
+ qWarning("QWSServerSocket:: could not listen on path %s", qPrintable(file));
+ break;
+ default:
+ break;
+ }
+ }
+#else
+ int backlog = 16; //#####
+
+// create socket
+ int s = ::socket(PF_LOCAL, SOCK_STREAM, 0);
+ if (s == -1) {
+ perror("QWSServerSocket::init");
+ qWarning("QWSServerSocket: unable to create socket.");
+ return;
+ }
+
+ QByteArray fn = file.toLocal8Bit();
+ unlink(fn.constData()); // doesn't have to succeed
+
+ // bind socket
+ struct sockaddr_un a;
+ memset(&a, 0, sizeof(a));
+ a.sun_family = PF_LOCAL;
+ strncpy(a.sun_path, fn.constData(), sizeof(a.sun_path) - 1);
+ int r = ::bind(s, (struct sockaddr*)&a, SUN_LEN(&a));
+ if (r < 0) {
+ perror("QWSServerSocket::init");
+ qWarning("QWSServerSocket: could not bind to file %s", fn.constData());
+ ::close(s);
+ return;
+ }
+
+ if (chmod(fn.constData(), 0600) < 0) {
+ perror("QWSServerSocket::init");
+ qWarning("Could not set permissions of %s", fn.constData());
+ ::close(s);
+ return;
+ }
+
+ // listen
+ if (::listen(s, backlog) == 0) {
+ if (!setSocketDescriptor(s))
+ qWarning( "QWSServerSocket could not set descriptor %d : %s", s, errorString().toLatin1().constData());
+ } else {
+ perror("QWSServerSocket::init");
+ qWarning("QWSServerSocket: could not listen to file %s", fn.constData());
+ ::close(s);
+ }
+#endif
+}
+
+QWSServerSocket::~QWSServerSocket()
+{
+}
+
+#ifndef QT_NO_SXE
+
+void QWSServerSocket::incomingConnection(int socketDescriptor)
+{
+ inboundConnections.append( socketDescriptor );
+ emit newConnection();
+}
+
+
+QWSSocket *QWSServerSocket::nextPendingConnection()
+{
+ QMutexLocker locker( &ssmx );
+ if ( inboundConnections.count() == 0 )
+ return 0;
+ QWSSocket *s = new QWSSocket();
+ s->setSocketDescriptor( inboundConnections.takeFirst() );
+ return s;
+}
+
+#endif // QT_NO_SXE
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_QWS_MULTIPROCESS
diff --git a/src/gui/embedded/qwssocket_qws.h b/src/gui/embedded/qwssocket_qws.h
new file mode 100644
index 0000000000..6b86d7c661
--- /dev/null
+++ b/src/gui/embedded/qwssocket_qws.h
@@ -0,0 +1,120 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSSOCKET_QWS_H
+#define QWSSOCKET_QWS_H
+
+#include <QtCore/qconfig.h>
+#include <QtGui/qwsutils_qws.h>
+
+#ifndef QT_NO_QWS_MULTIPROCESS
+
+#ifndef QT_NO_SXE
+#include <QtCore/qmutex.h>
+#include <QtGui/private/qunixsocketserver_p.h>
+#include <QtGui/private/qunixsocket_p.h>
+#else
+#include <QtNetwork/qtcpsocket.h>
+#include <QtNetwork/qtcpserver.h>
+#endif
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+
+class QWSSocket : public QWS_SOCK_BASE
+{
+ Q_OBJECT
+public:
+ explicit QWSSocket(QObject *parent=0);
+ ~QWSSocket();
+
+ bool connectToLocalFile(const QString &file);
+
+#ifndef QT_NO_SXE
+ QString errorString();
+Q_SIGNALS:
+ void connected();
+ void disconnected();
+ void error(QAbstractSocket::SocketError);
+private Q_SLOTS:
+ void forwardStateChange(SocketState);
+#endif
+
+private:
+ Q_DISABLE_COPY(QWSSocket)
+};
+
+
+class QWSServerSocket : public QWS_SOCK_SERVER_BASE
+{
+ Q_OBJECT
+public:
+ QWSServerSocket(const QString& file, QObject *parent=0);
+ ~QWSServerSocket();
+
+#ifndef QT_NO_SXE
+ QWSSocket *nextPendingConnection();
+Q_SIGNALS:
+ void newConnection();
+protected:
+ void incomingConnection(int socketDescriptor);
+private:
+ QMutex ssmx;
+ QList<int> inboundConnections;
+#endif
+
+private:
+ Q_DISABLE_COPY(QWSServerSocket)
+
+ void init(const QString &file);
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QT_NO_QWS_MULTIPROCESS
+
+#endif // QWSSOCKET_QWS_H
diff --git a/src/gui/embedded/qwsutils_qws.h b/src/gui/embedded/qwsutils_qws.h
new file mode 100644
index 0000000000..3aa96d184e
--- /dev/null
+++ b/src/gui/embedded/qwsutils_qws.h
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (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 either Technology Preview License Agreement or the
+** Beta Release License Agreement.
+**
+** 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.0, included in the file LGPL_EXCEPTION.txt in this
+** package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+** If you are unsure which license is appropriate for your use, please
+** contact the sales department at qt-sales@nokia.com.
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWSUTILS_QWS_H
+#define QWSUTILS_QWS_H
+
+#include <QtCore/QIODevice>
+
+#ifndef QT_NO_SXE
+#define QWS_SOCK_BASE QUnixSocket
+#define QWS_SOCK_SERVER_BASE QUnixSocketServer
+class QUnixSocket;
+class QUnixSocketServer;
+#else
+#define QWS_SOCK_BASE QTcpSocket
+#define QWS_SOCK_SERVER_BASE QTcpServer
+class QTcpSocket;
+class QTcpServer;
+#endif
+class QWSSocket;
+class QWSServerSocket;
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+/********************************************************************
+ *
+ * Convenient socket functions
+ *
+ ********************************************************************/
+#ifndef QT_NO_QWS_MULTIPROCESS
+inline int qws_read_uint(QIODevice *socket)
+{
+ if (!socket || socket->bytesAvailable() < (int)sizeof(int))
+ return -1;
+
+ int i;
+ socket->read(reinterpret_cast<char*>(&i), sizeof(i));
+
+ return i;
+}
+
+inline void qws_write_uint(QIODevice *socket, int i)
+{
+ if (!socket)
+ return;
+
+ socket->write(reinterpret_cast<char*>(&i), sizeof(i));
+}
+
+#endif // QT_NO_QWS_MULTIPROCESS
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif // QWSUTILS_QWS_H