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