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