From 266eb5fb14c07e67aa211a5860e9abf3009136e3 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Mon, 4 Oct 2010 00:22:14 +0200 Subject: Implement first version of basic input event support --- src/gui/frame.cpp | 246 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 234 insertions(+), 12 deletions(-) (limited to 'src/gui/frame.cpp') diff --git a/src/gui/frame.cpp b/src/gui/frame.cpp index cb79643..96ea26c 100644 --- a/src/gui/frame.cpp +++ b/src/gui/frame.cpp @@ -18,11 +18,14 @@ # ----------------------------------------------------------------------------- */ +#include #include "frame.h" #include #include #include +#define MOUSE_MOTION_SEND_INTERVAL 100 /* msecs */ + Frame::Frame(const QString & text, QWidget * parent) : QLabel(parent), _clientVNCThread(0) { @@ -51,10 +54,25 @@ Frame::Frame(const QString & text, QWidget * parent) : button_lock = createToolButton(tr("Lock this client"), QIcon(":/lock"),SLOT(setLock())); //button_unlock = createToolButton(tr("Unlock this client"), QIcon(":/lock"),SLOT(setLock())); button_dozent = createToolButton(tr("Set as Superclient"), QIcon(":/dozent2"),SLOT(setDozent())); + button_control = createToolButton(tr("Enable Remote Control"), QIcon(":/remotecontrol"), SLOT(remoteControlClicked())); + button_control->setCheckable(true); + button_control_all = createToolButton(tr("Remote Control All Clients"), QIcon(":/remotecontrolall"), SLOT(remoteControlAllClicked())); + button_control_all->setCheckable(true); connect(this, SIGNAL(clicked()), this, SLOT(slotClicked())); ip = ""; setToolButtonListVisible(false); + + _remoteControlEnabled = false; + _remoteControlToAll = false; + + _mouseMotionEventTimer = new QTimer(this); + _mouseMotionEventTimer->setInterval(MOUSE_MOTION_SEND_INTERVAL); + _mouseMotionEventTimer->setSingleShot(false); + connect(_mouseMotionEventTimer, SIGNAL(timeout()), this, SLOT(sendMouseMotionEvent())); + + _mousePositionChanged = true; + } Frame::~Frame() @@ -216,23 +234,45 @@ void Frame::slotClicked() void Frame::mousePressEvent(QMouseEvent* event) { - emit clicked(); - if (event->button() == Qt::RightButton) - { - /*if (!_dummy) - DelDummy->setDisabled(true); - menu->exec(QCursor::pos());*/ - } - else - { + if(!_remoteControlEnabled) + { + emit clicked(); + if (event->button() == Qt::RightButton) + { + /*if (!_dummy) + DelDummy->setDisabled(true); + menu->exec(QCursor::pos());*/ + } + else + { - } - QLabel::mousePressEvent(event); + } + QLabel::mousePressEvent(event); + } + else + { + event->accept(); + ConsoleLog writeLine("Captured remote control mousePressEvent"); + + updateMousePosition(event); + sendInputEvent(InputEvent::mousePressRelease(event)); + } } void Frame::mouseReleaseEvent ( QMouseEvent * event ) { - QLabel::mouseReleaseEvent(event); + if(!_remoteControlEnabled) + { + QLabel::mouseReleaseEvent(event); + } + else + { + event->accept(); + ConsoleLog writeLine("Captured remote control mouseReleaseEvent"); + + updateMousePosition(event); + sendInputEvent(InputEvent::mousePressRelease(event)); + } } QToolButton* Frame::createToolButton(const QString &toolTip, const QIcon &icon, const char *member) @@ -330,3 +370,185 @@ void Frame::setDozent() getConFrame()->setDozent(true); } } + +void Frame::remoteControlClicked() +{ + if(_remoteControlEnabled) + { + setMouseTracking(false); + _mouseMotionEventTimer->stop(); + button_control->setToolTip(tr("Enable Remote Control")); + _remoteControlEnabled = false; + button_control->setChecked(false); + releaseKeyboard(); + } + else + { + button_control->setToolTip(tr("Disable Remote Control")); + _remoteControlEnabled = true; + button_control->setChecked(true); + _mouseMotionEventTimer->start(); + setMouseTracking(true); + if(_mouseOver) + grabKeyboard(); + } +} + +void Frame::remoteControlAllClicked() +{ + if(_remoteControlToAll) + { + button_control_all->setToolTip(tr("Remote Control only this Client")); + button_control_all->setChecked(false); + _remoteControlToAll = false; + } + else + { + button_control_all->setToolTip(tr("Remote Control All Clients")); + button_control_all->setChecked(true); + _remoteControlToAll = true; + } +} + + + +void Frame::sendMouseMotionEvent() +{ + InputEvent evt = InputEvent::mouseMotion(_lastRecordedMousePosition.x(), _lastRecordedMousePosition.y()); + + if(!_mousePositionChanged) + return; + + _mousePositionChanged = false; + sendInputEvent(evt); +} + +void Frame::sendInputEvent(InputEvent const& evt) +{ + QString str; + eventToString(evt, str); + std::string evtStr = evt.toString(); + PVSMsg msg(PVSCOMMAND, "INPUTEVENT", str); + + if(_remoteControlEnabled) + { + if(_remoteControlToAll) + { + ConsoleLog writeLine(QString("sendInputEvent(%1) to one").arg(evtStr.c_str())); + PVSConnectionManager::getManager()->getServer()->sendToAll(msg); + } + else + { + ConsoleLog writeLine(QString("sendInputEvent(%1) to all").arg(evtStr.c_str())); + _cFrame->getConnection()->sendMessage(msg); + } + } + else + { + ConsoleLog writeLine("sendMouseMotionEvent() disabled"); + } +} + +void Frame::mouseMoveEvent(QMouseEvent* event) +{ + QPoint newPosition = rescalePosition(event->posF()); + if(newPosition != _lastRecordedMousePosition) { + _lastRecordedMousePosition = newPosition; + _mousePositionChanged = true; + ConsoleLog writeLine(QString("Mouse moved to (%1,%2)").arg(_lastRecordedMousePosition.x()).arg(_lastRecordedMousePosition.y())); + } +} + +QPoint Frame::rescalePosition(QPointF guipos) +{ + QSize s = size(); + QSize t = _clientVNCThread->getSize(); + qreal px, py; + px = guipos.x() * t.width() / (qreal)s.width(); + py = guipos.y() * t.height() / (qreal)s.height(); + return QPoint((int)px, (int)py); +} + +void Frame::updateMousePosition(QMouseEvent* event) +{ + QPoint oldPosition = _lastRecordedMousePosition; + _lastRecordedMousePosition = rescalePosition(event->posF()); + _mousePositionChanged = oldPosition != _lastRecordedMousePosition; + sendMouseMotionEvent(); +} + +void Frame::enterEvent(QEvent* event) +{ + _mouseOver = true; + if(_remoteControlEnabled) + { + grabKeyboard(); + } +} + +void Frame::leaveEvent(QEvent* event) +{ + _mouseOver = false; + if(_remoteControlEnabled) + { + releaseKeyboard(); + } +} + +void Frame::keyPressEvent(QKeyEvent* event) +{ + if(_remoteControlEnabled) + { + // The action of the keyboard may depend on the position of the pointer + sendMouseMotionEvent(); + InputEvent evt = InputEvent::keyboardPress(event); + sendInputEvent(evt); + } + else + { + QLabel::keyPressEvent(event); + } +} + +void Frame::keyReleaseEvent(QKeyEvent* event) +{ + if(_remoteControlEnabled) + { + // The action of the keyboard may depend on the position of the pointer + sendMouseMotionEvent(); + InputEvent evt = InputEvent::keyboardRelease(event); + sendInputEvent(evt); + } + else + { + QLabel::keyReleaseEvent(event); + } +} + +bool Frame::event(QEvent* event) +{ + if(_remoteControlEnabled) + { + bool recognized; + switch(event->type()) + { + case QEvent::ShortcutOverride: + recognized = true; + event->accept(); + break; + case QEvent::KeyPress: + recognized = true; + keyPressEvent(static_cast(event)); + break; + case QEvent::KeyRelease: + recognized = true; + keyReleaseEvent(static_cast(event)); + break; + default: + recognized = false; + } + if(recognized && event->isAccepted()) + return true; + } + return QLabel::event(event); +} -- cgit v1.2.3-55-g7522 From 6f5efe4759276bb5f4add3db93b14051700d2e0d Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Tue, 5 Oct 2010 14:57:32 +0200 Subject: Remove unnecessary Qt dependency from inputEvent.cpp --- src/gui/frame.cpp | 10 ++++------ src/input/inputEvent.cpp | 15 ++++++++------- src/input/inputEvent.h | 7 ++++--- 3 files changed, 16 insertions(+), 16 deletions(-) (limited to 'src/gui/frame.cpp') diff --git a/src/gui/frame.cpp b/src/gui/frame.cpp index 96ea26c..32257ec 100644 --- a/src/gui/frame.cpp +++ b/src/gui/frame.cpp @@ -255,7 +255,7 @@ void Frame::mousePressEvent(QMouseEvent* event) ConsoleLog writeLine("Captured remote control mousePressEvent"); updateMousePosition(event); - sendInputEvent(InputEvent::mousePressRelease(event)); + sendInputEvent(InputEvent::mousePressRelease(event->button(), event->buttons())); } } @@ -271,7 +271,7 @@ void Frame::mouseReleaseEvent ( QMouseEvent * event ) ConsoleLog writeLine("Captured remote control mouseReleaseEvent"); updateMousePosition(event); - sendInputEvent(InputEvent::mousePressRelease(event)); + sendInputEvent(InputEvent::mousePressRelease(event->button(), event->buttons())); } } @@ -501,8 +501,7 @@ void Frame::keyPressEvent(QKeyEvent* event) { // The action of the keyboard may depend on the position of the pointer sendMouseMotionEvent(); - InputEvent evt = InputEvent::keyboardPress(event); - sendInputEvent(evt); + sendInputEvent(InputEvent::keyboardPress(event->key(), event->modifiers())); } else { @@ -516,8 +515,7 @@ void Frame::keyReleaseEvent(QKeyEvent* event) { // The action of the keyboard may depend on the position of the pointer sendMouseMotionEvent(); - InputEvent evt = InputEvent::keyboardRelease(event); - sendInputEvent(evt); + sendInputEvent(InputEvent::keyboardRelease(event->key(), event->modifiers())); } else { diff --git a/src/input/inputEvent.cpp b/src/input/inputEvent.cpp index 04a84e7..9b69a3a 100644 --- a/src/input/inputEvent.cpp +++ b/src/input/inputEvent.cpp @@ -66,10 +66,10 @@ quint16 InputEvent::mouseButtonsFromQt(int b) return ret; } -InputEvent InputEvent::mousePressRelease(QMouseEvent const* evt) +InputEvent InputEvent::mousePressRelease(int qt_button, int qt_buttons) { - quint16 button = mouseButtonsFromQt(evt->button()); - quint16 buttons = mouseButtonsFromQt(evt->buttons()); + quint16 button = mouseButtonsFromQt(qt_button); + quint16 buttons = mouseButtonsFromQt(qt_buttons); quint16 code; if(buttons & button) @@ -85,14 +85,15 @@ InputEvent InputEvent::mousePressRelease(QMouseEvent const* evt) return InputEvent(ET_BUTTON, code, value); } -InputEvent InputEvent::keyboardPress(QKeyEvent const* evt) +InputEvent InputEvent::keyboardPress(int key, int mods) { - quint32 value = evt->key() | evt->modifiers(); + quint32 value = key | mods; return InputEvent(ET_KEY, EC_PRESS, value); } -InputEvent InputEvent::keyboardRelease(QKeyEvent const* evt) +InputEvent InputEvent::keyboardRelease(int key, int mods) { - quint32 value = evt->key() | evt->modifiers(); + quint32 value = key | mods; return InputEvent(ET_KEY, EC_RELEASE, value); } + diff --git a/src/input/inputEvent.h b/src/input/inputEvent.h index 917cc64..7a64bfc 100644 --- a/src/input/inputEvent.h +++ b/src/input/inputEvent.h @@ -62,9 +62,9 @@ public: static uint16_t mouseButtonsFromQt(int b); - static InputEvent mousePressRelease(QMouseEvent const* event); - static InputEvent keyboardPress(QKeyEvent const* event); - static InputEvent keyboardRelease(QKeyEvent const* event); + static InputEvent mousePressRelease(int button, int buttons); + static InputEvent keyboardPress(int key, int mods); + static InputEvent keyboardRelease(int key, int mods); static const uint16_t ET_KEY = 0; static const uint16_t ET_BUTTON = 1; @@ -76,6 +76,7 @@ public: static const uint16_t EC_REBOOT = 2; static const uint16_t EC_SYSRQ = 3; static const uint16_t EC_KILL_X = 4; + static const uint16_t EC_SAY_HELLO = 5; //< for debugging purposes typedef uint32_t event_key; -- cgit v1.2.3-55-g7522 From 21e7bf3b7579c4d9a5cf747ddd64f2fcfa2bf6bb Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Tue, 5 Oct 2010 15:32:11 +0200 Subject: Implement context menu in pvsmgr[touch] by pressing the Menu key for 5 seconds. --- src/gui/frame.cpp | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++----- src/gui/frame.h | 2 ++ 2 files changed, 64 insertions(+), 5 deletions(-) (limited to 'src/gui/frame.cpp') diff --git a/src/gui/frame.cpp b/src/gui/frame.cpp index 32257ec..ccc49cb 100644 --- a/src/gui/frame.cpp +++ b/src/gui/frame.cpp @@ -19,12 +19,14 @@ */ #include +#include #include "frame.h" #include #include #include #define MOUSE_MOTION_SEND_INTERVAL 100 /* msecs */ +#define SPECIAL_EVENT_WAIT_TIME 5000 /* msecs */ Frame::Frame(const QString & text, QWidget * parent) : QLabel(parent), _clientVNCThread(0) @@ -73,6 +75,11 @@ Frame::Frame(const QString & text, QWidget * parent) : _mousePositionChanged = true; + _specialEventTimer = new QTimer(this); + _specialEventTimer->setInterval(SPECIAL_EVENT_WAIT_TIME); + _specialEventTimer->setSingleShot(true); + connect(_specialEventTimer, SIGNAL(timeout()), this, SLOT(showSpecialEventMenu())); + } Frame::~Frame() @@ -499,9 +506,18 @@ void Frame::keyPressEvent(QKeyEvent* event) { if(_remoteControlEnabled) { - // The action of the keyboard may depend on the position of the pointer - sendMouseMotionEvent(); - sendInputEvent(InputEvent::keyboardPress(event->key(), event->modifiers())); + if(event->key() == Qt::Key_Menu) + { + qDebug("Menu has been pressed"); + if(!event->isAutoRepeat()) + _specialEventTimer->start(); + } + else + { + // The action of the keyboard may depend on the position of the pointer + sendMouseMotionEvent(); + sendInputEvent(InputEvent::keyboardPress(event->key(), event->modifiers())); + } } else { @@ -513,9 +529,27 @@ void Frame::keyReleaseEvent(QKeyEvent* event) { if(_remoteControlEnabled) { - // The action of the keyboard may depend on the position of the pointer sendMouseMotionEvent(); - sendInputEvent(InputEvent::keyboardRelease(event->key(), event->modifiers())); + if(event->key() == Qt::Key_Menu) + { + if(!event->isAutoRepeat()) + { + qDebug("Menu has been released"); + if(_specialEventTimer->isActive()) + { + qDebug("Pressing key on client"); + // Pressing the key has been deferred, so do it now: + sendInputEvent(InputEvent::keyboardPress(event->key(), event->modifiers())); + } + sendInputEvent(InputEvent::keyboardRelease(event->key(), event->modifiers())); + _specialEventTimer->stop(); + } + } + else + { + // The action of the keyboard may depend on the position of the pointer + sendInputEvent(InputEvent::keyboardRelease(event->key(), event->modifiers())); + } } else { @@ -550,3 +584,26 @@ bool Frame::event(QEvent* event) } return QLabel::event(event); } + +void Frame::showSpecialEventMenu() +{ + qDebug("Trying to show menu..."); + QMenu* menu = new QMenu(this); + QList specialEvents = privileged_handler_chain::describe(); + QList::iterator iter; + int i; + for(i = 0, iter = specialEvents.begin(); + iter != specialEvents.end(); + iter++, i++) + { + QAction* act = menu->addAction((*iter).descriptionString); + act->setData(i); + } + QAction* selected = menu->exec(QCursor::pos()); + if(selected) + { + int index = selected->data().toInt(); + sendInputEvent(specialEvents.at(index).toEvent()); + } + delete menu; +} diff --git a/src/gui/frame.h b/src/gui/frame.h index 19b330a..8271670 100644 --- a/src/gui/frame.h +++ b/src/gui/frame.h @@ -78,6 +78,7 @@ private Q_SLOTS: void remoteControlClicked(); void remoteControlAllClicked(); void sendMouseMotionEvent(); + void showSpecialEventMenu(); signals: void clicked(); @@ -107,6 +108,7 @@ private: bool _mousePositionChanged; QTimer* _mouseMotionEventTimer; bool _mouseOver; + QTimer* _specialEventTimer; QPoint rescalePosition(QPointF guiPosition); void updateMousePosition(QMouseEvent* event); void sendInputEvent(InputEvent const&); -- cgit v1.2.3-55-g7522 From 898c669b978fcebec5a6882c456d302d481f9513 Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Tue, 5 Oct 2010 15:32:40 +0200 Subject: Bug fix: If there is no VNC thread, do not attempt to rescale mouse position. --- src/gui/frame.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/gui/frame.cpp') diff --git a/src/gui/frame.cpp b/src/gui/frame.cpp index ccc49cb..1b80c3d 100644 --- a/src/gui/frame.cpp +++ b/src/gui/frame.cpp @@ -468,6 +468,9 @@ void Frame::mouseMoveEvent(QMouseEvent* event) QPoint Frame::rescalePosition(QPointF guipos) { + if(!_clientVNCThread) + return QPoint(); + QSize s = size(); QSize t = _clientVNCThread->getSize(); qreal px, py; -- cgit v1.2.3-55-g7522