diff options
author | Lars Knoll <lars.knoll@nokia.com> | 2009-03-23 09:18:55 (GMT) |
---|---|---|
committer | Simon Hausmann <simon.hausmann@nokia.com> | 2009-03-23 09:18:55 (GMT) |
commit | e5fcad302d86d316390c6b0f62759a067313e8a9 (patch) | |
tree | c2afbf6f1066b6ce261f14341cf6d310e5595bc1 /src/gui/embedded/qwscommand_qws.cpp | |
download | Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.zip Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.gz Qt-e5fcad302d86d316390c6b0f62759a067313e8a9.tar.bz2 |
Long live Qt 4.5!
Diffstat (limited to 'src/gui/embedded/qwscommand_qws.cpp')
-rw-r--r-- | src/gui/embedded/qwscommand_qws.cpp | 610 |
1 files changed, 610 insertions, 0 deletions
diff --git a/src/gui/embedded/qwscommand_qws.cpp b/src/gui/embedded/qwscommand_qws.cpp new file mode 100644 index 0000000..88e33a3 --- /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 |