Support for client side cursors in the VNC plugin

Client side cursors are a major performance optimization,
avoiding the need to transmit images to the client
just because the cursor has moved.

Change-Id: Icdf4ff948571d39d82c86d251bca46390889d02f
Reviewed-by: Frederik Gladhorn <frederik.gladhorn@qt.io>
bb10
Lars Knoll 2015-12-17 13:29:34 +01:00 committed by Andy Nichols
parent ef4db5a347
commit 1f1b773a35
4 changed files with 37 additions and 30 deletions

View File

@ -526,6 +526,9 @@ void QRfbRawEncoder::write()
QVncClientCursor::QVncClientCursor(QVncServer *s)
: server(s)
{
QWindow *w = QGuiApplication::focusWindow();
QCursor c = w ? w->cursor() : QCursor(Qt::ArrowCursor);
changeCursor(&c, 0);
}
QVncClientCursor::~QVncClientCursor()
@ -634,9 +637,6 @@ void QVncServer::init()
connect(serverSocket, SIGNAL(newConnection()), this, SLOT(newConnection()));
#ifndef QT_NO_QWS_CURSOR
qvnc_cursor = 0;
#endif
encoder = 0;
}
@ -646,10 +646,6 @@ QVncServer::~QVncServer()
encoder = 0;
delete client;
client = 0;
#ifndef QT_NO_QWS_CURSOR
delete qvnc_cursor;
qvnc_cursor = 0;
#endif
}
void QVncServer::setDirty()
@ -977,10 +973,8 @@ void QVncServer::setEncodings()
break;
case Cursor:
supportCursor = true;
if (!qvnc_screen->screen()) {
delete qvnc_cursor;
qvnc_cursor = new QVncClientCursor(this);
}
qDebug() << "client side cursor supported.";
qvnc_screen->enableClientCursor();
break;
case DesktopSize:
supportDesktopSize = true;
@ -1259,10 +1253,7 @@ void QVncServer::checkUpdate()
return;
if (dirtyCursor) {
#ifndef QT_NO_QWS_CURSOR
Q_ASSERT(qvnc_cursor);
qvnc_cursor->write();
#endif
qvnc_screen->clientCursor->write();
dirtyCursor = false;
wantUpdate = false;
return;
@ -1287,11 +1278,7 @@ void QVncServer::discardClient()
state = Disconnected;
delete encoder;
encoder = 0;
#ifndef QT_NO_QWS_CURSOR
delete qvnc_cursor;
qvnc_cursor = 0;
#endif
qvnc_screen->disableClientCursor();
qvnc_screen->setPowerState(QPlatformScreen::PowerStateOff);
}

View File

@ -416,9 +416,6 @@ public:
inline QTcpSocket* clientSocket() const { return client; }
QImage screenImage() const;
inline bool doPixelConversion() const { return needConversion; }
#ifndef QT_NO_QWS_CURSOR
inline bool hasClientCursor() const { return qvnc_cursor != 0; }
#endif
private:
void setPixelFormat();
@ -464,10 +461,6 @@ private:
bool dirtyCursor;
int refreshRate;
QVncScreen *qvnc_screen;
#ifndef QT_NO_QWS_CURSOR
QVncClientCursor *qvnc_cursor;
#endif
QRfbEncoder *encoder;
};

View File

@ -40,6 +40,7 @@
#include "qvncscreen.h"
#include "qvnc_p.h"
#include <QtPlatformSupport/private/qfbwindow_p.h>
#include <QtPlatformSupport/private/qfbcursor_p.h>
#include <QtGui/QPainter>
@ -55,6 +56,8 @@ QVncScreen::QVncScreen(const QStringList &args)
QVncScreen::~QVncScreen()
{
if (clientCursor)
delete clientCursor;
}
bool QVncScreen::initialize()
@ -67,7 +70,7 @@ bool QVncScreen::initialize()
QFbScreen::initializeCompositor();
QT_VNC_DEBUG() << "QVncScreen::init" << geometry();
mCursor = new QFbCursor(this);
disableClientCursor();
switch (depth()) {
case 32:
@ -104,6 +107,27 @@ QRegion QVncScreen::doRedraw()
return touched;
}
void QVncScreen::enableClientCursor()
{
delete mCursor;
mCursor = 0;
clientCursor = new QVncClientCursor(vncServer);
}
void QVncScreen::disableClientCursor()
{
if (vncServer && clientCursor) {
delete clientCursor;
clientCursor = 0;
}
mCursor = new QFbCursor(this);
}
QPlatformCursor *QVncScreen::cursor() const
{
return mCursor ? static_cast<QPlatformCursor *>(mCursor) : static_cast<QPlatformCursor *>(clientCursor);
}
// grabWindow() grabs "from the screen" not from the backingstores.
// In linuxfb's case it will also include the mouse cursor.
QPixmap QVncScreen::grabWindow(WId wid, int x, int y, int width, int height) const

View File

@ -49,6 +49,7 @@ class QFbCursor;
class QTcpSocket;
class QVncServer;
class QVncDirtyMap;
class QVncClientCursor;
class QVncScreen : public QFbScreen
{
@ -64,7 +65,9 @@ public:
QRegion doRedraw() Q_DECL_OVERRIDE;
QImage *image() const { return mScreenImage; }
// QPlatformCursor *cursor() const Q_DECL_OVERRIDE { return mCursor; }
void enableClientCursor();
void disableClientCursor();
QPlatformCursor *cursor() const Q_DECL_OVERRIDE;
void clearDirty() { dirtyRegion = QRegion(); }
@ -76,7 +79,7 @@ public:
QRegion dirtyRegion;
int refreshRate = 30;
QVncServer *vncServer = 0;
QVncClientCursor *clientCursor = 0;
};
QT_END_NAMESPACE