1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qvncserver.h"
43 
44 #include <QtCore/qtimer.h>
45 #include <QtCore/qregexp.h>
46 #include <QtGui/qwidget.h>
47 #include <QtGui/qpolygon.h>
48 #include <QtGui/qpainter.h>
49 
50 #include <QtGui/qevent.h>
51 #include <QWindowSystemInterface>
52 
53 #include <qplatformdefs.h>
54 
55 #include <qdebug.h>
56 
57 #include <stdlib.h>
58 
59 
60 #define QT_QWS_VNC_DEBUG
61 #define QT_NO_QWS_CURSOR //###
62 
63 
64 QT_BEGIN_NAMESPACE
65 
66 
67 
68 //copied from qscreen_qws.h
69 #ifndef QT_QWS_DEPTH16_RGB
70 #define QT_QWS_DEPTH16_RGB 565
71 #endif
72 static const int qt_rbits = (QT_QWS_DEPTH16_RGB/100);
73 static const int qt_gbits = (QT_QWS_DEPTH16_RGB/10%10);
74 static const int qt_bbits = (QT_QWS_DEPTH16_RGB%10);
75 static const int qt_red_shift = qt_bbits+qt_gbits-(8-qt_rbits);
76 static const int qt_green_shift = qt_bbits-(8-qt_gbits);
77 static const int qt_neg_blue_shift = 8-qt_bbits;
78 static const int qt_blue_mask = (1<<qt_bbits)-1;
79 static const int qt_green_mask = (1<<(qt_gbits+qt_bbits))-(1<<qt_bbits);
80 static const int qt_red_mask = (1<<(qt_rbits+qt_gbits+qt_bbits))-(1<<(qt_gbits+qt_bbits));
81 
82 static const int qt_red_rounding_shift = qt_red_shift + qt_rbits;
83 static const int qt_green_rounding_shift = qt_green_shift + qt_gbits;
84 static const int qt_blue_rounding_shift = qt_bbits - qt_neg_blue_shift;
85 
86 
qt_conv16ToRgb(ushort c)87 inline QRgb qt_conv16ToRgb(ushort c)
88 {
89     const int r=(c & qt_red_mask);
90     const int g=(c & qt_green_mask);
91     const int b=(c & qt_blue_mask);
92     const int tr = r >> qt_red_shift | r >> qt_red_rounding_shift;
93     const int tg = g >> qt_green_shift | g >> qt_green_rounding_shift;
94     const int tb = b << qt_neg_blue_shift | b >> qt_blue_rounding_shift;
95 
96     return qRgb(tr,tg,tb);
97 }
98 
99 
100 
101 //===========================================================================
102 
103 static const struct {
104     int keysym;
105     int keycode;
106 } keyMap[] = {
107     { 0xff08, Qt::Key_Backspace },
108     { 0xff09, Qt::Key_Tab       },
109     { 0xff0d, Qt::Key_Return    },
110     { 0xff1b, Qt::Key_Escape    },
111     { 0xff63, Qt::Key_Insert    },
112     { 0xffff, Qt::Key_Delete    },
113     { 0xff50, Qt::Key_Home      },
114     { 0xff57, Qt::Key_End       },
115     { 0xff55, Qt::Key_PageUp    },
116     { 0xff56, Qt::Key_PageDown  },
117     { 0xff51, Qt::Key_Left      },
118     { 0xff52, Qt::Key_Up        },
119     { 0xff53, Qt::Key_Right     },
120     { 0xff54, Qt::Key_Down      },
121     { 0xffbe, Qt::Key_F1        },
122     { 0xffbf, Qt::Key_F2        },
123     { 0xffc0, Qt::Key_F3        },
124     { 0xffc1, Qt::Key_F4        },
125     { 0xffc2, Qt::Key_F5        },
126     { 0xffc3, Qt::Key_F6        },
127     { 0xffc4, Qt::Key_F7        },
128     { 0xffc5, Qt::Key_F8        },
129     { 0xffc6, Qt::Key_F9        },
130     { 0xffc7, Qt::Key_F10       },
131     { 0xffc8, Qt::Key_F11       },
132     { 0xffc9, Qt::Key_F12       },
133     { 0xffe1, Qt::Key_Shift     },
134     { 0xffe2, Qt::Key_Shift     },
135     { 0xffe3, Qt::Key_Control   },
136     { 0xffe4, Qt::Key_Control   },
137     { 0xffe7, Qt::Key_Meta      },
138     { 0xffe8, Qt::Key_Meta      },
139     { 0xffe9, Qt::Key_Alt       },
140     { 0xffea, Qt::Key_Alt       },
141     { 0, 0 }
142 };
143 
read(QTcpSocket * s)144 void QRfbRect::read(QTcpSocket *s)
145 {
146     quint16 buf[4];
147     s->read((char*)buf, 8);
148     x = ntohs(buf[0]);
149     y = ntohs(buf[1]);
150     w = ntohs(buf[2]);
151     h = ntohs(buf[3]);
152 }
153 
write(QTcpSocket * s) const154 void QRfbRect::write(QTcpSocket *s) const
155 {
156     quint16 buf[4];
157     buf[0] = htons(x);
158     buf[1] = htons(y);
159     buf[2] = htons(w);
160     buf[3] = htons(h);
161     s->write((char*)buf, 8);
162 }
163 
read(QTcpSocket * s)164 void QRfbPixelFormat::read(QTcpSocket *s)
165 {
166     char buf[16];
167     s->read(buf, 16);
168     bitsPerPixel = buf[0];
169     depth = buf[1];
170     bigEndian = buf[2];
171     trueColor = buf[3];
172 
173     quint16 a = ntohs(*(quint16 *)(buf + 4));
174     redBits = 0;
175     while (a) { a >>= 1; redBits++; }
176 
177     a = ntohs(*(quint16 *)(buf + 6));
178     greenBits = 0;
179     while (a) { a >>= 1; greenBits++; }
180 
181     a = ntohs(*(quint16 *)(buf + 8));
182     blueBits = 0;
183     while (a) { a >>= 1; blueBits++; }
184 
185     redShift = buf[10];
186     greenShift = buf[11];
187     blueShift = buf[12];
188 }
189 
write(QTcpSocket * s)190 void QRfbPixelFormat::write(QTcpSocket *s)
191 {
192     char buf[16];
193     buf[0] = bitsPerPixel;
194     buf[1] = depth;
195     buf[2] = bigEndian;
196     buf[3] = trueColor;
197 
198     quint16 a = 0;
199     for (int i = 0; i < redBits; i++) a = (a << 1) | 1;
200     *(quint16 *)(buf + 4) = htons(a);
201 
202     a = 0;
203     for (int i = 0; i < greenBits; i++) a = (a << 1) | 1;
204     *(quint16 *)(buf + 6) = htons(a);
205 
206     a = 0;
207     for (int i = 0; i < blueBits; i++) a = (a << 1) | 1;
208     *(quint16 *)(buf + 8) = htons(a);
209 
210     buf[10] = redShift;
211     buf[11] = greenShift;
212     buf[12] = blueShift;
213     s->write(buf, 16);
214 }
215 
216 
setName(const char * n)217 void QRfbServerInit::setName(const char *n)
218 {
219     delete[] name;
220     name = new char [strlen(n) + 1];
221     strcpy(name, n);
222 }
223 
read(QTcpSocket * s)224 void QRfbServerInit::read(QTcpSocket *s)
225 {
226     s->read((char *)&width, 2);
227     width = ntohs(width);
228     s->read((char *)&height, 2);
229     height = ntohs(height);
230     format.read(s);
231 
232     quint32 len;
233     s->read((char *)&len, 4);
234     len = ntohl(len);
235 
236     name = new char [len + 1];
237     s->read(name, len);
238     name[len] = '\0';
239 }
240 
write(QTcpSocket * s)241 void QRfbServerInit::write(QTcpSocket *s)
242 {
243     quint16 t = htons(width);
244     s->write((char *)&t, 2);
245     t = htons(height);
246     s->write((char *)&t, 2);
247     format.write(s);
248     quint32 len = strlen(name);
249     len = htonl(len);
250     s->write((char *)&len, 4);
251     s->write(name, strlen(name));
252 }
253 
read(QTcpSocket * s)254 bool QRfbSetEncodings::read(QTcpSocket *s)
255 {
256     if (s->bytesAvailable() < 3)
257         return false;
258 
259     char tmp;
260     s->read(&tmp, 1);        // padding
261     s->read((char *)&count, 2);
262     count = ntohs(count);
263 
264     return true;
265 }
266 
read(QTcpSocket * s)267 bool QRfbFrameBufferUpdateRequest::read(QTcpSocket *s)
268 {
269     if (s->bytesAvailable() < 9)
270         return false;
271 
272     s->read(&incremental, 1);
273     rect.read(s);
274 
275     return true;
276 }
277 
read(QTcpSocket * s)278 bool QRfbKeyEvent::read(QTcpSocket *s)
279 {
280     if (s->bytesAvailable() < 7)
281         return false;
282 
283     s->read(&down, 1);
284     quint16 tmp;
285     s->read((char *)&tmp, 2);  // padding
286 
287     quint32 key;
288     s->read((char *)&key, 4);
289     key = ntohl(key);
290 
291     unicode = 0;
292     keycode = 0;
293     int i = 0;
294     while (keyMap[i].keysym && !keycode) {
295         if (keyMap[i].keysym == (int)key)
296             keycode = keyMap[i].keycode;
297         i++;
298     }
299     if (!keycode) {
300         if (key <= 0xff) {
301             unicode = key;
302             if (key >= 'a' && key <= 'z')
303                 keycode = Qt::Key_A + key - 'a';
304             else if (key >= ' ' && key <= '~')
305                 keycode = Qt::Key_Space + key - ' ';
306         }
307     }
308 
309     return true;
310 }
311 
read(QTcpSocket * s)312 bool QRfbPointerEvent::read(QTcpSocket *s)
313 {
314     if (s->bytesAvailable() < 5)
315         return false;
316 
317     char buttonMask;
318     s->read(&buttonMask, 1);
319 
320     buttons = Qt::NoButton;
321     wheelDirection = WheelNone;
322     if (buttonMask & 1)
323         buttons |= Qt::LeftButton;
324     if (buttonMask & 2)
325         buttons |= Qt::MidButton;
326     if (buttonMask & 4)
327         buttons |= Qt::RightButton;
328     if (buttonMask & 8)
329         wheelDirection = WheelUp;
330     if (buttonMask & 16)
331         wheelDirection = WheelDown;
332     if (buttonMask & 32)
333         wheelDirection = WheelLeft;
334     if (buttonMask & 64)
335         wheelDirection = WheelRight;
336 
337     quint16 tmp;
338     s->read((char *)&tmp, 2);
339     x = ntohs(tmp);
340     s->read((char *)&tmp, 2);
341     y = ntohs(tmp);
342 
343     return true;
344 }
345 
read(QTcpSocket * s)346 bool QRfbClientCutText::read(QTcpSocket *s)
347 {
348     if (s->bytesAvailable() < 7)
349         return false;
350 
351     char tmp[3];
352     s->read(tmp, 3);        // padding
353     s->read((char *)&length, 4);
354     length = ntohl(length);
355 
356     return true;
357 }
358 
359 //===========================================================================
360 
QVNCServer(QVNCScreen * screen)361 QVNCServer::QVNCServer(QVNCScreen *screen)
362     : qvnc_screen(screen), cursor(0)
363 {
364     init(5900);
365 }
366 
QVNCServer(QVNCScreen * screen,int id)367 QVNCServer::QVNCServer(QVNCScreen *screen, int id)
368     : qvnc_screen(screen), cursor(0)
369 {
370     init(5900 + id);
371 }
372 
init(uint port)373 void QVNCServer::init(uint port)
374 {
375     qDebug() << "QVNCServer::init" << port;
376 
377     handleMsg = false;
378     client = 0;
379     encodingsPending = 0;
380     cutTextPending = 0;
381     keymod = 0;
382     state = Unconnected;
383     dirtyCursor = false;
384 
385     refreshRate = 25;
386     timer = new QTimer(this);
387     timer->setSingleShot(true);
388     connect(timer, SIGNAL(timeout()), this, SLOT(checkUpdate()));
389 
390     serverSocket = new QTcpServer(this);
391     if (!serverSocket->listen(QHostAddress::Any, port))
392         qDebug() << "QVNCServer could not connect:" << serverSocket->errorString();
393     else
394         qDebug("QVNCServer created on port %d", port);
395 
396     connect(serverSocket, SIGNAL(newConnection()), this, SLOT(newConnection()));
397 
398 #ifndef QT_NO_QWS_CURSOR
399     qvnc_cursor = 0;
400 #endif
401     encoder = 0;
402 }
403 
~QVNCServer()404 QVNCServer::~QVNCServer()
405 {
406     delete encoder;
407     encoder = 0;
408     delete client;
409     client = 0;
410 #ifndef QT_NO_QWS_CURSOR
411     delete qvnc_cursor;
412     qvnc_cursor = 0;
413 #endif
414 }
415 
setDirty()416 void QVNCServer::setDirty()
417 {
418     if (state == Connected && !timer->isActive() &&
419         ((dirtyMap()->numDirty > 0) || dirtyCursor)) {
420         timer->start();
421     }
422 }
423 
newConnection()424 void QVNCServer::newConnection()
425 {
426     if (client)
427         delete client;
428 
429     client = serverSocket->nextPendingConnection();
430     connect(client,SIGNAL(readyRead()),this,SLOT(readClient()));
431     connect(client,SIGNAL(disconnected()),this,SLOT(discardClient()));
432     handleMsg = false;
433     encodingsPending = 0;
434     cutTextPending = 0;
435     supportHextile = false;
436     wantUpdate = false;
437 
438     timer->start(1000 / refreshRate);
439     dirtyMap()->reset();
440 
441     // send protocol version
442     const char *proto = "RFB 003.003\n";
443     client->write(proto, 12);
444     state = Protocol;
445 
446 //     if (!qvnc_screen->screen())
447 //         QWSServer::instance()->enablePainting(true);
448 }
449 
readClient()450 void QVNCServer::readClient()
451 {
452     switch (state) {
453         case Protocol:
454             if (client->bytesAvailable() >= 12) {
455                 char proto[13];
456                 client->read(proto, 12);
457                 proto[12] = '\0';
458                 qDebug("Client protocol version %s", proto);
459                 // No authentication
460                 quint32 auth = htonl(1);
461                 client->write((char *) &auth, sizeof(auth));
462                 state = Init;
463             }
464             break;
465 
466         case Init:
467             if (client->bytesAvailable() >= 1) {
468                 quint8 shared;
469                 client->read((char *) &shared, 1);
470 
471                 // Server Init msg
472                 QRfbServerInit sim;
473                 QRfbPixelFormat &format = sim.format;
474                 switch (qvnc_screen->depth()) {
475                 case 32:
476                     format.bitsPerPixel = 32;
477                     format.depth = 32;
478                     format.bigEndian = 0;
479                     format.trueColor = true;
480                     format.redBits = 8;
481                     format.greenBits = 8;
482                     format.blueBits = 8;
483                     format.redShift = 16;
484                     format.greenShift = 8;
485                     format.blueShift = 0;
486                     break;
487 
488                 case 24:
489                     format.bitsPerPixel = 24;
490                     format.depth = 24;
491                     format.bigEndian = 0;
492                     format.trueColor = true;
493                     format.redBits = 8;
494                     format.greenBits = 8;
495                     format.blueBits = 8;
496                     format.redShift = 16;
497                     format.greenShift = 8;
498                     format.blueShift = 0;
499                     break;
500 
501                 case 18:
502                     format.bitsPerPixel = 24;
503                     format.depth = 18;
504                     format.bigEndian = 0;
505                     format.trueColor = true;
506                     format.redBits = 6;
507                     format.greenBits = 6;
508                     format.blueBits = 6;
509                     format.redShift = 12;
510                     format.greenShift = 6;
511                     format.blueShift = 0;
512                     break;
513 
514                 case 16:
515                     format.bitsPerPixel = 16;
516                     format.depth = 16;
517                     format.bigEndian = 0;
518                     format.trueColor = true;
519                     format.redBits = 5;
520                     format.greenBits = 6;
521                     format.blueBits = 5;
522                     format.redShift = 11;
523                     format.greenShift = 5;
524                     format.blueShift = 0;
525                     break;
526 
527                 case 15:
528                     format.bitsPerPixel = 16;
529                     format.depth = 15;
530                     format.bigEndian = 0;
531                     format.trueColor = true;
532                     format.redBits = 5;
533                     format.greenBits = 5;
534                     format.blueBits = 5;
535                     format.redShift = 10;
536                     format.greenShift = 5;
537                     format.blueShift = 0;
538                     break;
539 
540                 case 12:
541                     format.bitsPerPixel = 16;
542                     format.depth = 12;
543                     format.bigEndian = 0;
544                     format.trueColor = true;
545                     format.redBits = 4;
546                     format.greenBits = 4;
547                     format.blueBits = 4;
548                     format.redShift = 8;
549                     format.greenShift = 4;
550                     format.blueShift = 0;
551                     break;
552 
553                 case 8:
554                 case 4:
555                     format.bitsPerPixel = 8;
556                     format.depth = 8;
557                     format.bigEndian = 0;
558                     format.trueColor = false;
559                     format.redBits = 0;
560                     format.greenBits = 0;
561                     format.blueBits = 0;
562                     format.redShift = 0;
563                     format.greenShift = 0;
564                     format.blueShift = 0;
565                     break;
566 
567                 default:
568                     qDebug("QVNC cannot drive depth %d", qvnc_screen->depth());
569                     discardClient();
570                     return;
571                 }
572                 sim.width = qvnc_screen->geometry().width();
573                 sim.height = qvnc_screen->geometry().height();
574                 sim.setName("Qt for Embedded Linux VNC Server");
575                 sim.write(client);
576                 state = Connected;
577             }
578             break;
579 
580         case Connected:
581             do {
582                 if (!handleMsg) {
583                     client->read((char *)&msgType, 1);
584                     handleMsg = true;
585                 }
586                 if (handleMsg) {
587                     switch (msgType ) {
588                     case SetPixelFormat:
589                         setPixelFormat();
590                         break;
591                     case FixColourMapEntries:
592                         qDebug("Not supported: FixColourMapEntries");
593                         handleMsg = false;
594                         break;
595                     case SetEncodings:
596                         setEncodings();
597                         break;
598                     case FramebufferUpdateRequest:
599                         frameBufferUpdateRequest();
600                         break;
601                     case KeyEvent:
602                         keyEvent();
603                         break;
604                     case PointerEvent:
605                         pointerEvent();
606                         break;
607                     case ClientCutText:
608                         clientCutText();
609                         break;
610                     default:
611                         qDebug("Unknown message type: %d", (int)msgType);
612                         handleMsg = false;
613                     }
614                 }
615             } while (!handleMsg && client->bytesAvailable());
616             break;
617     default:
618         break;
619     }
620 }
621 
622 #if 0//Q_BYTE_ORDER == Q_BIG_ENDIAN
623 bool QVNCScreen::swapBytes() const
624 {
625     if (depth() != 16)
626         return false;
627 
628     if (screen())
629         return screen()->frameBufferLittleEndian();
630     return frameBufferLittleEndian();
631 }
632 #endif
633 
setPixelFormat()634 void QVNCServer::setPixelFormat()
635 {
636     if (client->bytesAvailable() >= 19) {
637         char buf[3];
638         client->read(buf, 3); // just padding
639         pixelFormat.read(client);
640 #ifdef QT_QWS_VNC_DEBUG
641         qDebug("Want format: %d %d %d %d %d %d %d %d %d %d",
642             int(pixelFormat.bitsPerPixel),
643             int(pixelFormat.depth),
644             int(pixelFormat.bigEndian),
645             int(pixelFormat.trueColor),
646             int(pixelFormat.redBits),
647             int(pixelFormat.greenBits),
648             int(pixelFormat.blueBits),
649             int(pixelFormat.redShift),
650             int(pixelFormat.greenShift),
651             int(pixelFormat.blueShift));
652 #endif
653         if (!pixelFormat.trueColor) {
654             qDebug("Can only handle true color clients");
655             discardClient();
656         }
657         handleMsg = false;
658         sameEndian = (QSysInfo::ByteOrder == QSysInfo::BigEndian) == !!pixelFormat.bigEndian;
659         needConversion = pixelConversionNeeded();
660 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
661         swapBytes = qvnc_screen->swapBytes();
662 #endif
663     }
664 }
665 
setEncodings()666 void QVNCServer::setEncodings()
667 {
668     QRfbSetEncodings enc;
669 
670     if (!encodingsPending && enc.read(client)) {
671         encodingsPending = enc.count;
672         if (!encodingsPending)
673             handleMsg = false;
674     }
675 
676     if (encoder) {
677         delete encoder;
678         encoder = 0;
679     }
680 
681     enum Encodings {
682         Raw = 0,
683         CopyRect = 1,
684         RRE = 2,
685         CoRRE = 4,
686         Hextile = 5,
687         ZRLE = 16,
688         Cursor = -239,
689         DesktopSize = -223
690     };
691 
692     supportCursor = false;
693 
694     if (encodingsPending && (unsigned)client->bytesAvailable() >=
695                                 encodingsPending * sizeof(quint32)) {
696         for (int i = 0; i < encodingsPending; ++i) {
697             qint32 enc;
698             client->read((char *)&enc, sizeof(qint32));
699             enc = ntohl(enc);
700 #ifdef QT_QWS_VNC_DEBUG
701             qDebug("QVNCServer::setEncodings: %d", enc);
702 #endif
703             switch (enc) {
704             case Raw:
705                 if (!encoder) {
706                     encoder = new QRfbRawEncoder(this);
707 #ifdef QT_QWS_VNC_DEBUG
708                     qDebug("QVNCServer::setEncodings: using raw");
709 #endif
710                 }
711                break;
712             case CopyRect:
713                 supportCopyRect = true;
714                 break;
715             case RRE:
716                 supportRRE = true;
717                 break;
718             case CoRRE:
719                 supportCoRRE = true;
720                 break;
721             case Hextile:
722                 supportHextile = true;
723                 if (encoder)
724                     break;
725                 switch (qvnc_screen->depth()) {
726 #ifdef QT_QWS_DEPTH_8
727                 case 8:
728                     encoder = new QRfbHextileEncoder<quint8>(this);
729                     break;
730 #endif
731 #ifdef QT_QWS_DEPTH_12
732                 case 12:
733                     encoder = new QRfbHextileEncoder<qrgb444>(this);
734                     break;
735 #endif
736 #ifdef QT_QWS_DEPTH_15
737                 case 15:
738                     encoder = new QRfbHextileEncoder<qrgb555>(this);
739                     break;
740 #endif
741 #ifdef QT_QWS_DEPTH_16
742                 case 16:
743                     encoder = new QRfbHextileEncoder<quint16>(this);
744                     break;
745 #endif
746 #ifdef QT_QWS_DEPTH_18
747                 case 18:
748                     encoder = new QRfbHextileEncoder<qrgb666>(this);
749                     break;
750 #endif
751 #ifdef QT_QWS_DEPTH_24
752                 case 24:
753                     encoder = new QRfbHextileEncoder<qrgb888>(this);
754                     break;
755 #endif
756 #ifdef QT_QWS_DEPTH_32
757                 case 32:
758                     encoder = new QRfbHextileEncoder<quint32>(this);
759                     break;
760 #endif
761                 default:
762                     break;
763                 }
764 #ifdef QT_QWS_VNC_DEBUG
765                 qDebug("QVNCServer::setEncodings: using hextile");
766 #endif
767                 break;
768             case ZRLE:
769                 supportZRLE = true;
770                 break;
771             case Cursor:
772                 supportCursor = true;
773 #ifndef QT_NO_QWS_CURSOR
774                 if (!qvnc_screen->screen() || qt_screencursor->isAccelerated()) {
775                     delete qvnc_cursor;
776                     qvnc_cursor = new QVNCClientCursor(this);
777                 }
778 #endif
779                 break;
780             case DesktopSize:
781                 supportDesktopSize = true;
782                 break;
783             default:
784                 break;
785             }
786         }
787         handleMsg = false;
788         encodingsPending = 0;
789     }
790 
791     if (!encoder) {
792         encoder = new QRfbRawEncoder(this);
793 #ifdef QT_QWS_VNC_DEBUG
794         qDebug("QVNCServer::setEncodings: fallback using raw");
795 #endif
796     }
797 
798     if (cursor)
799         cursor->setCursorMode(supportCursor);
800 }
801 
frameBufferUpdateRequest()802 void QVNCServer::frameBufferUpdateRequest()
803 {
804     QRfbFrameBufferUpdateRequest ev;
805 
806     if (ev.read(client)) {
807         if (!ev.incremental) {
808             QRect r(ev.rect.x, ev.rect.y, ev.rect.w, ev.rect.h);
809 ////###            r.translate(qvnc_screen->offset());
810             qvnc_screen->d_ptr->setDirty(r, true);
811         }
812         wantUpdate = true;
813         checkUpdate();
814         handleMsg = false;
815     }
816 }
817 
buttonChange(Qt::MouseButtons before,Qt::MouseButtons after,Qt::MouseButton * button,bool * isPress)818 static bool buttonChange(Qt::MouseButtons before, Qt::MouseButtons after, Qt::MouseButton *button, bool *isPress)
819 {
820     if (before == after)
821         return false;
822     for (int b = Qt::LeftButton;  b <= Qt::MidButton; b<<=1) {
823         if ((before & b) != (after & b)) {
824             *button = static_cast<Qt::MouseButton>(b);
825             *isPress = (after & b);
826             return true;
827         }
828     }
829     return false;
830 }
831 
pointerEvent()832 void QVNCServer::pointerEvent()
833 {
834     QPoint screenOffset = this->screen()->geometry().topLeft();
835 
836     QRfbPointerEvent ev;
837     if (ev.read(client)) {
838         QPoint eventPoint(ev.x, ev.y);
839         eventPoint += screenOffset;         // local to global translation
840 
841         if (ev.wheelDirection == ev.WheelNone) {
842             QEvent::Type type = QEvent::MouseMove;
843             Qt::MouseButton button = Qt::NoButton;
844             bool isPress;
845             if (buttonChange(buttons, ev.buttons, &button, &isPress))
846                 type = isPress ? QEvent::MouseButtonPress : QEvent::MouseButtonRelease;
847             QWindowSystemInterface::handleMouseEvent(0, eventPoint, eventPoint, ev.buttons);
848         } else {
849             // No buttons or motion reported at the same time as wheel events
850             Qt::Orientation orientation;
851             if (ev.wheelDirection == ev.WheelLeft || ev.wheelDirection == ev.WheelRight)
852                 orientation = Qt::Horizontal;
853             else
854                 orientation = Qt::Vertical;
855             int delta = 120 * ((ev.wheelDirection == ev.WheelLeft || ev.wheelDirection == ev.WheelUp) ? 1 : -1);
856             QWindowSystemInterface::handleWheelEvent(0, eventPoint, eventPoint, delta, orientation);
857         }
858         handleMsg = false;
859     }
860 }
861 
keyEvent()862 void QVNCServer::keyEvent()
863 {
864     QRfbKeyEvent ev;
865 
866     if (ev.read(client)) {
867         if (ev.keycode == Qt::Key_Shift)
868             keymod = ev.down ? keymod | Qt::ShiftModifier :
869                                keymod & ~Qt::ShiftModifier;
870         else if (ev.keycode == Qt::Key_Control)
871             keymod = ev.down ? keymod | Qt::ControlModifier :
872                                keymod & ~Qt::ControlModifier;
873         else if (ev.keycode == Qt::Key_Alt)
874             keymod = ev.down ? keymod | Qt::AltModifier :
875                                keymod & ~Qt::AltModifier;
876         if (ev.unicode || ev.keycode) {
877 //            qDebug() << "keyEvent" << hex << ev.unicode << ev.keycode <<  keymod << ev.down;
878             QEvent::Type type = ev.down ? QEvent::KeyPress : QEvent::KeyRelease;
879             QString str;
880             if (ev.unicode && ev.unicode != 0xffff)
881                 str = QString(ev.unicode);
882             QWindowSystemInterface::handleKeyEvent(0, type, ev.keycode, keymod, str);
883         }
884         handleMsg = false;
885     }
886 }
887 
clientCutText()888 void QVNCServer::clientCutText()
889 {
890     QRfbClientCutText ev;
891 
892     if (cutTextPending == 0 && ev.read(client)) {
893         cutTextPending = ev.length;
894         if (!cutTextPending)
895             handleMsg = false;
896     }
897 
898     if (cutTextPending && client->bytesAvailable() >= cutTextPending) {
899         char *text = new char [cutTextPending+1];
900         client->read(text, cutTextPending);
901         delete [] text;
902         cutTextPending = 0;
903         handleMsg = false;
904     }
905 }
906 
907 // stride in bytes
908 template <class SRC>
read(const uchar * data,int width,int height,int stride)909 bool QRfbSingleColorHextile<SRC>::read(const uchar *data,
910                                        int width, int height, int stride)
911 {
912     const int depth = encoder->server->screen()->depth();
913     if (width % (depth / 8)) // hw: should rather fallback to simple loop
914         return false;
915 
916     static int alwaysFalse = qgetenv("QT_VNC_NOCHECKFILL").toInt();
917     if (alwaysFalse)
918         return false;
919 
920     switch (depth) {
921     case 4: {
922         const quint8 *data8 = reinterpret_cast<const quint8*>(data);
923         if ((data8[0] & 0xf) != (data8[0] >> 4))
924             return false;
925         width /= 2;
926     } // fallthrough
927     case 8: {
928         const quint8 *data8 = reinterpret_cast<const quint8*>(data);
929         if (data8[0] != data8[1])
930             return false;
931         width /= 2;
932     } // fallthrough
933     case 12:
934     case 15:
935     case 16: {
936         const quint16 *data16 = reinterpret_cast<const quint16*>(data);
937         if (data16[0] != data16[1])
938             return false;
939         width /= 2;
940     } // fallthrough
941     case 18:
942     case 24:
943     case 32: {
944         const quint32 *data32 = reinterpret_cast<const quint32*>(data);
945         const quint32 first = data32[0];
946         const int linestep = (stride / sizeof(quint32)) - width;
947         for (int y = 0; y < height; ++y) {
948             for (int x = 0; x < width; ++x) {
949                 if (*(data32++) != first)
950                     return false;
951             }
952             data32 += linestep;
953         }
954         break;
955     }
956     default:
957         return false;
958     }
959 
960     SRC color = reinterpret_cast<const SRC*>(data)[0];
961     encoder->newBg |= (color != encoder->bg);
962     encoder->bg = color;
963     return true;
964 }
965 
966 template <class SRC>
write(QTcpSocket * socket) const967 void QRfbSingleColorHextile<SRC>::write(QTcpSocket *socket) const
968 {
969     if (true || encoder->newBg) {
970         const int bpp = encoder->server->clientBytesPerPixel();
971         const int padding = 3;
972         QVarLengthArray<char> buffer(padding + 1 + bpp);
973         buffer[padding] = 2; // BackgroundSpecified
974         encoder->server->convertPixels(buffer.data() + padding + 1,
975                                        reinterpret_cast<char*>(&encoder->bg),
976                                        1);
977         socket->write(buffer.data() + padding, bpp + 1);
978 //        encoder->newBg = false;
979     } else {
980         char subenc = 0;
981         socket->write(&subenc, 1);
982     }
983 }
984 
985 template <class SRC>
read(const uchar * data,int width,int height,int stride)986 bool QRfbDualColorHextile<SRC>::read(const uchar *data,
987                                      int width, int height, int stride)
988 {
989     const SRC *ptr = reinterpret_cast<const SRC*>(data);
990     const int linestep = (stride / sizeof(SRC)) - width;
991 
992     SRC c1;
993     SRC c2 = 0;
994     int n1 = 0;
995     int n2 = 0;
996     int x = 0;
997     int y = 0;
998 
999     c1 = *ptr;
1000 
1001     // find second color
1002     while (y < height) {
1003         while (x < width) {
1004             if (*ptr == c1) {
1005                 ++n1;
1006             } else {
1007                 c2 = *ptr;
1008                 goto found_second_color;
1009             }
1010             ++ptr;
1011             ++x;
1012         }
1013         x = 0;
1014         ptr += linestep;
1015         ++y;
1016     }
1017 
1018 found_second_color:
1019     // finish counting
1020     while (y < height) {
1021         while (x < width) {
1022             if (*ptr == c1) {
1023                 ++n1;
1024             } else if (*ptr == c2) {
1025                 ++n2;
1026             } else {
1027                 return false;
1028             }
1029             ++ptr;
1030             ++x;
1031         }
1032         x = 0;
1033         ptr += linestep;
1034         ++y;
1035     }
1036 
1037     if (n2 > n1) {
1038         const quint32 tmpC = c1;
1039         c1 = c2;
1040         c2 = tmpC;
1041     }
1042 
1043     encoder->newBg |= (c1 != encoder->bg);
1044     encoder->newFg |= (c2 != encoder->fg);
1045 
1046     encoder->bg = c1;
1047     encoder->fg = c2;
1048 
1049     // create map
1050     bool inRect = false;
1051     numRects = 0;
1052     ptr = reinterpret_cast<const SRC*>(data);
1053     for (y = 0; y < height; ++y) {
1054         for (x = 0; x < width; ++x) {
1055             if (inRect && *ptr == encoder->bg) {
1056                 // rect finished
1057                 setWidth(x - lastx());
1058                 next();
1059                 inRect = false;
1060             } else if (!inRect && *ptr == encoder->fg) {
1061                 // rect start
1062                 setX(x);
1063                 setY(y);
1064                 setHeight(1);
1065                 inRect = true;
1066             }
1067             ++ptr;
1068         }
1069         if (inRect) {
1070             // finish rect
1071             setWidth(width - lastx());
1072             next();
1073             inRect = false;
1074         }
1075         ptr += linestep;
1076     }
1077 
1078     return true;
1079 }
1080 
1081 template <class SRC>
write(QTcpSocket * socket) const1082 void QRfbDualColorHextile<SRC>::write(QTcpSocket *socket) const
1083 {
1084     const int bpp = encoder->server->clientBytesPerPixel();
1085     const int padding = 3;
1086     QVarLengthArray<char> buffer(padding + 2 * bpp + sizeof(char) + sizeof(numRects));
1087     char &subenc = buffer[padding];
1088     int n = padding + sizeof(subenc);
1089 
1090     subenc = 0x8; // AnySubrects
1091 
1092     if (encoder->newBg) {
1093         subenc |= 0x2; // Background
1094         encoder->server->convertPixels(buffer.data() + n, (char*)&encoder->bg, 1);
1095         n += bpp;
1096 //        encoder->newBg = false;
1097     }
1098 
1099     if (encoder->newFg) {
1100         subenc |= 0x4; // Foreground
1101         encoder->server->convertPixels(buffer.data() + n, (char*)&encoder->fg, 1);
1102         n += bpp;
1103 //        encoder->newFg = false;
1104     }
1105     buffer[n] = numRects;
1106     n += sizeof(numRects);
1107 
1108     socket->write(buffer.data() + padding, n - padding);
1109     socket->write((char*)rects, numRects * sizeof(Rect));
1110 }
1111 
1112 template <class SRC>
next()1113 void QRfbDualColorHextile<SRC>::next()
1114 {
1115     for (int r = numRects - 1; r >= 0; --r) {
1116         if (recty(r) == lasty())
1117             continue;
1118         if (recty(r) < lasty() - 1) // only search previous scanline
1119             break;
1120         if (rectx(r) == lastx() && width(r) == width(numRects)) {
1121             ++rects[r].wh;
1122             return;
1123         }
1124     }
1125     ++numRects;
1126 }
1127 
1128 template <class SRC>
setColor(SRC color)1129 inline void QRfbMultiColorHextile<SRC>::setColor(SRC color)
1130 {
1131     encoder->server->convertPixels(reinterpret_cast<char*>(rect(numRects)),
1132                                    (const char*)&color, 1);
1133 }
1134 
1135 template <class SRC>
beginRect()1136 inline bool QRfbMultiColorHextile<SRC>::beginRect()
1137 {
1138     if ((rects.size() + bpp + 2) > maxRectsSize)
1139         return false;
1140     rects.resize(rects.size() + bpp + 2);
1141     return true;
1142 }
1143 
1144 template <class SRC>
endRect()1145 inline void QRfbMultiColorHextile<SRC>::endRect()
1146 {
1147     setHeight(numRects, 1);
1148     ++numRects;
1149 }
1150 
1151 template <class SRC>
read(const uchar * data,int width,int height,int stride)1152 bool QRfbMultiColorHextile<SRC>::read(const uchar *data,
1153                                       int width, int height, int stride)
1154 {
1155     const SRC *ptr = reinterpret_cast<const SRC*>(data);
1156     const int linestep = (stride / sizeof(SRC)) - width;
1157 
1158     bpp = encoder->server->clientBytesPerPixel();
1159 
1160     if (encoder->newBg)
1161         encoder->bg = ptr[0];
1162 
1163     const SRC bg = encoder->bg;
1164     SRC color = bg;
1165     bool inRect = false;
1166 
1167     numRects = 0;
1168     rects.clear();
1169 
1170     for (int y = 0; y < height; ++y) {
1171         for (int x = 0; x < width; ++x) {
1172             if (inRect && *ptr != color) { // end rect
1173                 setWidth(numRects, x - rectx(numRects));
1174                 endRect();
1175                 inRect = false;
1176             }
1177 
1178             if (!inRect && *ptr != bg) { // begin rect
1179                 if (!beginRect())
1180                     return false;
1181                 inRect = true;
1182                 color = *ptr;
1183                 setColor(color);
1184                 setX(numRects, x);
1185                 setY(numRects, y);
1186             }
1187             ++ptr;
1188         }
1189         if (inRect) { // end rect
1190             setWidth(numRects, width - rectx(numRects));
1191             endRect();
1192             inRect = false;
1193         }
1194         ptr += linestep;
1195     }
1196 
1197     return true;
1198 }
1199 
1200 template <class SRC>
write(QTcpSocket * socket) const1201 void QRfbMultiColorHextile<SRC>::write(QTcpSocket *socket) const
1202 {
1203     const int padding = 3;
1204     QVarLengthArray<quint8> buffer(bpp + padding + sizeof(quint8) + sizeof(numRects));
1205 
1206     quint8 &subenc = buffer[padding];
1207     int n = padding + sizeof(quint8);
1208 
1209     subenc = 8 | 16; // AnySubrects | SubrectsColoured
1210 
1211     if (encoder->newBg) {
1212         subenc |= 0x2; // Background
1213         encoder->server->convertPixels(reinterpret_cast<char*>(buffer.data() + n),
1214                                        reinterpret_cast<const char*>(&encoder->bg),
1215                                        1);
1216         n += bpp;
1217 //        encoder->newBg = false;
1218     }
1219 
1220     buffer[n] = numRects;
1221     n += sizeof(numRects);
1222 
1223     socket->write(reinterpret_cast<const char*>(buffer.data() + padding),
1224                   n - padding);
1225     socket->write(reinterpret_cast<const char*>(rects.constData()),
1226                   rects.size());
1227 }
1228 
pixelConversionNeeded() const1229 bool QVNCServer::pixelConversionNeeded() const
1230 {
1231     if (!sameEndian)
1232         return true;
1233 
1234 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
1235     if (qvnc_screen->swapBytes())
1236         return true;
1237 #endif
1238 
1239     const int screendepth = qvnc_screen->depth();
1240     if (screendepth != pixelFormat.bitsPerPixel)
1241         return true;
1242 
1243     switch (screendepth) {
1244     case 32:
1245     case 24:
1246         return false;
1247     case 18:
1248         return (pixelFormat.redBits == 6
1249                 && pixelFormat.greenBits == 6
1250                 && pixelFormat.blueBits == 6);
1251     case 16:
1252         return (pixelFormat.redBits == 5
1253                 && pixelFormat.greenBits == 6
1254                 && pixelFormat.blueBits == 5);
1255     case 15:
1256         return (pixelFormat.redBits == 5
1257                 && pixelFormat.greenBits == 5
1258                 && pixelFormat.blueBits == 5);
1259     case 12:
1260         return (pixelFormat.redBits == 4
1261                 && pixelFormat.greenBits == 4
1262                 && pixelFormat.blueBits == 4);
1263     }
1264     return true;
1265 }
1266 
1267 // count: number of pixels
convertPixels(char * dst,const char * src,int count) const1268 void QVNCServer::convertPixels(char *dst, const char *src, int count) const
1269 {
1270     const int screendepth = qvnc_screen->depth();
1271     const bool isBgr = false; //### qvnc_screen->pixelType() == QScreen::BGRPixel;
1272 
1273     // cutoffs
1274 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
1275     if (!swapBytes)
1276 #endif
1277     if (sameEndian) {
1278         if (screendepth == pixelFormat.bitsPerPixel) { // memcpy cutoffs
1279 
1280             switch (screendepth) {
1281             case 32:
1282                 memcpy(dst, src, count * sizeof(quint32));
1283                 return;
1284             case 16:
1285                 if (pixelFormat.redBits == 5
1286                     && pixelFormat.greenBits == 6
1287                     && pixelFormat.blueBits == 5)
1288                 {
1289                     memcpy(dst, src, count * sizeof(quint16));
1290                     return;
1291                 }
1292             }
1293         } else if (screendepth == 16 && pixelFormat.bitsPerPixel == 32) {
1294 #if defined(__i386__) // Currently fails on ARM if dst is not 4 byte aligned
1295             const quint32 *src32 = reinterpret_cast<const quint32*>(src);
1296             quint32 *dst32 = reinterpret_cast<quint32*>(dst);
1297             int count32 = count * sizeof(quint16) / sizeof(quint32);
1298             while (count32--) {
1299                 const quint32 s = *src32++;
1300                 quint32 result1;
1301                 quint32 result2;
1302 
1303                 // red
1304                 result1 = ((s & 0xf8000000) | ((s & 0xe0000000) >> 5)) >> 8;
1305                 result2 = ((s & 0x0000f800) | ((s & 0x0000e000) >> 5)) << 8;
1306 
1307                 // green
1308                 result1 |= ((s & 0x07e00000) | ((s & 0x06000000) >> 6)) >> 11;
1309                 result2 |= ((s & 0x000007e0) | ((s & 0x00000600) >> 6)) << 5;
1310 
1311                 // blue
1312                 result1 |= ((s & 0x001f0000) | ((s & 0x001c0000) >> 5)) >> 13;
1313                 result2 |= ((s & 0x0000001f) | ((s & 0x0000001c) >> 5)) << 3;
1314 
1315                 *dst32++ = result2;
1316                 *dst32++ = result1;
1317             }
1318             if (count & 0x1) {
1319                 const quint16 *src16 = reinterpret_cast<const quint16*>(src);
1320                 *dst32 = qt_conv16ToRgb(src16[count - 1]);
1321             }
1322             return;
1323 #endif
1324         }
1325     }
1326 
1327     const int bytesPerPixel = (pixelFormat.bitsPerPixel + 7) / 8;
1328 
1329 //    nibble = 0;
1330 
1331     for (int i = 0; i < count; ++i) {
1332         int r, g, b;
1333 
1334         switch (screendepth) {
1335 #if 0
1336         case 4: {
1337             if (!nibble) {
1338                 r = ((*src) & 0x0f) << 4;
1339             } else {
1340                 r = (*src) & 0xf0;
1341                 src++;
1342             }
1343             nibble = !nibble;
1344             g = b = r;
1345             break;
1346         }
1347 #endif
1348 #if 0
1349         case 8: {
1350             QRgb rgb = qvnc_screen->clut()[int(*src)];
1351             r = qRed(rgb);
1352             g = qGreen(rgb);
1353             b = qBlue(rgb);
1354             src++;
1355             break;
1356         }
1357 #endif
1358 #ifdef QT_QWS_DEPTH_12
1359         case 12: {
1360             quint32 p = quint32(*reinterpret_cast<const qrgb444*>(src));
1361             r = qRed(p);
1362             g = qGreen(p);
1363             b = qBlue(p);
1364             src += sizeof(qrgb444);
1365             break;
1366         }
1367 #endif
1368 #ifdef QT_QWS_DEPTH_15
1369         case 15: {
1370             quint32 p = quint32(*reinterpret_cast<const qrgb555*>(src));
1371             r = qRed(p);
1372             g = qGreen(p);
1373             b = qBlue(p);
1374             src += sizeof(qrgb555);
1375             break;
1376         }
1377 #endif
1378         case 16: {
1379             quint16 p = *reinterpret_cast<const quint16*>(src);
1380 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
1381             if (swapBytes)
1382                 p = ((p & 0xff) << 8) | ((p & 0xff00) >> 8);
1383 #endif
1384             r = (p >> 11) & 0x1f;
1385             g = (p >> 5) & 0x3f;
1386             b = p & 0x1f;
1387             r <<= 3;
1388             g <<= 2;
1389             b <<= 3;
1390             src += sizeof(quint16);
1391             break;
1392         }
1393 #ifdef QT_QWS_DEPTH_18
1394         case 18: {
1395             quint32 p = quint32(*reinterpret_cast<const qrgb666*>(src));
1396             r = qRed(p);
1397             g = qGreen(p);
1398             b = qBlue(p);
1399             src += sizeof(qrgb666);
1400             break;
1401         }
1402 #endif
1403 #ifdef QT_QWS_DEPTH_24
1404         case 24: {
1405             quint32 p = quint32(*reinterpret_cast<const qrgb888*>(src));
1406             r = qRed(p);
1407             g = qGreen(p);
1408             b = qBlue(p);
1409             src += sizeof(qrgb888);
1410             break;
1411         }
1412 #endif
1413         case 32: {
1414             quint32 p = *reinterpret_cast<const quint32*>(src);
1415             r = (p >> 16) & 0xff;
1416             g = (p >> 8) & 0xff;
1417             b = p & 0xff;
1418             src += sizeof(quint32);
1419             break;
1420         }
1421         default: {
1422             r = g = b = 0;
1423             qDebug("QVNCServer: don't support %dbpp display", screendepth);
1424             return;
1425         }
1426         }
1427 
1428 #if Q_BYTE_ORDER == Q_BIG_ENDIAN
1429         if (swapBytes ^ isBgr)
1430 #else
1431         if (isBgr)
1432 #endif
1433             qSwap(r, b);
1434 
1435         r >>= (8 - pixelFormat.redBits);
1436         g >>= (8 - pixelFormat.greenBits);
1437         b >>= (8 - pixelFormat.blueBits);
1438 
1439         int pixel = (r << pixelFormat.redShift) |
1440                     (g << pixelFormat.greenShift) |
1441                     (b << pixelFormat.blueShift);
1442 
1443         if (sameEndian || pixelFormat.bitsPerPixel == 8) {
1444             memcpy(dst, &pixel, bytesPerPixel); // XXX: do a simple for-loop instead?
1445             dst += bytesPerPixel;
1446             continue;
1447         }
1448 
1449 
1450         if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
1451             switch (pixelFormat.bitsPerPixel) {
1452             case 16:
1453                 pixel = (((pixel & 0x0000ff00) << 8)  |
1454                          ((pixel & 0x000000ff) << 24));
1455                 break;
1456             case 32:
1457                 pixel = (((pixel & 0xff000000) >> 24) |
1458                          ((pixel & 0x00ff0000) >> 8)  |
1459                          ((pixel & 0x0000ff00) << 8)  |
1460                          ((pixel & 0x000000ff) << 24));
1461                 break;
1462             default:
1463                 qDebug("Cannot handle %d bpp client", pixelFormat.bitsPerPixel);
1464             }
1465         } else { // QSysInfo::ByteOrder == QSysInfo::LittleEndian
1466             switch (pixelFormat.bitsPerPixel) {
1467             case 16:
1468                 pixel = (((pixel & 0xff000000) >> 8) |
1469                          ((pixel & 0x00ff0000) << 8));
1470                 break;
1471             case 32:
1472                 pixel = (((pixel & 0xff000000) >> 24) |
1473                          ((pixel & 0x00ff0000) >> 8)  |
1474                          ((pixel & 0x0000ff00) << 8)  |
1475                          ((pixel & 0x000000ff) << 24));
1476                 break;
1477             default:
1478                 qDebug("Cannot handle %d bpp client",
1479                        pixelFormat.bitsPerPixel);
1480                 break;
1481             }
1482         }
1483         memcpy(dst, &pixel, bytesPerPixel); // XXX: simple for-loop instead?
1484         dst += bytesPerPixel;
1485     }
1486 }
1487 
1488 #ifndef QT_NO_QWS_CURSOR
blendCursor(QImage & image,const QRect & imageRect)1489 static void blendCursor(QImage &image, const QRect &imageRect)
1490 {
1491     const QRect cursorRect = qt_screencursor->boundingRect();
1492     const QRect intersection = (cursorRect & imageRect);
1493     const QRect destRect = intersection.translated(-imageRect.topLeft());
1494     const QRect srcRect = intersection.translated(-cursorRect.topLeft());
1495 
1496     QPainter painter(&image);
1497     painter.drawImage(destRect, qt_screencursor->image(), srcRect);
1498     painter.end();
1499 }
1500 #endif // QT_NO_QWS_CURSOR
1501 
QVNCDirtyMap(QVNCScreen * s)1502 QVNCDirtyMap::QVNCDirtyMap(QVNCScreen *s)
1503     : bytesPerPixel(0), numDirty(0), screen(s)
1504 {
1505     bytesPerPixel = (screen->depth() + 7) / 8;
1506     QSize screenSize = screen->geometry().size();
1507     bufferWidth = screenSize.width();
1508     bufferHeight = screenSize.height();
1509     bufferStride = bufferWidth * bytesPerPixel;
1510     buffer = new uchar[bufferHeight * bufferStride];
1511 
1512     mapWidth = (bufferWidth + MAP_TILE_SIZE - 1) / MAP_TILE_SIZE;
1513     mapHeight = (bufferHeight + MAP_TILE_SIZE - 1) / MAP_TILE_SIZE;
1514     numTiles = mapWidth * mapHeight;
1515     map = new uchar[numTiles];
1516 }
1517 
~QVNCDirtyMap()1518 QVNCDirtyMap::~QVNCDirtyMap()
1519 {
1520     delete[] map;
1521     delete[] buffer;
1522 }
1523 
reset()1524 void QVNCDirtyMap::reset()
1525 {
1526     memset(map, 1, numTiles);
1527     memset(buffer, 0, bufferHeight * bufferStride);
1528     numDirty = numTiles;
1529 }
1530 
dirty(int x,int y) const1531 inline bool QVNCDirtyMap::dirty(int x, int y) const
1532 {
1533     return map[y * mapWidth + x];
1534 }
1535 
setClean(int x,int y)1536 inline void QVNCDirtyMap::setClean(int x, int y)
1537 {
1538     map[y * mapWidth + x] = 0;
1539     --numDirty;
1540 }
1541 
1542 template <class T>
setDirty(int tileX,int tileY,bool force)1543 void QVNCDirtyMapOptimized<T>::setDirty(int tileX, int tileY, bool force)
1544 {
1545     static bool alwaysForce = qgetenv("QT_VNC_NO_COMPAREBUFFER").toInt();
1546     if (alwaysForce)
1547         force = true;
1548 
1549     bool changed = false;
1550 
1551     if (!force) {
1552         const int lstep = screen->linestep();
1553         const int startX = tileX * MAP_TILE_SIZE;
1554         const int startY = tileY * MAP_TILE_SIZE;
1555         const uchar *scrn = screen->base()
1556                             + startY * lstep + startX * bytesPerPixel;
1557         uchar *old = buffer + startY * bufferStride + startX * sizeof(T);
1558 
1559         const int tileHeight = (startY + MAP_TILE_SIZE > bufferHeight ?
1560                                 bufferHeight - startY : MAP_TILE_SIZE);
1561         const int tileWidth = (startX + MAP_TILE_SIZE > bufferWidth ?
1562                                bufferWidth - startX : MAP_TILE_SIZE);
1563         const bool doInlines = (tileWidth == MAP_TILE_SIZE);
1564 
1565         int y = tileHeight;
1566 
1567         if (doInlines) { // hw: memcmp/memcpy is inlined when using constants
1568             while (y) {
1569                 if (memcmp(old, scrn, sizeof(T) * MAP_TILE_SIZE)) {
1570                     changed = true;
1571                     break;
1572                 }
1573                 scrn += lstep;
1574                 old += bufferStride;
1575                 --y;
1576             }
1577 
1578             while (y) {
1579                 memcpy(old, scrn, sizeof(T) * MAP_TILE_SIZE);
1580                 scrn += lstep;
1581                 old += bufferStride;
1582                 --y;
1583             }
1584         } else {
1585             while (y) {
1586                 if (memcmp(old, scrn, sizeof(T) * tileWidth)) {
1587                     changed = true;
1588                     break;
1589                 }
1590                 scrn += lstep;
1591                 old += bufferStride;
1592                 --y;
1593             }
1594 
1595             while (y) {
1596                 memcpy(old, scrn, sizeof(T) * tileWidth);
1597                 scrn += lstep;
1598                 old += bufferStride;
1599                 --y;
1600             }
1601         }
1602     }
1603 
1604     const int mapIndex = tileY * mapWidth + tileX;
1605     if ((force || changed) && !map[mapIndex]) {
1606         map[mapIndex] = 1;
1607         ++numDirty;
1608     }
1609 }
1610 
1611 template <class SRC>
QRfbHextileEncoder(QVNCServer * s)1612 QRfbHextileEncoder<SRC>::QRfbHextileEncoder(QVNCServer *s)
1613     : QRfbEncoder(s),
1614       singleColorHextile(this), dualColorHextile(this), multiColorHextile(this)
1615 {
1616 }
1617 
1618 /*
1619     \internal
1620     Send dirty rects using hextile encoding.
1621 */
1622 template <class SRC>
write()1623 void QRfbHextileEncoder<SRC>::write()
1624 {
1625 //    QWSDisplay::grab(true);
1626 
1627     QVNCDirtyMap *map = server->dirtyMap();
1628     QTcpSocket *socket = server->clientSocket();
1629 
1630     const quint32 encoding = htonl(5); // hextile encoding
1631     const int bytesPerPixel = server->clientBytesPerPixel();
1632 
1633     {
1634         const char tmp[2] = { 0, 0 }; // msg type, padding
1635         socket->write(tmp, sizeof(tmp));
1636     }
1637     {
1638         const quint16 count = htons(map->numDirty);
1639         socket->write((char *)&count, sizeof(count));
1640     }
1641 
1642     if (map->numDirty <= 0) {
1643 //        QWSDisplay::ungrab();
1644         return;
1645     }
1646 
1647     newBg = true;
1648     newFg = true;
1649 
1650     const QImage screenImage = server->screenImage();
1651     QRfbRect rect(0, 0, MAP_TILE_SIZE, MAP_TILE_SIZE);
1652 
1653     QSize screenSize = server->screen()->geometry().size();
1654 
1655     for (int y = 0; y < map->mapHeight; ++y) {
1656         if (rect.y + MAP_TILE_SIZE > screenSize.height())
1657             rect.h = screenSize.height() - rect.y;
1658         rect.w = MAP_TILE_SIZE;
1659         for (int x = 0; x < map->mapWidth; ++x) {
1660             if (!map->dirty(x, y))
1661                 continue;
1662             map->setClean(x, y);
1663 
1664             rect.x = x * MAP_TILE_SIZE;
1665             if (rect.x + MAP_TILE_SIZE > screenSize.width()) //###deviceWidth ???
1666                 rect.w = screenSize.width() - rect.x;
1667             rect.write(socket);
1668 
1669             socket->write((char *)&encoding, sizeof(encoding));
1670 
1671             const uchar *screendata = screenImage.scanLine(rect.y)
1672                                       + rect.x * screenImage.depth() / 8;
1673             int linestep = screenImage.bytesPerLine();
1674 
1675 #ifndef QT_NO_QWS_CURSOR
1676             // hardware cursors must be blended with the screen memory
1677             const bool doBlendCursor = qt_screencursor
1678                                        && !server->hasClientCursor()
1679                                        && qt_screencursor->isAccelerated();
1680             QImage tileImage;
1681             if (doBlendCursor) {
1682                 const QRect tileRect(rect.x, rect.y, rect.w, rect.h);
1683                 const QRect cursorRect = qt_screencursor->boundingRect()
1684                                          .translated(-server->screen()->offset());
1685                 if (tileRect.intersects(cursorRect)) {
1686                     tileImage = screenImage.copy(tileRect);
1687                     blendCursor(tileImage,
1688                                 tileRect.translated(server->screen()->offset()));
1689                     screendata = tileImage.bits();
1690                     linestep = tileImage.bytesPerLine();
1691                 }
1692             }
1693 #endif // QT_NO_QWS_CURSOR
1694 
1695             if (singleColorHextile.read(screendata, rect.w, rect.h, linestep)) {
1696                 singleColorHextile.write(socket);
1697             } else if (dualColorHextile.read(screendata, rect.w, rect.h, linestep)) {
1698                 dualColorHextile.write(socket);
1699             } else if (multiColorHextile.read(screendata, rect.w, rect.h, linestep)) {
1700                 multiColorHextile.write(socket);
1701             } else if (server->doPixelConversion()) {
1702                 const int bufferSize = rect.w * rect.h * bytesPerPixel + 1;
1703                 const int padding = sizeof(quint32) - sizeof(char);
1704                 buffer.resize(bufferSize + padding);
1705 
1706                 buffer[padding] = 1; // Raw subencoding
1707 
1708                 // convert pixels
1709                 char *b = buffer.data() + padding + 1;
1710                 const int bstep = rect.w * bytesPerPixel;
1711                 for (int i = 0; i < rect.h; ++i) {
1712                     server->convertPixels(b, (const char*)screendata, rect.w);
1713                     screendata += linestep;
1714                     b += bstep;
1715                 }
1716                 socket->write(buffer.constData() + padding, bufferSize);
1717             } else {
1718                 quint8 subenc = 1; // Raw subencoding
1719                 socket->write((char *)&subenc, 1);
1720 
1721                 // send pixels
1722                 for (int i = 0; i < rect.h; ++i) {
1723                     socket->write((const char*)screendata,
1724                                   rect.w * bytesPerPixel);
1725                     screendata += linestep;
1726                 }
1727             }
1728         }
1729         if (socket->state() == QAbstractSocket::UnconnectedState)
1730             break;
1731         rect.y += MAP_TILE_SIZE;
1732     }
1733     socket->flush();
1734     Q_ASSERT(map->numDirty == 0);
1735 
1736 //    QWSDisplay::ungrab();
1737 }
1738 
write()1739 void QRfbRawEncoder::write()
1740 {
1741 //    QWSDisplay::grab(false);
1742 
1743     QVNCDirtyMap *map = server->dirtyMap();
1744     QTcpSocket *socket = server->clientSocket();
1745 
1746     const int bytesPerPixel = server->clientBytesPerPixel();
1747     QSize screenSize = server->screen()->geometry().size();
1748 
1749     // create a region from the dirty rects and send the region's merged rects.
1750     QRegion rgn;
1751     if (map) {
1752         for (int y = 0; y < map->mapHeight; ++y) {
1753             for (int x = 0; x < map->mapWidth; ++x) {
1754                 if (!map->dirty(x, y))
1755                     continue;
1756                 rgn += QRect(x * MAP_TILE_SIZE, y * MAP_TILE_SIZE,
1757                              MAP_TILE_SIZE, MAP_TILE_SIZE);
1758                 map->setClean(x, y);
1759             }
1760         }
1761 
1762         rgn &= QRect(0, 0, screenSize.width(),
1763                      screenSize.height());
1764     }
1765     const QVector<QRect> rects = rgn.rects();
1766 
1767     {
1768         const char tmp[2] = { 0, 0 }; // msg type, padding
1769         socket->write(tmp, sizeof(tmp));
1770     }
1771 
1772     {
1773         const quint16 count = htons(rects.size());
1774         socket->write((char *)&count, sizeof(count));
1775     }
1776 
1777     if (rects.size() <= 0) {
1778 //        QWSDisplay::ungrab();
1779         return;
1780     }
1781 
1782     const QImage *screenImage = server->screenImage();
1783 
1784     for (int i = 0; i < rects.size(); ++i) {
1785         const QRect tileRect = rects.at(i);
1786         const QRfbRect rect(tileRect.x(), tileRect.y(),
1787                             tileRect.width(), tileRect.height());
1788         rect.write(socket);
1789 
1790         const quint32 encoding = htonl(0); // raw encoding
1791         socket->write((char *)&encoding, sizeof(encoding));
1792 
1793         int linestep = screenImage->bytesPerLine();
1794         const uchar *screendata = screenImage->scanLine(rect.y)
1795                                   + rect.x * screenImage->depth() / 8;
1796 
1797 #ifndef QT_NO_QWS_CURSOR
1798         // hardware cursors must be blended with the screen memory
1799         const bool doBlendCursor = qt_screencursor
1800                                    && !server->hasClientCursor()
1801                                    && qt_screencursor->isAccelerated();
1802         QImage tileImage;
1803         if (doBlendCursor) {
1804             const QRect cursorRect = qt_screencursor->boundingRect()
1805                                      .translated(-server->screen()->offset());
1806             if (tileRect.intersects(cursorRect)) {
1807                 tileImage = screenImage->copy(tileRect);
1808                 blendCursor(tileImage,
1809                             tileRect.translated(server->screen()->offset()));
1810                 screendata = tileImage.bits();
1811                 linestep = tileImage.bytesPerLine();
1812             }
1813         }
1814 #endif // QT_NO_QWS_CURSOR
1815 
1816         if (server->doPixelConversion()) {
1817             const int bufferSize = rect.w * rect.h * bytesPerPixel;
1818             if (bufferSize > buffer.size())
1819                 buffer.resize(bufferSize);
1820 
1821             // convert pixels
1822             char *b = buffer.data();
1823             const int bstep = rect.w * bytesPerPixel;
1824             for (int i = 0; i < rect.h; ++i) {
1825                 server->convertPixels(b, (const char*)screendata, rect.w);
1826                 screendata += linestep;
1827                 b += bstep;
1828             }
1829             socket->write(buffer.constData(), bufferSize);
1830         } else {
1831             for (int i = 0; i < rect.h; ++i) {
1832                 socket->write((const char*)screendata, rect.w * bytesPerPixel);
1833                 screendata += linestep;
1834             }
1835         }
1836         if (socket->state() == QAbstractSocket::UnconnectedState)
1837             break;
1838     }
1839     socket->flush();
1840 
1841 //    QWSDisplay::ungrab();
1842 }
1843 
screenImage() const1844 inline QImage *QVNCServer::screenImage() const
1845 {
1846     return qvnc_screen->image();
1847 }
1848 
checkUpdate()1849 void QVNCServer::checkUpdate()
1850 {
1851     if (!wantUpdate)
1852         return;
1853 
1854     if (dirtyCursor) {
1855 #ifndef QT_NO_QWS_CURSOR
1856         Q_ASSERT(qvnc_cursor);
1857         qvnc_cursor->write();
1858 #endif
1859         cursor->sendClientCursor();
1860         dirtyCursor = false;
1861         wantUpdate = false;
1862         return;
1863     }
1864 
1865     if (dirtyMap()->numDirty > 0) {
1866         if (encoder)
1867             encoder->write();
1868         wantUpdate = false;
1869     }
1870 }
1871 
discardClient()1872 void QVNCServer::discardClient()
1873 {
1874     timer->stop();
1875     state = Unconnected;
1876     delete encoder;
1877     encoder = 0;
1878 #ifndef QT_NO_QWS_CURSOR
1879     delete qvnc_cursor;
1880     qvnc_cursor = 0;
1881 #endif
1882 //     if (!qvnc_screen->screen())
1883 //         QWSServer::instance()->enablePainting(false);
1884 }
1885 
1886 
1887 
QVNCScreenPrivate(QVNCScreen * parent,int screenId)1888 QVNCScreenPrivate::QVNCScreenPrivate(QVNCScreen *parent, int screenId)
1889     : dpiX(72), dpiY(72), doOnScreenSurface(false), refreshRate(25),
1890       vncServer(0), q_ptr(parent)
1891 {
1892 #if 0//ndef QT_NO_QWS_SIGNALHANDLER
1893     QWSSignalHandler::instance()->addObject(this);
1894 #endif
1895 
1896     vncServer = new QVNCServer(q_ptr, screenId);
1897     vncServer->setRefreshRate(refreshRate);
1898 
1899 
1900     Q_ASSERT(q_ptr->depth() == 32);
1901 
1902     dirty = new QVNCDirtyMapOptimized<quint32>(q_ptr);
1903 }
1904 
~QVNCScreenPrivate()1905 QVNCScreenPrivate::~QVNCScreenPrivate()
1906 {
1907 }
1908 
1909 
setDirty(const QRect & rect,bool force)1910 void QVNCScreenPrivate::setDirty(const QRect& rect, bool force)
1911 {
1912     if (rect.isEmpty())
1913         return;
1914 
1915 //     if (q_ptr->screen())
1916 //         q_ptr->screen()->setDirty(rect);
1917 
1918     if (!vncServer || !vncServer->isConnected()) {
1919 //        qDebug() << "QVNCScreenPrivate::setDirty() - Not connected";
1920         return;
1921     }
1922     const QRect r = rect; // .translated(-q_ptr->offset());
1923     const int x1 = r.x() / MAP_TILE_SIZE;
1924     int y = r.y() / MAP_TILE_SIZE;
1925     for (; (y <= r.bottom() / MAP_TILE_SIZE) && y < dirty->mapHeight; y++)
1926         for (int x = x1; (x <= r.right() / MAP_TILE_SIZE) && x < dirty->mapWidth; x++)
1927             dirty->setDirty(x, y, force);
1928 
1929     vncServer->setDirty();
1930 }
1931 
1932 
1933 
1934 
1935 QT_END_NAMESPACE
1936