src/gui/embedded/qwscommand_qws.cpp
changeset 0 1918ee327afb
child 4 3b1da2848fc7
equal deleted inserted replaced
-1:000000000000 0:1918ee327afb
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include "qwscommand_qws_p.h"
       
    43 #include "qtransportauth_qws.h"
       
    44 #include "qtransportauth_qws_p.h"
       
    45 
       
    46 #include <unistd.h>
       
    47 
       
    48 // #define QWSCOMMAND_DEBUG 1 // Uncomment to debug client/server communication
       
    49 
       
    50 #ifdef QWSCOMMAND_DEBUG
       
    51 # include <qdebug.h>
       
    52 # include "qfile.h"
       
    53 # include <ctype.h>
       
    54 #endif
       
    55 
       
    56 QT_BEGIN_NAMESPACE
       
    57 
       
    58 #ifdef QWSCOMMAND_DEBUG
       
    59 // QWSHexDump -[ start ]---------------------------------------------
       
    60 # define QWSHEXDUMP_MAX 32
       
    61 class QWSHexDump
       
    62 {
       
    63 public:
       
    64 
       
    65     QWSHexDump(const void *address, int len, int wrapAt = 16)
       
    66         : wrap(wrapAt), dataSize(len)
       
    67     {
       
    68         init();
       
    69         data = reinterpret_cast<const char*>(address);
       
    70         if (len < 0)
       
    71             dataSize = 0;
       
    72     }
       
    73 
       
    74     QWSHexDump(const char *str, int len = -1, int wrapAt = 16)
       
    75         : wrap(wrapAt), dataSize(len)
       
    76     {
       
    77         init();
       
    78         data = str;
       
    79         if (len == -1)
       
    80             dataSize = str ? strlen(str) : 0;
       
    81     }
       
    82 
       
    83     QWSHexDump(const QByteArray &array, int wrapAt = 16)
       
    84         : wrap(wrapAt)
       
    85     {
       
    86         init();
       
    87         data = array.data();
       
    88         dataSize = array.size();
       
    89     }
       
    90 
       
    91     // Sets a customized prefix for the hexdump
       
    92     void setPrefix(const char *str) { prefix = str; }
       
    93 
       
    94     // Sets number of bytes to cluster together
       
    95     void setClusterSize(uint num) { clustering = num; }
       
    96 
       
    97     // Output hexdump to a text stream
       
    98     void intoTextStream(QTextStream &strm) {
       
    99         outstrm = &strm;
       
   100         hexDump();
       
   101     }
       
   102 
       
   103     // Output hexdump to a QString
       
   104     QString toString();
       
   105 
       
   106 protected:
       
   107     void init();
       
   108     void hexDump();
       
   109     void sideviewDump(int at);
       
   110 
       
   111 private:
       
   112     uint wrap;
       
   113     uint clustering;
       
   114     uint dataSize;
       
   115     int dataWidth;
       
   116     const char *data;
       
   117     const char *prefix;
       
   118     bool dirty;
       
   119 
       
   120     char sideviewLayout[QWSHEXDUMP_MAX + 1];
       
   121     char sideview[15];
       
   122 
       
   123     QTextStream *outstrm;
       
   124 };
       
   125 
       
   126 void QWSHexDump::init()
       
   127 {
       
   128     prefix = "> ";             // Standard line prefix
       
   129     clustering = 2;            // Word-size clustering by default
       
   130     if (wrap > QWSHEXDUMP_MAX) // No wider than QWSHexDump_MAX bytes
       
   131         wrap = QWSHEXDUMP_MAX;
       
   132 }
       
   133 
       
   134 void QWSHexDump::hexDump()
       
   135 {
       
   136     *outstrm << '(' << dataSize << " bytes):\n" << prefix;
       
   137     sprintf(sideviewLayout, " [%%-%us]", wrap);
       
   138     dataWidth = (2 * wrap) + (wrap / clustering);
       
   139 
       
   140     dirty = false;
       
   141     uint wrapIndex = 0;
       
   142     for (uint i = 0; i < dataSize; i++) {
       
   143         uint c = static_cast<uchar>(data[i]);
       
   144         sideview[wrapIndex = i%wrap] = isprint(c) ? c : '.';
       
   145 
       
   146         if (wrapIndex && (wrapIndex % clustering == 0))
       
   147             *outstrm << ' ';
       
   148 
       
   149         outstrm->setFieldWidth(2);
       
   150         outstrm->setPadChar('0');
       
   151         outstrm->setNumberFlags( QTextStream::ShowBase );
       
   152         *outstrm << hex << c;
       
   153         dirty = true;
       
   154 
       
   155         if (wrapIndex == wrap-1) {
       
   156             sideviewDump(wrapIndex);
       
   157             wrapIndex = 0;
       
   158             if (i+1 < dataSize)
       
   159                 *outstrm << endl << prefix;
       
   160         }
       
   161 
       
   162     }
       
   163     sideviewDump(wrapIndex);
       
   164 }
       
   165 
       
   166 void QWSHexDump::sideviewDump(int at)
       
   167 {
       
   168     if (dirty) {
       
   169         dirty = false;
       
   170         ++at;
       
   171         sideview[at] = '\0';
       
   172         int currentWidth = (2 * at) + (at / clustering) - (at%clustering?0:1);
       
   173         int missing = qMax(dataWidth - currentWidth, 0);
       
   174         while (missing--)
       
   175             *outstrm << ' ';
       
   176 
       
   177         *outstrm << " [";
       
   178         outstrm->setPadChar(' ');
       
   179         outstrm->setFieldWidth(wrap);
       
   180         outstrm->setFieldAlignment( QTextStream::AlignLeft );
       
   181         *outstrm << sideview;
       
   182         *outstrm << ']';
       
   183     }
       
   184 }
       
   185 
       
   186 // Output hexdump to a QString
       
   187 QString QWSHexDump::toString() {
       
   188     QString result;
       
   189     QTextStream strm(&result, QFile::WriteOnly);
       
   190     outstrm = &strm;
       
   191     hexDump();
       
   192     return result;
       
   193 }
       
   194 
       
   195 #ifndef QT_NO_DEBUG
       
   196 QDebug &operator<<(QDebug &dbg, QWSHexDump *hd) {
       
   197     if (!hd)
       
   198         return dbg << "QWSHexDump(0x0)";
       
   199     QString result = hd->toString();
       
   200     dbg.nospace() << result;
       
   201     return dbg.space();
       
   202 }
       
   203 
       
   204 // GCC & Intel wont handle references here
       
   205 QDebug operator<<(QDebug dbg, QWSHexDump hd) {
       
   206     return dbg << &hd;
       
   207 }
       
   208 #endif
       
   209 // QWSHexDump -[ end ]-----------------------------------------------
       
   210 
       
   211 
       
   212 QDebug &operator<<(QDebug &dbg, QWSCommand::Type tp)
       
   213 {
       
   214     dbg << qws_getCommandTypeString( tp );
       
   215     return dbg;
       
   216 }
       
   217 
       
   218 #define N_EVENTS 19
       
   219 const char * eventNames[N_EVENTS] =  {
       
   220         "NoEvent",
       
   221         "Connected",
       
   222         "Mouse", "Focus", "Key",
       
   223         "Region",
       
   224         "Creation",
       
   225         "PropertyNotify",
       
   226         "PropertyReply",
       
   227         "SelectionClear",
       
   228         "SelectionRequest",
       
   229         "SelectionNotify",
       
   230         "MaxWindowRect",
       
   231         "QCopMessage",
       
   232         "WindowOperation",
       
   233         "IMEvent",
       
   234         "IMQuery",
       
   235         "IMInit",
       
   236         "Font"
       
   237     };
       
   238 
       
   239 class QWSServer;
       
   240 extern QWSServer *qwsServer;
       
   241 #endif
       
   242 
       
   243 const char *qws_getCommandTypeString( QWSCommand::Type tp )
       
   244 {
       
   245     const char *typeStr;
       
   246     switch(tp) {
       
   247         case QWSCommand::Create:
       
   248             typeStr = "Create";
       
   249             break;
       
   250         case QWSCommand::Shutdown:
       
   251             typeStr = "Shutdown";
       
   252             break;
       
   253         case QWSCommand::Region:
       
   254             typeStr = "Region";
       
   255             break;
       
   256         case QWSCommand::RegionMove:
       
   257             typeStr = "RegionMove";
       
   258             break;
       
   259         case QWSCommand::RegionDestroy:
       
   260             typeStr = "RegionDestroy";
       
   261             break;
       
   262         case QWSCommand::SetProperty:
       
   263             typeStr = "SetProperty";
       
   264             break;
       
   265         case QWSCommand::AddProperty:
       
   266             typeStr = "AddProperty";
       
   267             break;
       
   268         case QWSCommand::RemoveProperty:
       
   269             typeStr = "RemoveProperty";
       
   270             break;
       
   271         case QWSCommand::GetProperty:
       
   272             typeStr = "GetProperty";
       
   273             break;
       
   274         case QWSCommand::SetSelectionOwner:
       
   275             typeStr = "SetSelectionOwner";
       
   276             break;
       
   277         case QWSCommand::ConvertSelection:
       
   278             typeStr = "ConvertSelection";
       
   279             break;
       
   280         case QWSCommand::RequestFocus:
       
   281             typeStr = "RequestFocus";
       
   282             break;
       
   283         case QWSCommand::ChangeAltitude:
       
   284             typeStr = "ChangeAltitude";
       
   285             break;
       
   286         case QWSCommand::SetOpacity:
       
   287             typeStr = "SetOpacity";
       
   288             break;
       
   289         case QWSCommand::DefineCursor:
       
   290             typeStr = "DefineCursor";
       
   291             break;
       
   292         case QWSCommand::SelectCursor:
       
   293             typeStr = "SelectCursor";
       
   294             break;
       
   295         case QWSCommand::PositionCursor:
       
   296             typeStr = "PositionCursor";
       
   297             break;
       
   298         case QWSCommand::GrabMouse:
       
   299             typeStr = "GrabMouse";
       
   300             break;
       
   301         case QWSCommand::PlaySound:
       
   302             typeStr = "PlaySound";
       
   303             break;
       
   304         case QWSCommand::QCopRegisterChannel:
       
   305             typeStr = "QCopRegisterChannel";
       
   306             break;
       
   307         case QWSCommand::QCopSend:
       
   308             typeStr = "QCopSend";
       
   309             break;
       
   310         case QWSCommand::RegionName:
       
   311             typeStr = "RegionName";
       
   312             break;
       
   313         case QWSCommand::Identify:
       
   314             typeStr = "Identify";
       
   315             break;
       
   316         case QWSCommand::GrabKeyboard:
       
   317             typeStr = "GrabKeyboard";
       
   318             break;
       
   319         case QWSCommand::RepaintRegion:
       
   320             typeStr = "RepaintRegion";
       
   321             break;
       
   322         case QWSCommand::IMMouse:
       
   323             typeStr = "IMMouse";
       
   324             break;
       
   325         case QWSCommand::IMUpdate:
       
   326             typeStr = "IMUpdate";
       
   327             break;
       
   328         case QWSCommand::IMResponse:
       
   329             typeStr = "IMResponse";
       
   330             break;
       
   331         case QWSCommand::Font:
       
   332             typeStr = "Font";
       
   333             break;
       
   334         case QWSCommand::Unknown:
       
   335         default:
       
   336             typeStr = "Unknown";
       
   337             break;
       
   338     }
       
   339     return typeStr;
       
   340 }
       
   341 
       
   342 
       
   343 /*********************************************************************
       
   344  *
       
   345  * Functions to read/write commands on/from a socket
       
   346  *
       
   347  *********************************************************************/
       
   348 
       
   349 #ifndef QT_NO_QWS_MULTIPROCESS
       
   350 void qws_write_command(QIODevice *socket, int type, char *simpleData, int simpleLen,
       
   351                        char *rawData, int rawLen)
       
   352 {
       
   353 #ifdef QWSCOMMAND_DEBUG
       
   354     if (simpleLen) qDebug() << "WRITE simpleData " << QWSHexDump(simpleData, simpleLen);
       
   355     if (rawLen > 0) qDebug() << "WRITE rawData " << QWSHexDump(rawData, rawLen);
       
   356 #endif
       
   357 
       
   358 #ifndef QT_NO_SXE
       
   359     QTransportAuth *a = QTransportAuth::getInstance();
       
   360     // ###### as soon as public API can be modified get rid of horrible casts
       
   361     QIODevice *ad = a->passThroughByClient(reinterpret_cast<QWSClient*>(socket));
       
   362     if (ad)
       
   363         socket = ad;
       
   364 #endif
       
   365 
       
   366     qws_write_uint(socket, type);
       
   367 
       
   368     if (rawLen > MAX_COMMAND_SIZE) {
       
   369         qWarning("qws_write_command: Message of size %d too big. "
       
   370                  "Truncated to %d", rawLen, MAX_COMMAND_SIZE);
       
   371         rawLen = MAX_COMMAND_SIZE;
       
   372     }
       
   373 
       
   374     qws_write_uint(socket, rawLen == -1 ? 0 : rawLen);
       
   375 
       
   376     if (simpleData && simpleLen)
       
   377         socket->write(simpleData, simpleLen);
       
   378 
       
   379     if (rawLen && rawData)
       
   380         socket->write(rawData, rawLen);
       
   381 }
       
   382 
       
   383 /*
       
   384   command format: [type][rawLen][simpleData][rawData]
       
   385   type is already read when entering this function
       
   386 */
       
   387 
       
   388 bool qws_read_command(QIODevice *socket, char *&simpleData, int &simpleLen,
       
   389                       char *&rawData, int &rawLen, int &bytesRead)
       
   390 {
       
   391 
       
   392     // read rawLen
       
   393     if (rawLen == -1) {
       
   394         rawLen = qws_read_uint(socket);
       
   395         if (rawLen == -1)
       
   396             return false;
       
   397     }
       
   398 
       
   399     // read simpleData, assumes socket is capable of buffering all the data
       
   400     if (simpleLen && !rawData) {
       
   401         if (socket->bytesAvailable() < uint(simpleLen))
       
   402             return false;
       
   403         int tmp = socket->read(simpleData, simpleLen);
       
   404         Q_ASSERT(tmp == simpleLen);
       
   405         Q_UNUSED(tmp);
       
   406     }
       
   407 
       
   408     if (rawLen > MAX_COMMAND_SIZE) {
       
   409         socket->close();
       
   410         qWarning("qws_read_command: Won't read command of length %d, "
       
   411                  "connection closed.", rawLen);
       
   412         return false;
       
   413     }
       
   414 
       
   415     // read rawData
       
   416     if (rawLen && !rawData) {
       
   417         rawData = new char[rawLen];
       
   418         bytesRead = 0;
       
   419     }
       
   420     if (bytesRead < rawLen && socket->bytesAvailable())
       
   421         bytesRead += socket->read(rawData + bytesRead, rawLen - bytesRead);
       
   422 
       
   423     return (bytesRead == rawLen);
       
   424 }
       
   425 #endif
       
   426 
       
   427 /*********************************************************************
       
   428  *
       
   429  * QWSCommand base class - only use derived classes from that
       
   430  *
       
   431  *********************************************************************/
       
   432 QWSProtocolItem::~QWSProtocolItem() {
       
   433     if (deleteRaw)
       
   434         delete []rawDataPtr;
       
   435 }
       
   436 
       
   437 #ifndef QT_NO_QWS_MULTIPROCESS
       
   438 void QWSProtocolItem::write(QIODevice *s) {
       
   439 #ifdef QWSCOMMAND_DEBUG
       
   440     if (!qwsServer)
       
   441         qDebug() << "QWSProtocolItem::write sending type " << static_cast<QWSCommand::Type>(type);
       
   442     else
       
   443         qDebug() << "QWSProtocolItem::write sending event " << (type < N_EVENTS ? eventNames[type] : "unknown");
       
   444 #endif
       
   445     qws_write_command(s, type, simpleDataPtr, simpleLen, rawDataPtr, rawLen);
       
   446 }
       
   447 
       
   448 bool QWSProtocolItem::read(QIODevice *s) {
       
   449 #ifdef QWSCOMMAND_DEBUG
       
   450     QLatin1String reread( (rawLen == -1) ? "" : "REREAD");
       
   451     if (qwsServer)
       
   452         qDebug() << "QWSProtocolItem::read reading type " << static_cast<QWSCommand::Type>(type) << reread;
       
   453     else
       
   454         qDebug() << "QWSProtocolItem::read reading event " << (type < N_EVENTS ? eventNames[type] : "unknown") << reread;
       
   455     //qDebug("QWSProtocolItem::read reading event %s", type < N_EVENTS ? eventNames[type] : "unknown");
       
   456 #endif
       
   457     bool b = qws_read_command(s, simpleDataPtr, simpleLen, rawDataPtr, rawLen, bytesRead);
       
   458     if (b) {
       
   459         setData(rawDataPtr, rawLen, false);
       
   460         deleteRaw = true;
       
   461     }
       
   462 #ifdef QWSCOMMAND_DEBUG
       
   463     else
       
   464     {
       
   465         qDebug() << "error in reading command " << static_cast<QWSCommand::Type>(type);
       
   466     }
       
   467 #endif
       
   468     return b;
       
   469 }
       
   470 #endif // QT_NO_QWS_MULTIPROCESS
       
   471 
       
   472 void QWSProtocolItem::copyFrom(const QWSProtocolItem *item) {
       
   473     if (this == item)
       
   474         return;
       
   475     simpleLen = item->simpleLen;
       
   476     memcpy(simpleDataPtr, item->simpleDataPtr, simpleLen);
       
   477     setData(item->rawDataPtr, item->rawLen);
       
   478 }
       
   479 
       
   480 void QWSProtocolItem::setData(const char *data, int len, bool allocateMem) {
       
   481     if (deleteRaw)
       
   482         delete [] rawDataPtr;
       
   483     if (!data || len <= 0) {
       
   484         rawDataPtr = 0;
       
   485         rawLen = 0;
       
   486         return;
       
   487     }
       
   488     if (allocateMem) {
       
   489         rawDataPtr = new char[len];
       
   490         memcpy(rawDataPtr, data, len);
       
   491         deleteRaw = true;
       
   492     } else {
       
   493         rawDataPtr = const_cast<char *>(data);
       
   494         deleteRaw = false;
       
   495     }
       
   496     rawLen = len;
       
   497 }
       
   498 
       
   499 QWSCommand *QWSCommand::factory(int type)
       
   500 {
       
   501     QWSCommand *command = 0;
       
   502     switch (type) {
       
   503     case QWSCommand::Create:
       
   504         command = new QWSCreateCommand;
       
   505         break;
       
   506     case QWSCommand::Shutdown:
       
   507         command = new QWSCommand(type, 0, 0);
       
   508         break;
       
   509     case QWSCommand::Region:
       
   510         command = new QWSRegionCommand;
       
   511         break;
       
   512     case QWSCommand::RegionMove:
       
   513         command = new QWSRegionMoveCommand;
       
   514         break;
       
   515     case QWSCommand::RegionDestroy:
       
   516         command = new QWSRegionDestroyCommand;
       
   517         break;
       
   518     case QWSCommand::AddProperty:
       
   519         command = new QWSAddPropertyCommand;
       
   520         break;
       
   521     case QWSCommand::SetProperty:
       
   522         command = new QWSSetPropertyCommand;
       
   523         break;
       
   524     case QWSCommand::RemoveProperty:
       
   525         command = new QWSRemovePropertyCommand;
       
   526         break;
       
   527     case QWSCommand::GetProperty:
       
   528         command = new QWSGetPropertyCommand;
       
   529         break;
       
   530     case QWSCommand::SetSelectionOwner:
       
   531         command = new QWSSetSelectionOwnerCommand;
       
   532         break;
       
   533     case QWSCommand::RequestFocus:
       
   534         command = new QWSRequestFocusCommand;
       
   535         break;
       
   536     case QWSCommand::ChangeAltitude:
       
   537         command = new QWSChangeAltitudeCommand;
       
   538         break;
       
   539     case QWSCommand::SetOpacity:
       
   540         command = new QWSSetOpacityCommand;
       
   541         break;
       
   542     case QWSCommand::DefineCursor:
       
   543         command = new QWSDefineCursorCommand;
       
   544         break;
       
   545     case QWSCommand::SelectCursor:
       
   546         command = new QWSSelectCursorCommand;
       
   547         break;
       
   548     case QWSCommand::GrabMouse:
       
   549         command = new QWSGrabMouseCommand;
       
   550         break;
       
   551     case QWSCommand::GrabKeyboard:
       
   552         command = new QWSGrabKeyboardCommand;
       
   553         break;
       
   554 #ifndef QT_NO_SOUND
       
   555     case QWSCommand::PlaySound:
       
   556         command = new QWSPlaySoundCommand;
       
   557         break;
       
   558 #endif
       
   559 #ifndef QT_NO_COP
       
   560     case QWSCommand::QCopRegisterChannel:
       
   561         command = new QWSQCopRegisterChannelCommand;
       
   562         break;
       
   563     case QWSCommand::QCopSend:
       
   564         command = new QWSQCopSendCommand;
       
   565         break;
       
   566 #endif
       
   567     case QWSCommand::RegionName:
       
   568         command = new QWSRegionNameCommand;
       
   569         break;
       
   570     case QWSCommand::Identify:
       
   571         command = new QWSIdentifyCommand;
       
   572         break;
       
   573     case QWSCommand::RepaintRegion:
       
   574         command = new QWSRepaintRegionCommand;
       
   575         break;
       
   576 #ifndef QT_NO_QWS_INPUTMETHODS
       
   577     case QWSCommand::IMUpdate:
       
   578         command = new QWSIMUpdateCommand;
       
   579         break;
       
   580 
       
   581     case QWSCommand::IMMouse:
       
   582         command = new QWSIMMouseCommand;
       
   583         break;
       
   584 
       
   585     case QWSCommand::IMResponse:
       
   586         command = new QWSIMResponseCommand;
       
   587         break;
       
   588 #endif
       
   589     case QWSCommand::PositionCursor:
       
   590         command = new QWSPositionCursorCommand;
       
   591         break;
       
   592 #ifndef QT_NO_QWSEMBEDWIDGET
       
   593     case QWSCommand::Embed:
       
   594         command = new QWSEmbedCommand;
       
   595         break;
       
   596 #endif
       
   597     case QWSCommand::Font:
       
   598         command = new QWSFontCommand;
       
   599         break;
       
   600     case QWSCommand::ScreenTransform:
       
   601         command = new QWSScreenTransformCommand;
       
   602         break;
       
   603     default:
       
   604         qWarning("QWSCommand::factory : Type error - got %08x!", type);
       
   605     }
       
   606     return command;
       
   607 }
       
   608 
       
   609 QT_END_NAMESPACE