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
---
CMakeLists.txt | 12 +
icons/README | 3 +
icons/remote-control-all.png | Bin 0 -> 5365 bytes
icons/remote-control.png | Bin 0 -> 3657 bytes
pvsmgr.qrc | 2 +
src/gui/frame.cpp | 246 ++++++++++-
src/gui/frame.h | 27 +-
src/input/CMakeLists.txt | 19 +
src/input/inputEvent.cpp | 98 +++++
src/input/inputEvent.h | 218 ++++++++++
src/input/inputEventHandler.h | 187 ++++++++
src/input/inputEventNonQt.cpp | 17 +
src/input/unprivilegedHandlerChain.h | 34 ++
src/input/x11FakeKeyboardHandler.cpp | 800 +++++++++++++++++++++++++++++++++++
src/input/x11FakeKeyboardHandler.h | 29 ++
src/input/x11FakeMouseHandler.cpp | 59 +++
src/input/x11FakeMouseHandler.h | 34 ++
src/input/x11InputUtils.cpp | 29 ++
src/input/x11InputUtils.h | 27 ++
src/pvs.cpp | 24 ++
src/pvs.h | 4 +
src/util/clientGUIUtils.cpp | 13 +-
src/util/clientGUIUtils.h | 6 +
23 files changed, 1874 insertions(+), 14 deletions(-)
create mode 100644 icons/README
create mode 100644 icons/remote-control-all.png
create mode 100644 icons/remote-control.png
create mode 100644 src/input/CMakeLists.txt
create mode 100644 src/input/inputEvent.cpp
create mode 100644 src/input/inputEvent.h
create mode 100644 src/input/inputEventHandler.h
create mode 100644 src/input/inputEventNonQt.cpp
create mode 100644 src/input/unprivilegedHandlerChain.h
create mode 100644 src/input/x11FakeKeyboardHandler.cpp
create mode 100644 src/input/x11FakeKeyboardHandler.h
create mode 100644 src/input/x11FakeMouseHandler.cpp
create mode 100644 src/input/x11FakeMouseHandler.h
create mode 100644 src/input/x11InputUtils.cpp
create mode 100644 src/input/x11InputUtils.h
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2153497..ec688b5 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -29,8 +29,16 @@ FIND_PACKAGE( VNC REQUIRED )
INCLUDE_DIRECTORIES(
${CMAKE_SOURCE_DIR}
${CMAKE_BINARY_DIR}
+ ${X11_INCLUDE_DIR}
+ ${X11_XTest_INCLUDE_PATH}
)
+IF(NOT X11_XTest_FOUND)
+ MESSAGE(FATAL_ERROR "Could not find X11 extension XTest. It is needed for PVS")
+ENDIF()
+
+ADD_SUBDIRECTORY(src/input)
+
################################################################################
# Variables
################################################################################
@@ -299,18 +307,22 @@ TARGET_LINK_LIBRARIES( pvsmgr
${QT_LIBRARIES}
${VNC_LIBRARIES}
${X11_LIBRARIES}
+ pvsinput
)
TARGET_LINK_LIBRARIES( pvsmgrtouch
${QT_LIBRARIES}
${VNC_LIBRARIES}
${X11_LIBRARIES}
+ pvsinput
)
TARGET_LINK_LIBRARIES( pvs
${QT_LIBRARIES}
${VNC_LIBRARIES}
${X11_LIBRARIES}
+ ${X11_XTest_LIB}
+ pvsinput
)
TARGET_LINK_LIBRARIES( pvsgui
diff --git a/icons/README b/icons/README
new file mode 100644
index 0000000..823d998
--- /dev/null
+++ b/icons/README
@@ -0,0 +1,3 @@
+remote-control.png and remote-control-all.png have been taken from the
+Nuvola 1.0 Icon Set, generously provided under the LGPL by its designer,
+David Vignoni. See http://www.icon-king.com/projects/nuvola/
diff --git a/icons/remote-control-all.png b/icons/remote-control-all.png
new file mode 100644
index 0000000..bc7e2ae
Binary files /dev/null and b/icons/remote-control-all.png differ
diff --git a/icons/remote-control.png b/icons/remote-control.png
new file mode 100644
index 0000000..ba460dd
Binary files /dev/null and b/icons/remote-control.png differ
diff --git a/pvsmgr.qrc b/pvsmgr.qrc
index 171412e..cd26abc 100644
--- a/pvsmgr.qrc
+++ b/pvsmgr.qrc
@@ -19,6 +19,8 @@
icons/dozent.png
icons/chat.png
icons/cam32.svg
+ icons/remote-control.png
+ icons/remote-control-all.png
AUTHORS
TRANSLATION
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);
+}
diff --git a/src/gui/frame.h b/src/gui/frame.h
index 3004e0c..19b330a 100644
--- a/src/gui/frame.h
+++ b/src/gui/frame.h
@@ -8,6 +8,7 @@ class VNCClientThread;
class ConnectionWindow;
class ConnectionFrame;
class MainWindow;
+class InputEvent;
class Frame: public QLabel
{
@@ -48,8 +49,13 @@ public:
QToolButton* button_lock;
QToolButton* button_unlock;
QToolButton* button_dozent;
+ QToolButton* button_control;
+ QToolButton* button_control_all;
QList toolButtonList;
+ bool _remoteControlEnabled;
+ bool _remoteControlToAll;
+
public Q_SLOTS:
void updateImage(int x, int y, int w, int h);
void iamDown();
@@ -68,13 +74,23 @@ public Q_SLOTS:
void setLock();
//void unlock();
void setDozent();
+private Q_SLOTS:
+ void remoteControlClicked();
+ void remoteControlAllClicked();
+ void sendMouseMotionEvent();
signals:
- void clicked();
+ void clicked();
protected:
void paintEvent(QPaintEvent *event);
void mousePressEvent ( QMouseEvent * event );
void mouseReleaseEvent ( QMouseEvent * event );
+ void mouseMoveEvent ( QMouseEvent * event );
+ void enterEvent(QEvent* event);
+ void leaveEvent(QEvent* event);
+ void keyPressEvent(QKeyEvent* event);
+ void keyReleaseEvent(QKeyEvent* event);
+ bool event(QEvent* event);
private:
QToolButton* createToolButton(const QString &toolTip, const QIcon &icon, const char *member);
@@ -85,6 +101,15 @@ private:
bool _isLocked;
bool _dozent;
int _ux, _uy;
+
+ // for remote control:
+ QPoint _lastRecordedMousePosition;
+ bool _mousePositionChanged;
+ QTimer* _mouseMotionEventTimer;
+ bool _mouseOver;
+ QPoint rescalePosition(QPointF guiPosition);
+ void updateMousePosition(QMouseEvent* event);
+ void sendInputEvent(InputEvent const&);
};
#endif /* FRAME_H_ */
diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt
new file mode 100644
index 0000000..aa52ec3
--- /dev/null
+++ b/src/input/CMakeLists.txt
@@ -0,0 +1,19 @@
+INCLUDE(${QT_USE_FILE})
+
+SET(pvsinput_SRCS
+ inputEvent.cpp
+ )
+
+IF(UNIX)
+ list(APPEND pvsinput_SRCS
+ x11InputUtils.cpp
+ x11FakeKeyboardHandler.cpp
+ x11FakeMouseHandler.cpp)
+ENDIF()
+
+ADD_LIBRARY(
+ pvsinput
+ STATIC
+ ${pvsinput_HDRS}
+ ${pvsinput_SRCS}
+)
diff --git a/src/input/inputEvent.cpp b/src/input/inputEvent.cpp
new file mode 100644
index 0000000..04a84e7
--- /dev/null
+++ b/src/input/inputEvent.cpp
@@ -0,0 +1,98 @@
+/*
+ * inputEvent.cpp
+ *
+ * Created on: 06.09.2010
+ * Author: brs
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include "inputEvent.h"
+#include
+
+// We implement operators to serialize and load an event:
+QDataStream& operator <<(QDataStream& ostrm, InputEvent const& evt)
+{
+ ostrm << evt.type_ << evt.code_ << evt.value_;
+ return ostrm;
+}
+
+QDataStream& operator >>(QDataStream& istrm, InputEvent& evt)
+{
+ istrm >> evt.type_ >> evt.code_ >> evt.value_;
+ return istrm;
+}
+
+void eventToString(InputEvent const& evt, QString& str)
+{
+ QByteArray ba;
+ QBuffer buf(&ba);
+ buf.open(QIODevice::WriteOnly);
+ QDataStream out(&buf);
+ out << evt;
+ str = QString::fromAscii(ba.toBase64());
+}
+
+bool eventFromString(QString const& str, InputEvent& evt)
+{
+ // TODO This does not do proper error checking. Only use from trusted sources!
+ QByteArray ba = QByteArray::fromBase64(str.toAscii());
+ QBuffer buf(&ba);
+ buf.open(QIODevice::ReadOnly);
+ QDataStream in(&buf);
+ in >> evt;
+ return true;
+}
+
+quint16 InputEvent::mouseButtonsFromQt(int b)
+{
+ quint16 ret = 0;
+ if(b & Qt::LeftButton)
+ {
+ ret |= EB_LEFT;
+ }
+ if(b & Qt::RightButton)
+ {
+ ret |= EB_RIGHT;
+ }
+ if(b & Qt::MidButton)
+ {
+ ret |= EB_MIDDLE;
+ }
+ return ret;
+}
+
+InputEvent InputEvent::mousePressRelease(QMouseEvent const* evt)
+{
+ quint16 button = mouseButtonsFromQt(evt->button());
+ quint16 buttons = mouseButtonsFromQt(evt->buttons());
+ quint16 code;
+
+ if(buttons & button)
+ {
+ code = EC_PRESS;
+ }
+ else
+ {
+ code = EC_RELEASE;
+ }
+
+ quint32 value = ((quint32)button << 16) | buttons;
+ return InputEvent(ET_BUTTON, code, value);
+}
+
+InputEvent InputEvent::keyboardPress(QKeyEvent const* evt)
+{
+ quint32 value = evt->key() | evt->modifiers();
+ return InputEvent(ET_KEY, EC_PRESS, value);
+}
+
+InputEvent InputEvent::keyboardRelease(QKeyEvent const* evt)
+{
+ quint32 value = evt->key() | evt->modifiers();
+ return InputEvent(ET_KEY, EC_RELEASE, value);
+}
diff --git a/src/input/inputEvent.h b/src/input/inputEvent.h
new file mode 100644
index 0000000..917cc64
--- /dev/null
+++ b/src/input/inputEvent.h
@@ -0,0 +1,218 @@
+/*
+ # Copyright (c) 2009 - 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/
+ # --------------------------------------------------------------------------
+ # inputEvent.h:
+ # - Definition of an input event
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef INPUTEVENT_H_
+#define INPUTEVENT_H_
+
+#include
+#include
+#include
+#include
+
+#ifndef __linux
+# error "This will only run on a Linux system. Porting is required for other systems."
+#endif
+
+struct QDataStream;
+struct QString;
+struct QMouseEvent;
+struct QKeyEvent;
+
+class InputEvent
+{
+private:
+ friend QDataStream& operator<<(QDataStream&, InputEvent const&);
+ friend QDataStream& operator>>(QDataStream&, InputEvent&);
+
+ friend void eventToString(InputEvent const& evt, QString& str);
+ friend bool eventFromString(QString const& str, InputEvent& evt);
+
+ uint16_t type_;
+ uint16_t code_;
+ uint32_t value_;
+
+ // InputEvents are immutable. Prohibit assignment:
+ InputEvent& operator=(InputEvent const&); // There intentionally is no implementation.
+public:
+ InputEvent(uint16_t type, uint16_t code, uint32_t value) : type_(type), code_(code), value_(value)
+ {
+ }
+
+ InputEvent()
+ {
+ }
+
+ static InputEvent mouseMotion(uint16_t x, uint16_t y)
+ {
+ return InputEvent(ET_POINTER, 0, ((uint32_t)x << 16) | y);
+ }
+
+ 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 const uint16_t ET_KEY = 0;
+ static const uint16_t ET_BUTTON = 1;
+ static const uint16_t ET_POINTER = 2;
+ static const uint16_t ET_SPECIAL = 3;
+
+ static const uint16_t EC_PRESS = 0;
+ static const uint16_t EC_RELEASE = 1;
+ static const uint16_t EC_REBOOT = 2;
+ static const uint16_t EC_SYSRQ = 3;
+ static const uint16_t EC_KILL_X = 4;
+
+ typedef uint32_t event_key;
+
+ typedef uint32_t event_key_modifiers;
+
+ static const uint16_t EB_LEFT = 1;
+ static const uint16_t EB_MIDDLE = 2;
+ static const uint16_t EB_RIGHT = 4;
+
+ static const uint32_t MODIFIER_MASK =
+ 0x7e000000;
+
+ uint16_t type() const
+ {
+ return type_;
+ }
+
+ uint16_t code() const
+ {
+ return code_;
+ }
+
+ uint32_t value() const
+ {
+ return value_;
+ }
+
+ bool isKeyboard() const
+ {
+ return type_ == ET_KEY;
+ }
+
+ bool isButton() const
+ {
+ return type_ == ET_BUTTON;
+ }
+
+ bool isPointer() const
+ {
+ return type_ == ET_POINTER;
+ }
+
+ bool isSpecial() const
+ {
+ return type_ == ET_SPECIAL;
+ }
+
+ bool isPress() const
+ {
+ return code_ == EC_PRESS;
+ }
+
+ bool isRelease() const
+ {
+ return code_ == EC_RELEASE;
+ }
+
+ uint16_t pressedButton() const
+ {
+ assert(type_ == ET_BUTTON);
+ return (value_ >> 16);
+ }
+
+ uint16_t heldButtons() const
+ {
+ assert(type_ == ET_BUTTON);
+ return (value_ & 0xffff);
+ }
+
+ uint16_t xCoord() const
+ {
+ assert(type_ == ET_POINTER);
+ return (value_ >> 16);
+ }
+
+ uint16_t yCoord() const
+ {
+ assert(type_ == ET_POINTER);
+ return (value_ & 0xffff);
+ }
+
+ static std::string typeToString(uint16_t type)
+ {
+ switch(type)
+ {
+ case ET_BUTTON:
+ return "BUTTON";
+ case ET_KEY:
+ return "KEY";
+ case ET_POINTER:
+ return "POINTER";
+ case ET_SPECIAL:
+ return "SPECIAL";
+ default:
+ std::ostringstream s;
+ s << std::hex << type;
+ return s.str();
+ }
+ }
+
+ static std::string codeToString(uint16_t code)
+ {
+ switch(code)
+ {
+ case EC_PRESS:
+ return "PRESS";
+ case EC_RELEASE:
+ return "RELEASE";
+ case EC_SYSRQ:
+ return "SYSRQ";
+ case EC_REBOOT:
+ return "REBOOT";
+ case EC_KILL_X:
+ return "KILL_X";
+ default:
+ std::ostringstream s;
+ s << std::hex << code;
+ return s.str();
+ }
+ }
+
+ std::string toString() const
+ {
+ std::ostringstream s;
+ s << typeToString(type_) << ':' << codeToString(code_) << ':' << std::hex << value_;
+ return s.str();
+ }
+
+ uint32_t qt_keysym() const
+ {
+ return value_ & ~MODIFIER_MASK;
+ }
+
+ uint32_t qt_modifiers() const
+ {
+ return value_ & MODIFIER_MASK;
+ }
+};
+
+#endif /* INPUTEVENT_H_ */
diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h
new file mode 100644
index 0000000..3910f93
--- /dev/null
+++ b/src/input/inputEventHandler.h
@@ -0,0 +1,187 @@
+/*
+ # Copyright (c) 2009 - 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/
+ # --------------------------------------------------------------------------
+ # inputEventHandler.h:
+ # - Common definitions for input event handlers
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef INPUTEVENTHANDLER_H_
+#define INPUTEVENTHANDLER_H_
+
+#include
+#include
+#include
+#include
+#include
+
+#define HANDLER_TYPE_DONT_CARE 0xffff
+#define HANDLER_CODE_DONT_CARE 0xffff
+#define HANDLER_VALUE_DONT_CARE 0xffffffff
+
+template
+class DefaultInputEventHandler {
+public:
+ static bool matches(InputEvent const& evt) {
+ if(Type != 0xffff) {
+ if(evt.type() != Type)
+ return false;
+ }
+ if(Code != 0xffff) {
+ if(evt.code() != Code)
+ return false;
+ }
+ if(Value != 0xffffffff) {
+ if(evt.value() != Value)
+ return false;
+ }
+ return true;
+ }
+
+ static void initialize()
+ {
+ }
+};
+
+namespace policy {
+
+struct NoSecurityCheck {
+ static bool allow(InputEvent const&) {
+ return true;
+ }
+};
+
+struct PhysicalSeatSecurityCheck {
+ static bool allow(InputEvent const&) {
+ return /* TODO implement */ true;
+ }
+};
+
+struct AlwaysDenySecurityCheck {
+ static bool allow(InputEvent const&) {
+ return false;
+ }
+};
+
+struct UnixLike;
+struct Linux;
+struct Windows;
+
+#if defined(__linux)
+typedef boost::mpl::vector2::type Systems;
+#elif defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__)
+typedef boost::mpl::vector1::type Systems;
+#else
+# error "Porting is needed!"
+#endif
+
+struct SystemEnabled;
+struct SystemDisabled;
+
+template
+struct RequireSystem
+{
+ typedef typename boost::mpl::contains::type enabled_type;
+ static const bool enabled = enabled_type::value;
+};
+
+struct RequireNoSystem
+{
+ typedef boost::mpl::bool_::type enabled_type;
+ static const bool enabled = enabled_type::value;
+};
+
+}
+
+template
+class HandlerHelper
+{
+public:
+ static bool handle(InputEvent const& evt) {
+ if(!SecurityPolicy::allow(evt))
+ {
+ return true;
+ }
+ if(Delegate::matches(evt)) {
+ Delegate::handle(evt);
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ static void initialize()
+ {
+ Delegate::initialize();
+ }
+};
+
+template
+class HandlerHelper
+{
+public:
+ static bool handle(InputEvent const& evt) {
+ return false;
+ }
+
+ static void initialize()
+ {
+ }
+};
+
+template
+struct Handler : public HandlerHelper
+{
+};
+
+template
+struct InputEventHandlerChainHelper
+{
+private:
+ typedef typename boost::mpl::next::type next_iterator_type;
+ typedef InputEventHandlerChainHelper next_in_chain;
+
+ typedef typename boost::mpl::deref::type handler_type;
+
+public:
+ static void handle(InputEvent const& evt) {
+ if(!handler_type::handle(evt)) {
+ next_in_chain::handle(evt);
+ }
+ }
+
+ static void initialize() {
+ handler_type::initialize();
+ next_in_chain::initialize();
+ }
+};
+
+template
+struct InputEventHandlerChainHelper
+{
+public:
+ static void handle(InputEvent const&) {
+ // do nothing
+ }
+
+ static void initialize() {
+ // do nothing
+ }
+};
+
+template
+struct InputEventHandlerChain : public InputEventHandlerChainHelper::type, typename boost::mpl::end::type>
+{
+};
+
+#endif /* INPUTEVENTHANDLER_H_ */
diff --git a/src/input/inputEventNonQt.cpp b/src/input/inputEventNonQt.cpp
new file mode 100644
index 0000000..a7455fd
--- /dev/null
+++ b/src/input/inputEventNonQt.cpp
@@ -0,0 +1,17 @@
+/*
+ # Copyright (c) 2009 - 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/
+ # --------------------------------------------------------------------------
+ # inputEvent.h:
+ # - Input Event routines that need not be linked against Qt
+ # --------------------------------------------------------------------------
+ */
+
+
diff --git a/src/input/unprivilegedHandlerChain.h b/src/input/unprivilegedHandlerChain.h
new file mode 100644
index 0000000..734720a
--- /dev/null
+++ b/src/input/unprivilegedHandlerChain.h
@@ -0,0 +1,34 @@
+/*
+ # Copyright (c) 2009 - 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/
+ # --------------------------------------------------------------------------
+ # inputHandlerChain.h:
+ # - Definition of the input handler chain
+ # --------------------------------------------------------------------------
+ */
+
+#ifndef INPUTHANDLERCHAIN_H_
+#define INPUTHANDLERCHAIN_H_
+
+#include
+#include "inputEventHandler.h"
+
+#include "x11FakeKeyboardHandler.h"
+#include "x11FakeMouseHandler.h"
+
+typedef boost::mpl::list<
+ Handler >,
+ Handler >,
+ Handler >
+>::type unprivileged_handler_list;
+
+typedef InputEventHandlerChain unprivileged_handler_chain;
+
+#endif /* INPUTHANDLERCHAIN_H_ */
diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp
new file mode 100644
index 0000000..bb14b76
--- /dev/null
+++ b/src/input/x11FakeKeyboardHandler.cpp
@@ -0,0 +1,800 @@
+/*
+ # Copyright (c) 2009 - 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/
+ # --------------------------------------------------------------------------
+ # x11FakeKeyboardHandler.h:
+ # - Handle keyboard events on X11 - interface
+ # --------------------------------------------------------------------------
+ */
+
+#include