Qt 4.8
qvncserver.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
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 
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 
85 
86 
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 
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 
154 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 
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 
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 
217 void QRfbServerInit::setName(const char *n)
218 {
219  delete[] name;
220  name = new char [strlen(n) + 1];
221  strcpy(name, n);
222 }
223 
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 
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 
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 
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 
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 
313 {
314  if (s->bytesAvailable() < 5)
315  return false;
316 
317  char buttonMask;
318  s->read(&buttonMask, 1);
319 
321  wheelDirection = WheelNone;
322  if (buttonMask & 1)
324  if (buttonMask & 2)
326  if (buttonMask & 4)
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 
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 
362  : qvnc_screen(screen), cursor(0)
363 {
364  init(5900);
365 }
366 
367 QVNCServer::QVNCServer(QVNCScreen *screen, int id)
368  : qvnc_screen(screen), cursor(0)
369 {
370  init(5900 + id);
371 }
372 
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 
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 
417 {
418  if (state == Connected && !timer->isActive() &&
419  ((dirtyMap()->numDirty > 0) || dirtyCursor)) {
420  timer->start();
421  }
422 }
423 
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 
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;
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 
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 
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 
803 {
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);
810  qvnc_screen->d_ptr->setDirty(r, true);
811  }
812  wantUpdate = true;
813  checkUpdate();
814  handleMsg = false;
815  }
816 }
817 
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 
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) {
843  Qt::MouseButton button = Qt::NoButton;
844  bool isPress;
845  if (buttonChange(buttons, ev.buttons, &button, &isPress))
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 
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;
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 
889 {
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>
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>
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>
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>
1082 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>
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>
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>
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>
1146 {
1147  setHeight(numRects, 1);
1148  ++numRects;
1149 }
1150 
1151 template <class SRC>
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>
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 
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
1268 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
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 
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();
1511 
1515  map = new uchar[numTiles];
1516 }
1517 
1519 {
1520  delete[] map;
1521  delete[] buffer;
1522 }
1523 
1524 void QVNCDirtyMap::reset()
1525 {
1526  memset(map, 1, numTiles);
1527  memset(buffer, 0, bufferHeight * bufferStride);
1528  numDirty = numTiles;
1529 }
1530 
1531 inline bool QVNCDirtyMap::dirty(int x, int y) const
1532 {
1533  return map[y * mapWidth + x];
1534 }
1535 
1536 inline void QVNCDirtyMap::setClean(int x, int y)
1537 {
1538  map[y * mapWidth + x] = 0;
1539  --numDirty;
1540 }
1541 
1542 template <class T>
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>
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>
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()
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 
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()
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 
1844 inline QImage *QVNCServer::screenImage() const
1845 {
1846  return qvnc_screen->image();
1847 }
1848 
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 
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 
1889  : dpiX(72), dpiY(72), doOnScreenSurface(false), refreshRate(25),
1890  vncServer(0), q_ptr(parent)
1891 {
1892 #if 0//ndef QT_NO_QWS_SIGNALHANDLER
1894 #endif
1895 
1896  vncServer = new QVNCServer(q_ptr, screenId);
1898 
1899 
1900  Q_ASSERT(q_ptr->depth() == 32);
1901 
1903 }
1904 
1906 {
1907 }
1908 
1909 
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 
The QPainter class performs low-level painting on widgets and other paint devices.
Definition: qpainter.h:86
void convertPixels(char *dst, const char *src, int count) const
Q_CORE_EXPORT QByteArray qgetenv(const char *varName)
unsigned int QRgb
Definition: qrgb.h:53
QImage copy(const QRect &rect=QRect()) const
Returns a sub-area of the image as a new image.
Definition: qimage.cpp:1410
int type
Definition: qmetatype.cpp:239
unsigned char c[8]
Definition: qnumeric_p.h:62
bool dirty(int x, int y) const
void frameBufferUpdateRequest()
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
int qint32
Definition: qglobal.h:937
uchar * buffer
Definition: qscreenvnc_p.h:124
quint16 x
Definition: qscreenvnc_p.h:152
static void blendCursor(QImage *dest, const QImage &cursor, const QPoint &offset)
QRgb qt_conv16ToRgb(ushort c)
Definition: qvncserver.cpp:87
void read(QTcpSocket *s)
static void keyEvent(KeyAction action, QWidget *widget, char ascii, Qt::KeyboardModifiers modifier=Qt::NoModifier, int delay=-1)
void setEncodings()
qint64 bytesAvailable() const
Returns the number of incoming bytes that are waiting to be read.
bool flush()
This function writes as much as possible from the internal write buffer to the underlying network soc...
bool isConnected() const
Definition: qscreenvnc_p.h:441
static bool buttonChange(Qt::MouseButtons before, Qt::MouseButtons after, Qt::MouseButton *button, bool *isPress)
Definition: qvncserver.cpp:818
static void handleWheelEvent(QWidget *w, const QPoint &local, const QPoint &global, int d, Qt::Orientation o)
void setDirty(const QRect &rect, bool force=false)
QVNCScreen * q_ptr
Definition: qscreenvnc_p.h:261
bool swapBytes() const
void setPixelFormat()
#define SLOT(a)
Definition: qobjectdefs.h:226
static Qt::MouseButtons buttons
static void handleKeyEvent(QWidget *w, QEvent::Type t, int k, Qt::KeyboardModifiers mods, const QString &text=QString(), bool autorep=false, ushort count=1)
void write(QTcpSocket *socket) const
static int bytesPerPixel(QImage::Format format)
QRect translated(int dx, int dy) const
Returns a copy of the rectangle that is translated dx along the x axis and dy along the y axis...
Definition: qrect.h:328
int width() const
Returns the width of the rectangle.
Definition: qrect.h:303
static const int qt_red_rounding_shift
Definition: qvncserver.cpp:82
int bytesPerLine() const
Returns the number of bytes per image scanline.
Definition: qimage.cpp:1812
long ASN1_INTEGER_get ASN1_INTEGER * a
#define MAP_TILE_SIZE
Definition: qscreenvnc_p.h:100
QVNCDirtyMap(QScreen *screen)
unsigned char quint8
Definition: qglobal.h:934
EventLoopTimerRef timer
int height() const
Returns the height of the rectangle.
Definition: qrect.h:306
int bottom() const
Returns the y-coordinate of the rectangle&#39;s bottom edge.
Definition: qrect.h:249
The QString class provides a Unicode character string.
Definition: qstring.h:83
#define Q_ASSERT(cond)
Definition: qglobal.h:1823
QVNCServer(QVNCScreen *screen)
QRfbHextileEncoder(QVNCServer *s)
bool read(QTcpSocket *s)
virtual void setDirty(int x, int y, bool force=false)=0
void addObject(QObject *object)
QImage image() const
Returns the cursor&#39;s image.
Definition: qscreen_qws.h:151
Q_GUI_EXPORT_INLINE int qRed(QRgb rgb)
Definition: qrgb.h:57
void read(QTcpSocket *s)
static QWSSignalHandler * instance()
qint64 read(char *data, qint64 maxlen)
Reads at most maxSize bytes from the device into data, and returns the number of bytes read...
Definition: qiodevice.cpp:791
bool read(QTcpSocket *s)
void setName(const char *n)
Q_CORE_EXPORT void qDebug(const char *,...)
#define SIGNAL(a)
Definition: qobjectdefs.h:227
unsigned char uchar
Definition: qglobal.h:994
bool isAccelerated() const
Returns true if the cursor is accelerated; otherwise false.
Definition: qscreen_qws.h:153
int width() const
Returns the width.
Definition: qsize.h:126
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
void setRefreshRate(int rate)
Definition: qscreenvnc_p.h:442
virtual int depth() const
Reimplement in subclass to return current depth of the screen.
Definition: fb_base.h:163
void read(QTcpSocket *s)
#define QT_QWS_DEPTH16_RGB
Definition: qvncserver.cpp:70
bool pixelConversionNeeded() const
The QVNCScreen class implements a screen driver for VNC servers.
static const int qt_red_shift
Definition: qvncserver.cpp:75
static bool init
bool read(const uchar *data, int width, int height, int stride)
const char * name
bool read(QTcpSocket *s)
QSize size() const
Returns the size of the rectangle.
Definition: qrect.h:309
static void handleMouseEvent(QWidget *w, const QPoint &local, const QPoint &global, Qt::MouseButtons b)
tlw == 0 means that ev is in global coords only
bool read(const uchar *data, int width, int height, int stride)
unsigned short quint16
Definition: qglobal.h:936
The QImage class provides a hardware-independent image representation that allows direct access to th...
Definition: qimage.h:87
static const char * data(const QByteArray &arr)
unsigned int uint
Definition: qglobal.h:996
int keycode
Definition: qvncserver.cpp:105
bool read(const uchar *data, int width, int height, int stride)
The QTcpSocket class provides a TCP socket.
Definition: qtcpsocket.h:56
void newConnection()
QRfbPixelFormat format
Definition: qscreenvnc_p.h:192
The QRegion class specifies a clip region for a painter.
Definition: qregion.h:68
const T * ptr(const T &t)
int depth() const
Returns the depth of the image.
Definition: qimage.cpp:1620
Q_GUI_EXPORT_INLINE int qBlue(QRgb rgb)
Definition: qrgb.h:63
void write(QTcpSocket *s)
int keysym
Definition: qvncserver.cpp:104
int linestep() const
void qSwap(T &value1, T &value2)
Definition: qglobal.h:2181
bool read(QTcpSocket *s)
void discardClient()
#define rgb(r, g, b)
Definition: qcolor_p.cpp:130
quint16 h
Definition: qscreenvnc_p.h:155
bool isEmpty() const
Returns true if the rectangle is empty, otherwise returns false.
Definition: qrect.h:234
QRgb qRgb(int r, int g, int b)
Returns the ARGB quadruplet (255, {r}, {g}, {b}).
Definition: qrgb.h:69
void write(QTcpSocket *s) const
uchar * bits()
Returns a pointer to the first pixel data.
Definition: qimage.cpp:1946
static QAuServer & server()
Definition: qsound.cpp:79
void init(uint port)
enum QRfbPointerEvent::@354 wheelDirection
int right() const
Returns the x-coordinate of the rectangle&#39;s right edge.
Definition: qrect.h:246
static const int qt_red_mask
Definition: qvncserver.cpp:80
Type
This enum type defines the valid event types in Qt.
Definition: qcoreevent.h:62
void write(QTcpSocket *socket) const
int y() const
Returns the y-coordinate of the rectangle&#39;s top edge.
Definition: qrect.h:255
unsigned short ushort
Definition: qglobal.h:995
void write(QTcpSocket *s)
int x() const
Returns the x-coordinate of the rectangle&#39;s left edge.
Definition: qrect.h:252
quint16 w
Definition: qscreenvnc_p.h:154
QRect boundingRect() const
Returns the cursor&#39;s bounding rectangle.
Definition: qscreen_qws.h:150
int toInt(bool *ok=0, int base=10) const
Returns the byte array converted to an int using base base, which is 10 by default and must be betwee...
int key
The QPoint class defines a point in the plane using integer precision.
Definition: qpoint.h:53
static const int qt_blue_mask
Definition: qvncserver.cpp:78
QVector< QRect > rects() const
Returns an array of non-overlapping rectangles that make up the region.
Definition: qregion.cpp:4412
void write(QTcpSocket *socket) const
void clientCutText()
unsigned int quint32
Definition: qglobal.h:938
The QTcpServer class provides a TCP-based server.
Definition: qtcpserver.h:61
quint16 y
Definition: qscreenvnc_p.h:153
int height() const
Returns the height.
Definition: qsize.h:129
The QRect class defines a rectangle in the plane using integer precision.
Definition: qrect.h:58
Definition: qnamespace.h:54
void drawImage(const QRectF &targetRect, const QImage &image, const QRectF &sourceRect, Qt::ImageConversionFlags flags=Qt::AutoColor)
Definition: qpainter.cpp:5936
Q_GUI_EXPORT_INLINE int qGreen(QRgb rgb)
Definition: qrgb.h:60
static const int qt_blue_rounding_shift
Definition: qvncserver.cpp:84
static const int qt_gbits
Definition: qvncserver.cpp:73
static const int qt_green_shift
Definition: qvncserver.cpp:76
static const struct @353 keyMap[]
The QSize class defines the size of a two-dimensional object using integer point precision.
Definition: qsize.h:53
QImage screenImage() const
bool intersects(const QRect &r) const
Returns true if this rectangle intersects with the given rectangle (i.
Definition: qrect.cpp:1429
virtual QRect geometry() const
Reimplement in subclass to return the pixel geometry of the screen.
Definition: fb_base.h:162
QVNCScreenPrivate(QVNCScreen *parent)
Q_GUI_EXPORT QScreenCursor * qt_screencursor
Definition: qscreen_qws.cpp:67
The QTimer class provides repetitive and single-shot timers.
Definition: qtimer.h:56
virtual ~QVNCDirtyMap()
qint64 write(const char *data, qint64 len)
Writes at most maxSize bytes of data from data to the device.
Definition: qiodevice.cpp:1342
static const int qt_rbits
Definition: qvncserver.cpp:72
static const int qt_bbits
Definition: qvncserver.cpp:74
void setClean(int x, int y)
uchar * base() const
static const int qt_green_mask
Definition: qvncserver.cpp:79
Orientation
Definition: qnamespace.h:174
QVNCDirtyMap * dirty
Definition: qscreenvnc_p.h:253
void setColor(SRC color)
static const int qt_green_rounding_shift
Definition: qvncserver.cpp:83
static const int qt_neg_blue_shift
Definition: qvncserver.cpp:77
uchar * scanLine(int)
Returns a pointer to the pixel data at the scanline with index i.
Definition: qimage.cpp:1886
bool end()
Ends painting.
Definition: qpainter.cpp:1929
SocketState state() const
Returns the state of the socket.
#define text
Definition: qobjectdefs.h:80
The KeyEvent object provides information about a key event.
void setDirty(int x, int y, bool force=false)
QPoint topLeft() const
Returns the position of the rectangle&#39;s top-left corner.
Definition: qrect.h:288
QVNCServer * vncServer
Definition: qscreenvnc_p.h:255
MouseButton
Definition: qnamespace.h:150