From 4a30aa26b608238eea90e7ecb97adc3b34d68f86 Mon Sep 17 00:00:00 2001 From: Simon Rettberg Date: Wed, 23 Apr 2014 20:30:48 +0200 Subject: Doxygen comments, removed incomplete unused event handling for VNC RW access, introduced terminateVnc method in VncWindow --- src/client/vnc/vncwindow.cpp | 333 +++++++++++++++++++------------------------ 1 file changed, 144 insertions(+), 189 deletions(-) (limited to 'src/client/vnc/vncwindow.cpp') diff --git a/src/client/vnc/vncwindow.cpp b/src/client/vnc/vncwindow.cpp index 2f2b427..581d503 100644 --- a/src/client/vnc/vncwindow.cpp +++ b/src/client/vnc/vncwindow.cpp @@ -19,7 +19,7 @@ #include "vncthread.h" VncWindow::VncWindow(QWidget *parent) : - QDialog(parent), _vncWorker(NULL), _viewOnly(true), _buttonMask(0), _clientId(0), _redrawTimer(0) + QDialog(parent), _vncWorker(NULL), _viewOnly(true), _clientId(0), _redrawTimer(0), _tcpTimeoutTimer(0) { // } @@ -29,24 +29,80 @@ VncWindow::~VncWindow() // } +//////////////////////////////////////////////////////////////////////////////// +// Private + +/** + * Terminates the vnc worker thread and stops all related timers. + * The thread will be signalled to stop, but we don't wait for it + * to actually terminate. All signaled of the thread are blocked, and we NULL + * our reference to it. It will finish running in a detached state and finally + * delete itself upon completion. + */ +void VncWindow::terminateVncThread() +{ + if(_vncWorker == NULL) + return; + + _vncWorker->blockSignals(true); + _vncWorker->stop(); + _vncWorker = NULL; + if(_redrawTimer != 0) + { + killTimer(_redrawTimer); + _redrawTimer = 0; + } + if(_tcpTimeoutTimer != 0) + { + killTimer(_tcpTimeoutTimer); + _tcpTimeoutTimer = 0; + } +} + +/** + * Draws given part of the current VNC frame buffer to the window. + * Gets the image from the _vncWorker thread in an unsafe way. :( + * + * @param x X offset of the region to draw + * @param y Y offset of the region to draw + * @param w width of the region to draw + * @param h height of the region to draw + */ +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.drawRect(x,y,w,h); // for debugging updated area +} + //////////////////////////////////////////////////////////////////////////////// // Public +/** + * Show the VNC client window and connect to the given VNC server. + * Any currently active VNC client connection is signaled to terminate, + * and a new VNC client worker thread is created for the new connection. + * + * @param host IP address of VNC server to connect to + * @param port Port of VNC server to connect to + * @param passwd (view only) password of VNC server to connect to + * @param ro currently unused + * @param fullscreen display VNC image in fullscreen mode + * @param caption caption of window (only visible if not running in fullscreen mode) + * @param clientId the ID of the client we're connecting to (echoed back to server, not used locally) + */ void VncWindow::open(const QString& host, int port, const QString& passwd, bool ro, bool fullscreen, const QString& caption, const int clientId) { - // start thread for vnc-updates - this->onProjectionStopped(); + this->terminateVncThread(); _clientId = clientId; _vncWorker = new VncThread(host, port, passwd, 1); connect(_vncWorker, SIGNAL(projectionStopped()), this, SLOT(onProjectionStopped()), Qt::QueuedConnection); connect(_vncWorker, SIGNAL(projectionStarted()), this, SLOT(onProjectionStarted()), Qt::QueuedConnection); - - _tcpTimeoutTimer = startTimer(4000); - _vncWorker->start(QThread::LowPriority); - //_rfbclient = _thread->getRfbClient(); - //installEventFilter(this); - setMouseTracking(true); // get mouse events even when there is no mousebutton pressed - setFocusPolicy(Qt::WheelFocus); //needed?!? + connect(_vncWorker, SIGNAL(imageUpdated(const int, const int, const int, const int)), this, + SLOT(onUpdateImage(const int, const int, const int, const int)), + Qt::QueuedConnection); setWindowTitle(caption); @@ -68,27 +124,49 @@ void VncWindow::open(const QString& host, int port, const QString& passwd, bool this->show(); _vncWorker->setTargetSize(this->size()); - connect(_vncWorker, SIGNAL(imageUpdated(const int, const int, const int, const int)), this, - SLOT(onUpdateImage(const int, const int, const int, const int)), - Qt::QueuedConnection); + _tcpTimeoutTimer = startTimer(4000); + _vncWorker->start(QThread::LowPriority); } +/** + * Called by Qt if the window is requested to be closed. This can either happen + * through code (this->close()), or a keypress (Alt-F4, Esc). We'll ignore the + * request and simply hide the window. + * + * @param e close event data + */ void VncWindow::closeEvent(QCloseEvent *e) { e->ignore(); qDebug("Closing VNC viewer window."); this->setVisible(false); - this->onProjectionStopped(); + this->terminateVncThread(); emit running(false, _clientId); } +//////////////////////////////////////////////////////////////////////////////// +// Slots + +/** + * Triggered by imageUpdate signal from the _vncWorker thread telling + * that the given region of the image changed. Simply repaints the + * given area of the window. Coordinates have already been scaled + * accordingly. + * + * @param x X offset of the region to update + * @param y Y offset of the region to update + * @param w width of the region to update + * @param h height of the region to update + */ void VncWindow::onUpdateImage(const int x, const int y, const int w, const int h) { this->repaint(x, y, w, h); } /** - * VNC Thread successfully connected to remote end - projection will start + * Triggered by _vncWorker after successfully connecting to the VNC server. + * This emits a signal that will eventually lead to the ServerConnection + * telling the server that we're now watching another client. */ void VncWindow::onProjectionStarted() { @@ -96,51 +174,77 @@ void VncWindow::onProjectionStarted() _redrawTimer = startTimer(5000); } +/** + * Triggered by _vncWorker when the connection to the VNC server is lost. + * We'll terminate the thread (detached) and close the window. A signal + * telling the server that we're not watching a VNC stream anymore will + * eventually be emited by the closeEvent. + */ void VncWindow::onProjectionStopped() { - if(_vncWorker == NULL) - return; - - _vncWorker->blockSignals(true); - _vncWorker->stop(); - _vncWorker = NULL; - if(_redrawTimer != 0) - { - killTimer(_redrawTimer); - _redrawTimer = 0; - } - this->close(); - + this->terminateVncThread(); + this->close(); } //////////////////////////////////////////////////////////////////////////////// // Protected -void VncWindow::close() + +/** + * Request to close the window. Overriden from QDialog/QWidget. + * If the window is already hidden, this just emits a signal that + * will tell the server that we're not watching a VNC stream + * currently. Otherwise it will just call the implementation of + * the super class. + * + * @return false + */ +bool VncWindow::close() { if (this->isVisible()) - QDialog::close(); - else - emit running(false, _clientId); - + return QDialog::close(); + emit running(false, _clientId); + return false; } + +/** + * Called when a Qt timer fires. + * + * redrawTimer: Redraw whole viewer window. + * + * tcpTimeoutTimer: Check if we're connected, close window if not. + * + * @param event the timer event + */ void VncWindow::timerEvent(QTimerEvent *event) { if (event->timerId() == _redrawTimer) { + killTimer(_redrawTimer); + _redrawTimer = 0; if (this->isVisible()) this->repaint(); } else if (event->timerId() == _tcpTimeoutTimer) { killTimer(_tcpTimeoutTimer); - if (_vncWorker != NULL && !_vncWorker->isConnected()){ - this->onProjectionStopped(); + _tcpTimeoutTimer = 0; + if (_vncWorker != NULL && !_vncWorker->isConnected()) + { + this->close(); } } else killTimer(event->timerId()); } +/** + * Called by Qt when a part of the window should be redrawn. This can either + * be caused by Qt (or the underlying graphical subsystem), or by + * an explicit call to QWidget::repaint() + * + * @param event the paint event, containing data like location and + * size area that should be repainted + */ void VncWindow::paintEvent(QPaintEvent *event) { const QRect &r = event->rect(); @@ -148,161 +252,12 @@ void VncWindow::paintEvent(QPaintEvent *event) event->accept(); } +/** + * Called by Qt if the window is being resized. + * + * @param event the resize event + */ void VncWindow::resizeEvent(QResizeEvent* event) { _vncWorker->setTargetSize(event->size()); } - -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.drawRect(x,y,w,h); // for debugging updated area -} - -//returns true if event was processed -/*bool VncWindow::event(QEvent *event) - { - switch (event->type()) { - case QEvent::KeyPress: - case QEvent::KeyRelease: - - keyEventHandler(static_cast(event)); - return true; - break; - case QEvent::MouseButtonDblClick: - case QEvent::MouseButtonPress: - case QEvent::MouseButtonRelease: - case QEvent::MouseMove: - mouseEventHandler(static_cast(event)); - return true; - break; - case QEvent::Wheel: - wheelEventHandler(static_cast(event)); - return true; - break; - default: - return false; - } - }*/ - -//handles mouseevents -void VncWindow::mouseEventHandler(QMouseEvent *e) -{ - if (e->type() != QEvent::MouseMove) - { - if ((e->type() == QEvent::MouseButtonPress) || (e->type() == QEvent::MouseButtonDblClick)) - { - if (e->button() & Qt::LeftButton) - _buttonMask |= 0x01; - if (e->button() & Qt::MidButton) - _buttonMask |= 0x02; - if (e->button() & Qt::RightButton) - _buttonMask |= 0x04; - } - else if (e->type() == QEvent::MouseButtonRelease) - { - if (e->button() & Qt::LeftButton) - _buttonMask &= 0xfe; - if (e->button() & Qt::MidButton) - _buttonMask &= 0xfd; - if (e->button() & Qt::RightButton) - _buttonMask &= 0xfb; - } - } - _vncWorker->mouseEvent(e->x(), e->y(), _buttonMask); -} - -//handles mousewheel -void VncWindow::wheelEventHandler(QWheelEvent *event) -{ - int eb = 0; - if (event->delta() < 0) - eb |= 0x10; - else - eb |= 0x8; - - const int x = event->x(); - const int y = event->y(); - - _vncWorker->mouseEvent(x, y, eb | _buttonMask); - _vncWorker->mouseEvent(x, y, _buttonMask); -} - -//Handles keypress -void VncWindow::keyEventHandler(QKeyEvent *e) -{ - rfbKeySym k = e->nativeVirtualKey(); - - // do not handle Key_Backtab separately because the Shift-modifier - // is already enabled - if (e->key() == Qt::Key_Backtab) - { - k = XK_Tab; - } - - const bool pressed = (e->type() == QEvent::KeyPress); - - // handle modifiers - if (k == XK_Shift_L || k == XK_Control_L || k == XK_Meta_L || k == XK_Alt_L) - { - if (pressed) - { - _modkeys[k] = true; - } - else if (_modkeys.contains(k)) - { - _modkeys.remove(k); - } - else - { - unpressModifiers(); - } - } - - if (k) - { - _vncWorker->keyEvent(k, pressed); - } -} - -void VncWindow::keyPressEvent(QKeyEvent* event) -{ - if (event->key() == Qt::Key_Escape) - { - _clientId = 0; - this->close(); - } -} - -//removes modifier keys which have been pressed -void VncWindow::unpressModifiers() -{ - const QList keys = _modkeys.keys(); - QList::const_iterator it = keys.constBegin(); - while (it != keys.end()) - { - _vncWorker->keyEvent(*it, false); - it++; - } - _modkeys.clear(); -} - -//(QT Function) Filters events, if _viewOnly is set, true is returned and the event is ignored -//TODO use this function when implementing viewonly switch -bool VncWindow::eventFilter(QObject *obj, QEvent *event) -{ - if (_viewOnly) - { - if (event->type() == QEvent::KeyPress || event->type() == QEvent::KeyRelease - || event->type() == QEvent::MouseButtonDblClick || event->type() == QEvent::MouseButtonPress - || event->type() == QEvent::MouseButtonRelease || event->type() == QEvent::Wheel - || event->type() == QEvent::MouseMove) - return true; - } - - return false; - //return RemoteView::eventFilter(obj, event); -} -- cgit v1.2.3-55-g7522