src/plugins/gfxdrivers/vnc/qscreenvnc_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 plugins 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 "qscreenvnc_qws.h"
       
    43 
       
    44 #ifndef QT_NO_QWS_VNC
       
    45 
       
    46 #include "qscreenvnc_p.h"
       
    47 #include "qwindowsystem_qws.h"
       
    48 #include "qwsdisplay_qws.h"
       
    49 #include "qscreendriverfactory_qws.h"
       
    50 #include <QtCore/qtimer.h>
       
    51 #include <QtCore/qregexp.h>
       
    52 #include <QtGui/qwidget.h>
       
    53 #include <QtGui/qpolygon.h>
       
    54 #include <QtGui/qpainter.h>
       
    55 #include <qdebug.h>
       
    56 #include <private/qwindowsurface_qws_p.h>
       
    57 #include <private/qwssignalhandler_p.h>
       
    58 #include <private/qwidget_p.h>
       
    59 #include <private/qdrawhelper_p.h>
       
    60 
       
    61 #include <stdlib.h>
       
    62 
       
    63 QT_BEGIN_NAMESPACE
       
    64 
       
    65 //#define QT_QWS_VNC_DEBUG
       
    66 
       
    67 extern QString qws_qtePipeFilename();
       
    68 
       
    69 #ifndef QT_NO_QWS_CURSOR
       
    70 
       
    71 QVNCCursor::QVNCCursor(QVNCScreen *s)
       
    72     : screen(s)
       
    73 {
       
    74     if (qt_screencursor)
       
    75         setScreenCursor(qt_screencursor);
       
    76     else
       
    77         hwaccel = true;
       
    78 }
       
    79 
       
    80 QVNCCursor::~QVNCCursor()
       
    81 {
       
    82     if (screenCursor())
       
    83         qt_screencursor = screenCursor();
       
    84 }
       
    85 
       
    86 void QVNCCursor::setDirty(const QRect &r) const
       
    87 {
       
    88     screen->d_ptr->setDirty(r, true);
       
    89 }
       
    90 
       
    91 void QVNCCursor::hide()
       
    92 {
       
    93     QProxyScreenCursor::hide();
       
    94     if (enable)
       
    95         setDirty(boundingRect());
       
    96 }
       
    97 
       
    98 void QVNCCursor::show()
       
    99 {
       
   100     QProxyScreenCursor::show();
       
   101     if (enable)
       
   102         setDirty(boundingRect());
       
   103 }
       
   104 
       
   105 void QVNCCursor::set(const QImage &image, int hotx, int hoty)
       
   106 {
       
   107     QRegion dirty = boundingRect();
       
   108     QProxyScreenCursor::set(image, hotx, hoty);
       
   109     dirty |= boundingRect();
       
   110     if (enable && hwaccel && !screen->d_ptr->vncServer->hasClientCursor()) {
       
   111         const QVector<QRect> rects = dirty.rects();
       
   112         for (int i = 0; i < rects.size(); ++i)
       
   113             setDirty(rects.at(i));
       
   114     }
       
   115 }
       
   116 
       
   117 void QVNCCursor::move(int x, int y)
       
   118 {
       
   119     if (enable && hwaccel && !screen->d_ptr->vncServer->hasClientCursor()) {
       
   120         QRegion dirty = boundingRect();
       
   121         QProxyScreenCursor::move(x, y);
       
   122         dirty |= boundingRect();
       
   123         if (enable) {
       
   124             const QVector<QRect> rects = dirty.rects();
       
   125             for (int i = 0; i < rects.size(); ++i)
       
   126                 setDirty(rects.at(i));
       
   127         }
       
   128     } else {
       
   129         QProxyScreenCursor::move(x, y);
       
   130     }
       
   131 }
       
   132 
       
   133 QVNCClientCursor::QVNCClientCursor(QVNCServer *s)
       
   134     : server(s)
       
   135 {
       
   136     setScreenCursor(qt_screencursor);
       
   137     Q_ASSERT(hwaccel);
       
   138     qt_screencursor = this; // hw: XXX
       
   139 
       
   140     set(image(), hotspot.x(), hotspot.y());
       
   141 }
       
   142 
       
   143 QVNCClientCursor::~QVNCClientCursor()
       
   144 {
       
   145     qt_screencursor = screenCursor();
       
   146 }
       
   147 
       
   148 void QVNCClientCursor::set(const QImage &image, int hotx, int hoty)
       
   149 {
       
   150     QScreenCursor::set(image, hotx, hoty);
       
   151     server->setDirtyCursor();
       
   152 }
       
   153 
       
   154 void QVNCClientCursor::write() const
       
   155 {
       
   156     QTcpSocket *socket = server->clientSocket();
       
   157 
       
   158     // FramebufferUpdate header
       
   159     {
       
   160         const quint16 tmp[6] = { htons(0),
       
   161                                  htons(1),
       
   162                                  htons(hotspot.x()), htons(hotspot.y()),
       
   163                                  htons(cursor.width()),
       
   164                                  htons(cursor.height()) };
       
   165         socket->write((char*)tmp, sizeof(tmp));
       
   166 
       
   167         const quint32 encoding = htonl(-239);
       
   168         socket->write((char*)(&encoding), sizeof(encoding));
       
   169     }
       
   170 
       
   171     if (cursor.isNull())
       
   172         return;
       
   173 
       
   174     // write pixels
       
   175     Q_ASSERT(cursor.hasAlphaChannel());
       
   176     const QImage img = cursor.convertToFormat(server->screen()->pixelFormat());
       
   177     const int n = server->clientBytesPerPixel() * img.width();
       
   178     char *buffer = new char[n];
       
   179     for (int i = 0; i < img.height(); ++i) {
       
   180         server->convertPixels(buffer, (const char*)img.scanLine(i), img.width());
       
   181         socket->write(buffer, n);
       
   182     }
       
   183     delete[] buffer;
       
   184 
       
   185     // write mask
       
   186     const QImage bitmap = cursor.createAlphaMask().convertToFormat(QImage::Format_Mono);
       
   187     Q_ASSERT(bitmap.depth() == 1);
       
   188     Q_ASSERT(bitmap.size() == img.size());
       
   189     const int width = (bitmap.width() + 7) / 8;
       
   190     for (int i = 0; i < bitmap.height(); ++i)
       
   191         socket->write((const char*)bitmap.scanLine(i), width);
       
   192 }
       
   193 
       
   194 #endif // QT_NO_QWS_CURSOR
       
   195 
       
   196 QVNCScreenPrivate::QVNCScreenPrivate(QVNCScreen *parent)
       
   197     : dpiX(72), dpiY(72), doOnScreenSurface(false), refreshRate(25),
       
   198       vncServer(0), q_ptr(parent), noDisablePainting(false)
       
   199 {
       
   200 #ifdef QT_BUILD_INTERNAL
       
   201     noDisablePainting = (qgetenv("QT_VNC_NO_DISABLEPAINTING").toInt() > 0);
       
   202 #endif
       
   203 #ifndef QT_NO_QWS_SIGNALHANDLER
       
   204     QWSSignalHandler::instance()->addObject(this);
       
   205 #endif
       
   206 }
       
   207 
       
   208 QVNCScreenPrivate::~QVNCScreenPrivate()
       
   209 {
       
   210 #if defined(QT_NO_QWS_MULTIPROCESS) || defined(QT_NO_SHAREDMEMORY)
       
   211     if (q_ptr->screen())
       
   212         return;
       
   213 
       
   214     delete[] q_ptr->data;
       
   215     q_ptr->data = 0;
       
   216 #else
       
   217     shm.detach();
       
   218 #endif
       
   219 }
       
   220 
       
   221 void QVNCScreenPrivate::configure()
       
   222 {
       
   223     if (q_ptr->screen())
       
   224         return;
       
   225 
       
   226     q_ptr->lstep = q_ptr->dw * ((q_ptr->d + 7) / 8);
       
   227     q_ptr->size = q_ptr->h * q_ptr->lstep;
       
   228     q_ptr->mapsize = q_ptr->size;
       
   229     q_ptr->physWidth = qRound(q_ptr->dw * qreal(25.4) / dpiX);
       
   230     q_ptr->physHeight = qRound(q_ptr->dh * qreal(25.4) / dpiY);
       
   231 
       
   232     switch (q_ptr->d) {
       
   233     case 1:
       
   234         q_ptr->setPixelFormat(QImage::Format_Mono); //### LSB???
       
   235         break;
       
   236     case 8:
       
   237         q_ptr->setPixelFormat(QImage::Format_Indexed8);
       
   238         break;
       
   239     case 12:
       
   240         q_ptr->setPixelFormat(QImage::Format_RGB444);
       
   241         break;
       
   242     case 15:
       
   243         q_ptr->setPixelFormat(QImage::Format_RGB555);
       
   244         break;
       
   245     case 16:
       
   246         q_ptr->setPixelFormat(QImage::Format_RGB16);
       
   247         break;
       
   248     case 18:
       
   249         q_ptr->setPixelFormat(QImage::Format_RGB666);
       
   250         break;
       
   251     case 24:
       
   252         q_ptr->setPixelFormat(QImage::Format_RGB888);
       
   253         break;
       
   254     case 32:
       
   255         q_ptr->setPixelFormat(QImage::Format_ARGB32_Premultiplied);
       
   256         break;
       
   257     }
       
   258 
       
   259 #if !defined(QT_NO_QWS_MULTIPROCESS) && !defined(QT_NO_SHAREDMEMORY)
       
   260     if (q_ptr->size != shm.size()) {
       
   261         shm.detach();
       
   262         const QString key = qws_qtePipeFilename() +
       
   263                             QString().sprintf("_vnc_%d_%d",
       
   264                                               q_ptr->displayId, q_ptr->size);
       
   265         shm.setKey(key);
       
   266         if (QApplication::type() == QApplication::GuiServer) {
       
   267             if (!shm.create(q_ptr->size)) {
       
   268                 qWarning() << "QVNCScreen could not create shared memory:"
       
   269                            << shm.errorString();
       
   270                 if (!shm.attach()) {
       
   271                     qWarning() << "QVNCScreen could not attach to shared memory:"
       
   272                                << shm.errorString();
       
   273                 }
       
   274             }
       
   275         } else if (!shm.attach()) {
       
   276             qWarning() << "QVNCScreen could not attach to shared memory:"
       
   277                        << shm.errorString();
       
   278         }
       
   279         q_ptr->data = reinterpret_cast<uchar*>(shm.data());
       
   280     }
       
   281 #else
       
   282     if (q_ptr->data)
       
   283         delete[] q_ptr->data;
       
   284     q_ptr->data = new uchar[q_ptr->size];
       
   285 #endif
       
   286 }
       
   287 
       
   288 //===========================================================================
       
   289 
       
   290 static const struct {
       
   291     int keysym;
       
   292     int keycode;
       
   293 } keyMap[] = {
       
   294     { 0xff08, Qt::Key_Backspace },
       
   295     { 0xff09, Qt::Key_Tab       },
       
   296     { 0xff0d, Qt::Key_Return    },
       
   297     { 0xff1b, Qt::Key_Escape    },
       
   298     { 0xff63, Qt::Key_Insert    },
       
   299     { 0xffff, Qt::Key_Delete    },
       
   300     { 0xff50, Qt::Key_Home      },
       
   301     { 0xff57, Qt::Key_End       },
       
   302     { 0xff55, Qt::Key_PageUp    },
       
   303     { 0xff56, Qt::Key_PageDown  },
       
   304     { 0xff51, Qt::Key_Left      },
       
   305     { 0xff52, Qt::Key_Up        },
       
   306     { 0xff53, Qt::Key_Right     },
       
   307     { 0xff54, Qt::Key_Down      },
       
   308     { 0xffbe, Qt::Key_F1        },
       
   309     { 0xffbf, Qt::Key_F2        },
       
   310     { 0xffc0, Qt::Key_F3        },
       
   311     { 0xffc1, Qt::Key_F4        },
       
   312     { 0xffc2, Qt::Key_F5        },
       
   313     { 0xffc3, Qt::Key_F6        },
       
   314     { 0xffc4, Qt::Key_F7        },
       
   315     { 0xffc5, Qt::Key_F8        },
       
   316     { 0xffc6, Qt::Key_F9        },
       
   317     { 0xffc7, Qt::Key_F10       },
       
   318     { 0xffc8, Qt::Key_F11       },
       
   319     { 0xffc9, Qt::Key_F12       },
       
   320     { 0xffe1, Qt::Key_Shift     },
       
   321     { 0xffe2, Qt::Key_Shift     },
       
   322     { 0xffe3, Qt::Key_Control   },
       
   323     { 0xffe4, Qt::Key_Control   },
       
   324     { 0xffe7, Qt::Key_Meta      },
       
   325     { 0xffe8, Qt::Key_Meta      },
       
   326     { 0xffe9, Qt::Key_Alt       },
       
   327     { 0xffea, Qt::Key_Alt       },
       
   328     { 0, 0 }
       
   329 };
       
   330 
       
   331 void QRfbRect::read(QTcpSocket *s)
       
   332 {
       
   333     quint16 buf[4];
       
   334     s->read((char*)buf, 8);
       
   335     x = ntohs(buf[0]);
       
   336     y = ntohs(buf[1]);
       
   337     w = ntohs(buf[2]);
       
   338     h = ntohs(buf[3]);
       
   339 }
       
   340 
       
   341 void QRfbRect::write(QTcpSocket *s) const
       
   342 {
       
   343     quint16 buf[4];
       
   344     buf[0] = htons(x);
       
   345     buf[1] = htons(y);
       
   346     buf[2] = htons(w);
       
   347     buf[3] = htons(h);
       
   348     s->write((char*)buf, 8);
       
   349 }
       
   350 
       
   351 void QRfbPixelFormat::read(QTcpSocket *s)
       
   352 {
       
   353     char buf[16];
       
   354     s->read(buf, 16);
       
   355     bitsPerPixel = buf[0];
       
   356     depth = buf[1];
       
   357     bigEndian = buf[2];
       
   358     trueColor = buf[3];
       
   359 
       
   360     quint16 a = ntohs(*(quint16 *)(buf + 4));
       
   361     redBits = 0;
       
   362     while (a) { a >>= 1; redBits++; }
       
   363 
       
   364     a = ntohs(*(quint16 *)(buf + 6));
       
   365     greenBits = 0;
       
   366     while (a) { a >>= 1; greenBits++; }
       
   367 
       
   368     a = ntohs(*(quint16 *)(buf + 8));
       
   369     blueBits = 0;
       
   370     while (a) { a >>= 1; blueBits++; }
       
   371 
       
   372     redShift = buf[10];
       
   373     greenShift = buf[11];
       
   374     blueShift = buf[12];
       
   375 }
       
   376 
       
   377 void QRfbPixelFormat::write(QTcpSocket *s)
       
   378 {
       
   379     char buf[16];
       
   380     buf[0] = bitsPerPixel;
       
   381     buf[1] = depth;
       
   382     buf[2] = bigEndian;
       
   383     buf[3] = trueColor;
       
   384 
       
   385     quint16 a = 0;
       
   386     for (int i = 0; i < redBits; i++) a = (a << 1) | 1;
       
   387     *(quint16 *)(buf + 4) = htons(a);
       
   388 
       
   389     a = 0;
       
   390     for (int i = 0; i < greenBits; i++) a = (a << 1) | 1;
       
   391     *(quint16 *)(buf + 6) = htons(a);
       
   392 
       
   393     a = 0;
       
   394     for (int i = 0; i < blueBits; i++) a = (a << 1) | 1;
       
   395     *(quint16 *)(buf + 8) = htons(a);
       
   396 
       
   397     buf[10] = redShift;
       
   398     buf[11] = greenShift;
       
   399     buf[12] = blueShift;
       
   400     s->write(buf, 16);
       
   401 }
       
   402 
       
   403 
       
   404 void QRfbServerInit::setName(const char *n)
       
   405 {
       
   406     delete[] name;
       
   407     name = new char [strlen(n) + 1];
       
   408     strcpy(name, n);
       
   409 }
       
   410 
       
   411 void QRfbServerInit::read(QTcpSocket *s)
       
   412 {
       
   413     s->read((char *)&width, 2);
       
   414     width = ntohs(width);
       
   415     s->read((char *)&height, 2);
       
   416     height = ntohs(height);
       
   417     format.read(s);
       
   418 
       
   419     quint32 len;
       
   420     s->read((char *)&len, 4);
       
   421     len = ntohl(len);
       
   422 
       
   423     name = new char [len + 1];
       
   424     s->read(name, len);
       
   425     name[len] = '\0';
       
   426 }
       
   427 
       
   428 void QRfbServerInit::write(QTcpSocket *s)
       
   429 {
       
   430     quint16 t = htons(width);
       
   431     s->write((char *)&t, 2);
       
   432     t = htons(height);
       
   433     s->write((char *)&t, 2);
       
   434     format.write(s);
       
   435     quint32 len = strlen(name);
       
   436     len = htonl(len);
       
   437     s->write((char *)&len, 4);
       
   438     s->write(name, strlen(name));
       
   439 }
       
   440 
       
   441 bool QRfbSetEncodings::read(QTcpSocket *s)
       
   442 {
       
   443     if (s->bytesAvailable() < 3)
       
   444         return false;
       
   445 
       
   446     char tmp;
       
   447     s->read(&tmp, 1);        // padding
       
   448     s->read((char *)&count, 2);
       
   449     count = ntohs(count);
       
   450 
       
   451     return true;
       
   452 }
       
   453 
       
   454 bool QRfbFrameBufferUpdateRequest::read(QTcpSocket *s)
       
   455 {
       
   456     if (s->bytesAvailable() < 9)
       
   457         return false;
       
   458 
       
   459     s->read(&incremental, 1);
       
   460     rect.read(s);
       
   461 
       
   462     return true;
       
   463 }
       
   464 
       
   465 bool QRfbKeyEvent::read(QTcpSocket *s)
       
   466 {
       
   467     if (s->bytesAvailable() < 7)
       
   468         return false;
       
   469 
       
   470     s->read(&down, 1);
       
   471     quint16 tmp;
       
   472     s->read((char *)&tmp, 2);  // padding
       
   473 
       
   474     quint32 key;
       
   475     s->read((char *)&key, 4);
       
   476     key = ntohl(key);
       
   477 
       
   478     unicode = 0;
       
   479     keycode = 0;
       
   480     int i = 0;
       
   481     while (keyMap[i].keysym && !keycode) {
       
   482         if (keyMap[i].keysym == (int)key)
       
   483             keycode = keyMap[i].keycode;
       
   484         i++;
       
   485     }
       
   486     if (!keycode) {
       
   487         if (key <= 0xff) {
       
   488             unicode = key;
       
   489             if (key >= 'a' && key <= 'z')
       
   490                 keycode = Qt::Key_A + key - 'a';
       
   491             else if (key >= ' ' && key <= '~')
       
   492                 keycode = Qt::Key_Space + key - ' ';
       
   493         }
       
   494     }
       
   495 
       
   496     return true;
       
   497 }
       
   498 
       
   499 bool QRfbPointerEvent::read(QTcpSocket *s)
       
   500 {
       
   501     if (s->bytesAvailable() < 5)
       
   502         return false;
       
   503 
       
   504     char buttonMask;
       
   505     s->read(&buttonMask, 1);
       
   506     buttons = 0;
       
   507     if (buttonMask & 1)
       
   508         buttons |= Qt::LeftButton;
       
   509     if (buttonMask & 2)
       
   510         buttons |= Qt::MidButton;
       
   511     if (buttonMask & 4)
       
   512         buttons |= Qt::RightButton;
       
   513 
       
   514     quint16 tmp;
       
   515     s->read((char *)&tmp, 2);
       
   516     x = ntohs(tmp);
       
   517     s->read((char *)&tmp, 2);
       
   518     y = ntohs(tmp);
       
   519 
       
   520     return true;
       
   521 }
       
   522 
       
   523 bool QRfbClientCutText::read(QTcpSocket *s)
       
   524 {
       
   525     if (s->bytesAvailable() < 7)
       
   526         return false;
       
   527 
       
   528     char tmp[3];
       
   529     s->read(tmp, 3);        // padding
       
   530     s->read((char *)&length, 4);
       
   531     length = ntohl(length);
       
   532 
       
   533     return true;
       
   534 }
       
   535 
       
   536 //===========================================================================
       
   537 
       
   538 QVNCServer::QVNCServer(QVNCScreen *screen)
       
   539     : qvnc_screen(screen)
       
   540 {
       
   541     init(5900);
       
   542 }
       
   543 
       
   544 QVNCServer::QVNCServer(QVNCScreen *screen, int id)
       
   545     : qvnc_screen(screen)
       
   546 {
       
   547     init(5900 + id);
       
   548 }
       
   549 
       
   550 void QVNCServer::init(uint port)
       
   551 {
       
   552     handleMsg = false;
       
   553     client = 0;
       
   554     encodingsPending = 0;
       
   555     cutTextPending = 0;
       
   556     keymod = 0;
       
   557     state = Unconnected;
       
   558     dirtyCursor = false;
       
   559 
       
   560     refreshRate = 25;
       
   561     timer = new QTimer(this);
       
   562     timer->setSingleShot(true);
       
   563     connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate()));
       
   564 
       
   565     serverSocket = new QTcpServer(this);
       
   566     if (!serverSocket->listen(QHostAddress::Any, port))
       
   567         qDebug() << "QVNCServer could not connect:" << serverSocket->errorString();
       
   568     else
       
   569         qDebug("QVNCServer created on port %d", port);
       
   570 
       
   571     connect(serverSocket, SIGNAL(newConnection()), this, SLOT(newConnection()));
       
   572 
       
   573 #ifndef QT_NO_QWS_CURSOR
       
   574     qvnc_cursor = 0;
       
   575 #endif
       
   576     encoder = 0;
       
   577 }
       
   578 
       
   579 QVNCServer::~QVNCServer()
       
   580 {
       
   581     delete encoder;
       
   582     encoder = 0;
       
   583     delete client;
       
   584     client = 0;
       
   585 #ifndef QT_NO_QWS_CURSOR
       
   586     delete qvnc_cursor;
       
   587     qvnc_cursor = 0;
       
   588 #endif
       
   589 }
       
   590 
       
   591 void QVNCServer::setDirty()
       
   592 {
       
   593     if (state == Connected && !timer->isActive() &&
       
   594         ((dirtyMap()->numDirty > 0) || dirtyCursor)) {
       
   595         timer->start();
       
   596     }
       
   597 }
       
   598 
       
   599 void QVNCServer::newConnection()
       
   600 {
       
   601     if (client)
       
   602         delete client;
       
   603 
       
   604     client = serverSocket->nextPendingConnection();
       
   605     connect(client,SIGNAL(readyRead()),this,SLOT(readClient()));
       
   606     connect(client,SIGNAL(disconnected()),this,SLOT(discardClient()));
       
   607     handleMsg = false;
       
   608     encodingsPending = 0;
       
   609     cutTextPending = 0;
       
   610     supportHextile = false;
       
   611     wantUpdate = false;
       
   612 
       
   613     timer->start(1000 / refreshRate);
       
   614     dirtyMap()->reset();
       
   615 
       
   616     // send protocol version
       
   617     const char *proto = "RFB 003.003\n";
       
   618     client->write(proto, 12);
       
   619     state = Protocol;
       
   620 
       
   621     if (!qvnc_screen->screen() && !qvnc_screen->d_ptr->noDisablePainting)
       
   622         QWSServer::instance()->enablePainting(true);
       
   623 }
       
   624 
       
   625 void QVNCServer::readClient()
       
   626 {
       
   627     switch (state) {
       
   628         case Protocol:
       
   629             if (client->bytesAvailable() >= 12) {
       
   630                 char proto[13];
       
   631                 client->read(proto, 12);
       
   632                 proto[12] = '\0';
       
   633                 qDebug("Client protocol version %s", proto);
       
   634                 // No authentication
       
   635                 quint32 auth = htonl(1);
       
   636                 client->write((char *) &auth, sizeof(auth));
       
   637                 state = Init;
       
   638             }
       
   639             break;
       
   640 
       
   641         case Init:
       
   642             if (client->bytesAvailable() >= 1) {
       
   643                 quint8 shared;
       
   644                 client->read((char *) &shared, 1);
       
   645 
       
   646                 // Server Init msg
       
   647                 QRfbServerInit sim;
       
   648                 QRfbPixelFormat &format = sim.format;
       
   649                 switch (qvnc_screen->depth()) {
       
   650                 case 32:
       
   651                     format.bitsPerPixel = 32;
       
   652                     format.depth = 32;
       
   653                     format.bigEndian = 0;
       
   654                     format.trueColor = true;
       
   655                     format.redBits = 8;
       
   656                     format.greenBits = 8;
       
   657                     format.blueBits = 8;
       
   658                     format.redShift = 16;
       
   659                     format.greenShift = 8;
       
   660                     format.blueShift = 0;
       
   661                     break;
       
   662 
       
   663                 case 24:
       
   664                     format.bitsPerPixel = 24;
       
   665                     format.depth = 24;
       
   666                     format.bigEndian = 0;
       
   667                     format.trueColor = true;
       
   668                     format.redBits = 8;
       
   669                     format.greenBits = 8;
       
   670                     format.blueBits = 8;
       
   671                     format.redShift = 16;
       
   672                     format.greenShift = 8;
       
   673                     format.blueShift = 0;
       
   674                     break;
       
   675 
       
   676                 case 18:
       
   677                     format.bitsPerPixel = 24;
       
   678                     format.depth = 18;
       
   679                     format.bigEndian = 0;
       
   680                     format.trueColor = true;
       
   681                     format.redBits = 6;
       
   682                     format.greenBits = 6;
       
   683                     format.blueBits = 6;
       
   684                     format.redShift = 12;
       
   685                     format.greenShift = 6;
       
   686                     format.blueShift = 0;
       
   687                     break;
       
   688 
       
   689                 case 16:
       
   690                     format.bitsPerPixel = 16;
       
   691                     format.depth = 16;
       
   692                     format.bigEndian = 0;
       
   693                     format.trueColor = true;
       
   694                     format.redBits = 5;
       
   695                     format.greenBits = 6;
       
   696                     format.blueBits = 5;
       
   697                     format.redShift = 11;
       
   698                     format.greenShift = 5;
       
   699                     format.blueShift = 0;
       
   700                     break;
       
   701 
       
   702                 case 15:
       
   703                     format.bitsPerPixel = 16;
       
   704                     format.depth = 15;
       
   705                     format.bigEndian = 0;
       
   706                     format.trueColor = true;
       
   707                     format.redBits = 5;
       
   708                     format.greenBits = 5;
       
   709                     format.blueBits = 5;
       
   710                     format.redShift = 10;
       
   711                     format.greenShift = 5;
       
   712                     format.blueShift = 0;
       
   713                     break;
       
   714 
       
   715                 case 12:
       
   716                     format.bitsPerPixel = 16;
       
   717                     format.depth = 12;
       
   718                     format.bigEndian = 0;
       
   719                     format.trueColor = true;
       
   720                     format.redBits = 4;
       
   721                     format.greenBits = 4;
       
   722                     format.blueBits = 4;
       
   723                     format.redShift = 8;
       
   724                     format.greenShift = 4;
       
   725                     format.blueShift = 0;
       
   726                     break;
       
   727 
       
   728                 case 8:
       
   729                 case 4:
       
   730                     format.bitsPerPixel = 8;
       
   731                     format.depth = 8;
       
   732                     format.bigEndian = 0;
       
   733                     format.trueColor = false;
       
   734                     format.redBits = 0;
       
   735                     format.greenBits = 0;
       
   736                     format.blueBits = 0;
       
   737                     format.redShift = 0;
       
   738                     format.greenShift = 0;
       
   739                     format.blueShift = 0;
       
   740                     break;
       
   741 
       
   742                 default:
       
   743                     qDebug("QVNC cannot drive depth %d", qvnc_screen->depth());
       
   744                     discardClient();
       
   745                     return;
       
   746                 }
       
   747                 sim.width = qvnc_screen->deviceWidth();
       
   748                 sim.height = qvnc_screen->deviceHeight();
       
   749                 sim.setName("Qt for Embedded Linux VNC Server");
       
   750                 sim.write(client);
       
   751                 state = Connected;
       
   752             }
       
   753             break;
       
   754 
       
   755         case Connected:
       
   756             do {
       
   757                 if (!handleMsg) {
       
   758                     client->read((char *)&msgType, 1);
       
   759                     handleMsg = true;
       
   760                 }
       
   761                 if (handleMsg) {
       
   762                     switch (msgType ) {
       
   763                     case SetPixelFormat:
       
   764                         setPixelFormat();
       
   765                         break;
       
   766                     case FixColourMapEntries:
       
   767                         qDebug("Not supported: FixColourMapEntries");
       
   768                         handleMsg = false;
       
   769                         break;
       
   770                     case SetEncodings:
       
   771                         setEncodings();
       
   772                         break;
       
   773                     case FramebufferUpdateRequest:
       
   774                         frameBufferUpdateRequest();
       
   775                         break;
       
   776                     case KeyEvent:
       
   777                         keyEvent();
       
   778                         break;
       
   779                     case PointerEvent:
       
   780                         pointerEvent();
       
   781                         break;
       
   782                     case ClientCutText:
       
   783                         clientCutText();
       
   784                         break;
       
   785                     default:
       
   786                         qDebug("Unknown message type: %d", (int)msgType);
       
   787                         handleMsg = false;
       
   788                     }
       
   789                 }
       
   790             } while (!handleMsg && client->bytesAvailable());
       
   791             break;
       
   792     default:
       
   793         break;
       
   794     }
       
   795 }
       
   796 
       
   797 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
       
   798 bool QVNCScreen::swapBytes() const
       
   799 {
       
   800     if (depth() != 16)
       
   801         return false;
       
   802 
       
   803     if (screen())
       
   804         return screen()->frameBufferLittleEndian();
       
   805     return frameBufferLittleEndian();
       
   806 }
       
   807 #endif
       
   808 
       
   809 void QVNCServer::setPixelFormat()
       
   810 {
       
   811     if (client->bytesAvailable() >= 19) {
       
   812         char buf[3];
       
   813         client->read(buf, 3); // just padding
       
   814         pixelFormat.read(client);
       
   815 #ifdef QT_QWS_VNC_DEBUG
       
   816         qDebug("Want format: %d %d %d %d %d %d %d %d %d %d",
       
   817             int(pixelFormat.bitsPerPixel),
       
   818             int(pixelFormat.depth),
       
   819             int(pixelFormat.bigEndian),
       
   820             int(pixelFormat.trueColor),
       
   821             int(pixelFormat.redBits),
       
   822             int(pixelFormat.greenBits),
       
   823             int(pixelFormat.blueBits),
       
   824             int(pixelFormat.redShift),
       
   825             int(pixelFormat.greenShift),
       
   826             int(pixelFormat.blueShift));
       
   827 #endif
       
   828         if (!pixelFormat.trueColor) {
       
   829             qDebug("Can only handle true color clients");
       
   830             discardClient();
       
   831         }
       
   832         handleMsg = false;
       
   833         sameEndian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) == !!pixelFormat.bigEndian;
       
   834         needConversion = pixelConversionNeeded();
       
   835 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
       
   836         swapBytes = qvnc_screen->swapBytes();
       
   837 #endif
       
   838     }
       
   839 }
       
   840 
       
   841 void QVNCServer::setEncodings()
       
   842 {
       
   843     QRfbSetEncodings enc;
       
   844 
       
   845     if (!encodingsPending && enc.read(client)) {
       
   846         encodingsPending = enc.count;
       
   847         if (!encodingsPending)
       
   848             handleMsg = false;
       
   849     }
       
   850 
       
   851     if (encoder) {
       
   852         delete encoder;
       
   853         encoder = 0;
       
   854     }
       
   855 
       
   856     enum Encodings {
       
   857         Raw = 0,
       
   858         CopyRect = 1,
       
   859         RRE = 2,
       
   860         CoRRE = 4,
       
   861         Hextile = 5,
       
   862         ZRLE = 16,
       
   863         Cursor = -239,
       
   864         DesktopSize = -223
       
   865     };
       
   866 
       
   867     if (encodingsPending && (unsigned)client->bytesAvailable() >=
       
   868                                 encodingsPending * sizeof(quint32)) {
       
   869         for (int i = 0; i < encodingsPending; ++i) {
       
   870             qint32 enc;
       
   871             client->read((char *)&enc, sizeof(qint32));
       
   872             enc = ntohl(enc);
       
   873 #ifdef QT_QWS_VNC_DEBUG
       
   874             qDebug("QVNCServer::setEncodings: %d", enc);
       
   875 #endif
       
   876             switch (enc) {
       
   877             case Raw:
       
   878                 if (!encoder) {
       
   879                     encoder = new QRfbRawEncoder(this);
       
   880 #ifdef QT_QWS_VNC_DEBUG
       
   881                     qDebug("QVNCServer::setEncodings: using raw");
       
   882 #endif
       
   883                 }
       
   884                break;
       
   885             case CopyRect:
       
   886                 supportCopyRect = true;
       
   887                 break;
       
   888             case RRE:
       
   889                 supportRRE = true;
       
   890                 break;
       
   891             case CoRRE:
       
   892                 supportCoRRE = true;
       
   893                 break;
       
   894             case Hextile:
       
   895                 supportHextile = true;
       
   896                 if (encoder)
       
   897                     break;
       
   898                 switch (qvnc_screen->depth()) {
       
   899 #ifdef QT_QWS_DEPTH_8
       
   900                 case 8:
       
   901                     encoder = new QRfbHextileEncoder<quint8>(this);
       
   902                     break;
       
   903 #endif
       
   904 #ifdef QT_QWS_DEPTH_12
       
   905                 case 12:
       
   906                     encoder = new QRfbHextileEncoder<qrgb444>(this);
       
   907                     break;
       
   908 #endif
       
   909 #ifdef QT_QWS_DEPTH_15
       
   910                 case 15:
       
   911                     encoder = new QRfbHextileEncoder<qrgb555>(this);
       
   912                     break;
       
   913 #endif
       
   914 #ifdef QT_QWS_DEPTH_16
       
   915                 case 16:
       
   916                     encoder = new QRfbHextileEncoder<quint16>(this);
       
   917                     break;
       
   918 #endif
       
   919 #ifdef QT_QWS_DEPTH_18
       
   920                 case 18:
       
   921                     encoder = new QRfbHextileEncoder<qrgb666>(this);
       
   922                     break;
       
   923 #endif
       
   924 #ifdef QT_QWS_DEPTH_24
       
   925                 case 24:
       
   926                     encoder = new QRfbHextileEncoder<qrgb888>(this);
       
   927                     break;
       
   928 #endif
       
   929 #ifdef QT_QWS_DEPTH_32
       
   930                 case 32:
       
   931                     encoder = new QRfbHextileEncoder<quint32>(this);
       
   932                     break;
       
   933 #endif
       
   934                 default:
       
   935                     break;
       
   936                 }
       
   937 #ifdef QT_QWS_VNC_DEBUG
       
   938                 qDebug("QVNCServer::setEncodings: using hextile");
       
   939 #endif
       
   940                 break;
       
   941             case ZRLE:
       
   942                 supportZRLE = true;
       
   943                 break;
       
   944             case Cursor:
       
   945                 supportCursor = true;
       
   946 #ifndef QT_NO_QWS_CURSOR
       
   947                 if (!qvnc_screen->screen() || qt_screencursor->isAccelerated()) {
       
   948                     delete qvnc_cursor;
       
   949                     qvnc_cursor = new QVNCClientCursor(this);
       
   950                 }
       
   951 #endif
       
   952                 break;
       
   953             case DesktopSize:
       
   954                 supportDesktopSize = true;
       
   955                 break;
       
   956             default:
       
   957                 break;
       
   958             }
       
   959         }
       
   960         handleMsg = false;
       
   961         encodingsPending = 0;
       
   962     }
       
   963 
       
   964     if (!encoder) {
       
   965         encoder = new QRfbRawEncoder(this);
       
   966 #ifdef QT_QWS_VNC_DEBUG
       
   967         qDebug("QVNCServer::setEncodings: fallback using raw");
       
   968 #endif
       
   969     }
       
   970 }
       
   971 
       
   972 void QVNCServer::frameBufferUpdateRequest()
       
   973 {
       
   974     QRfbFrameBufferUpdateRequest ev;
       
   975 
       
   976     if (ev.read(client)) {
       
   977         if (!ev.incremental) {
       
   978             QRect r(ev.rect.x, ev.rect.y, ev.rect.w, ev.rect.h);
       
   979             r.translate(qvnc_screen->offset());
       
   980             qvnc_screen->d_ptr->setDirty(r, true);
       
   981         }
       
   982         wantUpdate = true;
       
   983         checkUpdate();
       
   984         handleMsg = false;
       
   985     }
       
   986 }
       
   987 
       
   988 void QVNCServer::pointerEvent()
       
   989 {
       
   990     QRfbPointerEvent ev;
       
   991     if (ev.read(client)) {
       
   992         const QPoint offset = qvnc_screen->offset();
       
   993         QWSServer::sendMouseEvent(offset + QPoint(ev.x, ev.y), ev.buttons);
       
   994         handleMsg = false;
       
   995     }
       
   996 }
       
   997 
       
   998 void QVNCServer::keyEvent()
       
   999 {
       
  1000     QRfbKeyEvent ev;
       
  1001 
       
  1002     if (ev.read(client)) {
       
  1003         if (ev.keycode == Qt::Key_Shift)
       
  1004             keymod = ev.down ? keymod | Qt::ShiftModifier :
       
  1005                                keymod & ~Qt::ShiftModifier;
       
  1006         else if (ev.keycode == Qt::Key_Control)
       
  1007             keymod = ev.down ? keymod | Qt::ControlModifier :
       
  1008                                keymod & ~Qt::ControlModifier;
       
  1009         else if (ev.keycode == Qt::Key_Alt)
       
  1010             keymod = ev.down ? keymod | Qt::AltModifier :
       
  1011                                keymod & ~Qt::AltModifier;
       
  1012         if (ev.unicode || ev.keycode)
       
  1013             QWSServer::sendKeyEvent(ev.unicode, ev.keycode, keymod, ev.down, false);
       
  1014         handleMsg = false;
       
  1015     }
       
  1016 }
       
  1017 
       
  1018 void QVNCServer::clientCutText()
       
  1019 {
       
  1020     QRfbClientCutText ev;
       
  1021 
       
  1022     if (ev.read(client)) {
       
  1023         cutTextPending = ev.length;
       
  1024         if (!cutTextPending)
       
  1025             handleMsg = false;
       
  1026     }
       
  1027 
       
  1028     if (cutTextPending && client->bytesAvailable() >= cutTextPending) {
       
  1029         char *text = new char [cutTextPending+1];
       
  1030         client->read(text, cutTextPending);
       
  1031         delete [] text;
       
  1032         cutTextPending = 0;
       
  1033         handleMsg = false;
       
  1034     }
       
  1035 }
       
  1036 
       
  1037 // stride in bytes
       
  1038 template <class SRC>
       
  1039 bool QRfbSingleColorHextile<SRC>::read(const uchar *data,
       
  1040                                        int width, int height, int stride)
       
  1041 {
       
  1042     const int depth = encoder->server->screen()->depth();
       
  1043     if (width % (depth / 8)) // hw: should rather fallback to simple loop
       
  1044         return false;
       
  1045 
       
  1046     static int alwaysFalse = qgetenv("QT_VNC_NOCHECKFILL").toInt();
       
  1047     if (alwaysFalse)
       
  1048         return false;
       
  1049 
       
  1050     switch (depth) {
       
  1051     case 4: {
       
  1052         const quint8 *data8 = reinterpret_cast<const quint8*>(data);
       
  1053         if ((data8[0] & 0xf) != (data8[0] >> 4))
       
  1054             return false;
       
  1055         width /= 2;
       
  1056     } // fallthrough
       
  1057     case 8: {
       
  1058         const quint8 *data8 = reinterpret_cast<const quint8*>(data);
       
  1059         if (data8[0] != data8[1])
       
  1060             return false;
       
  1061         width /= 2;
       
  1062     } // fallthrough
       
  1063     case 12:
       
  1064     case 15:
       
  1065     case 16: {
       
  1066         const quint16 *data16 = reinterpret_cast<const quint16*>(data);
       
  1067         if (data16[0] != data16[1])
       
  1068             return false;
       
  1069         width /= 2;
       
  1070     } // fallthrough
       
  1071     case 18:
       
  1072     case 24:
       
  1073     case 32: {
       
  1074         const quint32 *data32 = reinterpret_cast<const quint32*>(data);
       
  1075         const quint32 first = data32[0];
       
  1076         const int linestep = (stride / sizeof(quint32)) - width;
       
  1077         for (int y = 0; y < height; ++y) {
       
  1078             for (int x = 0; x < width; ++x) {
       
  1079                 if (*(data32++) != first)
       
  1080                     return false;
       
  1081             }
       
  1082             data32 += linestep;
       
  1083         }
       
  1084         break;
       
  1085     }
       
  1086     default:
       
  1087         return false;
       
  1088     }
       
  1089 
       
  1090     SRC color = reinterpret_cast<const SRC*>(data)[0];
       
  1091     encoder->newBg |= (color != encoder->bg);
       
  1092     encoder->bg = color;
       
  1093     return true;
       
  1094 }
       
  1095 
       
  1096 template <class SRC>
       
  1097 void QRfbSingleColorHextile<SRC>::write(QTcpSocket *socket) const
       
  1098 {
       
  1099     if (true || encoder->newBg) {
       
  1100         const int bpp = encoder->server->clientBytesPerPixel();
       
  1101         const int padding = 3;
       
  1102         QVarLengthArray<char> buffer(padding + 1 + bpp);
       
  1103         buffer[padding] = 2; // BackgroundSpecified
       
  1104         encoder->server->convertPixels(buffer.data() + padding + 1,
       
  1105                                        reinterpret_cast<char*>(&encoder->bg),
       
  1106                                        1);
       
  1107         socket->write(buffer.data() + padding, bpp + 1);
       
  1108 //        encoder->newBg = false;
       
  1109     } else {
       
  1110         char subenc = 0;
       
  1111         socket->write(&subenc, 1);
       
  1112     }
       
  1113 }
       
  1114 
       
  1115 template <class SRC>
       
  1116 bool QRfbDualColorHextile<SRC>::read(const uchar *data,
       
  1117                                      int width, int height, int stride)
       
  1118 {
       
  1119     const SRC *ptr = reinterpret_cast<const SRC*>(data);
       
  1120     const int linestep = (stride / sizeof(SRC)) - width;
       
  1121 
       
  1122     SRC c1;
       
  1123     SRC c2 = 0;
       
  1124     int n1 = 0;
       
  1125     int n2 = 0;
       
  1126     int x = 0;
       
  1127     int y = 0;
       
  1128 
       
  1129     c1 = *ptr;
       
  1130 
       
  1131     // find second color
       
  1132     while (y < height) {
       
  1133         while (x < width) {
       
  1134             if (*ptr == c1) {
       
  1135                 ++n1;
       
  1136             } else {
       
  1137                 c2 = *ptr;
       
  1138                 goto found_second_color;
       
  1139             }
       
  1140             ++ptr;
       
  1141             ++x;
       
  1142         }
       
  1143         x = 0;
       
  1144         ptr += linestep;
       
  1145         ++y;
       
  1146     }
       
  1147 
       
  1148 found_second_color:
       
  1149     // finish counting
       
  1150     while (y < height) {
       
  1151         while (x < width) {
       
  1152             if (*ptr == c1) {
       
  1153                 ++n1;
       
  1154             } else if (*ptr == c2) {
       
  1155                 ++n2;
       
  1156             } else {
       
  1157                 return false;
       
  1158             }
       
  1159             ++ptr;
       
  1160             ++x;
       
  1161         }
       
  1162         x = 0;
       
  1163         ptr += linestep;
       
  1164         ++y;
       
  1165     }
       
  1166 
       
  1167     if (n2 > n1) {
       
  1168         const quint32 tmpC = c1;
       
  1169         c1 = c2;
       
  1170         c2 = tmpC;
       
  1171     }
       
  1172 
       
  1173     encoder->newBg |= (c1 != encoder->bg);
       
  1174     encoder->newFg |= (c2 != encoder->fg);
       
  1175 
       
  1176     encoder->bg = c1;
       
  1177     encoder->fg = c2;
       
  1178 
       
  1179     // create map
       
  1180     bool inRect = false;
       
  1181     numRects = 0;
       
  1182     ptr = reinterpret_cast<const SRC*>(data);
       
  1183     for (y = 0; y < height; ++y) {
       
  1184         for (x = 0; x < width; ++x) {
       
  1185             if (inRect && *ptr == encoder->bg) {
       
  1186                 // rect finished
       
  1187                 setWidth(x - lastx());
       
  1188                 next();
       
  1189                 inRect = false;
       
  1190             } else if (!inRect && *ptr == encoder->fg) {
       
  1191                 // rect start
       
  1192                 setX(x);
       
  1193                 setY(y);
       
  1194                 setHeight(1);
       
  1195                 inRect = true;
       
  1196             }
       
  1197             ++ptr;
       
  1198         }
       
  1199         if (inRect) {
       
  1200             // finish rect
       
  1201             setWidth(width - lastx());
       
  1202             next();
       
  1203             inRect = false;
       
  1204         }
       
  1205         ptr += linestep;
       
  1206     }
       
  1207 
       
  1208     return true;
       
  1209 }
       
  1210 
       
  1211 template <class SRC>
       
  1212 void QRfbDualColorHextile<SRC>::write(QTcpSocket *socket) const
       
  1213 {
       
  1214     const int bpp = encoder->server->clientBytesPerPixel();
       
  1215     const int padding = 3;
       
  1216     QVarLengthArray<char> buffer(padding + 2 * bpp + sizeof(char) + sizeof(numRects));
       
  1217     char &subenc = buffer[padding];
       
  1218     int n = padding + sizeof(subenc);
       
  1219 
       
  1220     subenc = 0x8; // AnySubrects
       
  1221 
       
  1222     if (encoder->newBg) {
       
  1223         subenc |= 0x2; // Background
       
  1224         encoder->server->convertPixels(buffer.data() + n, (char*)&encoder->bg, 1);
       
  1225         n += bpp;
       
  1226 //        encoder->newBg = false;
       
  1227     }
       
  1228 
       
  1229     if (encoder->newFg) {
       
  1230         subenc |= 0x4; // Foreground
       
  1231         encoder->server->convertPixels(buffer.data() + n, (char*)&encoder->fg, 1);
       
  1232         n += bpp;
       
  1233 //        encoder->newFg = false;
       
  1234     }
       
  1235     buffer[n] = numRects;
       
  1236     n += sizeof(numRects);
       
  1237 
       
  1238     socket->write(buffer.data() + padding, n - padding);
       
  1239     socket->write((char*)rects, numRects * sizeof(Rect));
       
  1240 }
       
  1241 
       
  1242 template <class SRC>
       
  1243 void QRfbDualColorHextile<SRC>::next()
       
  1244 {
       
  1245     for (int r = numRects - 1; r >= 0; --r) {
       
  1246         if (recty(r) == lasty())
       
  1247             continue;
       
  1248         if (recty(r) < lasty() - 1) // only search previous scanline
       
  1249             break;
       
  1250         if (rectx(r) == lastx() && width(r) == width(numRects)) {
       
  1251             ++rects[r].wh;
       
  1252             return;
       
  1253         }
       
  1254     }
       
  1255     ++numRects;
       
  1256 }
       
  1257 
       
  1258 template <class SRC>
       
  1259 inline void QRfbMultiColorHextile<SRC>::setColor(SRC color)
       
  1260 {
       
  1261     encoder->server->convertPixels(reinterpret_cast<char*>(rect(numRects)),
       
  1262                                    (const char*)&color, 1);
       
  1263 }
       
  1264 
       
  1265 template <class SRC>
       
  1266 inline bool QRfbMultiColorHextile<SRC>::beginRect()
       
  1267 {
       
  1268     if ((rects.size() + bpp + 2) > maxRectsSize)
       
  1269         return false;
       
  1270     rects.resize(rects.size() + bpp + 2);
       
  1271     return true;
       
  1272 }
       
  1273 
       
  1274 template <class SRC>
       
  1275 inline void QRfbMultiColorHextile<SRC>::endRect()
       
  1276 {
       
  1277     setHeight(numRects, 1);
       
  1278     ++numRects;
       
  1279 }
       
  1280 
       
  1281 template <class SRC>
       
  1282 bool QRfbMultiColorHextile<SRC>::read(const uchar *data,
       
  1283                                       int width, int height, int stride)
       
  1284 {
       
  1285     const SRC *ptr = reinterpret_cast<const SRC*>(data);
       
  1286     const int linestep = (stride / sizeof(SRC)) - width;
       
  1287 
       
  1288     bpp = encoder->server->clientBytesPerPixel();
       
  1289 
       
  1290     if (encoder->newBg)
       
  1291         encoder->bg = ptr[0];
       
  1292 
       
  1293     const SRC bg = encoder->bg;
       
  1294     SRC color = bg;
       
  1295     bool inRect = false;
       
  1296 
       
  1297     numRects = 0;
       
  1298     rects.clear();
       
  1299 
       
  1300     for (int y = 0; y < height; ++y) {
       
  1301         for (int x = 0; x < width; ++x) {
       
  1302             if (inRect && *ptr != color) { // end rect
       
  1303                 setWidth(numRects, x - rectx(numRects));
       
  1304                 endRect();
       
  1305                 inRect = false;
       
  1306             }
       
  1307 
       
  1308             if (!inRect && *ptr != bg) { // begin rect
       
  1309                 if (!beginRect())
       
  1310                     return false;
       
  1311                 inRect = true;
       
  1312                 color = *ptr;
       
  1313                 setColor(color);
       
  1314                 setX(numRects, x);
       
  1315                 setY(numRects, y);
       
  1316             }
       
  1317             ++ptr;
       
  1318         }
       
  1319         if (inRect) { // end rect
       
  1320             setWidth(numRects, width - rectx(numRects));
       
  1321             endRect();
       
  1322             inRect = false;
       
  1323         }
       
  1324         ptr += linestep;
       
  1325     }
       
  1326 
       
  1327     return true;
       
  1328 }
       
  1329 
       
  1330 template <class SRC>
       
  1331 void QRfbMultiColorHextile<SRC>::write(QTcpSocket *socket) const
       
  1332 {
       
  1333     const int padding = 3;
       
  1334     QVarLengthArray<quint8> buffer(bpp + padding + sizeof(quint8) + sizeof(numRects));
       
  1335 
       
  1336     quint8 &subenc = buffer[padding];
       
  1337     int n = padding + sizeof(quint8);
       
  1338 
       
  1339     subenc = 8 | 16; // AnySubrects | SubrectsColoured
       
  1340 
       
  1341     if (encoder->newBg) {
       
  1342         subenc |= 0x2; // Background
       
  1343         encoder->server->convertPixels(reinterpret_cast<char*>(buffer.data() + n),
       
  1344                                        reinterpret_cast<const char*>(&encoder->bg),
       
  1345                                        1);
       
  1346         n += bpp;
       
  1347 //        encoder->newBg = false;
       
  1348     }
       
  1349 
       
  1350     buffer[n] = numRects;
       
  1351     n += sizeof(numRects);
       
  1352 
       
  1353     socket->write(reinterpret_cast<const char*>(buffer.data() + padding),
       
  1354                   n - padding);
       
  1355     socket->write(reinterpret_cast<const char*>(rects.constData()),
       
  1356                   rects.size());
       
  1357 }
       
  1358 
       
  1359 bool QVNCServer::pixelConversionNeeded() const
       
  1360 {
       
  1361     if (!sameEndian)
       
  1362         return true;
       
  1363 
       
  1364 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
       
  1365     if (qvnc_screen->swapBytes())
       
  1366         return true;
       
  1367 #endif
       
  1368 
       
  1369     const int screendepth = qvnc_screen->depth();
       
  1370     if (screendepth != pixelFormat.bitsPerPixel)
       
  1371         return true;
       
  1372 
       
  1373     switch (screendepth) {
       
  1374     case 32:
       
  1375     case 24:
       
  1376         return false;
       
  1377     case 18:
       
  1378         return (pixelFormat.redBits == 6
       
  1379                 && pixelFormat.greenBits == 6
       
  1380                 && pixelFormat.blueBits == 6);
       
  1381     case 16:
       
  1382         return (pixelFormat.redBits == 5
       
  1383                 && pixelFormat.greenBits == 6
       
  1384                 && pixelFormat.blueBits == 5);
       
  1385     case 15:
       
  1386         return (pixelFormat.redBits == 5
       
  1387                 && pixelFormat.greenBits == 5
       
  1388                 && pixelFormat.blueBits == 5);
       
  1389     case 12:
       
  1390         return (pixelFormat.redBits == 4
       
  1391                 && pixelFormat.greenBits == 4
       
  1392                 && pixelFormat.blueBits == 4);
       
  1393     }
       
  1394     return true;
       
  1395 }
       
  1396 
       
  1397 // count: number of pixels
       
  1398 void QVNCServer::convertPixels(char *dst, const char *src, int count) const
       
  1399 {
       
  1400     const int screendepth = qvnc_screen->depth();
       
  1401     const bool isBgr = qvnc_screen->pixelType() == QScreen::BGRPixel;
       
  1402 
       
  1403     // cutoffs
       
  1404 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
       
  1405     if (!swapBytes)
       
  1406 #endif
       
  1407     if (sameEndian) {
       
  1408         if (screendepth == pixelFormat.bitsPerPixel) { // memcpy cutoffs
       
  1409 
       
  1410             switch (screendepth) {
       
  1411             case 32:
       
  1412                 memcpy(dst, src, count * sizeof(quint32));
       
  1413                 return;
       
  1414             case 16:
       
  1415                 if (pixelFormat.redBits == 5
       
  1416                     && pixelFormat.greenBits == 6
       
  1417                     && pixelFormat.blueBits == 5)
       
  1418                 {
       
  1419                     memcpy(dst, src, count * sizeof(quint16));
       
  1420                     return;
       
  1421                 }
       
  1422             }
       
  1423         } else if (screendepth == 16 && pixelFormat.bitsPerPixel == 32) {
       
  1424 #if defined(__i386__) // Currently fails on ARM if dst is not 4 byte aligned
       
  1425             const quint32 *src32 = reinterpret_cast<const quint32*>(src);
       
  1426             quint32 *dst32 = reinterpret_cast<quint32*>(dst);
       
  1427             int count32 = count * sizeof(quint16) / sizeof(quint32);
       
  1428             while (count32--) {
       
  1429                 const quint32 s = *src32++;
       
  1430                 quint32 result1;
       
  1431                 quint32 result2;
       
  1432 
       
  1433                 // red
       
  1434                 result1 = ((s & 0xf8000000) | ((s & 0xe0000000) >> 5)) >> 8;
       
  1435                 result2 = ((s & 0x0000f800) | ((s & 0x0000e000) >> 5)) << 8;
       
  1436 
       
  1437                 // green
       
  1438                 result1 |= ((s & 0x07e00000) | ((s & 0x06000000) >> 6)) >> 11;
       
  1439                 result2 |= ((s & 0x000007e0) | ((s & 0x00000600) >> 6)) << 5;
       
  1440 
       
  1441                 // blue
       
  1442                 result1 |= ((s & 0x001f0000) | ((s & 0x001c0000) >> 5)) >> 13;
       
  1443                 result2 |= ((s & 0x0000001f) | ((s & 0x0000001c) >> 5)) << 3;
       
  1444 
       
  1445                 *dst32++ = result2;
       
  1446                 *dst32++ = result1;
       
  1447             }
       
  1448             if (count & 0x1) {
       
  1449                 const quint16 *src16 = reinterpret_cast<const quint16*>(src);
       
  1450                 dst32[count - 1] = qt_conv16ToRgb(src16[count - 1]);
       
  1451             }
       
  1452             return;
       
  1453 #endif
       
  1454         }
       
  1455     }
       
  1456 
       
  1457     const int bytesPerPixel = (pixelFormat.bitsPerPixel + 7) / 8;
       
  1458 
       
  1459 //    nibble = 0;
       
  1460 
       
  1461     for (int i = 0; i < count; ++i) {
       
  1462         int r, g, b;
       
  1463 
       
  1464         switch (screendepth) {
       
  1465 #if 0
       
  1466         case 4: {
       
  1467             if (!nibble) {
       
  1468                 r = ((*src) & 0x0f) << 4;
       
  1469             } else {
       
  1470                 r = (*src) & 0xf0;
       
  1471                 src++;
       
  1472             }
       
  1473             nibble = !nibble;
       
  1474             g = b = r;
       
  1475             break;
       
  1476         }
       
  1477 #endif
       
  1478         case 8: {
       
  1479             QRgb rgb = qvnc_screen->clut()[int(*src)];
       
  1480             r = qRed(rgb);
       
  1481             g = qGreen(rgb);
       
  1482             b = qBlue(rgb);
       
  1483             src++;
       
  1484             break;
       
  1485         }
       
  1486 #ifdef QT_QWS_DEPTH_12
       
  1487         case 12: {
       
  1488             quint32 p = quint32(*reinterpret_cast<const qrgb444*>(src));
       
  1489             r = qRed(p);
       
  1490             g = qGreen(p);
       
  1491             b = qBlue(p);
       
  1492             src += sizeof(qrgb444);
       
  1493             break;
       
  1494         }
       
  1495 #endif
       
  1496 #ifdef QT_QWS_DEPTH_15
       
  1497         case 15: {
       
  1498             quint32 p = quint32(*reinterpret_cast<const qrgb555*>(src));
       
  1499             r = qRed(p);
       
  1500             g = qGreen(p);
       
  1501             b = qBlue(p);
       
  1502             src += sizeof(qrgb555);
       
  1503             break;
       
  1504         }
       
  1505 #endif
       
  1506         case 16: {
       
  1507             quint16 p = *reinterpret_cast<const quint16*>(src);
       
  1508 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
       
  1509             if (swapBytes)
       
  1510                 p = ((p & 0xff) << 8) | ((p & 0xff00) >> 8);
       
  1511 #endif
       
  1512             r = (p >> 11) & 0x1f;
       
  1513             g = (p >> 5) & 0x3f;
       
  1514             b = p & 0x1f;
       
  1515             r <<= 3;
       
  1516             g <<= 2;
       
  1517             b <<= 3;
       
  1518             src += sizeof(quint16);
       
  1519             break;
       
  1520         }
       
  1521 #ifdef QT_QWS_DEPTH_18
       
  1522         case 18: {
       
  1523             quint32 p = quint32(*reinterpret_cast<const qrgb666*>(src));
       
  1524             r = qRed(p);
       
  1525             g = qGreen(p);
       
  1526             b = qBlue(p);
       
  1527             src += sizeof(qrgb666);
       
  1528             break;
       
  1529         }
       
  1530 #endif
       
  1531 #ifdef QT_QWS_DEPTH_24
       
  1532         case 24: {
       
  1533             quint32 p = quint32(*reinterpret_cast<const qrgb888*>(src));
       
  1534             r = qRed(p);
       
  1535             g = qGreen(p);
       
  1536             b = qBlue(p);
       
  1537             src += sizeof(qrgb888);
       
  1538             break;
       
  1539         }
       
  1540 #endif
       
  1541         case 32: {
       
  1542             quint32 p = *reinterpret_cast<const quint32*>(src);
       
  1543             r = (p >> 16) & 0xff;
       
  1544             g = (p >> 8) & 0xff;
       
  1545             b = p & 0xff;
       
  1546             src += sizeof(quint32);
       
  1547             break;
       
  1548         }
       
  1549         default: {
       
  1550             r = g = b = 0;
       
  1551             qDebug("QVNCServer: don't support %dbpp display", screendepth);
       
  1552             return;
       
  1553         }
       
  1554         }
       
  1555 
       
  1556 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
       
  1557         if (swapBytes ^ isBgr)
       
  1558 #else
       
  1559         if (isBgr)
       
  1560 #endif
       
  1561             qSwap(r, b);
       
  1562 
       
  1563         r >>= (8 - pixelFormat.redBits);
       
  1564         g >>= (8 - pixelFormat.greenBits);
       
  1565         b >>= (8 - pixelFormat.blueBits);
       
  1566 
       
  1567         int pixel = (r << pixelFormat.redShift) |
       
  1568                     (g << pixelFormat.greenShift) |
       
  1569                     (b << pixelFormat.blueShift);
       
  1570 
       
  1571         if (sameEndian || pixelFormat.bitsPerPixel == 8) {
       
  1572             memcpy(dst, &pixel, bytesPerPixel); // XXX: do a simple for-loop instead?
       
  1573             dst += bytesPerPixel;
       
  1574             continue;
       
  1575         }
       
  1576 
       
  1577 
       
  1578         if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
       
  1579             switch (pixelFormat.bitsPerPixel) {
       
  1580             case 16:
       
  1581                 pixel = (((pixel & 0x0000ff00) << 8)  |
       
  1582                          ((pixel & 0x000000ff) << 24));
       
  1583                 break;
       
  1584             case 32:
       
  1585                 pixel = (((pixel & 0xff000000) >> 24) |
       
  1586                          ((pixel & 0x00ff0000) >> 8)  |
       
  1587                          ((pixel & 0x0000ff00) << 8)  |
       
  1588                          ((pixel & 0x000000ff) << 24));
       
  1589                 break;
       
  1590             default:
       
  1591                 qDebug("Cannot handle %d bpp client", pixelFormat.bitsPerPixel);
       
  1592             }
       
  1593         } else { // QSysInfo::ByteOrder == QSysInfo::LittleEndian
       
  1594             switch (pixelFormat.bitsPerPixel) {
       
  1595             case 16:
       
  1596                 pixel = (((pixel & 0xff000000) >> 8) |
       
  1597                          ((pixel & 0x00ff0000) << 8));
       
  1598                 break;
       
  1599             case 32:
       
  1600                 pixel = (((pixel & 0xff000000) >> 24) |
       
  1601                          ((pixel & 0x00ff0000) >> 8)  |
       
  1602                          ((pixel & 0x0000ff00) << 8)  |
       
  1603                          ((pixel & 0x000000ff) << 24));
       
  1604                 break;
       
  1605             default:
       
  1606                 qDebug("Cannot handle %d bpp client",
       
  1607                        pixelFormat.bitsPerPixel);
       
  1608                 break;
       
  1609             }
       
  1610         }
       
  1611         memcpy(dst, &pixel, bytesPerPixel); // XXX: simple for-loop instead?
       
  1612         dst += bytesPerPixel;
       
  1613     }
       
  1614 }
       
  1615 
       
  1616 #ifndef QT_NO_QWS_CURSOR
       
  1617 static void blendCursor(QImage &image, const QRect &imageRect)
       
  1618 {
       
  1619     const QRect cursorRect = qt_screencursor->boundingRect();
       
  1620     const QRect intersection = (cursorRect & imageRect);
       
  1621     const QRect destRect = intersection.translated(-imageRect.topLeft());
       
  1622     const QRect srcRect = intersection.translated(-cursorRect.topLeft());
       
  1623 
       
  1624     QPainter painter(&image);
       
  1625     painter.drawImage(destRect, qt_screencursor->image(), srcRect);
       
  1626     painter.end();
       
  1627 }
       
  1628 #endif // QT_NO_QWS_CURSOR
       
  1629 
       
  1630 QVNCDirtyMap::QVNCDirtyMap(QScreen *s)
       
  1631     : bytesPerPixel(0), numDirty(0), screen(s)
       
  1632 {
       
  1633     bytesPerPixel = (screen->depth() + 7) / 8;
       
  1634     bufferWidth = screen->deviceWidth();
       
  1635     bufferHeight = screen->deviceHeight();
       
  1636     bufferStride = bufferWidth * bytesPerPixel;
       
  1637     buffer = new uchar[bufferHeight * bufferStride];
       
  1638 
       
  1639     mapWidth = (bufferWidth + MAP_TILE_SIZE - 1) / MAP_TILE_SIZE;
       
  1640     mapHeight = (bufferHeight + MAP_TILE_SIZE - 1) / MAP_TILE_SIZE;
       
  1641     numTiles = mapWidth * mapHeight;
       
  1642     map = new uchar[numTiles];
       
  1643 }
       
  1644 
       
  1645 QVNCDirtyMap::~QVNCDirtyMap()
       
  1646 {
       
  1647     delete[] map;
       
  1648     delete[] buffer;
       
  1649 }
       
  1650 
       
  1651 void QVNCDirtyMap::reset()
       
  1652 {
       
  1653     memset(map, 1, numTiles);
       
  1654     memset(buffer, 0, bufferHeight * bufferStride);
       
  1655     numDirty = numTiles;
       
  1656 }
       
  1657 
       
  1658 inline bool QVNCDirtyMap::dirty(int x, int y) const
       
  1659 {
       
  1660     return map[y * mapWidth + x];
       
  1661 }
       
  1662 
       
  1663 inline void QVNCDirtyMap::setClean(int x, int y)
       
  1664 {
       
  1665     map[y * mapWidth + x] = 0;
       
  1666     --numDirty;
       
  1667 }
       
  1668 
       
  1669 template <class T>
       
  1670 void QVNCDirtyMapOptimized<T>::setDirty(int tileX, int tileY, bool force)
       
  1671 {
       
  1672     static bool alwaysForce = qgetenv("QT_VNC_NO_COMPAREBUFFER").toInt();
       
  1673     if (alwaysForce)
       
  1674         force = true;
       
  1675 
       
  1676     bool changed = false;
       
  1677 
       
  1678     if (!force) {
       
  1679         const int lstep = screen->linestep();
       
  1680         const int startX = tileX * MAP_TILE_SIZE;
       
  1681         const int startY = tileY * MAP_TILE_SIZE;
       
  1682         const uchar *scrn = screen->base()
       
  1683                             + startY * lstep + startX * bytesPerPixel;
       
  1684         uchar *old = buffer + startY * bufferStride + startX * sizeof(T);
       
  1685 
       
  1686         const int tileHeight = (startY + MAP_TILE_SIZE > bufferHeight ?
       
  1687                                 bufferHeight - startY : MAP_TILE_SIZE);
       
  1688         const int tileWidth = (startX + MAP_TILE_SIZE > bufferWidth ?
       
  1689                                bufferWidth - startX : MAP_TILE_SIZE);
       
  1690         const bool doInlines = (tileWidth == MAP_TILE_SIZE);
       
  1691 
       
  1692         int y = tileHeight;
       
  1693 
       
  1694         if (doInlines) { // hw: memcmp/memcpy is inlined when using constants
       
  1695             while (y) {
       
  1696                 if (memcmp(old, scrn, sizeof(T) * MAP_TILE_SIZE)) {
       
  1697                     changed = true;
       
  1698                     break;
       
  1699                 }
       
  1700                 scrn += lstep;
       
  1701                 old += bufferStride;
       
  1702                 --y;
       
  1703             }
       
  1704 
       
  1705             while (y) {
       
  1706                 memcpy(old, scrn, sizeof(T) * MAP_TILE_SIZE);
       
  1707                 scrn += lstep;
       
  1708                 old += bufferStride;
       
  1709                 --y;
       
  1710             }
       
  1711         } else {
       
  1712             while (y) {
       
  1713                 if (memcmp(old, scrn, sizeof(T) * tileWidth)) {
       
  1714                     changed = true;
       
  1715                     break;
       
  1716                 }
       
  1717                 scrn += lstep;
       
  1718                 old += bufferStride;
       
  1719                 --y;
       
  1720             }
       
  1721 
       
  1722             while (y) {
       
  1723                 memcpy(old, scrn, sizeof(T) * tileWidth);
       
  1724                 scrn += lstep;
       
  1725                 old += bufferStride;
       
  1726                 --y;
       
  1727             }
       
  1728         }
       
  1729     }
       
  1730 
       
  1731     const int mapIndex = tileY * mapWidth + tileX;
       
  1732     if ((force || changed) && !map[mapIndex]) {
       
  1733         map[mapIndex] = 1;
       
  1734         ++numDirty;
       
  1735     }
       
  1736 }
       
  1737 
       
  1738 template <class SRC>
       
  1739 QRfbHextileEncoder<SRC>::QRfbHextileEncoder(QVNCServer *s)
       
  1740     : QRfbEncoder(s),
       
  1741       singleColorHextile(this), dualColorHextile(this), multiColorHextile(this)
       
  1742 {
       
  1743 }
       
  1744 
       
  1745 /*
       
  1746     \internal
       
  1747     Send dirty rects using hextile encoding.
       
  1748 */
       
  1749 template <class SRC>
       
  1750 void QRfbHextileEncoder<SRC>::write()
       
  1751 {
       
  1752     QWSDisplay::grab(true);
       
  1753 
       
  1754     QVNCDirtyMap *map = server->dirtyMap();
       
  1755     QTcpSocket *socket = server->clientSocket();
       
  1756 
       
  1757     const quint32 encoding = htonl(5); // hextile encoding
       
  1758     const int bytesPerPixel = server->clientBytesPerPixel();
       
  1759 
       
  1760     {
       
  1761         const char tmp[2] = { 0, 0 }; // msg type, padding
       
  1762         socket->write(tmp, sizeof(tmp));
       
  1763     }
       
  1764     {
       
  1765         const quint16 count = htons(map->numDirty);
       
  1766         socket->write((char *)&count, sizeof(count));
       
  1767     }
       
  1768 
       
  1769     if (map->numDirty <= 0) {
       
  1770         QWSDisplay::ungrab();
       
  1771         return;
       
  1772     }
       
  1773 
       
  1774     newBg = true;
       
  1775     newFg = true;
       
  1776 
       
  1777     const QImage screenImage = server->screenImage();
       
  1778     QRfbRect rect(0, 0, MAP_TILE_SIZE, MAP_TILE_SIZE);
       
  1779 
       
  1780     for (int y = 0; y < map->mapHeight; ++y) {
       
  1781         if (rect.y + MAP_TILE_SIZE > server->screen()->height())
       
  1782             rect.h = server->screen()->height() - rect.y;
       
  1783         rect.w = MAP_TILE_SIZE;
       
  1784         for (int x = 0; x < map->mapWidth; ++x) {
       
  1785             if (!map->dirty(x, y))
       
  1786                 continue;
       
  1787             map->setClean(x, y);
       
  1788 
       
  1789             rect.x = x * MAP_TILE_SIZE;
       
  1790             if (rect.x + MAP_TILE_SIZE > server->screen()->deviceWidth())
       
  1791                 rect.w = server->screen()->deviceWidth() - rect.x;
       
  1792             rect.write(socket);
       
  1793 
       
  1794             socket->write((char *)&encoding, sizeof(encoding));
       
  1795 
       
  1796             const uchar *screendata = screenImage.scanLine(rect.y)
       
  1797                                       + rect.x * screenImage.depth() / 8;
       
  1798             int linestep = screenImage.bytesPerLine();
       
  1799 
       
  1800 #ifndef QT_NO_QWS_CURSOR
       
  1801             // hardware cursors must be blended with the screen memory
       
  1802             const bool doBlendCursor = qt_screencursor
       
  1803                                        && !server->hasClientCursor()
       
  1804                                        && qt_screencursor->isAccelerated();
       
  1805             QImage tileImage;
       
  1806             if (doBlendCursor) {
       
  1807                 const QRect tileRect(rect.x, rect.y, rect.w, rect.h);
       
  1808                 const QRect cursorRect = qt_screencursor->boundingRect()
       
  1809                                          .translated(-server->screen()->offset());
       
  1810                 if (tileRect.intersects(cursorRect)) {
       
  1811                     tileImage = screenImage.copy(tileRect);
       
  1812                     blendCursor(tileImage,
       
  1813                                 tileRect.translated(server->screen()->offset()));
       
  1814                     screendata = tileImage.bits();
       
  1815                     linestep = tileImage.bytesPerLine();
       
  1816                 }
       
  1817             }
       
  1818 #endif // QT_NO_QWS_CURSOR
       
  1819 
       
  1820             if (singleColorHextile.read(screendata, rect.w, rect.h, linestep)) {
       
  1821                 singleColorHextile.write(socket);
       
  1822             } else if (dualColorHextile.read(screendata, rect.w, rect.h, linestep)) {
       
  1823                 dualColorHextile.write(socket);
       
  1824             } else if (multiColorHextile.read(screendata, rect.w, rect.h, linestep)) {
       
  1825                 multiColorHextile.write(socket);
       
  1826             } else if (server->doPixelConversion()) {
       
  1827                 const int bufferSize = rect.w * rect.h * bytesPerPixel + 1;
       
  1828                 const int padding = sizeof(quint32) - sizeof(char);
       
  1829                 buffer.resize(bufferSize + padding);
       
  1830 
       
  1831                 buffer[padding] = 1; // Raw subencoding
       
  1832 
       
  1833                 // convert pixels
       
  1834                 char *b = buffer.data() + padding + 1;
       
  1835                 const int bstep = rect.w * bytesPerPixel;
       
  1836                 for (int i = 0; i < rect.h; ++i) {
       
  1837                     server->convertPixels(b, (const char*)screendata, rect.w);
       
  1838                     screendata += linestep;
       
  1839                     b += bstep;
       
  1840                 }
       
  1841                 socket->write(buffer.constData() + padding, bufferSize);
       
  1842             } else {
       
  1843                 quint8 subenc = 1; // Raw subencoding
       
  1844                 socket->write((char *)&subenc, 1);
       
  1845 
       
  1846                 // send pixels
       
  1847                 for (int i = 0; i < rect.h; ++i) {
       
  1848                     socket->write((const char*)screendata,
       
  1849                                   rect.w * bytesPerPixel);
       
  1850                     screendata += linestep;
       
  1851                 }
       
  1852             }
       
  1853         }
       
  1854         if (socket->state() == QAbstractSocket::UnconnectedState)
       
  1855             break;
       
  1856         rect.y += MAP_TILE_SIZE;
       
  1857     }
       
  1858     socket->flush();
       
  1859     Q_ASSERT(map->numDirty == 0);
       
  1860 
       
  1861     QWSDisplay::ungrab();
       
  1862 }
       
  1863 
       
  1864 void QRfbRawEncoder::write()
       
  1865 {
       
  1866     QWSDisplay::grab(false);
       
  1867 
       
  1868     QVNCDirtyMap *map = server->dirtyMap();
       
  1869     QTcpSocket *socket = server->clientSocket();
       
  1870 
       
  1871     const int bytesPerPixel = server->clientBytesPerPixel();
       
  1872 
       
  1873     // create a region from the dirty rects and send the region's merged rects.
       
  1874     QRegion rgn;
       
  1875     if (map) {
       
  1876         for (int y = 0; y < map->mapHeight; ++y) {
       
  1877             for (int x = 0; x < map->mapWidth; ++x) {
       
  1878                 if (!map->dirty(x, y))
       
  1879                     continue;
       
  1880                 rgn += QRect(x * MAP_TILE_SIZE, y * MAP_TILE_SIZE,
       
  1881                              MAP_TILE_SIZE, MAP_TILE_SIZE);
       
  1882                 map->setClean(x, y);
       
  1883             }
       
  1884         }
       
  1885 
       
  1886         rgn &= QRect(0, 0, server->screen()->deviceWidth(),
       
  1887                      server->screen()->deviceHeight());
       
  1888     }
       
  1889     const QVector<QRect> rects = rgn.rects();
       
  1890 
       
  1891     {
       
  1892         const char tmp[2] = { 0, 0 }; // msg type, padding
       
  1893         socket->write(tmp, sizeof(tmp));
       
  1894     }
       
  1895 
       
  1896     {
       
  1897         const quint16 count = htons(rects.size());
       
  1898         socket->write((char *)&count, sizeof(count));
       
  1899     }
       
  1900 
       
  1901     if (rects.size() <= 0) {
       
  1902         QWSDisplay::ungrab();
       
  1903         return;
       
  1904     }
       
  1905 
       
  1906     const QImage screenImage = server->screenImage();
       
  1907 
       
  1908     for (int i = 0; i < rects.size(); ++i) {
       
  1909         const QRect tileRect = rects.at(i);
       
  1910         const QRfbRect rect(tileRect.x(), tileRect.y(),
       
  1911                             tileRect.width(), tileRect.height());
       
  1912         rect.write(socket);
       
  1913 
       
  1914         const quint32 encoding = htonl(0); // raw encoding
       
  1915         socket->write((char *)&encoding, sizeof(encoding));
       
  1916 
       
  1917         int linestep = screenImage.bytesPerLine();
       
  1918         const uchar *screendata = screenImage.scanLine(rect.y)
       
  1919                                   + rect.x * screenImage.depth() / 8;
       
  1920 
       
  1921 #ifndef QT_NO_QWS_CURSOR
       
  1922         // hardware cursors must be blended with the screen memory
       
  1923         const bool doBlendCursor = qt_screencursor
       
  1924                                    && !server->hasClientCursor()
       
  1925                                    && qt_screencursor->isAccelerated();
       
  1926         QImage tileImage;
       
  1927         if (doBlendCursor) {
       
  1928             const QRect cursorRect = qt_screencursor->boundingRect()
       
  1929                                      .translated(-server->screen()->offset());
       
  1930             if (tileRect.intersects(cursorRect)) {
       
  1931                 tileImage = screenImage.copy(tileRect);
       
  1932                 blendCursor(tileImage,
       
  1933                             tileRect.translated(server->screen()->offset()));
       
  1934                 screendata = tileImage.bits();
       
  1935                 linestep = tileImage.bytesPerLine();
       
  1936             }
       
  1937         }
       
  1938 #endif // QT_NO_QWS_CURSOR
       
  1939 
       
  1940         if (server->doPixelConversion()) {
       
  1941             const int bufferSize = rect.w * rect.h * bytesPerPixel;
       
  1942             if (bufferSize > buffer.size())
       
  1943                 buffer.resize(bufferSize);
       
  1944 
       
  1945             // convert pixels
       
  1946             char *b = buffer.data();
       
  1947             const int bstep = rect.w * bytesPerPixel;
       
  1948             for (int i = 0; i < rect.h; ++i) {
       
  1949                 server->convertPixels(b, (const char*)screendata, rect.w);
       
  1950                 screendata += linestep;
       
  1951                 b += bstep;
       
  1952             }
       
  1953             socket->write(buffer.constData(), bufferSize);
       
  1954         } else {
       
  1955             for (int i = 0; i < rect.h; ++i) {
       
  1956                 socket->write((const char*)screendata, rect.w * bytesPerPixel);
       
  1957                 screendata += linestep;
       
  1958             }
       
  1959         }
       
  1960         if (socket->state() == QAbstractSocket::UnconnectedState)
       
  1961             break;
       
  1962     }
       
  1963     socket->flush();
       
  1964 
       
  1965     QWSDisplay::ungrab();
       
  1966 }
       
  1967 
       
  1968 inline QImage QVNCServer::screenImage() const
       
  1969 {
       
  1970     return QImage(qvnc_screen->base(), qvnc_screen->deviceWidth(),
       
  1971                   qvnc_screen->deviceHeight(), qvnc_screen->linestep(),
       
  1972                   qvnc_screen->pixelFormat());
       
  1973 }
       
  1974 
       
  1975 void QVNCServer::checkUpdate()
       
  1976 {
       
  1977     if (!wantUpdate)
       
  1978         return;
       
  1979 
       
  1980     if (dirtyCursor) {
       
  1981 #ifndef QT_NO_QWS_CURSOR
       
  1982         Q_ASSERT(qvnc_cursor);
       
  1983         qvnc_cursor->write();
       
  1984 #endif
       
  1985         dirtyCursor = false;
       
  1986         wantUpdate = false;
       
  1987         return;
       
  1988     }
       
  1989 
       
  1990     if (dirtyMap()->numDirty > 0) {
       
  1991         if (encoder)
       
  1992             encoder->write();
       
  1993         wantUpdate = false;
       
  1994     }
       
  1995 }
       
  1996 
       
  1997 void QVNCServer::discardClient()
       
  1998 {
       
  1999     timer->stop();
       
  2000     state = Unconnected;
       
  2001     delete encoder;
       
  2002     encoder = 0;
       
  2003 #ifndef QT_NO_QWS_CURSOR
       
  2004     delete qvnc_cursor;
       
  2005     qvnc_cursor = 0;
       
  2006 #endif
       
  2007     if (!qvnc_screen->screen() && !qvnc_screen->d_ptr->noDisablePainting)
       
  2008         QWSServer::instance()->enablePainting(false);
       
  2009 }
       
  2010 
       
  2011 
       
  2012 //===========================================================================
       
  2013 
       
  2014 /*!
       
  2015     \class QVNCScreen
       
  2016     \internal
       
  2017     \ingroup qws
       
  2018 
       
  2019     \brief The QVNCScreen class implements a screen driver for VNC
       
  2020     servers.
       
  2021 
       
  2022     Note that this class is only available in \l{Qt for Embedded Linux}.
       
  2023     Custom screen drivers can be added by subclassing the QScreen
       
  2024     class, using the QScreenDriverFactory class to dynamically load
       
  2025     the driver into the application.
       
  2026 
       
  2027     The VNC protocol allows you to view and interact with the
       
  2028     computer's display from anywhere on the network. See the
       
  2029     \l{The VNC Protocol and Qt for Embedded Linux}{VNC protocol}
       
  2030     documentation for more details.
       
  2031 
       
  2032     The default implementation of QVNCScreen inherits QLinuxFbScreen,
       
  2033     but any QScreen subclass, or QScreen itself, can serve as its base
       
  2034     class. This is easily achieved by manipulating the \c
       
  2035     VNCSCREEN_BASE definition in the header file.
       
  2036 
       
  2037     \sa QScreen, {Running Applications}
       
  2038 */
       
  2039 
       
  2040 /*!
       
  2041     \fn QVNCScreen::QVNCScreen(int displayId)
       
  2042 
       
  2043     Constructs a QVNCScreen object. The \a displayId argument
       
  2044     identifies the Qt for Embedded Linux server to connect to.
       
  2045 */
       
  2046 QVNCScreen::QVNCScreen(int display_id)
       
  2047     : QProxyScreen(display_id, VNCClass)
       
  2048 {
       
  2049     d_ptr = new QVNCScreenPrivate(this);
       
  2050 }
       
  2051 
       
  2052 /*!
       
  2053     Destroys this QVNCScreen object.
       
  2054 */
       
  2055 QVNCScreen::~QVNCScreen()
       
  2056 {
       
  2057     delete d_ptr;
       
  2058 }
       
  2059 
       
  2060 /*!
       
  2061     \reimp
       
  2062 */
       
  2063 void QVNCScreen::setDirty(const QRect &rect)
       
  2064 {
       
  2065     d_ptr->setDirty(rect);
       
  2066 }
       
  2067 
       
  2068 void QVNCScreenPrivate::setDirty(const QRect& rect, bool force)
       
  2069 {
       
  2070     if (rect.isEmpty())
       
  2071         return;
       
  2072 
       
  2073     if (q_ptr->screen())
       
  2074         q_ptr->screen()->setDirty(rect);
       
  2075 
       
  2076     if (!vncServer || !vncServer->isConnected())
       
  2077         return;
       
  2078 
       
  2079     const QRect r = rect.translated(-q_ptr->offset());
       
  2080     const int x1 = r.x() / MAP_TILE_SIZE;
       
  2081     int y = r.y() / MAP_TILE_SIZE;
       
  2082     for (; (y <= r.bottom() / MAP_TILE_SIZE) && y < dirty->mapHeight; y++)
       
  2083         for (int x = x1; (x <= r.right() / MAP_TILE_SIZE) && x < dirty->mapWidth; x++)
       
  2084             dirty->setDirty(x, y, force);
       
  2085 
       
  2086     vncServer->setDirty();
       
  2087 }
       
  2088 
       
  2089 static int getDisplayId(const QString &spec)
       
  2090 {
       
  2091     QRegExp regexp(QLatin1String(":(\\d+)\\b"));
       
  2092     if (regexp.lastIndexIn(spec) != -1) {
       
  2093         const QString capture = regexp.cap(1);
       
  2094         return capture.toInt();
       
  2095     }
       
  2096     return 0;
       
  2097 }
       
  2098 
       
  2099 /*!
       
  2100     \reimp
       
  2101 */
       
  2102 bool QVNCScreen::connect(const QString &displaySpec)
       
  2103 {
       
  2104     QString dspec = displaySpec;
       
  2105     if (dspec.startsWith(QLatin1String("vnc:"), Qt::CaseInsensitive))
       
  2106         dspec = dspec.mid(QString::fromLatin1("vnc:").size());
       
  2107     else if (dspec.compare(QLatin1String("vnc"), Qt::CaseInsensitive) == 0)
       
  2108         dspec = QString();
       
  2109 
       
  2110     const QString displayIdSpec = QString::fromLatin1(" :%1").arg(displayId);
       
  2111     if (dspec.endsWith(displayIdSpec))
       
  2112         dspec = dspec.left(dspec.size() - displayIdSpec.size());
       
  2113 
       
  2114     QStringList args = dspec.split(QLatin1Char(':'),
       
  2115                                    QString::SkipEmptyParts);
       
  2116     QRegExp refreshRegexp(QLatin1String("^refreshrate=(\\d+)$"));
       
  2117     int index = args.indexOf(refreshRegexp);
       
  2118     if (index >= 0) {
       
  2119         d_ptr->refreshRate = refreshRegexp.cap(1).toInt();
       
  2120         args.removeAt(index);
       
  2121         dspec = args.join(QLatin1String(":"));
       
  2122     }
       
  2123 
       
  2124     QString driver = dspec;
       
  2125     int colon = driver.indexOf(QLatin1Char(':'));
       
  2126     if (colon >= 0)
       
  2127         driver.truncate(colon);
       
  2128 
       
  2129     if (QScreenDriverFactory::keys().contains(driver, Qt::CaseInsensitive)) {
       
  2130         const int id = getDisplayId(dspec);
       
  2131         QScreen *s = qt_get_screen(id, dspec.toLatin1().constData());
       
  2132         setScreen(s);
       
  2133     } else { // create virtual screen
       
  2134 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
       
  2135         QScreen::setFrameBufferLittleEndian(false);
       
  2136 #endif
       
  2137 
       
  2138         d = qgetenv("QWS_DEPTH").toInt();
       
  2139         if (!d)
       
  2140             d = 16;
       
  2141 
       
  2142         QByteArray str = qgetenv("QWS_SIZE");
       
  2143         if(!str.isEmpty()) {
       
  2144             sscanf(str.constData(), "%dx%d", &w, &h);
       
  2145             dw = w;
       
  2146             dh = h;
       
  2147         } else {
       
  2148             dw = w = 640;
       
  2149             dh = h = 480;
       
  2150         }
       
  2151 
       
  2152         const QStringList args = displaySpec.split(QLatin1Char(':'),
       
  2153                                                    QString::SkipEmptyParts);
       
  2154 
       
  2155         if (args.contains(QLatin1String("paintonscreen"), Qt::CaseInsensitive))
       
  2156             d_ptr->doOnScreenSurface = true;
       
  2157 
       
  2158         QRegExp depthRegexp(QLatin1String("^depth=(\\d+)$"));
       
  2159         if (args.indexOf(depthRegexp) != -1)
       
  2160             d = depthRegexp.cap(1).toInt();
       
  2161 
       
  2162         QRegExp sizeRegexp(QLatin1String("^size=(\\d+)x(\\d+)$"));
       
  2163         if (args.indexOf(sizeRegexp) != -1) {
       
  2164             dw = w = sizeRegexp.cap(1).toInt();
       
  2165             dh = h = sizeRegexp.cap(2).toInt();
       
  2166         }
       
  2167 
       
  2168         // Handle display physical size spec.
       
  2169         QRegExp mmWidthRegexp(QLatin1String("^mmWidth=?(\\d+)$"));
       
  2170         if (args.indexOf(mmWidthRegexp) != -1) {
       
  2171             const int mmWidth = mmWidthRegexp.cap(1).toInt();
       
  2172             if (mmWidth > 0)
       
  2173                 d_ptr->dpiX = dw * 25.4 / mmWidth;
       
  2174         }
       
  2175         QRegExp mmHeightRegexp(QLatin1String("^mmHeight=?(\\d+)$"));
       
  2176         if (args.indexOf(mmHeightRegexp) != -1) {
       
  2177             const int mmHeight = mmHeightRegexp.cap(1).toInt();
       
  2178             if (mmHeight > 0)
       
  2179                 d_ptr->dpiY = dh * 25.4 / mmHeight;
       
  2180         }
       
  2181         QRegExp dpiRegexp(QLatin1String("^dpi=(\\d+)(?:,(\\d+))?$"));
       
  2182         if (args.indexOf(dpiRegexp) != -1) {
       
  2183             const qreal dpiX = dpiRegexp.cap(1).toFloat();
       
  2184             const qreal dpiY = dpiRegexp.cap(2).toFloat();
       
  2185             if (dpiX > 0)
       
  2186                 d_ptr->dpiX = dpiX;
       
  2187             d_ptr->dpiY = (dpiY > 0 ? dpiY : dpiX);
       
  2188         }
       
  2189 
       
  2190         if (args.contains(QLatin1String("noDisablePainting")))
       
  2191             d_ptr->noDisablePainting = true;
       
  2192 
       
  2193         QWSServer::setDefaultMouse("None");
       
  2194         QWSServer::setDefaultKeyboard("None");
       
  2195 
       
  2196         d_ptr->configure();
       
  2197     }
       
  2198 
       
  2199     // XXX
       
  2200     qt_screen = this;
       
  2201 
       
  2202     return true;
       
  2203 }
       
  2204 
       
  2205 /*!
       
  2206     \reimp
       
  2207 */
       
  2208 void QVNCScreen::disconnect()
       
  2209 {
       
  2210     QProxyScreen::disconnect();
       
  2211 #if !defined(QT_NO_QWS_MULTIPROCESS) && !defined(QT_NO_SHAREDMEMORY)
       
  2212     d_ptr->shm.detach();
       
  2213 #endif
       
  2214 }
       
  2215 
       
  2216 /*!
       
  2217     \reimp
       
  2218 */
       
  2219 bool QVNCScreen::initDevice()
       
  2220 {
       
  2221     if (!QProxyScreen::screen() && d == 4) {
       
  2222         screencols = 16;
       
  2223         int val = 0;
       
  2224         for (int idx = 0; idx < 16; idx++, val += 17) {
       
  2225             screenclut[idx] = qRgb(val, val, val);
       
  2226         }
       
  2227     }
       
  2228     d_ptr->vncServer = new QVNCServer(this, displayId);
       
  2229     d_ptr->vncServer->setRefreshRate(d_ptr->refreshRate);
       
  2230 
       
  2231     switch (depth()) {
       
  2232 #ifdef QT_QWS_DEPTH_32
       
  2233     case 32:
       
  2234         d_ptr->dirty = new QVNCDirtyMapOptimized<quint32>(this);
       
  2235         break;
       
  2236 #endif
       
  2237 #ifdef QT_QWS_DEPTH_24
       
  2238     case 24:
       
  2239         d_ptr->dirty = new QVNCDirtyMapOptimized<qrgb888>(this);
       
  2240         break;
       
  2241 #endif
       
  2242 #ifdef QT_QWS_DEPTH_18
       
  2243     case 18:
       
  2244         d_ptr->dirty = new QVNCDirtyMapOptimized<qrgb666>(this);
       
  2245         break;
       
  2246 #endif
       
  2247 #ifdef QT_QWS_DEPTH_16
       
  2248     case 16:
       
  2249         d_ptr->dirty = new QVNCDirtyMapOptimized<quint16>(this);
       
  2250         break;
       
  2251 #endif
       
  2252 #ifdef QT_QWS_DEPTH_15
       
  2253     case 15:
       
  2254         d_ptr->dirty = new QVNCDirtyMapOptimized<qrgb555>(this);
       
  2255         break;
       
  2256 #endif
       
  2257 #ifdef QT_QWS_DEPTH_12
       
  2258     case 12:
       
  2259         d_ptr->dirty = new QVNCDirtyMapOptimized<qrgb444>(this);
       
  2260         break;
       
  2261 #endif
       
  2262 #ifdef QT_QWS_DEPTH_8
       
  2263     case 8:
       
  2264         d_ptr->dirty = new QVNCDirtyMapOptimized<quint8>(this);
       
  2265         break;
       
  2266 #endif
       
  2267     default:
       
  2268         qWarning("QVNCScreen::initDevice: No support for screen depth %d",
       
  2269                  depth());
       
  2270         d_ptr->dirty = 0;
       
  2271         return false;
       
  2272     }
       
  2273 
       
  2274 
       
  2275     const bool ok = QProxyScreen::initDevice();
       
  2276 #ifndef QT_NO_QWS_CURSOR
       
  2277     qt_screencursor = new QVNCCursor(this);
       
  2278 #endif
       
  2279     if (QProxyScreen::screen())
       
  2280         return ok;
       
  2281 
       
  2282     // Disable painting if there is only 1 display and nothing is attached to the VNC server
       
  2283     if (!d_ptr->noDisablePainting)
       
  2284         QWSServer::instance()->enablePainting(false);
       
  2285 
       
  2286     return true;
       
  2287 }
       
  2288 
       
  2289 /*!
       
  2290     \reimp
       
  2291 */
       
  2292 void QVNCScreen::shutdownDevice()
       
  2293 {
       
  2294     QProxyScreen::shutdownDevice();
       
  2295     delete d_ptr->vncServer;
       
  2296     delete d_ptr->dirty;
       
  2297 }
       
  2298 
       
  2299 QT_END_NAMESPACE
       
  2300 
       
  2301 #endif // QT_NO_QWS_VNC