diff options
Diffstat (limited to 'src/gui/clientVNCViewer.cpp')
| -rw-r--r-- | src/gui/clientVNCViewer.cpp | 273 |
1 files changed, 273 insertions, 0 deletions
diff --git a/src/gui/clientVNCViewer.cpp b/src/gui/clientVNCViewer.cpp new file mode 100644 index 0000000..d6a218b --- /dev/null +++ b/src/gui/clientVNCViewer.cpp @@ -0,0 +1,273 @@ +/* + # 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 "clientVNCViewer.h" + +ClientVNCViewer::ClientVNCViewer(QWidget *parent) : + QDialog(parent), _thread(0), _viewOnly(true), _buttonMask(0) +{ + // connect to D-Bus and get interface + QDBusConnection dbus = QDBusConnection::sessionBus(); + dbus.registerObject("/vnc", this); + dbus.registerService("org.openslx.pvsgui"); + _ifaceDBus = new OrgOpenslxPvsInterface("org.openslx.pvs", "/", dbus, this); + connect(_ifaceDBus, SIGNAL(project(QString, int, QString, bool, bool, int)), + this, SLOT(open(QString, int, QString, bool, bool, int))); + connect(_ifaceDBus, SIGNAL(unproject()), this, SLOT(close())); +} + +ClientVNCViewer::~ClientVNCViewer() +{ + close(); +} + +//////////////////////////////////////////////////////////////////////////////// +// Public + +void ClientVNCViewer::open(QString host, int port, QString passwd, bool fs, + bool mode, int quality) +{ + // start thread for vnc-updates + _thread = new VNCClientThread(host, port, passwd, quality); + _thread->start(); + //_rfbclient = _thread->getRfbClient(); + //installEventFilter(this); + setMouseTracking(true); // get mouse events even when there is no mousebutton pressed + setFocusPolicy(Qt::WheelFocus); //needed?!? + + setAttribute(Qt::WA_OpaquePaintEvent); + + // smooth transformation? + if (mode) + _mode = Qt::SmoothTransformation; + else + _mode = Qt::FastTransformation; + + // fullscreen? + if (fs) + { + setWindowFlags(Qt::WindowStaysOnTopHint); + showFullScreen(); + activateWindow(); + raise(); + } + else + showNormal(); + + connect(this, SIGNAL(rejected()), this, SLOT(close())); + connect(_thread, SIGNAL(imageUpdated(int,int,int,int)), this, + SLOT(updateImage(int,int,int,int)), Qt::BlockingQueuedConnection); +} + +void ClientVNCViewer::close() +{ + setVisible(false); + if (_thread) + { + disconnect(_thread, SIGNAL(imageUpdated(int,int,int,int)), this, + SLOT(updateImage(int,int,int,int))); + + _thread->terminate = true; + _thread->wait(1000); + delete _thread; + _thread = NULL; + } + disconnect(this, SIGNAL(rejected()), this, SLOT(close())); +} + +void ClientVNCViewer::updateImage(int x, int y, int w, int h) +{ + if (_thread->getSize() != size()) // scaling needed? + { + // grow the update rectangle to avoid artifacts + x -= 1; + y -= 1; + w += 2; + h += 2; + + _img = _thread->getImage().copy(x, y, w, h); + + qreal sx = qreal(width()) / qreal(_thread->getSize().width()); + qreal sy = qreal(height()) / qreal(_thread->getSize().height()); + + x = qRound(qreal(x) * sx); + y = qRound(qreal(y) * sy); + w = qRound(qreal(w) * sx); + h = qRound(qreal(h) * sy); + } + else + { + _img = _thread->getImage().copy(x, y, w, h); + } + + repaint(x, y, w, h); +} + +//////////////////////////////////////////////////////////////////////////////// +// Protected + +void ClientVNCViewer::paintEvent(QPaintEvent *event) +{ + if (_img.isNull()) + return; + + QPainter painter(this); + QRect r = event->rect(); + + if (r == rect()) + _img = _thread->getImage(); // redraw complete image (e.g. on resize) + + if (_thread->getSize() == size()) + { + painter.drawImage(r.topLeft(), _img); // don't scale + } + else + { + QImage i = _img.scaled(r.size(), Qt::IgnoreAspectRatio, _mode); + painter.drawImage(r.topLeft(), i); + } + event->accept(); +} +//returns true if event was processed +/*bool ClientVNCViewer::event(QEvent *event) +{ + switch (event->type()) { + case QEvent::KeyPress: + case QEvent::KeyRelease: + + keyEventHandler(static_cast<QKeyEvent*>(event)); + return true; + break; + case QEvent::MouseButtonDblClick: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseMove: + mouseEventHandler(static_cast<QMouseEvent*>(event)); + return true; + break; + case QEvent::Wheel: + wheelEventHandler(static_cast<QWheelEvent*>(event)); + return true; + break; + default: + return false; + } +}*/ + +//handles mouseevents +void ClientVNCViewer::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; + } + } + qreal sx = qreal(width()) / qreal(_thread->getSize().width()); + qreal sy = qreal(height()) / qreal(_thread->getSize().height()); + _thread->mouseEvent(qRound(e->x() / sx), qRound(e->y() / sy), _buttonMask); +} + +//handles mousewheel +void ClientVNCViewer::wheelEventHandler(QWheelEvent *event) +{ + int eb = 0; + if (event->delta() < 0) + eb |= 0x10; + else + eb |= 0x8; + + qreal sx = qreal(width()) / qreal(_thread->getSize().width()); + qreal sy = qreal(height()) / qreal(_thread->getSize().height()); + const int x = qRound(event->x() / sx); + const int y = qRound(event->y() / sy); + + _thread->mouseEvent(x, y, eb | _buttonMask); + _thread->mouseEvent(x, y, _buttonMask); +} + +//Handles keypress +void ClientVNCViewer::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) { + _thread->keyEvent(k, pressed); + } +} + +//removes modifier keys which have been pressed +void ClientVNCViewer::unpressModifiers() +{ + const QList<unsigned int> keys = _modkeys.keys(); + QList<unsigned int>::const_iterator it = keys.constBegin(); + while (it != keys.end()) { + _thread->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 ClientVNCViewer::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); +} |
