/* # Copyright (c) 2009, 2010 - OpenSLX Project, Computer Center University of # Freiburg # # This program is free software distributed under the GPL version 2. # See http://openslx.org/COPYING # # If you have any feedback please consult http://openslx.org/feedback and # send your suggestions, praise, or complaints to feedback@openslx.org # # General information about OpenSLX can be found at http://openslx.org/ # ----------------------------------------------------------------------------- # clientVNCViewer.cpp # - connetct to vnc server and show remote screen (window/full) # ----------------------------------------------------------------------------- */ #include "vncwindow.h" #include "vncthread.h" VncWindow::VncWindow(QWidget *parent) : QDialog(parent), _vncWorker(NULL), _viewOnly(true), _buttonMask(0), _clientId(0), _redrawTimer(0) { // } VncWindow::~VncWindow() { // } //////////////////////////////////////////////////////////////////////////////// // Public 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(); _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?!? setWindowTitle(caption); setAttribute(Qt::WA_OpaquePaintEvent); if (fullscreen) { setWindowFlags(Qt::WindowStaysOnTopHint); showFullScreen(); activateWindow(); raise(); } else { resize(800, 600); showNormal(); } 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); } void VncWindow::closeEvent(QCloseEvent *e) { e->ignore(); qDebug("Closing VNC viewer window."); this->setVisible(false); this->onProjectionStopped(); emit running(false, _clientId); } 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 */ void VncWindow::onProjectionStarted() { emit running(true, _clientId); _redrawTimer = startTimer(5000); } void VncWindow::onProjectionStopped() { if(_vncWorker == NULL) return; _vncWorker->blockSignals(true); _vncWorker->stop(); _vncWorker = NULL; if(_redrawTimer != 0) { killTimer(_redrawTimer); _redrawTimer = 0; } this->close(); } //////////////////////////////////////////////////////////////////////////////// // Protected void VncWindow::close() { if (this->isVisible()) QDialog::close(); else emit running(false, _clientId); } void VncWindow::timerEvent(QTimerEvent *event) { if (event->timerId() == _redrawTimer) { if (this->isVisible()) this->repaint(); } else if (event->timerId() == _tcpTimeoutTimer) { killTimer(_tcpTimeoutTimer); if (_vncWorker != NULL && !_vncWorker->isConnected()){ this->onProjectionStopped(); } } else killTimer(event->timerId()); } void VncWindow::paintEvent(QPaintEvent *event) { const QRect &r = event->rect(); this->draw(r.left(), r.top(), r.width(), r.height()); event->accept(); } 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); }