6#include "QtNetwork/qtcpserver.h"
7#include "QtNetwork/qtcpsocket.h"
11#include <QtGui/qguiapplication.h>
12#include <QtGui/QWindow>
20#include <QtCore/QDebug>
33 buffer =
new uchar[bufferHeight * bufferStride];
38 map =
new uchar[numTiles];
49 memset(map, 1, numTiles);
50 memset(buffer, 0, bufferHeight * bufferStride);
56 return map[y * mapWidth + x];
61 map[y * mapWidth + x] = 0;
68 static bool alwaysForce = qEnvironmentVariableIsSet(
"QT_VNC_NO_COMPAREBUFFER");
78 const uchar *scrn =
screen->image()->constBits()
80 uchar *old = buffer + startY * bufferStride + startX *
sizeof(T);
109 if (memcmp(old, scrn,
sizeof(T) * tileWidth)) {
119 memcpy(old, scrn,
sizeof(T) * tileWidth);
127 const int mapIndex = tileY *
mapWidth + tileX;
128 if ((force || changed) && !map[mapIndex]) {
134template class QVncDirtyMapOptimized<
unsigned char>;
135template class QVncDirtyMapOptimized<
unsigned short>;
136template class QVncDirtyMapOptimized<
unsigned int>;
142 { 0xff08, Qt::Key_Backspace },
143 { 0xff09, Qt::Key_Tab },
144 { 0xff0d, Qt::Key_Return },
145 { 0xff1b, Qt::Key_Escape },
146 { 0xff63, Qt::Key_Insert },
147 { 0xffff, Qt::Key_Delete },
148 { 0xff50, Qt::Key_Home },
149 { 0xff57, Qt::Key_End },
150 { 0xff55, Qt::Key_PageUp },
151 { 0xff56, Qt::Key_PageDown },
152 { 0xff51, Qt::Key_Left },
153 { 0xff52, Qt::Key_Up },
154 { 0xff53, Qt::Key_Right },
155 { 0xff54, Qt::Key_Down },
156 { 0xffbe, Qt::Key_F1 },
157 { 0xffbf, Qt::Key_F2 },
158 { 0xffc0, Qt::Key_F3 },
159 { 0xffc1, Qt::Key_F4 },
160 { 0xffc2, Qt::Key_F5 },
161 { 0xffc3, Qt::Key_F6 },
162 { 0xffc4, Qt::Key_F7 },
163 { 0xffc5, Qt::Key_F8 },
164 { 0xffc6, Qt::Key_F9 },
165 { 0xffc7, Qt::Key_F10 },
166 { 0xffc8, Qt::Key_F11 },
167 { 0xffc9, Qt::Key_F12 },
168 { 0xffe1, Qt::Key_Shift },
169 { 0xffe2, Qt::Key_Shift },
170 { 0xffe3, Qt::Key_Control },
171 { 0xffe4, Qt::Key_Control },
172 { 0xffe7, Qt::Key_Meta },
173 { 0xffe8, Qt::Key_Meta },
174 { 0xffe9, Qt::Key_Alt },
175 { 0xffea, Qt::Key_Alt },
177 { 0xffb0, Qt::Key_0 },
178 { 0xffb1, Qt::Key_1 },
179 { 0xffb2, Qt::Key_2 },
180 { 0xffb3, Qt::Key_3 },
181 { 0xffb4, Qt::Key_4 },
182 { 0xffb5, Qt::Key_5 },
183 { 0xffb6, Qt::Key_6 },
184 { 0xffb7, Qt::Key_7 },
185 { 0xffb8, Qt::Key_8 },
186 { 0xffb9, Qt::Key_9 },
188 { 0xff8d, Qt::Key_Return },
189 { 0xffaa, Qt::Key_Asterisk },
190 { 0xffab, Qt::Key_Plus },
191 { 0xffad, Qt::Key_Minus },
192 { 0xffae, Qt::Key_Period },
193 { 0xffaf, Qt::Key_Slash },
195 { 0xff95, Qt::Key_Home },
196 { 0xff96, Qt::Key_Left },
197 { 0xff97, Qt::Key_Up },
198 { 0xff98, Qt::Key_Right },
199 { 0xff99, Qt::Key_Down },
200 { 0xff9a, Qt::Key_PageUp },
201 { 0xff9b, Qt::Key_PageDown },
202 { 0xff9c, Qt::Key_End },
203 { 0xff9e, Qt::Key_Insert },
204 { 0xff9f, Qt::Key_Delete },
212 s->read(
reinterpret_cast<
char*>(buf), 8);
226 s->write(
reinterpret_cast<
char*>(buf) , 8);
238 quint16 a = ntohs(*
reinterpret_cast<quint16 *>(buf + 4));
240 while (a) { a >>= 1;
redBits++; }
242 a = ntohs(*
reinterpret_cast<quint16 *>(buf + 6));
246 a = ntohs(*
reinterpret_cast<quint16 *>(buf + 8));
264 for (
int i = 0; i <
redBits; i++) a = (a << 1) | 1;
265 *
reinterpret_cast<quint16 *>(buf + 4) = htons(a);
268 for (
int i = 0; i <
greenBits; i++) a = (a << 1) | 1;
269 *
reinterpret_cast<quint16 *>(buf + 6) = htons(a);
272 for (
int i = 0; i <
blueBits; i++) a = (a << 1) | 1;
273 *
reinterpret_cast<quint16 *>(buf + 8) = htons(a);
285 name =
new char [strlen(n) + 1];
291 s->read(
reinterpret_cast<
char *>(&width), 2);
292 width = ntohs(width);
293 s->read(
reinterpret_cast<
char *>(&height), 2);
294 height = ntohs(height);
298 s->read(
reinterpret_cast<
char *>(&len), 4);
301 name =
new char [len + 1];
308 quint16 t = htons(width);
309 s->write(
reinterpret_cast<
char *>(&t), 2);
311 s->write(
reinterpret_cast<
char *>(&t), 2);
313 quint32 len =
static_cast<quint32>(strlen(name));
315 s->write(
reinterpret_cast<
char *>(&len), 4);
316 s->write(name,
static_cast<qint64>(strlen(name)));
321 if (s->bytesAvailable() < 3)
326 s->read(
reinterpret_cast<
char *>(&count), 2);
327 count = ntohs(count);
334 if (s->bytesAvailable() < 9)
345 if (s->bytesAvailable() < 7)
350 s->read(
reinterpret_cast<
char *>(&tmp), 2);
353 s->read(
reinterpret_cast<
char *>(&key), 4);
360 if (keyMap[i]
.keysym ==
static_cast<
int>(key))
371 if (key >=
'a' && key <=
'z')
372 keycode = Qt::Key_A + key -
'a';
373 else if (key >=
' ' && key <=
'~')
374 keycode = Qt::Key_Space + key -
' ';
383 if (s->bytesAvailable() < 5)
387 s->read(&buttonMask, 1);
388 buttons = Qt::NoButton;
390 buttons |= Qt::LeftButton;
392 buttons |= Qt::MiddleButton;
394 buttons |= Qt::RightButton;
397 s->read(
reinterpret_cast<
char *>(&tmp), 2);
399 s->read(
reinterpret_cast<
char *>(&tmp), 2);
407 if (s->bytesAvailable() < 7)
412 s->read(
reinterpret_cast<
char *>(&length), 4);
413 length = ntohl(length);
427 QRegion rgn =
client->dirtyRegion();
428 qCDebug(lcVnc) <<
"QRfbRawEncoder::write()" << rgn;
445 rgn &= screenImage.rect();
447 const auto rectsInRegion = rgn.rectCount();
450 const char tmp[2] = { 0, 0 };
451 socket->write(tmp,
sizeof(tmp));
455 const quint16 count = htons(rectsInRegion);
456 socket->write(
reinterpret_cast<
const char *>(&count),
sizeof(count));
459 if (rectsInRegion <= 0)
462 for (
const QRect &tileRect: rgn) {
463 const QRfbRect rect(tileRect.x(), tileRect.y(),
464 tileRect.width(), tileRect.height());
467 const quint32 encoding = htonl(0);
468 socket->write(
reinterpret_cast<
const char *>(&encoding),
sizeof(encoding));
470 qsizetype linestep = screenImage.bytesPerLine();
471 const uchar *screendata = screenImage.scanLine(rect.y)
472 + rect.x * screenImage.depth() / 8;
474 if (client->doPixelConversion()) {
475 const int bufferSize = rect.w * rect.h * bytesPerPixel;
476 if (bufferSize > buffer.size())
477 buffer.resize(bufferSize);
480 char *b = buffer.data();
481 const int bstep = rect.w * bytesPerPixel;
482 const int depth = screenImage.depth();
483 for (
int i = 0; i < rect.h; ++i) {
484 client->convertPixels(b,
reinterpret_cast<
const char*>(screendata), rect.w, depth);
485 screendata += linestep;
488 socket->write(buffer.constData(), bufferSize);
490 for (
int i = 0; i < rect.h; ++i) {
491 socket->write(
reinterpret_cast<
const char*>(screendata), rect.w * bytesPerPixel);
492 screendata += linestep;
495 if (socket->state() == QAbstractSocket::UnconnectedState)
502QVncClientCursor::QVncClientCursor()
504 QWindow *w = QGuiApplication::focusWindow();
505 QCursor c = w ? w->cursor() : QCursor(Qt::ArrowCursor);
506 changeCursor(&c,
nullptr);
509QVncClientCursor::~QVncClientCursor()
513void QVncClientCursor::write(QVncClient *client)
const
515 QTcpSocket *socket = client->clientSocket();
519 const quint16 tmp[6] = { htons(0),
521 htons(
static_cast<uint16_t>(hotspot.x())), htons(
static_cast<uint16_t>(hotspot.y())),
522 htons(
static_cast<uint16_t>(cursor.width())),
523 htons(
static_cast<uint16_t>(cursor.height())) };
524 socket->write(
reinterpret_cast<
const char*>(tmp),
sizeof(tmp));
526 const qint32 encoding = qToBigEndian(-239);
527 socket->write(
reinterpret_cast<
const char*>(&encoding),
sizeof(encoding));
534 Q_ASSERT(cursor.hasAlphaChannel());
535 const QImage img = cursor.convertToFormat(client->server()->screen()->format());
536 const int n = client->clientBytesPerPixel() * img.width();
537 const int depth = img.depth();
538 char *buffer =
new char[n];
539 for (
int i = 0; i < img.height(); ++i) {
540 client->convertPixels(buffer, (
const char*)img.scanLine(i), img.width(), depth);
541 socket->write(buffer, n);
546 const QImage bitmap = cursor.createAlphaMask().convertToFormat(QImage::Format_Mono);
547 Q_ASSERT(bitmap.depth() == 1);
548 Q_ASSERT(bitmap.size() == img.size());
549 const int width = (bitmap.width() + 7) / 8;
550 for (
int i = 0; i < bitmap.height(); ++i)
551 socket->write(
reinterpret_cast<
const char*>(bitmap.scanLine(i)), width);
554void QVncClientCursor::changeCursor(QCursor *widgetCursor, QWindow *window)
557 const Qt::CursorShape shape = widgetCursor ? widgetCursor->shape() : Qt::ArrowCursor;
559 if (shape == Qt::BitmapCursor) {
561 hotspot = widgetCursor->hotSpot();
562 cursor = widgetCursor->pixmap().toImage();
565 QPlatformCursorImage platformImage(
nullptr,
nullptr, 0, 0, 0, 0);
566 platformImage.set(shape);
567 cursor = *platformImage.image();
568 hotspot = platformImage.hotspot();
570 for (
auto client : std::as_const(clients))
571 client->setDirtyCursor();
574void QVncClientCursor::addClient(QVncClient *client)
576 if (!clients.contains(client)) {
577 clients.append(client);
579 client->setDirtyCursor();
583uint QVncClientCursor::removeClient(QVncClient *client)
585 clients.removeOne(client);
586 return clients.size();
591 : qvnc_screen(screen)
594 QMetaObject::invokeMethod(
this,
"init", Qt::QueuedConnection);
599 serverSocket =
new QTcpServer(
this);
600 if (!serverSocket->listen(QHostAddress::Any, m_port))
601 qWarning() <<
"QVncServer could not connect:" << serverSocket->errorString();
603 qWarning(
"QVncServer created on port %d", m_port);
605 connect(serverSocket, SIGNAL(newConnection()),
this, SLOT(newConnection()));
616 for (
auto client : std::as_const(clients))
617 client->setDirty(qvnc_screen->dirtyRegion);
625 auto clientSocket = serverSocket->nextPendingConnection();
626 clients.append(
new QVncClient(clientSocket,
this));
630 qCDebug(lcVnc) <<
"new Connection from: " << clientSocket->localAddress();
632 qvnc_screen->setPowerState(QPlatformScreen::PowerStateOn);
637 clients.removeOne(client);
639 client->deleteLater();
640 if (clients.isEmpty())
641 qvnc_screen->setPowerState(QPlatformScreen::PowerStateOff);
646 return *qvnc_screen->image();
651#include "moc_qvnc_p.cpp"
void write(QTcpSocket *s) const
void setName(const char *n)
void write(QTcpSocket *s)
int clientBytesPerPixel() const
QTcpSocket * clientSocket() const
QVncServer * server() const
void setDirty(int x, int y, bool force=false) override
QVncDirtyMap(QVncScreen *screen)
bool dirty(int x, int y) const
void setClean(int x, int y)
void disableClientCursor(QVncClient *client)
QImage screenImage() const
void discardClient(QVncClient *client)
QVncDirtyMap * dirtyMap() const
Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher")