summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2018-07-17 17:33:19 +0200
committerSimon Rettberg2018-07-17 17:33:19 +0200
commit74d42e667d4094844929c49c0670c752ebc57cc3 (patch)
tree2e1238affb20a1ee96ab6b0738069e13ec73162b
parent[client] Fix uninitialized variable access (diff)
downloadpvs2-74d42e667d4094844929c49c0670c752ebc57cc3.tar.gz
pvs2-74d42e667d4094844929c49c0670c752ebc57cc3.tar.xz
pvs2-74d42e667d4094844929c49c0670c752ebc57cc3.zip
[client] Rewrite thread sync between VNC worker and VNC window
-rw-r--r--src/client/vnc/vncthread.cpp82
-rw-r--r--src/client/vnc/vncthread.h15
-rw-r--r--src/client/vnc/vncwindow.cpp28
-rw-r--r--src/client/vnc/vncwindow.h3
4 files changed, 62 insertions, 66 deletions
diff --git a/src/client/vnc/vncthread.cpp b/src/client/vnc/vncthread.cpp
index cafdace..dcc61d0 100644
--- a/src/client/vnc/vncthread.cpp
+++ b/src/client/vnc/vncthread.cpp
@@ -44,7 +44,7 @@ static int gcd(int a, int b)
* @param quality The desired quality level for the VNC stream
*/
VncThread::VncThread(QString host, int port, QString passwd, int quality) :
- QThread(), _frameBuffer(NULL), _painter(NULL), _hasNewLocalSize(false), _run(true)
+ QThread(), _frameBuffer(NULL), _run(true), _started(false)
{
_srcStepX = _srcStepY = _dstStepX = _dstStepY = 0;
_host = host;
@@ -60,7 +60,7 @@ VncThread::~VncThread()
{
qDebug("VNC worker destructor called.");
Q_ASSERT(_run == false);
- if (_frameBuffer)
+ if (_frameBuffer != NULL)
delete[] _frameBuffer;
if (_client != NULL) {
if (_client->sock != -1)
@@ -69,8 +69,6 @@ VncThread::~VncThread()
_client->frameBuffer = NULL;
rfbClientCleanup(_client);
}
- if (_painter != NULL)
- delete _painter;
}
/**
@@ -85,9 +83,9 @@ VncThread::~VncThread()
*/
void VncThread::calcScaling()
{
- if (_localSize.isEmpty() || _localSize.width() == 0 || _localSize.height() == 0)
+ if (_localSize.isEmpty())
return;
- if (_clientSize.isEmpty() || _clientSize.width() == 0 || _clientSize.height() == 0)
+ if (_clientSize.isEmpty())
return;
const int gcdX = gcd(_localSize.width(), _clientSize.width());
const int gcdY = gcd(_localSize.height(), _clientSize.height());
@@ -107,16 +105,9 @@ void VncThread::calcScaling()
*
* @param size The new size of the viewer window
*/
-void VncThread::setTargetSize(const QSize size)
+void VncThread::setTargetBuffer(QSharedPointer<QImage> &buffer)
{
- if (_localSize == size)
- return;
- qDebug() << "Setting target size to " << size;
- {
- QMutexLocker lock(&_mutex);
- _newLocalSize = size;
- _hasNewLocalSize = true;
- }
+ _imgScaled = buffer;
}
/**
@@ -175,7 +166,6 @@ void VncThread::run()
// Main VNC event loop
if (_run) {
_connected = true;
- emit projectionStarted();
}
while (_run) {
const int i = WaitForMessage(_client, 100 * 1000); // wait 100ms for message. returns -1 on error/disconnect, 0 if nothing happened, 1 if new data arrived
@@ -183,17 +173,6 @@ void VncThread::run()
break;
if (i > 0 && !HandleRFBServerMessage(_client))
break;
-
- if (_hasNewLocalSize) {
- QMutexLocker lock(&_mutex);
- _hasNewLocalSize = false;
- _localSize = _newLocalSize;
- if (_painter != NULL)
- delete _painter;
- _imgScaled = QImage(_localSize, QImage::Format_RGB32);
- _painter = new QPainter(&_imgScaled);
- this->calcScaling();
- }
}
}
@@ -226,8 +205,18 @@ const QString VncThread::getDesktopName() const
* @param w width of the area in the framebuffer that changed
* @param h height of the area in the framebuffer that changed
*/
-void VncThread::processImageUpdate(const int x, const int y, const int w, const int h)
+void VncThread::processImageUpdate(int x, int y, int w, int h)
{
+ QSharedPointer<QImage> buffer = _imgScaled;
+ QPainter painter(buffer.data());
+ if (buffer->size() != _localSize) {
+ _localSize = buffer->size();
+ this->calcScaling();
+ x = 0;
+ y = 0;
+ w = _img.width();
+ h = _img.height();
+ }
if (_srcStepX > 1 || _srcStepY > 1) {
// Scaling is required as vnc server and client are using different resolutions
// Calc section offsets first
@@ -241,24 +230,24 @@ void VncThread::processImageUpdate(const int x, const int y, const int w, const
const int srcW = endX * _srcStepX - srcX;
const int srcH = endY * _srcStepY - srcY;
// Pixel offsets for destination
- const int dstX = startX * _dstStepX;
- const int dstY = startY * _dstStepY;
- const int dstW = endX * _dstStepX - dstX;
- const int dstH = endY * _dstStepY - dstY;
+ x = startX * _dstStepX;
+ y = startY * _dstStepY;
+ w = endX * _dstStepX - x;
+ h = endY * _dstStepY - y;
// Rescale
- {
- QMutexLocker lock(&_mutex);
- if (_painter != NULL) {
- QImage scaled(
- _img.copy(srcX, srcY, srcW, srcH).scaled(dstW, dstH, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
- _painter->drawImage(dstX, dstY, scaled, 0, 0, dstW, dstH);
- }
- }
- emit imageUpdated(dstX, dstY, dstW, dstH);
+ QImage scaled(
+ _img.copy(srcX, srcY, srcW, srcH).scaled(w, h, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
+ painter.drawImage(x, y, scaled, 0, 0, w, h);
} else {
// Same resolution, nothing to do
- emit imageUpdated(x, y, w, h);
+ painter.drawImage(x, y, _img, x, y, w, h);
}
+ emit imageUpdated(x, y, w, h);
+}
+
+void VncThread::emitStarted()
+{
+ emit projectionStarted();
}
// *** callback stuff ***
@@ -290,9 +279,7 @@ rfbBool VncThread::frameBufferHandler(rfbClient *client)
const int size = width * height * (depth / 8);
qDebug("[%s] Remote desktop: %ix%ix%i", t->metaObject()->className(), width, height, depth);
- QMutexLocker lock(&(t->_mutex));
-
- if (t->_frameBuffer)
+ if (t->_frameBuffer != NULL)
delete[] t->_frameBuffer;
t->_frameBuffer = new uint8_t[size];
@@ -341,6 +328,11 @@ rfbBool VncThread::frameBufferHandler(rfbClient *client)
SendFramebufferUpdateRequest(client, 0, 0, width, height, false);
+ if (!t->_started) {
+ t->_started = true;
+ t->emitStarted();
+ }
+
return true;
}
diff --git a/src/client/vnc/vncthread.h b/src/client/vnc/vncthread.h
index afdb92a..38f5e17 100644
--- a/src/client/vnc/vncthread.h
+++ b/src/client/vnc/vncthread.h
@@ -17,6 +17,7 @@
#include <QtCore>
#include <QImage>
#include <QThread>
+#include <QSharedPointer>
class QPainter;
@@ -45,23 +46,20 @@ private:
QString _passwd;
int _quality;
- QPainter *_painter;
QImage _img;
- QImage _imgScaled;
+ QSharedPointer<QImage> _imgScaled;
QSize _clientSize;
QSize _localSize;
- QMutex _mutex;
-
- QSize _newLocalSize;
- volatile bool _hasNewLocalSize;
int _srcStepX, _srcStepY, _dstStepX, _dstStepY;
volatile bool _connected;
volatile bool _run;
+ bool _started;
void calcScaling();
- void processImageUpdate(const int x, const int y, const int w, const int h);
+ void processImageUpdate(int x, int y, int w, int h);
+ void emitStarted();
// Callbacks for rfb lib. make them class members so the callbacks can access private members of the class.
@@ -73,12 +71,11 @@ public:
VncThread(QString host, int port, QString passwd, int quality);
~VncThread();
- const QImage& getImage() const { if (_srcStepX > 1 || _srcStepY > 1) return _imgScaled; return _img; }
const QSize& getSourceSize() const { return _clientSize; }
const QString getDesktopName() const;
bool isConnected() { return _connected; }
void stop() { _run = false; }
- void setTargetSize(const QSize size);
+ void setTargetBuffer(QSharedPointer<QImage> &buffer);
void run();
int const static HIGH = 0;
diff --git a/src/client/vnc/vncwindow.cpp b/src/client/vnc/vncwindow.cpp
index 3ad75e8..4976bbd 100644
--- a/src/client/vnc/vncwindow.cpp
+++ b/src/client/vnc/vncwindow.cpp
@@ -22,7 +22,8 @@
#include <QTimer>
VncWindow::VncWindow(QWidget *parent) :
- QWidget(parent), _vncWorker(NULL), _viewOnly(true), _multiScreen(false), _clientId(0), _redrawTimer(0), _tcpTimeoutTimer(0)
+ QWidget(parent), _vncWorker(NULL), _viewOnly(true), _multiScreen(false), _clientId(0), _redrawTimer(0), _tcpTimeoutTimer(0),
+ _image(new QImage)
{
QTimer *upper = new QTimer(this);
connect(upper, SIGNAL(timeout()), this, SLOT(timer_moveToTop()));
@@ -85,7 +86,7 @@ void VncWindow::draw(const int x, const int y, const int w, const int h)
if (_vncWorker == NULL)
return;
QPainter painter(this);
- painter.drawImage(x, y, _vncWorker->getImage(), x, y, w, h);
+ painter.drawImage(x, y, *_image, x, y, w, h);
//painter.drawRect(x,y,w,h); // for debugging updated area
}
@@ -125,7 +126,7 @@ void VncWindow::open(const QString& host, int port, const QString& passwd, bool
QSize size;
if (fullscreen) {
- setWindowFlags(Qt::WindowStaysOnTopHint); // | Qt::X11BypassWindowManagerHint); <- better, but window won't get any keyboard input
+ setWindowFlags(Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::Tool); // | Qt::X11BypassWindowManagerHint); <- better, but window won't get any keyboard input
// Show projection on rightmost screen
QDesktopWidget *desktop = QApplication::desktop();
int ns = desktop->numScreens();
@@ -137,9 +138,11 @@ void VncWindow::open(const QString& host, int port, const QString& passwd, bool
}
}
_multiScreen = ns > 1;
+ qDebug() << "Spawning at" << best;
size = best.size();
setGeometry(best);
- showFullScreen();
+ move(best.topLeft());
+ //showFullScreen();
activateWindow();
raise();
} else {
@@ -150,7 +153,7 @@ void VncWindow::open(const QString& host, int port, const QString& passwd, bool
this->repaint();
this->show();
- _vncWorker->setTargetSize(size);
+ _vncWorker->setTargetBuffer(_image);
_tcpTimeoutTimer = startTimer(10000);
_vncWorker->start(QThread::LowPriority);
@@ -204,8 +207,7 @@ void VncWindow::onProjectionStarted()
_tcpTimeoutTimer = 0;
}
emit running(true, _clientId);
- _redrawTimer = startTimer(3000);
- _vncWorker->setTargetSize(this->size());
+ _redrawTimer = startTimer(500);
}
/**
@@ -246,8 +248,7 @@ void VncWindow::timerEvent(QTimerEvent *event)
if (event->timerId() == _redrawTimer) {
killTimer(_redrawTimer);
_redrawTimer = 0;
- if (this->isVisible())
- this->repaint();
+ this->update();
} else if (event->timerId() == _tcpTimeoutTimer) {
killTimer(_tcpTimeoutTimer);
_tcpTimeoutTimer = 0;
@@ -293,10 +294,13 @@ void VncWindow::paintEvent(QPaintEvent *event)
*/
void VncWindow::resizeEvent(QResizeEvent* event)
{
+ const QSize size = event->size();
+ if (size != _image->size()) {
+ _image = QSharedPointer<QImage>(new QImage(size, QImage::Format_RGB32));
+ }
if (_vncWorker != NULL) {
- _vncWorker->setTargetSize(event->size());
+ _vncWorker->setTargetBuffer(_image);
}
- this->repaint();
}
/**
@@ -304,7 +308,7 @@ void VncWindow::resizeEvent(QResizeEvent* event)
*/
void VncWindow::keyReleaseEvent(QKeyEvent* event)
{
- if (event->modifiers() == 0 && event->key() == Qt::Key_Escape && !clientApp->isConnectedToLocalManager()) {
+ if (event->modifiers() == 0 && event->key() == Qt::Key_Escape && clientApp->isConnectedToLocalManager()) {
this->close();
} else {
QWidget::keyReleaseEvent(event);
diff --git a/src/client/vnc/vncwindow.h b/src/client/vnc/vncwindow.h
index df37513..cdcf51f 100644
--- a/src/client/vnc/vncwindow.h
+++ b/src/client/vnc/vncwindow.h
@@ -15,6 +15,8 @@
#define CLIENTVNCVIEWER_H_
#include <QtWidgets>
+#include <QSharedPointer>
+#include <QImage>
class VncThread;
class QPainter;
@@ -55,6 +57,7 @@ private:
int _redrawTimer;
int _tcpTimeoutTimer;
QPixmap _remoteThumb;
+ QSharedPointer<QImage> _image;
void draw(const int x, const int y, const int w, const int h);
void terminateVncThread();